Skip to content

Commit 8f06259

Browse files
authored
fix: loading script in wrong thread and load non existing scripts (#189)
1 parent 2a2ce09 commit 8f06259

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

javascript.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2929
/**************************************************************************/
3030

31+
/* This is implementation is for loading/saving JS files. */
32+
/* After loading it contains the code/bytecode of the loaded file. */
33+
3134
#include "javascript.h"
3235
#include "core/config/engine.h"
3336
#include "core/io/file_access_encrypted.h"
@@ -110,8 +113,17 @@ Error JavaScript::reload(bool p_keep_state) {
110113
javascript_class = NULL;
111114
Error err = OK;
112115
JavaScriptBinder *binder = JavaScriptLanguage::get_thread_binder(Thread::get_caller_id());
116+
#ifdef TOOLS_ENABLED
117+
// This is a workaround for files generated outside of the godot editor
118+
if (binder == NULL) {
119+
binder = JavaScriptLanguage::get_thread_binder(Thread::MAIN_ID);
120+
}
121+
#endif
113122
ERR_FAIL_COND_V_MSG(binder == NULL, ERR_INVALID_DATA, "Cannot load script in this thread");
114123
JavaScriptError js_err;
124+
125+
// TODO: We should have a setting/option to skip parsing or reading .mjs files which aren't Godot classes for example "chunk-xxx.mjs" build from esbuild
126+
115127
if (!bytecode.is_empty()) {
116128
javascript_class = binder->parse_javascript_class(bytecode, script_path, true, &js_err);
117129
} else {
@@ -268,6 +280,11 @@ Ref<Resource> ResourceFormatLoaderJavaScript::load(const String &p_path, const S
268280
Ref<JavaScriptModule> module = ResourceFormatLoaderJavaScriptModule::load_static(p_path, p_original_path, &err);
269281
if (r_error)
270282
*r_error = err;
283+
284+
if (err == ERR_FILE_NOT_FOUND) {
285+
return module;
286+
}
287+
271288
ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot load script file '" + p_path + "'.");
272289
Ref<JavaScript> javaScript;
273290
javaScript.instantiate();
@@ -377,9 +394,17 @@ String ResourceFormatLoaderJavaScriptModule::get_resource_type(const String &p_p
377394

378395
Ref<Resource> ResourceFormatLoaderJavaScriptModule::load_static(const String &p_path, const String &p_original_path, Error *r_error) {
379396
Error err = ERR_FILE_CANT_OPEN;
397+
bool fileExists = FileAccess::exists(p_path);
398+
if (!fileExists) {
399+
*r_error = ERR_FILE_NOT_FOUND;
400+
WARN_PRINT("Cannot find file '" + p_path + "'. Maybe you deleted the file.");
401+
return Ref<Resource>();
402+
}
403+
380404
Ref<JavaScriptModule> module;
381405
module.instantiate();
382406
module->set_script_path(p_path);
407+
383408
if (p_path.ends_with("." EXT_JSMODULE) || p_path.ends_with("." EXT_JSCLASS) || p_path.ends_with("." EXT_JSON)) {
384409
String code = FileAccess::get_file_as_string(p_path, &err);
385410
if (r_error)
@@ -388,6 +413,7 @@ Ref<Resource> ResourceFormatLoaderJavaScriptModule::load_static(const String &p_
388413
module->set_source_code(code);
389414
}
390415

416+
// TODO: Check what this block is for
391417
#if 0
392418
else if (p_path.ends_with("." EXT_JSMODULE_BYTECODE) || p_path.ends_with("." EXT_JSCLASS_BYTECODE)) {
393419
module->set_bytecode(FileAccess::get_file_as_array(p_path, &err));

javascript_language.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2929
/**************************************************************************/
3030

31+
/* This is the language server implementation. It handles how/when to use JS Scripts. */
32+
3133
#include "javascript_language.h"
3234
#include "core/io/file_access.h"
3335
#include "core/object/class_db.h"
@@ -343,10 +345,20 @@ void JavaScriptLanguage::reload_script(const Ref<Script> &p_script, bool p_soft_
343345
if (s.is_valid()) {
344346
Error err = OK;
345347
Ref<JavaScriptModule> module = ResourceFormatLoaderJavaScriptModule::load_static(s->get_script_path(), "", &err);
346-
ERR_FAIL_COND_MSG(err != OK, ("Cannot load script file '" + s->get_script_path() + "'."));
347-
s->set_source_code(module->get_source_code());
348-
err = s->reload(p_soft_reload);
349-
ERR_FAIL_COND_MSG(err != OK, "Parse source code from file '" + s->get_script_path() + "' failed.");
348+
349+
if (err != ERR_FILE_NOT_FOUND) {
350+
// We don't need to reload a script if it isn't existing
351+
352+
ERR_FAIL_COND_MSG(err != OK, ("Cannot reload script file '" + s->get_script_path() + "'."));
353+
s->set_source_code(module->get_source_code());
354+
err = s->reload(p_soft_reload);
355+
ERR_FAIL_COND_MSG(err != OK, "Parse source code from file '" + s->get_script_path() + "' failed.");
356+
} else {
357+
// If we are in the editor we need to erase the script from the language server to avoid reload on focus (editor_tools.cpp[_notification()])
358+
#ifdef TOOLS_ENABLED
359+
singleton->get_scripts().erase(s);
360+
#endif
361+
}
350362
}
351363
}
352364

0 commit comments

Comments
 (0)