Skip to content

Commit 03a12ec

Browse files
committed
Remove require from the core binding
1 parent dfbd376 commit 03a12ec

File tree

5 files changed

+25
-142
lines changed

5 files changed

+25
-142
lines changed

ecmascript.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
#include "scene/resources/text_file.h"
99

1010
#define EXT_JSCLASS "jsx"
11-
#define EXT_JSCLASS_BYTECODE "jsxb"
12-
#define EXT_JSCLASS_ENCRYPTED "jsxe"
11+
#define EXT_JSCLASS_BYTECODE EXT_JSCLASS "b"
12+
#define EXT_JSCLASS_ENCRYPTED EXT_JSCLASS "e"
1313
#define EXT_JSMODULE "js"
14-
#define EXT_JSMODULE_BYTECODE "jsb"
15-
#define EXT_JSMODULE_ENCRYPTED "jse"
14+
#define EXT_JSMODULE_BYTECODE EXT_JSMODULE "b"
15+
#define EXT_JSMODULE_ENCRYPTED EXT_JSMODULE "e"
1616
#define EXT_JSON "json"
1717

1818
class ECMAScript : public Script {

misc/godot.d.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ declare module globalThis {
1919
*/
2020
function cancelAnimationFrame(request_id: FrameRequetID): void;
2121

22-
/** Used to import CommonJS modules or load resources */
23-
function require(path: string): any;
24-
const module: { exports: any };
25-
const exports: any;
26-
2722
/**
2823
* The Console API provides functionality to allow developers to perform debugging tasks, such as logging messages or the values of variables at set points in your code, or timing how long an operation takes to complete.
2924
*/

quickjs/quickjs_binder.cpp

Lines changed: 15 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,6 @@ void QuickJSBinder::add_global_console() {
128128
}
129129

130130
void QuickJSBinder::add_global_properties() {
131-
// globalThis.require
132-
JSValue js_func_require = JS_NewCFunction(ctx, require_function, "require", 1);
133-
JS_DefinePropertyValueStr(ctx, global_object, "require", js_func_require, PROP_DEF_DEFAULT);
134-
135131
// globalThis.requestAnimationFrame
136132
JSValue js_func_requestAnimationFrame = JS_NewCFunction(ctx, global_request_animation_frame, "requestAnimationFrame", 1);
137133
JS_DefinePropertyValueStr(ctx, global_object, "requestAnimationFrame", js_func_requestAnimationFrame, PROP_DEF_DEFAULT);
@@ -579,7 +575,7 @@ void QuickJSBinder::add_debug_binding_info(JSContext *ctx, JSValueConst p_obj, c
579575

580576
static HashMap<String, String> resolve_path_cache;
581577

582-
static String resolve_module_file(const String &file, bool allow_node_module = false) {
578+
String QuickJSBinder::resolve_module_file(const String &file) {
583579
if (const String *ptr = resolve_path_cache.getptr(file)) {
584580
return *ptr;
585581
}
@@ -604,34 +600,6 @@ static String resolve_module_file(const String &file, bool allow_node_module = f
604600
return path;
605601
}
606602
}
607-
608-
if (allow_node_module && !file.begins_with(".")) {
609-
String package_file = "node_modules/" + file + "/package.json";
610-
bool package_found = false;
611-
if (FileAccess::exists("user://" + package_file)) {
612-
package_file = "user://" + package_file;
613-
package_found = true;
614-
} else if (FileAccess::exists("res://" + package_file)) {
615-
package_file = "res://" + package_file;
616-
package_found = true;
617-
}
618-
if (package_found) {
619-
Error err;
620-
String package_content = FileAccess::get_file_as_string(package_file, &err);
621-
ERR_FAIL_COND_V_MSG(err != OK, "", "Fail to load module package: " + package_file);
622-
Variant package_parse_ret;
623-
String package_parse_err;
624-
int error_line;
625-
if (OK != JSON::parse(package_content, package_parse_ret, package_parse_err, error_line)) {
626-
ERR_FAIL_V_MSG("", "Fail to parse module package:" + package_file + ENDL + package_parse_err + ENDL + "At " + itos(error_line));
627-
}
628-
Dictionary dict = package_parse_ret;
629-
String entry = dict.has("main") ? dict["main"] : "index.js";
630-
entry = "node_modules/" + file + "/" + entry;
631-
ERR_FAIL_COND_V_MSG(!FileAccess::exists(entry), "", "Module entry does not exists: " + entry);
632-
return entry;
633-
}
634-
}
635603
return "";
636604
}
637605

@@ -642,7 +610,7 @@ JSModuleDef *QuickJSBinder::js_module_loader(JSContext *ctx, const char *module_
642610
String resolving_file;
643611
resolving_file.parse_utf8(module_name);
644612

645-
String file = resolve_module_file(resolving_file, false);
613+
String file = resolve_module_file(resolving_file);
646614
ERR_FAIL_COND_V_MSG(file.empty(), NULL, "Failed to resolve module: '" + resolving_file + "'.");
647615
resolve_path_cache.set(resolving_file, file);
648616

@@ -684,14 +652,9 @@ JSModuleDef *QuickJSBinder::js_module_loader(JSContext *ctx, const char *module_
684652
JS_ThrowReferenceError(ctx, "Could not load module '%s'", file.utf8().get_data());
685653
return NULL;
686654
}
687-
// hack the quick module to make the resource value as default entry
688-
m = JS_NewCModule(ctx, file.utf8().get_data(), resource_module_initializer);
689-
JS_AddModuleExport(ctx, m, "default");
690-
JSValue func = JS_MKPTR(JS_TAG_MODULE, m);
691-
JS_DupValue(ctx, func);
692-
JS_EvalFunction(ctx, func);
693655
JSValue val = variant_to_var(ctx, res);
694-
JS_SetModuleExport(ctx, m, "default", val);
656+
m = js_make_module(ctx, file, val);
657+
JS_FreeValue(ctx, val);
695658

696659
ModuleCache module;
697660
Variant hash_var = res;
@@ -701,14 +664,24 @@ JSModuleDef *QuickJSBinder::js_module_loader(JSContext *ctx, const char *module_
701664
module.res->reference(); // Avoid auto release as module don't release automaticly
702665
module.res_value = val;
703666
module.flags = MODULE_FLAG_RESOURCE;
704-
module.module = static_cast<JSModuleDef *>(JS_VALUE_GET_PTR(func));
667+
module.module = m;
705668
binder->module_cache.set(file, module);
706669
}
707670
}
708671

709672
return m;
710673
}
711674

675+
JSModuleDef *QuickJSBinder::js_make_module(JSContext *ctx, const String &p_id, const JSValue &p_value) {
676+
JSModuleDef *m = JS_NewCModule(ctx, p_id.utf8().get_data(), resource_module_initializer);
677+
JS_AddModuleExport(ctx, m, "default");
678+
JSValue func = JS_MKPTR(JS_TAG_MODULE, m);
679+
JS_DupValue(ctx, func);
680+
JS_EvalFunction(ctx, func);
681+
JS_SetModuleExport(ctx, m, "default", JS_DupValue(ctx, p_value));
682+
return m;
683+
}
684+
712685
QuickJSBinder::ModuleCache QuickJSBinder::js_compile_module(JSContext *ctx, const String &p_code, const String &p_filename, ECMAscriptScriptError *r_error) {
713686

714687
if (NULL != compiling_modules.find(p_filename)) {
@@ -822,91 +795,6 @@ int QuickJSBinder::resource_module_initializer(JSContext *ctx, JSModuleDef *m) {
822795
return JS_SetModuleExport(ctx, m, "default", JS_UNDEFINED);
823796
}
824797

825-
JSValue QuickJSBinder::require_function(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
826-
ERR_FAIL_COND_V(argc < 1 || !validate_type(ctx, Variant::STRING, argv[0]), JS_ThrowTypeError(ctx, "A string argument expected for require"));
827-
String file = js_to_string(ctx, argv[0]);
828-
if (file.begins_with(".")) {
829-
JSValue func = JS_GetStackFunction(ctx, 1);
830-
JSValue filename = JS_GetProperty(ctx, func, JS_ATOM_fileName);
831-
String caller_path = js_to_string(ctx, filename);
832-
JS_FreeValue(ctx, filename);
833-
JS_FreeValue(ctx, func);
834-
file = ECMAScriptLanguage::globalize_relative_path(file, caller_path.get_base_dir());
835-
}
836-
String resolving_file = file;
837-
file = resolve_module_file(file, true);
838-
ERR_FAIL_COND_V_MSG(file.empty(), (JS_UNDEFINED), "Failed to resolve module '" + resolving_file + "'.");
839-
resolve_path_cache.set(resolving_file, file);
840-
841-
if (NULL != compiling_modules.find(file)) {
842-
String chain;
843-
for (List<String>::Element *E = compiling_modules.front(); E; E = E->next()) {
844-
chain += E->get();
845-
if (E->next() != NULL) {
846-
chain += " <- ";
847-
}
848-
}
849-
return JS_ThrowTypeError(ctx, "Cyclic module import detected:\r\n %s", chain.utf8().get_data());
850-
}
851-
852-
JSValue ret = JS_UNDEFINED;
853-
String md5 = FileAccess::get_md5(file);
854-
QuickJSBinder *binder = QuickJSBinder::get_context_binder(ctx);
855-
if (CommonJSModule *ptr = binder->commonjs_module_cache.getptr(md5)) {
856-
ret = JS_DupValue(ctx, ptr->exports);
857-
} else {
858-
CommonJSModule m;
859-
m.md5 = md5;
860-
m.exports = JS_UNDEFINED;
861-
List<String> extensions;
862-
ECMAScriptLanguage::get_singleton()->get_recognized_extensions(&extensions);
863-
if (extensions.find(file.get_extension()) != NULL) {
864-
Error err;
865-
Ref<ECMAScriptModule> em = ResourceFormatLoaderECMAScriptModule::load_static(file, "", &err);
866-
ERR_FAIL_COND_V(err != OK || em.is_null(), JS_ThrowTypeError(ctx, "Error to load module file %s", file.utf8().get_data()));
867-
String text = em->get_source_code();
868-
if (!text.empty()) {
869-
if (file.ends_with(EXT_JSON)) {
870-
CharString utf8code = text.utf8();
871-
ret = JS_ParseJSON(ctx, utf8code.get_data(), utf8code.length(), file.utf8().get_data());
872-
} else {
873-
String code = "(function() {"
874-
" const module = {"
875-
" exports: {}"
876-
" };"
877-
" let exports = module.exports;"
878-
" (function(){ " +
879-
text +
880-
" }"
881-
" )();"
882-
" return module.exports;"
883-
"})();";
884-
CharString utf8code = code.utf8();
885-
compiling_modules.push_back(file);
886-
ret = JS_Eval(ctx, utf8code.get_data(), utf8code.length(), file.utf8().get_data(), JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_STRICT);
887-
compiling_modules.pop_back();
888-
}
889-
} else {
890-
// TODO: require module from bytecode
891-
}
892-
m.exports = JS_DupValue(ctx, ret);
893-
m.flags = MODULE_FLAG_SCRIPT;
894-
} else {
895-
RES res = ResourceLoader::load(file);
896-
if (!res.is_null()) {
897-
ret = variant_to_var(ctx, res);
898-
m.exports = ret;
899-
m.flags = MODULE_FLAG_RESOURCE;
900-
m.res = res;
901-
} else {
902-
ret = JS_ThrowReferenceError(ctx, "Cannot load resource from '%s'", file.utf8().get_data());
903-
}
904-
}
905-
binder->commonjs_module_cache.set(md5, m);
906-
}
907-
return ret;
908-
}
909-
910798
JSClassID QuickJSBinder::register_class(const ClassDB::ClassInfo *p_cls) {
911799

912800
ClassBindData data;
@@ -1392,7 +1280,6 @@ void QuickJSBinder::initialize() {
13921280
add_global_console();
13931281
// binding script
13941282
String script_binding_error;
1395-
13961283
ECMAScriptGCHandler eval_ret;
13971284
if (OK == safe_eval_text(ECMAScriptBinder::BINDING_SCRIPT_CONTENT, ECMAScriptBinder::EVAL_TYPE_GLOBAL, "<internal: binding_script.js>", script_binding_error, eval_ret)) {
13981285
#ifdef TOOLS_ENABLED

quickjs/quickjs_binder.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ class QuickJSBinder : public ECMAScriptBinder {
5555

5656
enum ECMAScriptModuleFlags {
5757
MODULE_FLAG_SCRIPT = 1,
58-
MODULE_FLAG_EVALUATED = 1 << 1,
59-
MODULE_FLAG_RESOURCE = 1 << 2,
58+
MODULE_FLAG_NATIVE = 2,
59+
MODULE_FLAG_EVALUATED = 1 << 3,
60+
MODULE_FLAG_RESOURCE = 1 << 4,
6061
};
6162

6263
struct ModuleCache {
@@ -121,14 +122,14 @@ class QuickJSBinder : public ECMAScriptBinder {
121122
}
122123
_FORCE_INLINE_ static void *js_binder_realloc(JSMallocState *s, void *ptr, size_t size) { return memrealloc(ptr, size); }
123124

125+
static String resolve_module_file(const String &file);
124126
static JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, void *opaque);
127+
static JSModuleDef *js_make_module(JSContext *ctx, const String &p_id, const JSValueConst &p_value);
125128
ModuleCache *js_compile_and_cache_module(JSContext *ctx, const String &p_code, const String &p_filename, ECMAscriptScriptError *r_error);
126129
ModuleCache *js_compile_and_cache_module(JSContext *ctx, const Vector<uint8_t> &p_bytecode, const String &p_filename, ECMAscriptScriptError *r_error);
127130
ModuleCache js_compile_module(JSContext *ctx, const String &p_code, const String &p_filename, ECMAscriptScriptError *r_error);
128131
static Error js_evalute_module(JSContext *ctx, ModuleCache *p_module, ECMAscriptScriptError *r_error);
129-
130132
static int resource_module_initializer(JSContext *ctx, JSModuleDef *m);
131-
static JSValue require_function(JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
132133

133134
struct ClassBindData {
134135
JSClassID class_id;

quickjs/quickjs_worker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ JSValue QuickJSWorker::global_import_scripts(JSContext *ctx, JSValue this_val, i
7777
for (int i = 0; i < argc; i++) {
7878
if (JS_IsString(argv[i])) {
7979
Error err;
80-
String path = js_to_string(ctx, argv[0]);
80+
String path = resolve_module_file(js_to_string(ctx, argv[0]));
8181
String source = FileAccess::get_file_as_string(path, &err);
8282
QuickJSBinder *bind = get_context_binder(ctx);
8383
ECMAScriptGCHandler eval_ret;

0 commit comments

Comments
 (0)