1/**************************************************************************/
2/* gdscript.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "gdscript.h"
32
33#include "gdscript_analyzer.h"
34#include "gdscript_cache.h"
35#include "gdscript_compiler.h"
36#include "gdscript_parser.h"
37#include "gdscript_rpc_callable.h"
38#include "gdscript_warning.h"
39
40#ifdef TOOLS_ENABLED
41#include "editor/gdscript_docgen.h"
42#endif
43
44#ifdef TESTS_ENABLED
45#include "tests/gdscript_test_runner.h"
46#endif
47
48#include "core/config/engine.h"
49#include "core/config/project_settings.h"
50#include "core/core_constants.h"
51#include "core/core_string_names.h"
52#include "core/io/file_access.h"
53#include "core/io/file_access_encrypted.h"
54#include "core/os/os.h"
55
56#ifdef TOOLS_ENABLED
57#include "editor/editor_paths.h"
58#endif
59
60#include <stdint.h>
61
62///////////////////////////
63
64GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) {
65 name = p_name;
66}
67
68bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const {
69 bool ok;
70 int64_t v = ClassDB::get_integer_constant(name, p_name, &ok);
71
72 if (ok) {
73 r_ret = v;
74 return true;
75 } else {
76 return false;
77 }
78}
79
80void GDScriptNativeClass::_bind_methods() {
81 ClassDB::bind_method(D_METHOD("new"), &GDScriptNativeClass::_new);
82}
83
84Variant GDScriptNativeClass::_new() {
85 Object *o = instantiate();
86 ERR_FAIL_COND_V_MSG(!o, Variant(), "Class type: '" + String(name) + "' is not instantiable.");
87
88 RefCounted *rc = Object::cast_to<RefCounted>(o);
89 if (rc) {
90 return Ref<RefCounted>(rc);
91 } else {
92 return o;
93 }
94}
95
96Object *GDScriptNativeClass::instantiate() {
97 return ClassDB::instantiate(name);
98}
99
100Variant GDScriptNativeClass::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
101 if (p_method == SNAME("new")) {
102 // Constructor.
103 return Object::callp(p_method, p_args, p_argcount, r_error);
104 }
105 MethodBind *method = ClassDB::get_method(name, p_method);
106 if (method && method->is_static()) {
107 // Native static method.
108 return method->call(nullptr, p_args, p_argcount, r_error);
109 }
110
111 r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
112 return Variant();
113}
114
115GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) {
116 if (p_script->initializer) {
117 return p_script->initializer;
118 } else {
119 GDScript *base_src = p_script->_base;
120 if (base_src != nullptr) {
121 return _super_constructor(base_src);
122 } else {
123 return nullptr;
124 }
125 }
126}
127
128void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error) {
129 GDScript *base_src = p_script->_base;
130 if (base_src != nullptr) {
131 _super_implicit_constructor(base_src, p_instance, r_error);
132 if (r_error.error != Callable::CallError::CALL_OK) {
133 return;
134 }
135 }
136 ERR_FAIL_NULL(p_script->implicit_initializer);
137 p_script->implicit_initializer->call(p_instance, nullptr, 0, r_error);
138}
139
140GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) {
141 /* STEP 1, CREATE */
142
143 GDScriptInstance *instance = memnew(GDScriptInstance);
144 instance->base_ref_counted = p_is_ref_counted;
145 instance->members.resize(member_indices.size());
146 instance->script = Ref<GDScript>(this);
147 instance->owner = p_owner;
148 instance->owner_id = p_owner->get_instance_id();
149#ifdef DEBUG_ENABLED
150 //needed for hot reloading
151 for (const KeyValue<StringName, MemberInfo> &E : member_indices) {
152 instance->member_indices_cache[E.key] = E.value.index;
153 }
154#endif
155 instance->owner->set_script_instance(instance);
156
157 /* STEP 2, INITIALIZE AND CONSTRUCT */
158 {
159 MutexLock lock(GDScriptLanguage::singleton->mutex);
160 instances.insert(instance->owner);
161 }
162
163 _super_implicit_constructor(this, instance, r_error);
164 if (r_error.error != Callable::CallError::CALL_OK) {
165 instance->script = Ref<GDScript>();
166 instance->owner->set_script_instance(nullptr);
167 {
168 MutexLock lock(GDScriptLanguage::singleton->mutex);
169 instances.erase(p_owner);
170 }
171 ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance.");
172 }
173
174 if (p_argcount < 0) {
175 return instance;
176 }
177
178 initializer = _super_constructor(this);
179 if (initializer != nullptr) {
180 initializer->call(instance, p_args, p_argcount, r_error);
181 if (r_error.error != Callable::CallError::CALL_OK) {
182 instance->script = Ref<GDScript>();
183 instance->owner->set_script_instance(nullptr);
184 {
185 MutexLock lock(GDScriptLanguage::singleton->mutex);
186 instances.erase(p_owner);
187 }
188 ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance.");
189 }
190 }
191 //@TODO make thread safe
192 return instance;
193}
194
195Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
196 /* STEP 1, CREATE */
197
198 if (!valid) {
199 r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
200 return Variant();
201 }
202
203 r_error.error = Callable::CallError::CALL_OK;
204 Ref<RefCounted> ref;
205 Object *owner = nullptr;
206
207 GDScript *_baseptr = this;
208 while (_baseptr->_base) {
209 _baseptr = _baseptr->_base;
210 }
211
212 ERR_FAIL_COND_V(_baseptr->native.is_null(), Variant());
213 if (_baseptr->native.ptr()) {
214 owner = _baseptr->native->instantiate();
215 } else {
216 owner = memnew(RefCounted); //by default, no base means use reference
217 }
218 ERR_FAIL_COND_V_MSG(!owner, Variant(), "Can't inherit from a virtual class.");
219
220 RefCounted *r = Object::cast_to<RefCounted>(owner);
221 if (r) {
222 ref = Ref<RefCounted>(r);
223 }
224
225 GDScriptInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error);
226 if (!instance) {
227 if (ref.is_null()) {
228 memdelete(owner); //no owner, sorry
229 }
230 return Variant();
231 }
232
233 if (ref.is_valid()) {
234 return ref;
235 } else {
236 return owner;
237 }
238}
239
240bool GDScript::can_instantiate() const {
241#ifdef TOOLS_ENABLED
242 return valid && (tool || ScriptServer::is_scripting_enabled());
243#else
244 return valid;
245#endif
246}
247
248Ref<Script> GDScript::get_base_script() const {
249 if (_base) {
250 return Ref<GDScript>(_base);
251 } else {
252 return Ref<Script>();
253 }
254}
255
256StringName GDScript::get_global_name() const {
257 return global_name;
258}
259
260StringName GDScript::get_instance_base_type() const {
261 if (native.is_valid()) {
262 return native->get_name();
263 }
264 if (base.is_valid() && base->is_valid()) {
265 return base->get_instance_base_type();
266 }
267 return StringName();
268}
269
270struct _GDScriptMemberSort {
271 int index = 0;
272 StringName name;
273 _FORCE_INLINE_ bool operator<(const _GDScriptMemberSort &p_member) const { return index < p_member.index; }
274};
275
276#ifdef TOOLS_ENABLED
277
278void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
279 placeholders.erase(p_placeholder);
280}
281#endif
282
283void GDScript::_get_script_method_list(List<MethodInfo> *r_list, bool p_include_base) const {
284 const GDScript *current = this;
285 while (current) {
286 for (const KeyValue<StringName, GDScriptFunction *> &E : current->member_functions) {
287 r_list->push_back(E.value->get_method_info());
288 }
289
290 if (!p_include_base) {
291 return;
292 }
293
294 current = current->_base;
295 }
296}
297
298void GDScript::get_script_method_list(List<MethodInfo> *r_list) const {
299 _get_script_method_list(r_list, true);
300}
301
302void GDScript::_get_script_property_list(List<PropertyInfo> *r_list, bool p_include_base) const {
303 const GDScript *sptr = this;
304 List<PropertyInfo> props;
305
306 while (sptr) {
307 Vector<_GDScriptMemberSort> msort;
308 for (const KeyValue<StringName, MemberInfo> &E : sptr->member_indices) {
309 _GDScriptMemberSort ms;
310 ms.index = E.value.index;
311 ms.name = E.key;
312 msort.push_back(ms);
313 }
314
315 msort.sort();
316 msort.reverse();
317 for (int i = 0; i < msort.size(); i++) {
318 props.push_front(sptr->member_indices[msort[i].name].property_info);
319 }
320
321#ifdef TOOLS_ENABLED
322 r_list->push_back(sptr->get_class_category());
323#endif // TOOLS_ENABLED
324
325 for (const PropertyInfo &E : props) {
326 r_list->push_back(E);
327 }
328
329 if (!p_include_base) {
330 break;
331 }
332
333 props.clear();
334 sptr = sptr->_base;
335 }
336}
337
338void GDScript::get_script_property_list(List<PropertyInfo> *r_list) const {
339 _get_script_property_list(r_list, true);
340}
341
342bool GDScript::has_method(const StringName &p_method) const {
343 return member_functions.has(p_method);
344}
345
346MethodInfo GDScript::get_method_info(const StringName &p_method) const {
347 HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
348 if (!E) {
349 return MethodInfo();
350 }
351
352 return E->value->get_method_info();
353}
354
355bool GDScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
356#ifdef TOOLS_ENABLED
357
358 HashMap<StringName, Variant>::ConstIterator E = member_default_values_cache.find(p_property);
359 if (E) {
360 r_value = E->value;
361 return true;
362 }
363
364 if (base_cache.is_valid()) {
365 return base_cache->get_property_default_value(p_property, r_value);
366 }
367#endif
368 return false;
369}
370
371ScriptInstance *GDScript::instance_create(Object *p_this) {
372 GDScript *top = this;
373 while (top->_base) {
374 top = top->_base;
375 }
376
377 if (top->native.is_valid()) {
378 if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) {
379 if (EngineDebugger::is_active()) {
380 GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type: '" + p_this->get_class() + "'");
381 }
382 ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type '" + p_this->get_class() + "'" + ".");
383 }
384 }
385
386 Callable::CallError unchecked_error;
387 return _create_instance(nullptr, 0, p_this, Object::cast_to<RefCounted>(p_this) != nullptr, unchecked_error);
388}
389
390PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) {
391#ifdef TOOLS_ENABLED
392 PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(), Ref<Script>(this), p_this));
393 placeholders.insert(si);
394 _update_exports(nullptr, false, si);
395 return si;
396#else
397 return nullptr;
398#endif
399}
400
401bool GDScript::instance_has(const Object *p_this) const {
402 MutexLock lock(GDScriptLanguage::singleton->mutex);
403
404 return instances.has((Object *)p_this);
405}
406
407bool GDScript::has_source_code() const {
408 return !source.is_empty();
409}
410
411String GDScript::get_source_code() const {
412 return source;
413}
414
415void GDScript::set_source_code(const String &p_code) {
416 if (source == p_code) {
417 return;
418 }
419 source = p_code;
420#ifdef TOOLS_ENABLED
421 source_changed_cache = true;
422#endif
423}
424
425#ifdef TOOLS_ENABLED
426void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
427 for (const KeyValue<StringName, Variant> &E : member_default_values_cache) {
428 values[E.key] = E.value;
429 }
430
431 for (const PropertyInfo &E : members_cache) {
432 propnames.push_back(E);
433 }
434
435 if (base_cache.is_valid()) {
436 base_cache->_update_exports_values(values, propnames);
437 }
438}
439
440void GDScript::_add_doc(const DocData::ClassDoc &p_inner_class) {
441 if (_owner) { // Only the top-level class stores doc info
442 _owner->_add_doc(p_inner_class);
443 } else { // Remove old docs, add new
444 for (int i = 0; i < docs.size(); i++) {
445 if (docs[i].name == p_inner_class.name) {
446 docs.remove_at(i);
447 break;
448 }
449 }
450 docs.append(p_inner_class);
451 }
452}
453
454void GDScript::_clear_doc() {
455 docs.clear();
456 doc = DocData::ClassDoc();
457}
458
459String GDScript::get_class_icon_path() const {
460 return simplified_icon_path;
461}
462#endif
463
464bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderScriptInstance *p_instance_to_update) {
465#ifdef TOOLS_ENABLED
466
467 static Vector<GDScript *> base_caches;
468 if (!p_recursive_call) {
469 base_caches.clear();
470 }
471 base_caches.append(this);
472
473 bool changed = false;
474
475 if (source_changed_cache) {
476 source_changed_cache = false;
477 changed = true;
478
479 String basedir = path;
480
481 if (basedir.is_empty()) {
482 basedir = get_path();
483 }
484
485 if (!basedir.is_empty()) {
486 basedir = basedir.get_base_dir();
487 }
488
489 GDScriptParser parser;
490 GDScriptAnalyzer analyzer(&parser);
491 Error err = parser.parse(source, path, false);
492
493 if (err == OK && analyzer.analyze() == OK) {
494 const GDScriptParser::ClassNode *c = parser.get_tree();
495
496 if (base_cache.is_valid()) {
497 base_cache->inheriters_cache.erase(get_instance_id());
498 base_cache = Ref<GDScript>();
499 }
500
501 GDScriptParser::DataType base_type = parser.get_tree()->base_type;
502 if (base_type.kind == GDScriptParser::DataType::CLASS) {
503 Ref<GDScript> bf = GDScriptCache::get_full_script(base_type.script_path, err, path);
504 if (err == OK) {
505 bf = Ref<GDScript>(bf->find_class(base_type.class_type->fqcn));
506 if (bf.is_valid()) {
507 base_cache = bf;
508 bf->inheriters_cache.insert(get_instance_id());
509 }
510 }
511 }
512
513 members_cache.clear();
514 member_default_values_cache.clear();
515 _signals.clear();
516
517 members_cache.push_back(get_class_category());
518
519 for (int i = 0; i < c->members.size(); i++) {
520 const GDScriptParser::ClassNode::Member &member = c->members[i];
521
522 switch (member.type) {
523 case GDScriptParser::ClassNode::Member::VARIABLE: {
524 if (!member.variable->exported) {
525 continue;
526 }
527
528 members_cache.push_back(member.variable->export_info);
529 Variant default_value = analyzer.make_variable_default_value(member.variable);
530 member_default_values_cache[member.variable->identifier->name] = default_value;
531 } break;
532 case GDScriptParser::ClassNode::Member::SIGNAL: {
533 _signals[member.signal->identifier->name] = member.signal->method_info;
534 } break;
535 case GDScriptParser::ClassNode::Member::GROUP: {
536 members_cache.push_back(member.annotation->export_info);
537 } break;
538 default:
539 break; // Nothing.
540 }
541 }
542 } else {
543 placeholder_fallback_enabled = true;
544 return false;
545 }
546 } else if (placeholder_fallback_enabled) {
547 return false;
548 }
549
550 placeholder_fallback_enabled = false;
551
552 if (base_cache.is_valid() && base_cache->is_valid()) {
553 for (int i = 0; i < base_caches.size(); i++) {
554 if (base_caches[i] == base_cache.ptr()) {
555 if (r_err) {
556 *r_err = true;
557 }
558 valid = false; // to show error in the editor
559 base_cache->valid = false;
560 base_cache->inheriters_cache.clear(); // to prevent future stackoverflows
561 base_cache.unref();
562 base.unref();
563 _base = nullptr;
564 ERR_FAIL_V_MSG(false, "Cyclic inheritance in script class.");
565 }
566 }
567 if (base_cache->_update_exports(r_err, true)) {
568 if (r_err && *r_err) {
569 return false;
570 }
571 changed = true;
572 }
573 }
574
575 if ((changed || p_instance_to_update) && placeholders.size()) { //hm :(
576
577 // update placeholders if any
578 HashMap<StringName, Variant> values;
579 List<PropertyInfo> propnames;
580 _update_exports_values(values, propnames);
581
582 if (changed) {
583 for (PlaceHolderScriptInstance *E : placeholders) {
584 E->update(propnames, values);
585 }
586 } else {
587 p_instance_to_update->update(propnames, values);
588 }
589 }
590
591 return changed;
592
593#else
594 return false;
595#endif
596}
597
598void GDScript::update_exports() {
599#ifdef TOOLS_ENABLED
600
601 bool cyclic_error = false;
602 _update_exports(&cyclic_error);
603 if (cyclic_error) {
604 return;
605 }
606
607 HashSet<ObjectID> copy = inheriters_cache; //might get modified
608
609 for (const ObjectID &E : copy) {
610 Object *id = ObjectDB::get_instance(E);
611 GDScript *s = Object::cast_to<GDScript>(id);
612 if (!s) {
613 continue;
614 }
615 s->update_exports();
616 }
617
618#endif
619}
620
621String GDScript::_get_debug_path() const {
622 if (is_built_in() && !get_name().is_empty()) {
623 return vformat("%s(%s)", get_name(), get_script_path());
624 } else {
625 return get_script_path();
626 }
627}
628
629Error GDScript::_static_init() {
630 if (static_initializer) {
631 Callable::CallError call_err;
632 static_initializer->call(nullptr, nullptr, 0, call_err);
633 if (call_err.error != Callable::CallError::CALL_OK) {
634 return ERR_CANT_CREATE;
635 }
636 }
637 Error err = OK;
638 for (KeyValue<StringName, Ref<GDScript>> &inner : subclasses) {
639 err = inner.value->_static_init();
640 if (err) {
641 break;
642 }
643 }
644 return err;
645}
646
647#ifdef TOOLS_ENABLED
648
649void GDScript::_save_old_static_data() {
650 old_static_variables_indices = static_variables_indices;
651 old_static_variables = static_variables;
652 for (KeyValue<StringName, Ref<GDScript>> &inner : subclasses) {
653 inner.value->_save_old_static_data();
654 }
655}
656
657void GDScript::_restore_old_static_data() {
658 for (KeyValue<StringName, MemberInfo> &E : old_static_variables_indices) {
659 if (static_variables_indices.has(E.key)) {
660 static_variables.write[static_variables_indices[E.key].index] = old_static_variables[E.value.index];
661 }
662 }
663 old_static_variables_indices.clear();
664 old_static_variables.clear();
665 for (KeyValue<StringName, Ref<GDScript>> &inner : subclasses) {
666 inner.value->_restore_old_static_data();
667 }
668}
669
670#endif
671
672Error GDScript::reload(bool p_keep_state) {
673 if (reloading) {
674 return OK;
675 }
676 reloading = true;
677
678 bool has_instances;
679 {
680 MutexLock lock(GDScriptLanguage::singleton->mutex);
681
682 has_instances = instances.size();
683 }
684
685 ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
686
687 String basedir = path;
688
689 if (basedir.is_empty()) {
690 basedir = get_path();
691 }
692
693 if (!basedir.is_empty()) {
694 basedir = basedir.get_base_dir();
695 }
696
697 // Loading a template, don't parse.
698#ifdef TOOLS_ENABLED
699 if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) {
700 reloading = false;
701 return OK;
702 }
703#endif
704
705 {
706 String source_path = path;
707 if (source_path.is_empty()) {
708 source_path = get_path();
709 }
710 Ref<GDScript> cached_script = GDScriptCache::get_cached_script(source_path);
711 if (!source_path.is_empty() && cached_script.is_null()) {
712 MutexLock lock(GDScriptCache::singleton->mutex);
713 GDScriptCache::singleton->shallow_gdscript_cache[source_path] = Ref<GDScript>(this);
714 }
715 }
716
717 bool can_run = ScriptServer::is_scripting_enabled() || is_tool();
718
719#ifdef TOOLS_ENABLED
720 if (p_keep_state && can_run && is_valid()) {
721 _save_old_static_data();
722 }
723#endif
724
725 valid = false;
726 GDScriptParser parser;
727 Error err = parser.parse(source, path, false);
728 if (err) {
729 if (EngineDebugger::is_active()) {
730 GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message);
731 }
732 // TODO: Show all error messages.
733 _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
734 reloading = false;
735 return ERR_PARSE_ERROR;
736 }
737
738 GDScriptAnalyzer analyzer(&parser);
739 err = analyzer.analyze();
740
741 if (err) {
742 if (EngineDebugger::is_active()) {
743 GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message);
744 }
745
746 const List<GDScriptParser::ParserError>::Element *e = parser.get_errors().front();
747 while (e != nullptr) {
748 _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
749 e = e->next();
750 }
751 reloading = false;
752 return ERR_PARSE_ERROR;
753 }
754
755 can_run = ScriptServer::is_scripting_enabled() || parser.is_tool();
756
757 GDScriptCompiler compiler;
758 err = compiler.compile(&parser, this, p_keep_state);
759
760 if (err) {
761 _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
762 if (can_run) {
763 if (EngineDebugger::is_active()) {
764 GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error());
765 }
766 reloading = false;
767 return ERR_COMPILATION_FAILED;
768 } else {
769 reloading = false;
770 return err;
771 }
772 }
773
774#ifdef TOOLS_ENABLED
775 // Done after compilation because it needs the GDScript object's inner class GDScript objects,
776 // which are made by calling make_scripts() within compiler.compile() above.
777 GDScriptDocGen::generate_docs(this, parser.get_tree());
778#endif
779
780#ifdef DEBUG_ENABLED
781 for (const GDScriptWarning &warning : parser.get_warnings()) {
782 if (EngineDebugger::is_active()) {
783 Vector<ScriptLanguage::StackInfo> si;
784 EngineDebugger::get_script_debugger()->send_error("", get_script_path(), warning.start_line, warning.get_name(), warning.get_message(), false, ERR_HANDLER_WARNING, si);
785 }
786 }
787#endif
788
789 if (can_run) {
790 err = _static_init();
791 if (err) {
792 return err;
793 }
794 }
795
796#ifdef TOOLS_ENABLED
797 if (can_run && p_keep_state) {
798 _restore_old_static_data();
799 }
800#endif
801
802 reloading = false;
803 return OK;
804}
805
806ScriptLanguage *GDScript::get_language() const {
807 return GDScriptLanguage::get_singleton();
808}
809
810void GDScript::get_constants(HashMap<StringName, Variant> *p_constants) {
811 if (p_constants) {
812 for (const KeyValue<StringName, Variant> &E : constants) {
813 (*p_constants)[E.key] = E.value;
814 }
815 }
816}
817
818void GDScript::get_members(HashSet<StringName> *p_members) {
819 if (p_members) {
820 for (const StringName &E : members) {
821 p_members->insert(E);
822 }
823 }
824}
825
826const Variant GDScript::get_rpc_config() const {
827 return rpc_config;
828}
829
830void GDScript::unload_static() const {
831 GDScriptCache::remove_script(fully_qualified_name);
832}
833
834Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
835 GDScript *top = this;
836 while (top) {
837 HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method);
838 if (E) {
839 ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script.");
840
841 return E->value->call(nullptr, p_args, p_argcount, r_error);
842 }
843 top = top->_base;
844 }
845
846 //none found, regular
847
848 return Script::callp(p_method, p_args, p_argcount, r_error);
849}
850
851bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
852 if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) {
853 r_ret = get_source_code();
854 return true;
855 }
856
857 const GDScript *top = this;
858 while (top) {
859 {
860 HashMap<StringName, Variant>::ConstIterator E = top->constants.find(p_name);
861 if (E) {
862 r_ret = E->value;
863 return true;
864 }
865 }
866
867 {
868 HashMap<StringName, MemberInfo>::ConstIterator E = top->static_variables_indices.find(p_name);
869 if (E) {
870 if (E->value.getter) {
871 Callable::CallError ce;
872 r_ret = const_cast<GDScript *>(this)->callp(E->value.getter, nullptr, 0, ce);
873 return true;
874 }
875 r_ret = top->static_variables[E->value.index];
876 return true;
877 }
878 }
879
880 {
881 HashMap<StringName, GDScriptFunction *>::ConstIterator E = top->member_functions.find(p_name);
882 if (E && E->value->is_static()) {
883 if (top->rpc_config.has(p_name)) {
884 r_ret = Callable(memnew(GDScriptRPCCallable(const_cast<GDScript *>(top), E->key)));
885 } else {
886 r_ret = Callable(const_cast<GDScript *>(top), E->key);
887 }
888 return true;
889 }
890 }
891
892 {
893 HashMap<StringName, Ref<GDScript>>::ConstIterator E = top->subclasses.find(p_name);
894 if (E) {
895 r_ret = E->value;
896 return true;
897 }
898 }
899
900 top = top->_base;
901 }
902
903 return false;
904}
905
906bool GDScript::_set(const StringName &p_name, const Variant &p_value) {
907 if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) {
908 set_source_code(p_value);
909 reload();
910 return true;
911 }
912
913 GDScript *top = this;
914 while (top) {
915 HashMap<StringName, MemberInfo>::ConstIterator E = top->static_variables_indices.find(p_name);
916 if (E) {
917 const MemberInfo *member = &E->value;
918 Variant value = p_value;
919 if (member->data_type.has_type && !member->data_type.is_type(value)) {
920 const Variant *args = &p_value;
921 Callable::CallError err;
922 Variant::construct(member->data_type.builtin_type, value, &args, 1, err);
923 if (err.error != Callable::CallError::CALL_OK || !member->data_type.is_type(value)) {
924 return false;
925 }
926 }
927 if (member->setter) {
928 const Variant *args = &value;
929 Callable::CallError err;
930 callp(member->setter, &args, 1, err);
931 return err.error == Callable::CallError::CALL_OK;
932 } else {
933 top->static_variables.write[member->index] = value;
934 return true;
935 }
936 }
937
938 top = top->_base;
939 }
940
941 return false;
942}
943
944void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {
945 p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
946
947 List<const GDScript *> classes;
948 const GDScript *top = this;
949 while (top) {
950 classes.push_back(top);
951 top = top->_base;
952 }
953
954 for (const List<const GDScript *>::Element *E = classes.back(); E; E = E->prev()) {
955 Vector<_GDScriptMemberSort> msort;
956 for (const KeyValue<StringName, MemberInfo> &F : E->get()->static_variables_indices) {
957 _GDScriptMemberSort ms;
958 ms.index = F.value.index;
959 ms.name = F.key;
960 msort.push_back(ms);
961 }
962 msort.sort();
963
964 for (int i = 0; i < msort.size(); i++) {
965 p_properties->push_back(E->get()->static_variables_indices[msort[i].name].property_info);
966 }
967 }
968}
969
970void GDScript::_bind_methods() {
971 ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &GDScript::_new, MethodInfo("new"));
972}
973
974void GDScript::set_path(const String &p_path, bool p_take_over) {
975 if (is_root_script()) {
976 Script::set_path(p_path, p_take_over);
977 }
978
979 String old_path = path;
980 path = p_path;
981 GDScriptCache::move_script(old_path, p_path);
982
983 for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) {
984 kv.value->set_path(p_path, p_take_over);
985 }
986}
987
988String GDScript::get_script_path() const {
989 return path;
990}
991
992Error GDScript::load_source_code(const String &p_path) {
993 if (p_path.is_empty() || p_path.begins_with("gdscript://") || ResourceLoader::get_resource_type(p_path.get_slice("::", 0)) == "PackedScene") {
994 return OK;
995 }
996
997 Vector<uint8_t> sourcef;
998 Error err;
999 Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
1000 if (err) {
1001 const char *err_name;
1002 if (err < 0 || err >= ERR_MAX) {
1003 err_name = "(invalid error code)";
1004 } else {
1005 err_name = error_names[err];
1006 }
1007 ERR_FAIL_COND_V_MSG(err, err, "Attempt to open script '" + p_path + "' resulted in error '" + err_name + "'.");
1008 }
1009
1010 uint64_t len = f->get_length();
1011 sourcef.resize(len + 1);
1012 uint8_t *w = sourcef.ptrw();
1013 uint64_t r = f->get_buffer(w, len);
1014 ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
1015 w[len] = 0;
1016
1017 String s;
1018 if (s.parse_utf8((const char *)w) != OK) {
1019 ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
1020 }
1021
1022 source = s;
1023 path = p_path;
1024#ifdef TOOLS_ENABLED
1025 source_changed_cache = true;
1026 set_edited(false);
1027 set_last_modified_time(FileAccess::get_modified_time(path));
1028#endif // TOOLS_ENABLED
1029 return OK;
1030}
1031
1032const HashMap<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const {
1033 return member_functions;
1034}
1035
1036StringName GDScript::debug_get_member_by_index(int p_idx) const {
1037 for (const KeyValue<StringName, MemberInfo> &E : member_indices) {
1038 if (E.value.index == p_idx) {
1039 return E.key;
1040 }
1041 }
1042
1043 return "<error>";
1044}
1045
1046StringName GDScript::debug_get_static_var_by_index(int p_idx) const {
1047 for (const KeyValue<StringName, MemberInfo> &E : static_variables_indices) {
1048 if (E.value.index == p_idx) {
1049 return E.key;
1050 }
1051 }
1052
1053 return "<error>";
1054}
1055
1056Ref<GDScript> GDScript::get_base() const {
1057 return base;
1058}
1059
1060bool GDScript::inherits_script(const Ref<Script> &p_script) const {
1061 Ref<GDScript> gd = p_script;
1062 if (gd.is_null()) {
1063 return false;
1064 }
1065
1066 const GDScript *s = this;
1067
1068 while (s) {
1069 if (s == p_script.ptr()) {
1070 return true;
1071 }
1072 s = s->_base;
1073 }
1074
1075 return false;
1076}
1077
1078GDScript *GDScript::find_class(const String &p_qualified_name) {
1079 String first = p_qualified_name.get_slice("::", 0);
1080
1081 Vector<String> class_names;
1082 GDScript *result = nullptr;
1083 // Empty initial name means start here.
1084 if (first.is_empty() || first == global_name) {
1085 class_names = p_qualified_name.split("::");
1086 result = this;
1087 } else if (p_qualified_name.begins_with(get_root_script()->path)) {
1088 // Script path could have a class path separator("::") in it.
1089 class_names = p_qualified_name.trim_prefix(get_root_script()->path).split("::");
1090 result = get_root_script();
1091 } else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) {
1092 class_names = p_qualified_name.split("::");
1093 result = E->value.ptr();
1094 } else if (_owner != nullptr) {
1095 // Check parent scope.
1096 return _owner->find_class(p_qualified_name);
1097 }
1098
1099 // Starts at index 1 because index 0 was handled above.
1100 for (int i = 1; result != nullptr && i < class_names.size(); i++) {
1101 String current_name = class_names[i];
1102 if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) {
1103 result = E->value.ptr();
1104 } else {
1105 // Couldn't find inner class.
1106 return nullptr;
1107 }
1108 }
1109
1110 return result;
1111}
1112
1113bool GDScript::has_class(const GDScript *p_script) {
1114 String fqn = p_script->fully_qualified_name;
1115 if (fully_qualified_name.is_empty() && fqn.get_slice("::", 0).is_empty()) {
1116 return p_script == this;
1117 } else if (fqn.begins_with(fully_qualified_name)) {
1118 return p_script == find_class(fqn.trim_prefix(fully_qualified_name));
1119 }
1120 return false;
1121}
1122
1123GDScript *GDScript::get_root_script() {
1124 GDScript *result = this;
1125 while (result->_owner) {
1126 result = result->_owner;
1127 }
1128 return result;
1129}
1130
1131RBSet<GDScript *> GDScript::get_dependencies() {
1132 RBSet<GDScript *> dependencies;
1133
1134 _get_dependencies(dependencies, this);
1135 dependencies.erase(this);
1136
1137 return dependencies;
1138}
1139
1140RBSet<GDScript *> GDScript::get_inverted_dependencies() {
1141 RBSet<GDScript *> inverted_dependencies;
1142
1143 List<GDScript *> scripts;
1144 {
1145 MutexLock lock(GDScriptLanguage::singleton->mutex);
1146
1147 SelfList<GDScript> *elem = GDScriptLanguage::singleton->script_list.first();
1148 while (elem) {
1149 scripts.push_back(elem->self());
1150 elem = elem->next();
1151 }
1152 }
1153
1154 for (GDScript *scr : scripts) {
1155 if (scr == nullptr || scr == this || scr->destructing) {
1156 continue;
1157 }
1158
1159 RBSet<GDScript *> scr_dependencies = scr->get_dependencies();
1160 if (scr_dependencies.has(this)) {
1161 inverted_dependencies.insert(scr);
1162 }
1163 }
1164
1165 return inverted_dependencies;
1166}
1167
1168RBSet<GDScript *> GDScript::get_must_clear_dependencies() {
1169 RBSet<GDScript *> dependencies = get_dependencies();
1170 RBSet<GDScript *> must_clear_dependencies;
1171 HashMap<GDScript *, RBSet<GDScript *>> inverted_dependencies;
1172
1173 for (GDScript *E : dependencies) {
1174 inverted_dependencies.insert(E, E->get_inverted_dependencies());
1175 }
1176
1177 RBSet<GDScript *> cant_clear;
1178 for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) {
1179 for (GDScript *F : E.value) {
1180 if (!dependencies.has(F)) {
1181 cant_clear.insert(E.key);
1182 for (GDScript *G : E.key->get_dependencies()) {
1183 cant_clear.insert(G);
1184 }
1185 break;
1186 }
1187 }
1188 }
1189
1190 for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) {
1191 if (cant_clear.has(E.key) || ScriptServer::is_global_class(E.key->get_fully_qualified_name())) {
1192 continue;
1193 }
1194 must_clear_dependencies.insert(E.key);
1195 }
1196
1197 cant_clear.clear();
1198 dependencies.clear();
1199 inverted_dependencies.clear();
1200 return must_clear_dependencies;
1201}
1202
1203bool GDScript::has_script_signal(const StringName &p_signal) const {
1204 if (_signals.has(p_signal)) {
1205 return true;
1206 }
1207 if (base.is_valid()) {
1208 return base->has_script_signal(p_signal);
1209 }
1210#ifdef TOOLS_ENABLED
1211 else if (base_cache.is_valid()) {
1212 return base_cache->has_script_signal(p_signal);
1213 }
1214#endif
1215 return false;
1216}
1217
1218void GDScript::_get_script_signal_list(List<MethodInfo> *r_list, bool p_include_base) const {
1219 for (const KeyValue<StringName, MethodInfo> &E : _signals) {
1220 r_list->push_back(E.value);
1221 }
1222
1223 if (!p_include_base) {
1224 return;
1225 }
1226
1227 if (base.is_valid()) {
1228 base->get_script_signal_list(r_list);
1229 }
1230#ifdef TOOLS_ENABLED
1231 else if (base_cache.is_valid()) {
1232 base_cache->get_script_signal_list(r_list);
1233 }
1234#endif
1235}
1236
1237void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
1238 _get_script_signal_list(r_signals, true);
1239}
1240
1241GDScript *GDScript::_get_gdscript_from_variant(const Variant &p_variant) {
1242 Object *obj = p_variant;
1243 if (obj == nullptr || obj->get_instance_id().is_null()) {
1244 return nullptr;
1245 }
1246 return Object::cast_to<GDScript>(obj);
1247}
1248
1249void GDScript::_get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except) {
1250 if (p_dependencies.has(this)) {
1251 return;
1252 }
1253 p_dependencies.insert(this);
1254
1255 for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
1256 if (E.value == nullptr) {
1257 continue;
1258 }
1259 for (const Variant &V : E.value->constants) {
1260 GDScript *scr = _get_gdscript_from_variant(V);
1261 if (scr != nullptr && scr != p_except) {
1262 scr->_get_dependencies(p_dependencies, p_except);
1263 }
1264 }
1265 }
1266
1267 if (implicit_initializer) {
1268 for (const Variant &V : implicit_initializer->constants) {
1269 GDScript *scr = _get_gdscript_from_variant(V);
1270 if (scr != nullptr && scr != p_except) {
1271 scr->_get_dependencies(p_dependencies, p_except);
1272 }
1273 }
1274 }
1275
1276 if (implicit_ready) {
1277 for (const Variant &V : implicit_ready->constants) {
1278 GDScript *scr = _get_gdscript_from_variant(V);
1279 if (scr != nullptr && scr != p_except) {
1280 scr->_get_dependencies(p_dependencies, p_except);
1281 }
1282 }
1283 }
1284
1285 for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
1286 if (E.value != p_except) {
1287 E.value->_get_dependencies(p_dependencies, p_except);
1288 }
1289 }
1290
1291 for (const KeyValue<StringName, Variant> &E : constants) {
1292 GDScript *scr = _get_gdscript_from_variant(E.value);
1293 if (scr != nullptr && scr != p_except) {
1294 scr->_get_dependencies(p_dependencies, p_except);
1295 }
1296 }
1297}
1298
1299GDScript::GDScript() :
1300 script_list(this) {
1301 {
1302 MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
1303
1304 GDScriptLanguage::get_singleton()->script_list.add(&script_list);
1305 }
1306
1307 path = vformat("gdscript://%d.gd", get_instance_id());
1308}
1309
1310void GDScript::_save_orphaned_subclasses(ClearData *p_clear_data) {
1311 struct ClassRefWithName {
1312 ObjectID id;
1313 String fully_qualified_name;
1314 };
1315 Vector<ClassRefWithName> weak_subclasses;
1316 // collect subclasses ObjectID and name
1317 for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
1318 E.value->_owner = nullptr; //bye, you are no longer owned cause I died
1319 ClassRefWithName subclass;
1320 subclass.id = E.value->get_instance_id();
1321 subclass.fully_qualified_name = E.value->fully_qualified_name;
1322 weak_subclasses.push_back(subclass);
1323 }
1324
1325 // clear subclasses to allow unused subclasses to be deleted
1326 for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
1327 p_clear_data->scripts.insert(E.value);
1328 }
1329 subclasses.clear();
1330 // subclasses are also held by constants, clear those as well
1331 for (KeyValue<StringName, Variant> &E : constants) {
1332 GDScript *gdscr = _get_gdscript_from_variant(E.value);
1333 if (gdscr != nullptr) {
1334 p_clear_data->scripts.insert(gdscr);
1335 }
1336 }
1337 constants.clear();
1338
1339 // keep orphan subclass only for subclasses that are still in use
1340 for (int i = 0; i < weak_subclasses.size(); i++) {
1341 ClassRefWithName subclass = weak_subclasses[i];
1342 Object *obj = ObjectDB::get_instance(subclass.id);
1343 if (!obj) {
1344 continue;
1345 }
1346 // subclass is not released
1347 GDScriptLanguage::get_singleton()->add_orphan_subclass(subclass.fully_qualified_name, subclass.id);
1348 }
1349}
1350
1351#ifdef DEBUG_ENABLED
1352String GDScript::debug_get_script_name(const Ref<Script> &p_script) {
1353 if (p_script.is_valid()) {
1354 Ref<GDScript> gdscript = p_script;
1355 if (gdscript.is_valid()) {
1356 if (gdscript->get_local_name() != StringName()) {
1357 return gdscript->get_local_name();
1358 }
1359 return gdscript->get_fully_qualified_name().get_file();
1360 }
1361
1362 if (p_script->get_global_name() != StringName()) {
1363 return p_script->get_global_name();
1364 } else if (!p_script->get_path().is_empty()) {
1365 return p_script->get_path().get_file();
1366 } else if (!p_script->get_name().is_empty()) {
1367 return p_script->get_name(); // Resource name.
1368 }
1369 }
1370
1371 return "<unknown script>";
1372}
1373#endif
1374
1375void GDScript::clear(ClearData *p_clear_data) {
1376 if (clearing) {
1377 return;
1378 }
1379 clearing = true;
1380
1381 ClearData data;
1382 ClearData *clear_data = p_clear_data;
1383 bool is_root = false;
1384
1385 // If `clear_data` is `nullptr`, it means that it's the root.
1386 // The root is in charge to clear functions and scripts of itself and its dependencies
1387 if (clear_data == nullptr) {
1388 clear_data = &data;
1389 is_root = true;
1390 }
1391
1392 RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies();
1393 for (GDScript *E : must_clear_dependencies) {
1394 clear_data->scripts.insert(E);
1395 E->clear(clear_data);
1396 }
1397
1398 for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
1399 clear_data->functions.insert(E.value);
1400 }
1401 member_functions.clear();
1402
1403 for (KeyValue<StringName, MemberInfo> &E : member_indices) {
1404 clear_data->scripts.insert(E.value.data_type.script_type_ref);
1405 E.value.data_type.script_type_ref = Ref<Script>();
1406 }
1407
1408 for (KeyValue<StringName, MemberInfo> &E : static_variables_indices) {
1409 clear_data->scripts.insert(E.value.data_type.script_type_ref);
1410 E.value.data_type.script_type_ref = Ref<Script>();
1411 }
1412 static_variables.clear();
1413 static_variables_indices.clear();
1414
1415 if (implicit_initializer) {
1416 clear_data->functions.insert(implicit_initializer);
1417 implicit_initializer = nullptr;
1418 }
1419
1420 if (implicit_ready) {
1421 clear_data->functions.insert(implicit_ready);
1422 implicit_ready = nullptr;
1423 }
1424
1425 if (static_initializer) {
1426 clear_data->functions.insert(static_initializer);
1427 static_initializer = nullptr;
1428 }
1429
1430 _save_orphaned_subclasses(clear_data);
1431
1432#ifdef TOOLS_ENABLED
1433 // Clearing inner class doc, script doc only cleared when the script source deleted.
1434 if (_owner) {
1435 _clear_doc();
1436 }
1437#endif
1438
1439 // If it's not the root, skip clearing the data
1440 if (is_root) {
1441 // All dependencies have been accounted for
1442 for (GDScriptFunction *E : clear_data->functions) {
1443 memdelete(E);
1444 }
1445 for (Ref<Script> &E : clear_data->scripts) {
1446 Ref<GDScript> gdscr = E;
1447 if (gdscr.is_valid()) {
1448 GDScriptCache::remove_script(gdscr->get_path());
1449 }
1450 }
1451 clear_data->clear();
1452 }
1453}
1454
1455GDScript::~GDScript() {
1456 if (destructing) {
1457 return;
1458 }
1459 destructing = true;
1460
1461 clear();
1462
1463 {
1464 MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
1465
1466 while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
1467 // Order matters since clearing the stack may already cause
1468 // the GDScriptFunctionState to be destroyed and thus removed from the list.
1469 pending_func_states.remove(E);
1470 GDScriptFunctionState *state = E->self();
1471 ObjectID state_id = state->get_instance_id();
1472 state->_clear_connections();
1473 if (ObjectDB::get_instance(state_id)) {
1474 state->_clear_stack();
1475 }
1476 }
1477 }
1478
1479 {
1480 MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
1481
1482 script_list.remove_from_list();
1483 }
1484}
1485
1486//////////////////////////////
1487// INSTANCE //
1488//////////////////////////////
1489
1490bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
1491 {
1492 HashMap<StringName, GDScript::MemberInfo>::Iterator E = script->member_indices.find(p_name);
1493 if (E) {
1494 const GDScript::MemberInfo *member = &E->value;
1495 Variant value = p_value;
1496 if (member->data_type.has_type && !member->data_type.is_type(value)) {
1497 const Variant *args = &p_value;
1498 Callable::CallError err;
1499 Variant::construct(member->data_type.builtin_type, value, &args, 1, err);
1500 if (err.error != Callable::CallError::CALL_OK || !member->data_type.is_type(value)) {
1501 return false;
1502 }
1503 }
1504 if (member->setter) {
1505 const Variant *args = &value;
1506 Callable::CallError err;
1507 callp(member->setter, &args, 1, err);
1508 return err.error == Callable::CallError::CALL_OK;
1509 } else {
1510 members.write[member->index] = value;
1511 return true;
1512 }
1513 }
1514 }
1515
1516 GDScript *sptr = script.ptr();
1517 while (sptr) {
1518 {
1519 HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = sptr->static_variables_indices.find(p_name);
1520 if (E) {
1521 const GDScript::MemberInfo *member = &E->value;
1522 Variant value = p_value;
1523 if (member->data_type.has_type && !member->data_type.is_type(value)) {
1524 const Variant *args = &p_value;
1525 Callable::CallError err;
1526 Variant::construct(member->data_type.builtin_type, value, &args, 1, err);
1527 if (err.error != Callable::CallError::CALL_OK || !member->data_type.is_type(value)) {
1528 return false;
1529 }
1530 }
1531 if (member->setter) {
1532 const Variant *args = &value;
1533 Callable::CallError err;
1534 callp(member->setter, &args, 1, err);
1535 return err.error == Callable::CallError::CALL_OK;
1536 } else {
1537 sptr->static_variables.write[member->index] = value;
1538 return true;
1539 }
1540 }
1541 }
1542
1543 {
1544 HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
1545 if (E) {
1546 Variant name = p_name;
1547 const Variant *args[2] = { &name, &p_value };
1548
1549 Callable::CallError err;
1550 Variant ret = E->value->call(this, (const Variant **)args, 2, err);
1551 if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) {
1552 return true;
1553 }
1554 }
1555 }
1556
1557 sptr = sptr->_base;
1558 }
1559
1560 return false;
1561}
1562
1563bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
1564 {
1565 HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = script->member_indices.find(p_name);
1566 if (E) {
1567 if (E->value.getter) {
1568 Callable::CallError err;
1569 r_ret = const_cast<GDScriptInstance *>(this)->callp(E->value.getter, nullptr, 0, err);
1570 if (err.error == Callable::CallError::CALL_OK) {
1571 return true;
1572 }
1573 }
1574 r_ret = members[E->value.index];
1575 return true;
1576 }
1577 }
1578
1579 const GDScript *sptr = script.ptr();
1580 while (sptr) {
1581 {
1582 HashMap<StringName, Variant>::ConstIterator E = sptr->constants.find(p_name);
1583 if (E) {
1584 r_ret = E->value;
1585 return true;
1586 }
1587 }
1588
1589 {
1590 HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = sptr->static_variables_indices.find(p_name);
1591 if (E) {
1592 if (E->value.getter) {
1593 Callable::CallError ce;
1594 r_ret = const_cast<GDScript *>(sptr)->callp(E->value.getter, nullptr, 0, ce);
1595 return true;
1596 }
1597 r_ret = sptr->static_variables[E->value.index];
1598 return true;
1599 }
1600 }
1601
1602 {
1603 HashMap<StringName, MethodInfo>::ConstIterator E = sptr->_signals.find(p_name);
1604 if (E) {
1605 r_ret = Signal(this->owner, E->key);
1606 return true;
1607 }
1608 }
1609
1610 {
1611 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_name);
1612 if (E) {
1613 if (sptr->rpc_config.has(p_name)) {
1614 r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key)));
1615 } else {
1616 r_ret = Callable(this->owner, E->key);
1617 }
1618 return true;
1619 }
1620 }
1621
1622 {
1623 HashMap<StringName, Ref<GDScript>>::ConstIterator E = sptr->subclasses.find(p_name);
1624 if (E) {
1625 r_ret = E->value;
1626 return true;
1627 }
1628 }
1629
1630 {
1631 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
1632 if (E) {
1633 Variant name = p_name;
1634 const Variant *args[1] = { &name };
1635
1636 Callable::CallError err;
1637 Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err);
1638 if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
1639 r_ret = ret;
1640 return true;
1641 }
1642 }
1643 }
1644 sptr = sptr->_base;
1645 }
1646
1647 return false;
1648}
1649
1650Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
1651 const GDScript *sptr = script.ptr();
1652 while (sptr) {
1653 if (sptr->member_indices.has(p_name)) {
1654 if (r_is_valid) {
1655 *r_is_valid = true;
1656 }
1657 return sptr->member_indices[p_name].property_info.type;
1658 }
1659 sptr = sptr->_base;
1660 }
1661
1662 if (r_is_valid) {
1663 *r_is_valid = false;
1664 }
1665 return Variant::NIL;
1666}
1667
1668void GDScriptInstance::validate_property(PropertyInfo &p_property) const {
1669 Variant property = (Dictionary)p_property;
1670 const Variant *args[1] = { &property };
1671
1672 const GDScript *sptr = script.ptr();
1673 while (sptr) {
1674 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property);
1675 if (E) {
1676 Callable::CallError err;
1677 Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
1678 if (err.error == Callable::CallError::CALL_OK) {
1679 p_property = PropertyInfo::from_dict(property);
1680 return;
1681 }
1682 }
1683 sptr = sptr->_base;
1684 }
1685}
1686
1687void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
1688 // exported members, not done yet!
1689
1690 const GDScript *sptr = script.ptr();
1691 List<PropertyInfo> props;
1692
1693 while (sptr) {
1694 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
1695 if (E) {
1696 Callable::CallError err;
1697 Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err);
1698 if (err.error == Callable::CallError::CALL_OK) {
1699 ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries.");
1700
1701 Array arr = ret;
1702 for (int i = 0; i < arr.size(); i++) {
1703 Dictionary d = arr[i];
1704 ERR_CONTINUE(!d.has("name"));
1705 ERR_CONTINUE(!d.has("type"));
1706
1707 PropertyInfo pinfo;
1708 pinfo.name = d["name"];
1709 pinfo.type = Variant::Type(d["type"].operator int());
1710 if (d.has("hint")) {
1711 pinfo.hint = PropertyHint(d["hint"].operator int());
1712 }
1713 if (d.has("hint_string")) {
1714 pinfo.hint_string = d["hint_string"];
1715 }
1716 if (d.has("usage")) {
1717 pinfo.usage = d["usage"];
1718 }
1719 if (d.has("class_name")) {
1720 pinfo.class_name = d["class_name"];
1721 }
1722
1723 ERR_CONTINUE(pinfo.name.is_empty() && (pinfo.usage & PROPERTY_USAGE_STORAGE));
1724 ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX);
1725
1726 props.push_back(pinfo);
1727 }
1728 }
1729 }
1730
1731 //instance a fake script for editing the values
1732
1733 Vector<_GDScriptMemberSort> msort;
1734 for (const KeyValue<StringName, GDScript::MemberInfo> &F : sptr->member_indices) {
1735 _GDScriptMemberSort ms;
1736 ms.index = F.value.index;
1737 ms.name = F.key;
1738 msort.push_back(ms);
1739 }
1740
1741 msort.sort();
1742 msort.reverse();
1743 for (int i = 0; i < msort.size(); i++) {
1744 props.push_front(sptr->member_indices[msort[i].name].property_info);
1745 }
1746
1747#ifdef TOOLS_ENABLED
1748 p_properties->push_back(sptr->get_class_category());
1749#endif // TOOLS_ENABLED
1750
1751 for (PropertyInfo &prop : props) {
1752 validate_property(prop);
1753 p_properties->push_back(prop);
1754 }
1755
1756 props.clear();
1757
1758 sptr = sptr->_base;
1759 }
1760}
1761
1762bool GDScriptInstance::property_can_revert(const StringName &p_name) const {
1763 Variant name = p_name;
1764 const Variant *args[1] = { &name };
1765
1766 const GDScript *sptr = script.ptr();
1767 while (sptr) {
1768 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_can_revert);
1769 if (E) {
1770 Callable::CallError err;
1771 Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
1772 if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) {
1773 return true;
1774 }
1775 }
1776 sptr = sptr->_base;
1777 }
1778
1779 return false;
1780}
1781
1782bool GDScriptInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const {
1783 Variant name = p_name;
1784 const Variant *args[1] = { &name };
1785
1786 const GDScript *sptr = script.ptr();
1787 while (sptr) {
1788 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_get_revert);
1789 if (E) {
1790 Callable::CallError err;
1791 Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
1792 if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
1793 r_ret = ret;
1794 return true;
1795 }
1796 }
1797 sptr = sptr->_base;
1798 }
1799
1800 return false;
1801}
1802
1803void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
1804 const GDScript *sptr = script.ptr();
1805 while (sptr) {
1806 for (const KeyValue<StringName, GDScriptFunction *> &E : sptr->member_functions) {
1807 p_list->push_back(E.value->get_method_info());
1808 }
1809 sptr = sptr->_base;
1810 }
1811}
1812
1813bool GDScriptInstance::has_method(const StringName &p_method) const {
1814 const GDScript *sptr = script.ptr();
1815 while (sptr) {
1816 HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_method);
1817 if (E) {
1818 return true;
1819 }
1820 sptr = sptr->_base;
1821 }
1822
1823 return false;
1824}
1825
1826Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
1827 GDScript *sptr = script.ptr();
1828 if (unlikely(p_method == SNAME("_ready"))) {
1829 // Call implicit ready first, including for the super classes.
1830 while (sptr) {
1831 if (sptr->implicit_ready) {
1832 sptr->implicit_ready->call(this, nullptr, 0, r_error);
1833 }
1834 sptr = sptr->_base;
1835 }
1836
1837 // Reset this back for the regular call.
1838 sptr = script.ptr();
1839 }
1840 while (sptr) {
1841 HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method);
1842 if (E) {
1843 return E->value->call(this, p_args, p_argcount, r_error);
1844 }
1845 sptr = sptr->_base;
1846 }
1847 r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
1848 return Variant();
1849}
1850
1851void GDScriptInstance::notification(int p_notification, bool p_reversed) {
1852 //notification is not virtual, it gets called at ALL levels just like in C.
1853 Variant value = p_notification;
1854 const Variant *args[1] = { &value };
1855
1856 List<GDScript *> pl;
1857 GDScript *sptr = script.ptr();
1858 while (sptr) {
1859 if (p_reversed) {
1860 pl.push_back(sptr);
1861 } else {
1862 pl.push_front(sptr);
1863 }
1864 sptr = sptr->_base;
1865 }
1866 for (GDScript *sc : pl) {
1867 HashMap<StringName, GDScriptFunction *>::Iterator E = sc->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
1868 if (E) {
1869 Callable::CallError err;
1870 E->value->call(this, args, 1, err);
1871 if (err.error != Callable::CallError::CALL_OK) {
1872 //print error about notification call
1873 }
1874 }
1875 }
1876}
1877
1878String GDScriptInstance::to_string(bool *r_valid) {
1879 if (has_method(CoreStringNames::get_singleton()->_to_string)) {
1880 Callable::CallError ce;
1881 Variant ret = callp(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
1882 if (ce.error == Callable::CallError::CALL_OK) {
1883 if (ret.get_type() != Variant::STRING) {
1884 if (r_valid) {
1885 *r_valid = false;
1886 }
1887 ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String.");
1888 }
1889 if (r_valid) {
1890 *r_valid = true;
1891 }
1892 return ret.operator String();
1893 }
1894 }
1895 if (r_valid) {
1896 *r_valid = false;
1897 }
1898 return String();
1899}
1900
1901Ref<Script> GDScriptInstance::get_script() const {
1902 return script;
1903}
1904
1905ScriptLanguage *GDScriptInstance::get_language() {
1906 return GDScriptLanguage::get_singleton();
1907}
1908
1909const Variant GDScriptInstance::get_rpc_config() const {
1910 return script->get_rpc_config();
1911}
1912
1913void GDScriptInstance::reload_members() {
1914#ifdef DEBUG_ENABLED
1915
1916 Vector<Variant> new_members;
1917 new_members.resize(script->member_indices.size());
1918
1919 //pass the values to the new indices
1920 for (KeyValue<StringName, GDScript::MemberInfo> &E : script->member_indices) {
1921 if (member_indices_cache.has(E.key)) {
1922 Variant value = members[member_indices_cache[E.key]];
1923 new_members.write[E.value.index] = value;
1924 }
1925 }
1926
1927 members.resize(new_members.size()); //resize
1928
1929 //apply
1930 members = new_members;
1931
1932 //pass the values to the new indices
1933 member_indices_cache.clear();
1934 for (const KeyValue<StringName, GDScript::MemberInfo> &E : script->member_indices) {
1935 member_indices_cache[E.key] = E.value.index;
1936 }
1937
1938#endif
1939}
1940
1941GDScriptInstance::GDScriptInstance() {
1942 owner = nullptr;
1943 base_ref_counted = false;
1944}
1945
1946GDScriptInstance::~GDScriptInstance() {
1947 MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
1948
1949 while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
1950 // Order matters since clearing the stack may already cause
1951 // the GDSCriptFunctionState to be destroyed and thus removed from the list.
1952 pending_func_states.remove(E);
1953 GDScriptFunctionState *state = E->self();
1954 ObjectID state_id = state->get_instance_id();
1955 state->_clear_connections();
1956 if (ObjectDB::get_instance(state_id)) {
1957 state->_clear_stack();
1958 }
1959 }
1960
1961 if (script.is_valid() && owner) {
1962 script->instances.erase(owner);
1963 }
1964}
1965
1966/************* SCRIPT LANGUAGE **************/
1967
1968GDScriptLanguage *GDScriptLanguage::singleton = nullptr;
1969
1970String GDScriptLanguage::get_name() const {
1971 return "GDScript";
1972}
1973
1974/* LANGUAGE FUNCTIONS */
1975
1976void GDScriptLanguage::_add_global(const StringName &p_name, const Variant &p_value) {
1977 if (globals.has(p_name)) {
1978 //overwrite existing
1979 global_array.write[globals[p_name]] = p_value;
1980 return;
1981 }
1982 globals[p_name] = global_array.size();
1983 global_array.push_back(p_value);
1984 _global_array = global_array.ptrw();
1985}
1986
1987void GDScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) {
1988 _add_global(p_variable, p_value);
1989}
1990
1991void GDScriptLanguage::add_named_global_constant(const StringName &p_name, const Variant &p_value) {
1992 named_globals[p_name] = p_value;
1993}
1994
1995Variant GDScriptLanguage::get_any_global_constant(const StringName &p_name) {
1996 if (named_globals.has(p_name)) {
1997 return named_globals[p_name];
1998 }
1999 if (globals.has(p_name)) {
2000 return _global_array[globals[p_name]];
2001 }
2002 ERR_FAIL_V_MSG(Variant(), vformat("Could not find any global constant with name: %s.", p_name));
2003}
2004
2005void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) {
2006 ERR_FAIL_COND(!named_globals.has(p_name));
2007 named_globals.erase(p_name);
2008}
2009
2010void GDScriptLanguage::init() {
2011 //populate global constants
2012 int gcc = CoreConstants::get_global_constant_count();
2013 for (int i = 0; i < gcc; i++) {
2014 _add_global(StaticCString::create(CoreConstants::get_global_constant_name(i)), CoreConstants::get_global_constant_value(i));
2015 }
2016
2017 _add_global(StaticCString::create("PI"), Math_PI);
2018 _add_global(StaticCString::create("TAU"), Math_TAU);
2019 _add_global(StaticCString::create("INF"), INFINITY);
2020 _add_global(StaticCString::create("NAN"), NAN);
2021
2022 //populate native classes
2023
2024 List<StringName> class_list;
2025 ClassDB::get_class_list(&class_list);
2026 for (const StringName &n : class_list) {
2027 if (globals.has(n)) {
2028 continue;
2029 }
2030 Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(n));
2031 _add_global(n, nc);
2032 }
2033
2034 //populate singletons
2035
2036 List<Engine::Singleton> singletons;
2037 Engine::get_singleton()->get_singletons(&singletons);
2038 for (const Engine::Singleton &E : singletons) {
2039 _add_global(E.name, E.ptr);
2040 }
2041
2042#ifdef TESTS_ENABLED
2043 GDScriptTests::GDScriptTestRunner::handle_cmdline();
2044#endif
2045}
2046
2047String GDScriptLanguage::get_type() const {
2048 return "GDScript";
2049}
2050
2051String GDScriptLanguage::get_extension() const {
2052 return "gd";
2053}
2054
2055void GDScriptLanguage::finish() {
2056 _call_stack.free();
2057
2058 // Clear the cache before parsing the script_list
2059 GDScriptCache::clear();
2060
2061 // Clear dependencies between scripts, to ensure cyclic references are broken
2062 // (to avoid leaks at exit).
2063 SelfList<GDScript> *s = script_list.first();
2064 while (s) {
2065 // This ensures the current script is not released before we can check
2066 // what's the next one in the list (we can't get the next upfront because we
2067 // don't know if the reference breaking will cause it -or any other after
2068 // it, for that matter- to be released so the next one is not the same as
2069 // before).
2070 Ref<GDScript> scr = s->self();
2071 if (scr.is_valid()) {
2072 for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
2073 GDScriptFunction *func = E.value;
2074 for (int i = 0; i < func->argument_types.size(); i++) {
2075 func->argument_types.write[i].script_type_ref = Ref<Script>();
2076 }
2077 func->return_type.script_type_ref = Ref<Script>();
2078 }
2079 for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
2080 E.value.data_type.script_type_ref = Ref<Script>();
2081 }
2082
2083 // Clear backup for scripts that could slip out of the cyclic reference
2084 // check
2085 scr->clear();
2086 }
2087 s = s->next();
2088 }
2089 script_list.clear();
2090 function_list.clear();
2091}
2092
2093void GDScriptLanguage::profiling_start() {
2094#ifdef DEBUG_ENABLED
2095 MutexLock lock(this->mutex);
2096
2097 SelfList<GDScriptFunction> *elem = function_list.first();
2098 while (elem) {
2099 elem->self()->profile.call_count.set(0);
2100 elem->self()->profile.self_time.set(0);
2101 elem->self()->profile.total_time.set(0);
2102 elem->self()->profile.frame_call_count.set(0);
2103 elem->self()->profile.frame_self_time.set(0);
2104 elem->self()->profile.frame_total_time.set(0);
2105 elem->self()->profile.last_frame_call_count = 0;
2106 elem->self()->profile.last_frame_self_time = 0;
2107 elem->self()->profile.last_frame_total_time = 0;
2108 elem = elem->next();
2109 }
2110
2111 profiling = true;
2112#endif
2113}
2114
2115void GDScriptLanguage::profiling_stop() {
2116#ifdef DEBUG_ENABLED
2117 MutexLock lock(this->mutex);
2118
2119 profiling = false;
2120#endif
2121}
2122
2123int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
2124 int current = 0;
2125#ifdef DEBUG_ENABLED
2126
2127 MutexLock lock(this->mutex);
2128
2129 SelfList<GDScriptFunction> *elem = function_list.first();
2130 while (elem) {
2131 if (current >= p_info_max) {
2132 break;
2133 }
2134 p_info_arr[current].call_count = elem->self()->profile.call_count.get();
2135 p_info_arr[current].self_time = elem->self()->profile.self_time.get();
2136 p_info_arr[current].total_time = elem->self()->profile.total_time.get();
2137 p_info_arr[current].signature = elem->self()->profile.signature;
2138 elem = elem->next();
2139 current++;
2140 }
2141#endif
2142
2143 return current;
2144}
2145
2146int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
2147 int current = 0;
2148
2149#ifdef DEBUG_ENABLED
2150 MutexLock lock(this->mutex);
2151
2152 SelfList<GDScriptFunction> *elem = function_list.first();
2153 while (elem) {
2154 if (current >= p_info_max) {
2155 break;
2156 }
2157 if (elem->self()->profile.last_frame_call_count > 0) {
2158 p_info_arr[current].call_count = elem->self()->profile.last_frame_call_count;
2159 p_info_arr[current].self_time = elem->self()->profile.last_frame_self_time;
2160 p_info_arr[current].total_time = elem->self()->profile.last_frame_total_time;
2161 p_info_arr[current].signature = elem->self()->profile.signature;
2162 current++;
2163 }
2164 elem = elem->next();
2165 }
2166#endif
2167
2168 return current;
2169}
2170
2171struct GDScriptDepSort {
2172 //must support sorting so inheritance works properly (parent must be reloaded first)
2173 bool operator()(const Ref<GDScript> &A, const Ref<GDScript> &B) const {
2174 if (A == B) {
2175 return false; //shouldn't happen but..
2176 }
2177 const GDScript *I = B->get_base().ptr();
2178 while (I) {
2179 if (I == A.ptr()) {
2180 // A is a base of B
2181 return true;
2182 }
2183
2184 I = I->get_base().ptr();
2185 }
2186
2187 return false; //not a base
2188 }
2189};
2190
2191void GDScriptLanguage::reload_all_scripts() {
2192#ifdef DEBUG_ENABLED
2193 print_verbose("GDScript: Reloading all scripts");
2194 List<Ref<GDScript>> scripts;
2195 {
2196 MutexLock lock(this->mutex);
2197
2198 SelfList<GDScript> *elem = script_list.first();
2199 while (elem) {
2200 // Scripts will reload all subclasses, so only reload root scripts.
2201 if (elem->self()->is_root_script() && elem->self()->get_path().is_resource_file()) {
2202 print_verbose("GDScript: Found: " + elem->self()->get_path());
2203 scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
2204 }
2205 elem = elem->next();
2206 }
2207 }
2208
2209 //as scripts are going to be reloaded, must proceed without locking here
2210
2211 scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
2212
2213 for (Ref<GDScript> &scr : scripts) {
2214 print_verbose("GDScript: Reloading: " + scr->get_path());
2215 scr->load_source_code(scr->get_path());
2216 scr->reload(true);
2217 }
2218#endif
2219}
2220
2221void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
2222#ifdef DEBUG_ENABLED
2223
2224 List<Ref<GDScript>> scripts;
2225 {
2226 MutexLock lock(this->mutex);
2227
2228 SelfList<GDScript> *elem = script_list.first();
2229 while (elem) {
2230 // Scripts will reload all subclasses, so only reload root scripts.
2231 if (elem->self()->is_root_script() && elem->self()->get_path().is_resource_file()) {
2232 scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
2233 }
2234 elem = elem->next();
2235 }
2236 }
2237
2238 //when someone asks you why dynamically typed languages are easier to write....
2239
2240 HashMap<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> to_reload;
2241
2242 //as scripts are going to be reloaded, must proceed without locking here
2243
2244 scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
2245
2246 for (Ref<GDScript> &scr : scripts) {
2247 bool reload = scr == p_script || to_reload.has(scr->get_base());
2248
2249 if (!reload) {
2250 continue;
2251 }
2252
2253 to_reload.insert(scr, HashMap<ObjectID, List<Pair<StringName, Variant>>>());
2254
2255 if (!p_soft_reload) {
2256 //save state and remove script from instances
2257 HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[scr];
2258
2259 while (scr->instances.front()) {
2260 Object *obj = scr->instances.front()->get();
2261 //save instance info
2262 List<Pair<StringName, Variant>> state;
2263 if (obj->get_script_instance()) {
2264 obj->get_script_instance()->get_property_state(state);
2265 map[obj->get_instance_id()] = state;
2266 obj->set_script(Variant());
2267 }
2268 }
2269
2270//same thing for placeholders
2271#ifdef TOOLS_ENABLED
2272
2273 while (scr->placeholders.size()) {
2274 Object *obj = (*scr->placeholders.begin())->get_owner();
2275
2276 //save instance info
2277 if (obj->get_script_instance()) {
2278 map.insert(obj->get_instance_id(), List<Pair<StringName, Variant>>());
2279 List<Pair<StringName, Variant>> &state = map[obj->get_instance_id()];
2280 obj->get_script_instance()->get_property_state(state);
2281 obj->set_script(Variant());
2282 } else {
2283 // no instance found. Let's remove it so we don't loop forever
2284 scr->placeholders.erase(*scr->placeholders.begin());
2285 }
2286 }
2287
2288#endif
2289
2290 for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : scr->pending_reload_state) {
2291 map[F.key] = F.value; //pending to reload, use this one instead
2292 }
2293 }
2294 }
2295
2296 for (KeyValue<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) {
2297 Ref<GDScript> scr = E.key;
2298 scr->reload(p_soft_reload);
2299
2300 //restore state if saved
2301 for (KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : E.value) {
2302 List<Pair<StringName, Variant>> &saved_state = F.value;
2303
2304 Object *obj = ObjectDB::get_instance(F.key);
2305 if (!obj) {
2306 continue;
2307 }
2308
2309 if (!p_soft_reload) {
2310 //clear it just in case (may be a pending reload state)
2311 obj->set_script(Variant());
2312 }
2313 obj->set_script(scr);
2314
2315 ScriptInstance *script_inst = obj->get_script_instance();
2316
2317 if (!script_inst) {
2318 //failed, save reload state for next time if not saved
2319 if (!scr->pending_reload_state.has(obj->get_instance_id())) {
2320 scr->pending_reload_state[obj->get_instance_id()] = saved_state;
2321 }
2322 continue;
2323 }
2324
2325 if (script_inst->is_placeholder() && scr->is_placeholder_fallback_enabled()) {
2326 PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_inst);
2327 for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) {
2328 placeholder->property_set_fallback(G->get().first, G->get().second);
2329 }
2330 } else {
2331 for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) {
2332 script_inst->set(G->get().first, G->get().second);
2333 }
2334 }
2335
2336 scr->pending_reload_state.erase(obj->get_instance_id()); //as it reloaded, remove pending state
2337 }
2338
2339 //if instance states were saved, set them!
2340 }
2341
2342#endif
2343}
2344
2345void GDScriptLanguage::frame() {
2346 calls = 0;
2347
2348#ifdef DEBUG_ENABLED
2349 if (profiling) {
2350 MutexLock lock(this->mutex);
2351
2352 SelfList<GDScriptFunction> *elem = function_list.first();
2353 while (elem) {
2354 elem->self()->profile.last_frame_call_count = elem->self()->profile.frame_call_count.get();
2355 elem->self()->profile.last_frame_self_time = elem->self()->profile.frame_self_time.get();
2356 elem->self()->profile.last_frame_total_time = elem->self()->profile.frame_total_time.get();
2357 elem->self()->profile.frame_call_count.set(0);
2358 elem->self()->profile.frame_self_time.set(0);
2359 elem->self()->profile.frame_total_time.set(0);
2360 elem = elem->next();
2361 }
2362 }
2363
2364#endif
2365}
2366
2367/* EDITOR FUNCTIONS */
2368void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
2369 // TODO: Add annotations here?
2370 static const char *_reserved_words[] = {
2371 // operators
2372 "and",
2373 "in",
2374 "not",
2375 "or",
2376 // types and values
2377 "false",
2378 "float",
2379 "int",
2380 "bool",
2381 "null",
2382 "PI",
2383 "TAU",
2384 "INF",
2385 "NAN",
2386 "self",
2387 "true",
2388 "void",
2389 // functions
2390 "as",
2391 "assert",
2392 "await",
2393 "breakpoint",
2394 "class",
2395 "class_name",
2396 "extends",
2397 "is",
2398 "func",
2399 "preload",
2400 "signal",
2401 "super",
2402 // var
2403 "const",
2404 "enum",
2405 "static",
2406 "var",
2407 // control flow
2408 "break",
2409 "continue",
2410 "if",
2411 "elif",
2412 "else",
2413 "for",
2414 "pass",
2415 "return",
2416 "match",
2417 "while",
2418 // These keywords are not implemented currently, but reserved for (potential) future use.
2419 // We highlight them as keywords to make errors easier to understand.
2420 "trait",
2421 "namespace",
2422 "yield",
2423 nullptr
2424 };
2425
2426 const char **w = _reserved_words;
2427
2428 while (*w) {
2429 p_words->push_back(*w);
2430 w++;
2431 }
2432
2433 List<StringName> functions;
2434 GDScriptUtilityFunctions::get_function_list(&functions);
2435
2436 for (const StringName &E : functions) {
2437 p_words->push_back(String(E));
2438 }
2439}
2440
2441bool GDScriptLanguage::is_control_flow_keyword(String p_keyword) const {
2442 return p_keyword == "break" ||
2443 p_keyword == "continue" ||
2444 p_keyword == "elif" ||
2445 p_keyword == "else" ||
2446 p_keyword == "if" ||
2447 p_keyword == "for" ||
2448 p_keyword == "match" ||
2449 p_keyword == "pass" ||
2450 p_keyword == "return" ||
2451 p_keyword == "while";
2452}
2453
2454bool GDScriptLanguage::handles_global_class_type(const String &p_type) const {
2455 return p_type == "GDScript";
2456}
2457
2458String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const {
2459 Error err;
2460 Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
2461 if (err) {
2462 return String();
2463 }
2464
2465 String source = f->get_as_utf8_string();
2466
2467 GDScriptParser parser;
2468 err = parser.parse(source, p_path, false);
2469
2470 const GDScriptParser::ClassNode *c = parser.get_tree();
2471 if (!c) {
2472 return String(); // No class parsed.
2473 }
2474
2475 /* **WARNING**
2476 *
2477 * This function is written with the goal to be *extremely* error tolerant, as such
2478 * it should meet the following requirements:
2479 *
2480 * - It must not rely on the analyzer (in fact, the analyzer must not be used here),
2481 * because at the time global classes are parsed, the dependencies may not be present
2482 * yet, hence the function will fail (which is unintended).
2483 * - It must not fail even if the parsing fails, because even if the file is broken,
2484 * it should attempt its best to retrieve the inheritance metadata.
2485 *
2486 * Before changing this function, please ask the current maintainer of EditorFileSystem.
2487 */
2488
2489 if (r_base_type) {
2490 const GDScriptParser::ClassNode *subclass = c;
2491 String path = p_path;
2492 GDScriptParser subparser;
2493 while (subclass) {
2494 if (subclass->extends_used) {
2495 if (!subclass->extends_path.is_empty()) {
2496 if (subclass->extends.size() == 0) {
2497 get_global_class_name(subclass->extends_path, r_base_type);
2498 subclass = nullptr;
2499 break;
2500 } else {
2501 Vector<GDScriptParser::IdentifierNode *> extend_classes = subclass->extends;
2502
2503 Ref<FileAccess> subfile = FileAccess::open(subclass->extends_path, FileAccess::READ);
2504 if (subfile.is_null()) {
2505 break;
2506 }
2507 String subsource = subfile->get_as_utf8_string();
2508
2509 if (subsource.is_empty()) {
2510 break;
2511 }
2512 String subpath = subclass->extends_path;
2513 if (subpath.is_relative_path()) {
2514 subpath = path.get_base_dir().path_join(subpath).simplify_path();
2515 }
2516
2517 if (OK != subparser.parse(subsource, subpath, false)) {
2518 break;
2519 }
2520 path = subpath;
2521 subclass = subparser.get_tree();
2522
2523 while (extend_classes.size() > 0) {
2524 bool found = false;
2525 for (int i = 0; i < subclass->members.size(); i++) {
2526 if (subclass->members[i].type != GDScriptParser::ClassNode::Member::CLASS) {
2527 continue;
2528 }
2529
2530 const GDScriptParser::ClassNode *inner_class = subclass->members[i].m_class;
2531 if (inner_class->identifier->name == extend_classes[0]->name) {
2532 extend_classes.remove_at(0);
2533 found = true;
2534 subclass = inner_class;
2535 break;
2536 }
2537 }
2538 if (!found) {
2539 subclass = nullptr;
2540 break;
2541 }
2542 }
2543 }
2544 } else if (subclass->extends.size() == 1) {
2545 *r_base_type = subclass->extends[0]->name;
2546 subclass = nullptr;
2547 } else {
2548 break;
2549 }
2550 } else {
2551 *r_base_type = "RefCounted";
2552 subclass = nullptr;
2553 }
2554 }
2555 }
2556 if (r_icon_path) {
2557 *r_icon_path = c->simplified_icon_path;
2558 }
2559 return c->identifier != nullptr ? String(c->identifier->name) : String();
2560}
2561
2562thread_local GDScriptLanguage::CallStack GDScriptLanguage::_call_stack;
2563
2564GDScriptLanguage::GDScriptLanguage() {
2565 calls = 0;
2566 ERR_FAIL_COND(singleton);
2567 singleton = this;
2568 strings._init = StaticCString::create("_init");
2569 strings._static_init = StaticCString::create("_static_init");
2570 strings._notification = StaticCString::create("_notification");
2571 strings._set = StaticCString::create("_set");
2572 strings._get = StaticCString::create("_get");
2573 strings._get_property_list = StaticCString::create("_get_property_list");
2574 strings._validate_property = StaticCString::create("_validate_property");
2575 strings._property_can_revert = StaticCString::create("_property_can_revert");
2576 strings._property_get_revert = StaticCString::create("_property_get_revert");
2577 strings._script_source = StaticCString::create("script/source");
2578 _debug_parse_err_line = -1;
2579 _debug_parse_err_file = "";
2580
2581 profiling = false;
2582 script_frame_time = 0;
2583
2584 int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "512," + itos(GDScriptFunction::MAX_CALL_DEPTH - 1) + ",1"), 1024);
2585
2586 if (EngineDebugger::is_active()) {
2587 //debugging enabled!
2588
2589 _debug_max_call_stack = dmcs;
2590 } else {
2591 _debug_max_call_stack = 0;
2592 }
2593
2594#ifdef DEBUG_ENABLED
2595 GLOBAL_DEF("debug/gdscript/warnings/enable", true);
2596 GLOBAL_DEF("debug/gdscript/warnings/exclude_addons", true);
2597 for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
2598 GDScriptWarning::Code code = (GDScriptWarning::Code)i;
2599 Variant default_enabled = GDScriptWarning::get_default_value(code);
2600 String path = GDScriptWarning::get_settings_path_from_code(code);
2601 GLOBAL_DEF(GDScriptWarning::get_property_info(code), default_enabled);
2602 }
2603#endif // DEBUG_ENABLED
2604}
2605
2606GDScriptLanguage::~GDScriptLanguage() {
2607 singleton = nullptr;
2608}
2609
2610void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass) {
2611 orphan_subclasses[p_qualified_name] = p_subclass;
2612}
2613
2614Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_name) {
2615 HashMap<String, ObjectID>::Iterator orphan_subclass_element = orphan_subclasses.find(p_qualified_name);
2616 if (!orphan_subclass_element) {
2617 return Ref<GDScript>();
2618 }
2619 ObjectID orphan_subclass = orphan_subclass_element->value;
2620 Object *obj = ObjectDB::get_instance(orphan_subclass);
2621 orphan_subclasses.remove(orphan_subclass_element);
2622 if (!obj) {
2623 return Ref<GDScript>();
2624 }
2625 return Ref<GDScript>(Object::cast_to<GDScript>(obj));
2626}
2627
2628Ref<GDScript> GDScriptLanguage::get_script_by_fully_qualified_name(const String &p_name) {
2629 {
2630 MutexLock lock(mutex);
2631
2632 SelfList<GDScript> *elem = script_list.first();
2633 while (elem) {
2634 GDScript *scr = elem->self();
2635 if (scr->fully_qualified_name == p_name) {
2636 return scr;
2637 }
2638 elem = elem->next();
2639 }
2640 }
2641
2642 Ref<GDScript> scr;
2643 scr.instantiate();
2644 scr->fully_qualified_name = p_name;
2645 return scr;
2646}
2647
2648/*************** RESOURCE ***************/
2649
2650Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
2651 Error err;
2652 Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE);
2653
2654 if (err && scr.is_valid()) {
2655 // If !scr.is_valid(), the error was likely from scr->load_source_code(), which already generates an error.
2656 ERR_PRINT_ED(vformat(R"(Failed to load script "%s" with error "%s".)", p_path, error_names[err]));
2657 }
2658
2659 if (r_error) {
2660 // Don't fail loading because of parsing error.
2661 *r_error = scr.is_valid() ? OK : err;
2662 }
2663
2664 return scr;
2665}
2666
2667void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const {
2668 p_extensions->push_back("gd");
2669}
2670
2671bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const {
2672 return (p_type == "Script" || p_type == "GDScript");
2673}
2674
2675String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const {
2676 String el = p_path.get_extension().to_lower();
2677 if (el == "gd") {
2678 return "GDScript";
2679 }
2680 return "";
2681}
2682
2683void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
2684 Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ);
2685 ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'.");
2686
2687 String source = file->get_as_utf8_string();
2688 if (source.is_empty()) {
2689 return;
2690 }
2691
2692 GDScriptParser parser;
2693 if (OK != parser.parse(source, p_path, false)) {
2694 return;
2695 }
2696
2697 for (const String &E : parser.get_dependencies()) {
2698 p_dependencies->push_back(E);
2699 }
2700}
2701
2702Error ResourceFormatSaverGDScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
2703 Ref<GDScript> sqscr = p_resource;
2704 ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
2705
2706 String source = sqscr->get_source_code();
2707
2708 {
2709 Error err;
2710 Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
2711
2712 ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'.");
2713
2714 file->store_string(source);
2715 if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
2716 return ERR_CANT_CREATE;
2717 }
2718 }
2719
2720 if (ScriptServer::is_reload_scripts_on_save_enabled()) {
2721 GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, true);
2722 }
2723
2724 return OK;
2725}
2726
2727void ResourceFormatSaverGDScript::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
2728 if (Object::cast_to<GDScript>(*p_resource)) {
2729 p_extensions->push_back("gd");
2730 }
2731}
2732
2733bool ResourceFormatSaverGDScript::recognize(const Ref<Resource> &p_resource) const {
2734 return Object::cast_to<GDScript>(*p_resource) != nullptr;
2735}
2736