See More

/**************************************************************************/ /* javascript_language.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /**************************************************************************/ /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ #include "javascript_language.h" #include "core/io/file_access.h" #include "core/object/class_db.h" #include "javascript_binder.h" #include "thirdparty/quickjs/quickjs_binder.h" JavaScriptLanguage *JavaScriptLanguage::singleton = nullptr; namespace JavaScriptInstanceBindingCallbacks { static void *create_callback(void *p_token, void *p_instance) { if (JavaScriptBinder *binder = JavaScriptLanguage::get_singleton()->get_thread_binder(Thread::get_caller_id())) { return binder->alloc_object_binding_data(static_cast(p_instance)); } return nullptr; } static void free_callback(void *p_token, void *p_instance, void *p_binding) { if (JavaScriptBinder *binder = JavaScriptLanguage::get_singleton()->get_thread_binder(Thread::get_caller_id())) { return binder->free_object_binding_data(static_cast(p_binding)); } } static GDExtensionBool reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference) { if (JavaScriptBinder *binder = JavaScriptLanguage::get_singleton()->get_thread_binder(Thread::get_caller_id())) { if (p_reference) { binder->godot_refcount_incremented(static_cast(p_binding)); return false; } else { return binder->godot_refcount_decremented(static_cast(p_binding)); } } return true; } } // namespace JavaScriptInstanceBindingCallbacks JavaScriptLanguage::JavaScriptLanguage() { ERR_FAIL_COND(singleton); singleton = this; main_binder = memnew(QuickJSBinder); callable_middleman = memnew(CallableMiddleman); instance_binding_callbacks.create_callback = JavaScriptInstanceBindingCallbacks::create_callback; instance_binding_callbacks.free_callback = JavaScriptInstanceBindingCallbacks::free_callback; instance_binding_callbacks.reference_callback = JavaScriptInstanceBindingCallbacks::reference_callback; } JavaScriptLanguage::~JavaScriptLanguage() { memdelete(main_binder); memdelete(callable_middleman); } void JavaScriptLanguage::init() { ERR_FAIL_NULL(main_binder); main_binder->initialize(); execute_file("modules/javascript/tests/UnitTest.js"); } void JavaScriptLanguage::finish() { ERR_FAIL_NULL(main_binder); main_binder->uninitialize(); main_binder->language_finalize(); } Error JavaScriptLanguage::execute_file(const String &p_path) { ERR_FAIL_NULL_V(main_binder, ERR_BUG); Error err; String code = FileAccess::get_file_as_string(p_path, &err); if (err == OK) { JavaScriptGCHandler eval_ret; err = main_binder->eval_string(code, JavaScriptBinder::EVAL_TYPE_GLOBAL, p_path, eval_ret); } return err; } void JavaScriptLanguage::get_reserved_words(List *p_words) const { static const char *_reserved_words[] = { "null", "false", "true", "if", "else", "return", "var", "this", "delete", "void", "typeof", "new", "in", "instanceof", "do", "while", "for", "break", "continue", "switch", "case", "default", "throw", "try", "catch", "finally", "function", "debugger", "with", "class", "const", "enum", "export", "default", "extends", "import", "super", "implements", "interface", "let", "package", "private", "protected", "public", "static", "yield", "await", "prototype", "constructor", "get", "set", "of", "__proto__", "undefined", "number", "boolean", "string", "object", "symbol", "arguments", "join", "global", "as", "from", "default", "*", "then", "resolve", "reject", "promise", "proxy", "revoke", "async", "globalThis", "Object", "Array", "Error", "Number", "String", "Boolean", "Symbol", "Arguments", "Math", "JSON", "Date", "Function", "GeneratorFunction", "ForInIterator", "RegExp", "ArrayBuffer", "SharedArrayBuffer", "Uint8ClampedArray", "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "BigInt64Array", "BigUint64Array", "Float32Array", "Float64Array", "DataView", "Map", "Set", "WeakMap", "WeakSet", "Generator", "Proxy", "Promise", 0 }; const char **w = _reserved_words; while (*w) { p_words->push_back(*w); w++; } } bool JavaScriptLanguage::is_control_flow_keyword(String p_keyword) const { return p_keyword == "if" || p_keyword == "else" || p_keyword == "return" || p_keyword == "do" || p_keyword == "while" || p_keyword == "for" || p_keyword == "break" || p_keyword == "continue" || p_keyword == "switch" || p_keyword == "case" || p_keyword == "throw" || p_keyword == "try" || p_keyword == "catch" || p_keyword == "finally"; } void JavaScriptLanguage::get_comment_delimiters(List *p_delimiters) const { p_delimiters->push_back("//"); // single-line comment p_delimiters->push_back("/* */"); // delimited comment } void JavaScriptLanguage::get_string_delimiters(List *p_delimiters) const { p_delimiters->push_back("' '"); p_delimiters->push_back("\" \""); p_delimiters->push_back("` `"); } Ref