From 783517ae6de6e8cd8390d81dd7a61c5a67831bed Mon Sep 17 00:00:00 2001 From: Darrin Lowery Date: Thu, 20 Oct 2022 19:47:32 -0500 Subject: [PATCH 01/57] Update README.md Added a section to make it more clear to new users that this is self contained like vanilla Godot. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 3b3a3b0f..35dd2914 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ This module implements JavaScript/TypeScript language support for the godot game - Full code completion support for all godot APIs including signals and enumerations - Debug in Visual Studio Code with the [plugin](https://marketplace.visualstudio.com/items?itemName=geequlim.godot-javascript-debug) +### Installation +No installation or setup necessary. The binaries for download are the complete, usable Godot editor and engine with Javascript/Typescript language support. + ### Download You can try the pre-compiled binaries from the [release page](https://github.com/GodotExplorer/ECMAScript/releases) You can also get the binaries with lastest commits from the [github build action result](https://github.com/GodotExplorer/ECMAScript/actions) From 01457b93157f8f4a23ab6b2fe2e3dda6057eb0cd Mon Sep 17 00:00:00 2001 From: "K. S. Ernest (iFire) Lee" Date: Sun, 23 Apr 2023 12:34:07 -0700 Subject: [PATCH 02/57] Fix Godot 4.0 compile errors, update JavaScript integration, refactor code, and address minor issues Fixed compilation errors, improved RefCounted bindings, renamed ECMAScript to JavaScript, implemented JavaScriptCallable, fixed typos, updated GDExtension migration, updated JS modules, and refactored code for Godot 4.0. Co-Authored-By: Malik Ahmed --- .github/workflows/linux_builds.yml | 2 +- .gitignore | 2 +- README.md | 22 +- SCsub | 122 +- build_github_actions.py | 7 +- config.py | 5 +- generate_builtin_api.py | 694 +++-- javascript.cpp | 44 +- javascript.h | 36 +- javascript_binder.h | 240 +- javascript_callable.h | 33 +- javascript_gc_handler.h | 334 +-- javascript_instance.cpp | 30 + javascript_instance.h | 36 +- javascript_language.cpp | 744 +++--- javascript_language.h | 38 +- misc/binding_script.js | 219 ++ misc/decorators.ts | 2 +- misc/godot.d.ts | 488 ++-- quickjs/quickjs_binder.cpp | 2362 ----------------- quickjs/quickjs_binder.h | 350 --- register_types.cpp | 58 +- register_types.h | 64 +- tests/UnitTest.js.disable | 100 + .../quickjs}/builtin_binding_generator.py | 760 +++--- .../quickjs}/quickjs/VERSION.txt | 0 .../quickjs}/quickjs/cutils.c | 4 +- .../quickjs}/quickjs/cutils.h | 16 +- .../quickjs}/quickjs/libbf.c | 534 ++-- .../quickjs}/quickjs/libbf.h | 20 +- .../quickjs}/quickjs/libregexp-opcode.h | 2 +- .../quickjs}/quickjs/libregexp.c | 98 +- .../quickjs}/quickjs/libregexp.h | 4 +- .../quickjs}/quickjs/libunicode-table.h | 0 .../quickjs}/quickjs/libunicode.c | 50 +- .../quickjs}/quickjs/libunicode.h | 2 +- .../quickjs}/quickjs/list.h | 4 +- .../quickjs}/quickjs/quickjs-atom.h | 6 +- .../quickjs}/quickjs/quickjs-debugger.c | 8 +- .../quickjs}/quickjs/quickjs-debugger.h | 4 +- .../quickjs}/quickjs/quickjs-opcode.h | 10 +- .../quickjs}/quickjs/quickjs.c | 536 ++-- .../quickjs}/quickjs/quickjs.h | 6 +- .../quickjs}/quickjs_builtin_binder.cpp | 0 .../quickjs}/quickjs_builtin_binder.h | 0 thirdparty/quickjs/quickjs_callable.cpp | 65 + thirdparty/quickjs/quickjs_callable.h | 30 + .../quickjs}/quickjs_debugger.cpp | 0 .../quickjs}/quickjs_debugger.h | 0 .../quickjs}/quickjs_worker.cpp | 0 .../quickjs}/quickjs_worker.h | 0 tools/editor_tools.cpp | 160 +- tools/editor_tools.h | 37 +- 53 files changed, 3220 insertions(+), 5168 deletions(-) delete mode 100644 quickjs/quickjs_binder.cpp delete mode 100644 quickjs/quickjs_binder.h create mode 100644 tests/UnitTest.js.disable rename {quickjs => thirdparty/quickjs}/builtin_binding_generator.py (50%) rename {quickjs => thirdparty/quickjs}/quickjs/VERSION.txt (100%) rename {quickjs => thirdparty/quickjs}/quickjs/cutils.c (99%) rename {quickjs => thirdparty/quickjs}/quickjs/cutils.h (94%) rename {quickjs => thirdparty/quickjs}/quickjs/libbf.c (98%) rename {quickjs => thirdparty/quickjs}/quickjs/libbf.h (98%) rename {quickjs => thirdparty/quickjs}/quickjs/libregexp-opcode.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs/libregexp.c (99%) rename {quickjs => thirdparty/quickjs}/quickjs/libregexp.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs/libunicode-table.h (100%) rename {quickjs => thirdparty/quickjs}/quickjs/libunicode.c (99%) rename {quickjs => thirdparty/quickjs}/quickjs/libunicode.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs/list.h (98%) rename {quickjs => thirdparty/quickjs}/quickjs/quickjs-atom.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs/quickjs-debugger.c (99%) rename {quickjs => thirdparty/quickjs}/quickjs/quickjs-debugger.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs/quickjs-opcode.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs/quickjs.c (99%) rename {quickjs => thirdparty/quickjs}/quickjs/quickjs.h (99%) rename {quickjs => thirdparty/quickjs}/quickjs_builtin_binder.cpp (100%) rename {quickjs => thirdparty/quickjs}/quickjs_builtin_binder.h (100%) create mode 100644 thirdparty/quickjs/quickjs_callable.cpp create mode 100644 thirdparty/quickjs/quickjs_callable.h rename {quickjs => thirdparty/quickjs}/quickjs_debugger.cpp (100%) rename {quickjs => thirdparty/quickjs}/quickjs_debugger.h (100%) rename {quickjs => thirdparty/quickjs}/quickjs_worker.cpp (100%) rename {quickjs => thirdparty/quickjs}/quickjs_worker.h (100%) diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 3b33ad58..afa4ac04 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -56,7 +56,7 @@ jobs: cache-name: linux-template-minimal target: template_release tests: false - sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no + sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no steps: - name: Checkout Godot uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 6a7d3c7d..a3c7a391 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ *.os *.gen.cpp *.gen.json -.vscode \ No newline at end of file +.vscode diff --git a/README.md b/README.md index 35dd2914..1562ff78 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This module implements JavaScript/TypeScript language support for the godot game - Almost complete ES2020 support - All godot api avaliable - Operator overriding for builtin types (Vector3, Color, etc) -- TypeScript support +- TypeScript support - [Using thirdpart libraries from npm](https://github.com/GodotExplorer/ECMAScriptDemos/tree/master/npm_module) - Multi-thread support with Worker API - Full code completion support for all godot APIs including signals and enumerations @@ -18,7 +18,7 @@ This module implements JavaScript/TypeScript language support for the godot game No installation or setup necessary. The binaries for download are the complete, usable Godot editor and engine with Javascript/Typescript language support. ### Download -You can try the pre-compiled binaries from the [release page](https://github.com/GodotExplorer/ECMAScript/releases) +You can try the pre-compiled binaries from the [release page](https://github.com/GodotExplorer/ECMAScript/releases) You can also get the binaries with lastest commits from the [github build action result](https://github.com/GodotExplorer/ECMAScript/actions) ### Compilation @@ -35,18 +35,18 @@ You can also get the binaries with lastest commits from the [github build action ```js // The default export entry is treated as an exported class to godot export default class MySprite extends godot.Sprite { - + // this is _init() in GDScript constructor() { super(); } - + _ready() { - + } - + _process(delta) { - + } } ``` @@ -173,7 +173,7 @@ Label.Align.ALIGN_LEFT | godot.Label.Align.ALIGN_LEFT // In worker thread let id = godot.abandon_value(object); postMessage({ type: 'return_value', id: id }); - + // In the host thread worker.onmessage = function(msg) { if (typeof msg === 'object' && msg.type === 'return_value') { @@ -181,7 +181,7 @@ Label.Align.ALIGN_LEFT | godot.Label.Align.ALIGN_LEFT } } ``` - + ### TypeScript support - Run the menu command `Project > Tools > JavaScript > Generate TypeScript Project` from the godot editor to generate a TypeScript project - Run `tsc -w -p .` under your project folder in the terminal to compile scripts @@ -213,7 +213,7 @@ export default class InputLine extends godot.HBoxContainer { // register offset property with the godot inspector with default value of Vector2(0, 0) @property({ default: godot.Vector2.ZERO }) offset: godot.Vector2; - + // register properties for godot editor inspector @property({ type: godot.VariantType.TYPE_STRING }) get title() { return this._title; } @@ -250,7 +250,7 @@ export default class InputLine extends godot.HBoxContainer { _ready() { // get first child with the type of godot.Label this._label = this.get_node(godot.Label); - + // Apply the inspector filled values with property setters this.title = this.title; this.hint = this.hint; diff --git a/SCsub b/SCsub index 795f1df1..d1cef8ad 100644 --- a/SCsub +++ b/SCsub @@ -1,77 +1,85 @@ #!/usr/bin/env python import platform, os, sys -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_module = env_modules.Clone() -JS_ENGINE = 'quickjs' -TOOLS = ('editor' == env_module['target']) #env.get('TOOLS'); +JS_ENGINE = "quickjs" +TOOLS = "editor" == env_module["target"] # env.get('TOOLS'); + def open_file(path, mode): - if platform.python_version() > '3': - return open(path, mode, encoding='utf8') - else: - return open(path, mode) + if platform.python_version() > "3": + return open(path, mode, encoding="utf8") + else: + return open(path, mode) + def dump_text_file_to_cpp(file): - source = open_file(file, 'r').read() - lines = source.split('\n') - source = "" - length = len(lines) - for i in range(length): - line = lines[i].replace('"', '\\"') - line = '\t"' + line + '\\n"' - if i < length -1: - line += "\n" - source += line - return source + source = open_file(file, "r").read() + lines = source.split("\n") + source = "" + length = len(lines) + for i in range(length): + line = lines[i].replace('"', '\\"') + line = '\t"' + line + '\\n"' + if i < length - 1: + line += "\n" + source += line + return source + + +if JS_ENGINE == "quickjs": + # generate builtin binding code + import generate_builtin_api + + generate_builtin_api.generate_api_json(os.path.join(GetLaunchDir(), "modules", os.path.basename(os.getcwd()))) + import thirdparty.quickjs.builtin_binding_generator -if JS_ENGINE == 'quickjs': - # generate builtin binding code - import generate_builtin_api - generate_builtin_api.generate_api_json(os.path.join(GetLaunchDir(), "modules", os.path.basename(os.getcwd()))) - import quickjs.builtin_binding_generator - quickjs.builtin_binding_generator.generate_builtin_bindings() - # build quickjs source - version = open('quickjs/quickjs/VERSION.txt', 'r').read().split('\n')[0] - env_module.Append(CPPDEFINES={"QUICKJS_CONFIG_VERSION": '"'+ version +'"'}) - env_module.Append(CPPDEFINES=["CONFIG_BIGNUM"]) - if 'release' not in (env_module['target'] or ''): - env_module.Append(CPPDEFINES={"DUMP_LEAKS": 1}) - env_module.Append(CPPDEFINES={"QUICKJS_WITH_DEBUGGER": 1}) - env_module.Append(CPPPATH=["quickjs/quickjs"]) - # env_module.Append(CXXFLAGS=["-std=c++20"]) - # env_module.Append(CCFLAGS=["-std=c++20"]) - if TOOLS: - env_module.add_source_files(env.modules_sources, 'tools/editor_tools.cpp') - env_module.add_source_files(env.modules_sources, 'quickjs/quickjs_builtin_binder.gen.cpp') - env_module.add_source_files(env.modules_sources, 'quickjs/*.cpp') - env_module.add_source_files(env.modules_sources, 'quickjs/quickjs/*.c') + thirdparty.quickjs.builtin_binding_generator.generate_builtin_bindings() + # build quickjs source + version = open("thirdparty/quickjs/quickjs/VERSION.txt", "r").read().split("\n")[0] + env_module.Append(CPPDEFINES={"QUICKJS_CONFIG_VERSION": '"' + version + '"'}) + env_module.Append(CPPDEFINES=["CONFIG_BIGNUM"]) + if "release" not in (env_module["target"] or ""): + env_module.Append(CPPDEFINES={"DUMP_LEAKS": 1}) + env_module.Append(CPPDEFINES={"QUICKJS_WITH_DEBUGGER": 1}) + env_module.Append(CPPPATH=["thirdparty/quickjs/quickjs"]) + # env_module.Append(CXXFLAGS=["-std=c++20"]) + # env_module.Append(CCFLAGS=["-std=c++20"]) + if TOOLS: + env_module.add_source_files(env.modules_sources, "tools/editor_tools.cpp") + env_module.add_source_files(env.modules_sources, "thirdparty/quickjs/quickjs_builtin_binder.gen.cpp") + env_module.add_source_files(env.modules_sources, "thirdparty/quickjs/*.cpp") + env_module.add_source_files(env.modules_sources, "thirdparty/quickjs/quickjs/*.c") # Binding script to run at engine initializing with open("misc/godot.binding_script.gen.cpp", "w") as f: - text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "../javascript_binder.h"\nString JavaScriptBinder::BINDING_SCRIPT_CONTENT = \n${source};' - f.write(text.replace('${source}', dump_text_file_to_cpp("misc/binding_script.js"))) + text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "../javascript_binder.h"\nString JavaScriptBinder::BINDING_SCRIPT_CONTENT = \n${source};' + f.write(text.replace("${source}", dump_text_file_to_cpp("misc/binding_script.js"))) sources = [ - 'register_types.cpp', - 'javascript_language.cpp', - 'javascript_instance.cpp', - 'javascript.cpp', - 'misc/godot.binding_script.gen.cpp', + "register_types.cpp", + "javascript_language.cpp", + "javascript_instance.cpp", + "javascript.cpp", + "misc/godot.binding_script.gen.cpp", ] if TOOLS: - base_text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "editor_tools.h"\nString JavaScriptPlugin::{} = \n{};' - tool_fns = {"tools/godot.d.ts.gen.cpp": ("BUILTIN_DECLARATION_TEXT", dump_text_file_to_cpp("misc/godot.d.ts")), - "tools/tsconfig.json.gen.cpp": ("TSCONFIG_CONTENT", dump_text_file_to_cpp("misc/tsconfig.json")), - "tools/decorators.ts.gen.cpp": ("TS_DECORATORS_CONTENT", dump_text_file_to_cpp("misc/decorators.ts")), - "tools/package.json.gen.cpp": ("PACKAGE_JSON_CONTENT", dump_text_file_to_cpp("misc/package.json")), - } - for fn, subs in tool_fns.items(): - with open_file(fn, "w") as fh: - fh.write(base_text.format(*subs)) - env_module.add_source_files(env.modules_sources, fn) + base_text = ( + '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "editor_tools.h"\nString JavaScriptPlugin::{} = \n{};' + ) + tool_fns = { + "tools/godot.d.ts.gen.cpp": ("BUILTIN_DECLARATION_TEXT", dump_text_file_to_cpp("misc/godot.d.ts")), + "tools/tsconfig.json.gen.cpp": ("TSCONFIG_CONTENT", dump_text_file_to_cpp("misc/tsconfig.json")), + "tools/decorators.ts.gen.cpp": ("TS_DECORATORS_CONTENT", dump_text_file_to_cpp("misc/decorators.ts")), + "tools/package.json.gen.cpp": ("PACKAGE_JSON_CONTENT", dump_text_file_to_cpp("misc/package.json")), + } + for fn, subs in tool_fns.items(): + with open_file(fn, "w") as fh: + fh.write(base_text.format(*subs)) + env_module.add_source_files(env.modules_sources, fn) env_module.Append(CPPPATH=["#modules/javascript"]) diff --git a/build_github_actions.py b/build_github_actions.py index bd28f338..78bef44b 100644 --- a/build_github_actions.py +++ b/build_github_actions.py @@ -16,6 +16,7 @@ from typing import Dict, List, Any import copy + # https://stackoverflow.com/a/33300001 + some changes def str_presenter(dumper, data): if len(data.splitlines()) > 1 or "\n" in data: # check for multiline string @@ -64,7 +65,7 @@ def checkout_local_godot_install(tag: str): raise RuntimeError(f"godot not setup properly, could not checkout '{' '.join(cmd)}'") -def get_windows_mingw_checkout_steps() -> List[Dict[str, Any]]: +def get_windows_mingw_checkout_steps() -> List[object]: out = [ { "name": "setup-msys2", @@ -313,9 +314,7 @@ def main(): for x in ["actions", "workflows"]: subprocess.call(["rm", "-rf", os.path.join(args.js_github_folder, x)]) - subprocess.call( - ["cp", "-r", os.path.join(args.godot_github_folder, x), os.path.join(args.js_github_folder, x)] - ) + subprocess.call(["cp", "-r", os.path.join(args.godot_github_folder, x), os.path.join(args.js_github_folder, x)]) basic_flags = " " actions = [ diff --git a/config.py b/config.py index 53bc8270..d22f9454 100644 --- a/config.py +++ b/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return True + return True + def configure(env): - pass + pass diff --git a/generate_builtin_api.py b/generate_builtin_api.py index a4d71800..745226ea 100755 --- a/generate_builtin_api.py +++ b/generate_builtin_api.py @@ -3,445 +3,377 @@ import xml.etree.ElementTree as ET BUILTIN_CLASSES = [ - 'Vector2', - 'Rect2', - 'Color', - 'Vector3', - 'Basis', - 'Quaternion', - 'RID', - 'Transform2D', - 'Plane', - 'AABB', - "Transform3D", - "PackedByteArray", - "PackedInt32Array", - "PackedInt64Array", - "PackedFloat32Array", - "PackedFloat64Array", - "PackedStringArray", - "PackedVector2Array", - "PackedVector3Array", - "PackedColorArray", + "Vector2", + "Rect2", + "Color", + "Vector3", + "Basis", + "Quaternion", + "RID", + "Transform2D", + "Plane", + "AABB", + "Transform3D", + "PackedByteArray", + "PackedInt32Array", + "PackedInt64Array", + "PackedFloat32Array", + "PackedFloat64Array", + "PackedStringArray", + "PackedVector2Array", + "PackedVector3Array", + "PackedColorArray", ] MAX_CONSTRUCTOR_ARGC = { - 'Vector2': 2, - 'Rect2': 4, - 'Color': 4, - 'Vector3': 3, - 'Basis': 0, - 'Quaternion': 0, - 'RID': 0, - 'Transform2D': 0, - 'Plane': 0, - 'AABB': 0, - "Transform3D": 0, - "PackedByteArray": 0, - "PackedInt32Array": 0, - "PackedInt64Array": 0, - "PackedFloat32Array": 0, - "PackedFloat64Array": 0, - "PackedStringArray": 0, - "PackedVector2Array": 0, - "PackedVector3Array": 0, - "PackedColorArray": 0, + "Vector2": 2, + "Rect2": 4, + "Color": 4, + "Vector3": 3, + "Basis": 0, + "Quaternion": 0, + "RID": 0, + "Transform2D": 0, + "Plane": 0, + "AABB": 0, + "Transform3D": 0, + "PackedByteArray": 0, + "PackedInt32Array": 0, + "PackedInt64Array": 0, + "PackedFloat32Array": 0, + "PackedFloat64Array": 0, + "PackedStringArray": 0, + "PackedVector2Array": 0, + "PackedVector3Array": 0, + "PackedColorArray": 0, } TYPE_MAP = { - 'int': 'number', - 'float': 'number', - 'bool': 'boolean', - 'String': 'string', - 'NodePath': 'string', + "int": "number", + "float": "number", + "bool": "boolean", + "String": "string", + "NodePath": "string", } METHOD_OP_EQUALS = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "equals", - "native_method": "operator==", - "return": "boolean" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "equals", + "native_method": "operator==", + "return": "boolean", } METHOD_OP_ADD = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "add", - "native_method": "operator+", - "return": "${class_name}" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "add", + "native_method": "operator+", + "return": "${class_name}", } METHOD_OP_ADD_ASSIGN = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "add_assign", - "native_method": "operator+=", - "return": "this" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "add_assign", + "native_method": "operator+=", + "return": "this", } METHOD_OP_SUB = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "subtract", - "native_method": "operator-", - "return": "${class_name}" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "subtract", + "native_method": "operator-", + "return": "${class_name}", } METHOD_OP_SUB_ASSIGN = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "subtract_assign", - "native_method": "operator-=", - "return": "this" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "subtract_assign", + "native_method": "operator-=", + "return": "this", } METHOD_OP_MUL = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "multiply", - "native_method": "operator*", - "return": "${class_name}" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "multiply", + "native_method": "operator*", + "return": "${class_name}", } METHOD_OP_MUL_ASSIGN = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "multiply_assign", - "native_method": "operator*=", - "return": "this" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "multiply_assign", + "native_method": "operator*=", + "return": "this", } METHOD_OP_DIV = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "multiply", - "native_method": "operator/", - "return": "${class_name}" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "multiply", + "native_method": "operator/", + "return": "${class_name}", } METHOD_OP_DIV_ASSIGN = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "multiply_assign", - "native_method": "operator/=", - "return": "this" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "multiply_assign", + "native_method": "operator/=", + "return": "this", } -METHOD_OP_NEG = { - "arguments": [], - "name": "negate", - "native_method": "operator-", - "return": "${class_name}" -} +METHOD_OP_NEG = {"arguments": [], "name": "negate", "native_method": "operator-", "return": "${class_name}"} METHOD_OP_LESS = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "less", - "native_method": "operator<", - "return": "boolean" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "less", + "native_method": "operator<", + "return": "boolean", } METHOD_OP_LESS_EQAUL = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "${class_name}" - } - ], - "name": "less_equal", - "native_method": "operator<=", - "return": "boolean" + "arguments": [{"default_value": None, "has_default_value": False, "type": "${class_name}"}], + "name": "less_equal", + "native_method": "operator<=", + "return": "boolean", } METHOD_PACKED_ARRAY_GET = { - "arguments": [ - { - "default_value": None, - "has_default_value": False, - "type": "number" - } - ], - "name": "get", - "native_method": "operator[]", - "return": "Variant" + "arguments": [{"default_value": None, "has_default_value": False, "type": "number"}], + "name": "get", + "native_method": "operator[]", + "return": "Variant", } IGNORED_PROPS = { - "Rect2": ['end', 'grow_side'], - "Color": ['h', 's', 'v', 'r8', 'g8', 'b8', 'a8'], - "Transform2D": ['xform', 'xform_inv'], - "Quaternion": ['get_euler'], - "Basis": ['is_equal_approx', 'get_euler', 'from_euler'], - "Plane": ['intersects_segment', 'intersects_ray', 'intersect_3'], - "AABB": ['end'], - "Transform3D": ['xform', 'xform_inv'], - "PackedByteArray": [ - 'compress', - 'decompress', - 'decompress_dynamic', - 'get_string_from_ascii', - 'get_string_from_utf8', - 'get_string_from_utf16', - 'get_string_from_utf32', - 'hex_encode', - 'to_float32_array', - 'to_float64_array', - 'to_int32_array', - 'to_int64_array', - 'has_encoded_var', - ], + "Rect2": ["end", "grow_side"], + "Color": ["h", "s", "v", "r8", "g8", "b8", "a8"], + "Transform2D": ["xform", "xform_inv"], + "Quaternion": ["get_euler"], + "Basis": ["is_equal_approx", "get_euler", "from_euler"], + "Plane": ["intersects_segment", "intersects_ray", "intersect_3"], + "AABB": ["end"], + "Transform3D": ["xform", "xform_inv"], + "PackedByteArray": [ + "compress", + "decompress", + "decompress_dynamic", + "get_string_from_ascii", + "get_string_from_utf8", + "get_string_from_utf16", + "get_string_from_utf32", + "hex_encode", + "to_float32_array", + "to_float64_array", + "to_int32_array", + "to_int64_array", + "has_encoded_var", + ], } PROPERTY_REMAP = { - "Transform2D": { - "x": "columns[0]", - "y": "columns[1]", - "origin": "columns[2]", - }, - "Basis": { - "x": "rows[0]", - "y": "rows[1]", - "z": "rows[2]", - }, - "Plane": { - "x": "normal.x", - "y": "normal.y", - "z": "normal.z", - } + "Transform2D": { + "x": "columns[0]", + "y": "columns[1]", + "origin": "columns[2]", + }, + "Basis": { + "x": "rows[0]", + "y": "rows[1]", + "z": "rows[2]", + }, + "Plane": { + "x": "normal.x", + "y": "normal.y", + "z": "normal.z", + }, } OPERATOR_METHODS = { - "Vector2": [ - METHOD_OP_NEG, - METHOD_OP_EQUALS, - METHOD_OP_LESS, - METHOD_OP_LESS_EQAUL, - METHOD_OP_ADD, - METHOD_OP_ADD_ASSIGN, - METHOD_OP_SUB, - METHOD_OP_SUB_ASSIGN, - METHOD_OP_MUL, - METHOD_OP_MUL_ASSIGN, - METHOD_OP_DIV, - METHOD_OP_DIV_ASSIGN, - ], - "Vector3": [ - METHOD_OP_NEG, - METHOD_OP_EQUALS, - METHOD_OP_LESS, - METHOD_OP_LESS_EQAUL, - METHOD_OP_ADD, - METHOD_OP_ADD_ASSIGN, - METHOD_OP_SUB, - METHOD_OP_SUB_ASSIGN, - METHOD_OP_MUL, - METHOD_OP_MUL_ASSIGN, - METHOD_OP_DIV, - METHOD_OP_DIV_ASSIGN, - ], - "Basis": [ - METHOD_OP_EQUALS, - METHOD_OP_ADD, - METHOD_OP_ADD_ASSIGN, - METHOD_OP_SUB, - METHOD_OP_SUB_ASSIGN, - METHOD_OP_MUL, - METHOD_OP_MUL_ASSIGN, - ], - "Quaternion": [ - METHOD_OP_NEG, - METHOD_OP_EQUALS, - METHOD_OP_ADD, - METHOD_OP_ADD_ASSIGN, - METHOD_OP_SUB, - METHOD_OP_SUB_ASSIGN, - ], - "Rect2": [ - METHOD_OP_EQUALS - ], - "Transform2D": [ - METHOD_OP_EQUALS, - METHOD_OP_MUL, - METHOD_OP_MUL_ASSIGN, - ], - "Color": [ - METHOD_OP_NEG, - METHOD_OP_EQUALS, - METHOD_OP_LESS, - METHOD_OP_ADD, - METHOD_OP_ADD_ASSIGN, - METHOD_OP_SUB, - METHOD_OP_SUB_ASSIGN, - METHOD_OP_MUL, - METHOD_OP_MUL_ASSIGN, - METHOD_OP_DIV, - METHOD_OP_DIV_ASSIGN, - ], - "RID": [ - METHOD_OP_EQUALS, - METHOD_OP_LESS, - METHOD_OP_LESS_EQAUL, - ], - "Plane": [ - METHOD_OP_NEG, - METHOD_OP_EQUALS, - ], - "AABB": [ - METHOD_OP_EQUALS, - ], - "Transform3D": [ - METHOD_OP_EQUALS, - METHOD_OP_MUL, - METHOD_OP_MUL_ASSIGN, - ] + "Vector2": [ + METHOD_OP_NEG, + METHOD_OP_EQUALS, + METHOD_OP_LESS, + METHOD_OP_LESS_EQAUL, + METHOD_OP_ADD, + METHOD_OP_ADD_ASSIGN, + METHOD_OP_SUB, + METHOD_OP_SUB_ASSIGN, + METHOD_OP_MUL, + METHOD_OP_MUL_ASSIGN, + METHOD_OP_DIV, + METHOD_OP_DIV_ASSIGN, + ], + "Vector3": [ + METHOD_OP_NEG, + METHOD_OP_EQUALS, + METHOD_OP_LESS, + METHOD_OP_LESS_EQAUL, + METHOD_OP_ADD, + METHOD_OP_ADD_ASSIGN, + METHOD_OP_SUB, + METHOD_OP_SUB_ASSIGN, + METHOD_OP_MUL, + METHOD_OP_MUL_ASSIGN, + METHOD_OP_DIV, + METHOD_OP_DIV_ASSIGN, + ], + "Basis": [ + METHOD_OP_EQUALS, + METHOD_OP_ADD, + METHOD_OP_ADD_ASSIGN, + METHOD_OP_SUB, + METHOD_OP_SUB_ASSIGN, + METHOD_OP_MUL, + METHOD_OP_MUL_ASSIGN, + ], + "Quaternion": [ + METHOD_OP_NEG, + METHOD_OP_EQUALS, + METHOD_OP_ADD, + METHOD_OP_ADD_ASSIGN, + METHOD_OP_SUB, + METHOD_OP_SUB_ASSIGN, + ], + "Rect2": [METHOD_OP_EQUALS], + "Transform2D": [ + METHOD_OP_EQUALS, + METHOD_OP_MUL, + METHOD_OP_MUL_ASSIGN, + ], + "Color": [ + METHOD_OP_NEG, + METHOD_OP_EQUALS, + METHOD_OP_LESS, + METHOD_OP_ADD, + METHOD_OP_ADD_ASSIGN, + METHOD_OP_SUB, + METHOD_OP_SUB_ASSIGN, + METHOD_OP_MUL, + METHOD_OP_MUL_ASSIGN, + METHOD_OP_DIV, + METHOD_OP_DIV_ASSIGN, + ], + "RID": [ + METHOD_OP_EQUALS, + METHOD_OP_LESS, + METHOD_OP_LESS_EQAUL, + ], + "Plane": [ + METHOD_OP_NEG, + METHOD_OP_EQUALS, + ], + "AABB": [ + METHOD_OP_EQUALS, + ], + "Transform3D": [ + METHOD_OP_EQUALS, + METHOD_OP_MUL, + METHOD_OP_MUL_ASSIGN, + ], } + def apply_pattern(template, values): - for key in values: - template = template.replace( '${' + key + '}', values[key]) - return template + for key in values: + template = template.replace("${" + key + "}", values[key]) + return template + def parse_class(cls): - class_name = cls.get('name') - ret = {'name': class_name} - members = [] - methods = [] - operators = [] - constants = [] - ret['properties'] = members - ret['methods'] = methods - ret['operators'] = operators - ret['constants'] = constants - ret['constructor_argc'] = MAX_CONSTRUCTOR_ARGC[class_name] - - for m in (cls.find("members") if cls.find("members") is not None else []): - m_dict = dict(m.attrib) - type = m_dict['type'] - name = m_dict['name'] - if (class_name in IGNORED_PROPS) and (name in IGNORED_PROPS[class_name]): - continue - if type in TYPE_MAP: - type = TYPE_MAP[type] - native_prop = name - if class_name in PROPERTY_REMAP: - if name in PROPERTY_REMAP[class_name]: - native_prop = PROPERTY_REMAP[class_name][name] - members.append({'name': name, 'type': type, 'native': native_prop}) - - for m in (cls.find("methods") if cls.find("methods") is not None else []): - m_dict = dict(m.attrib) - method_name = m_dict['name'] - if method_name == class_name: - continue# ignore constructors - if class_name in IGNORED_PROPS and method_name in IGNORED_PROPS[class_name]: - continue# ignored methods - if class_name == 'PackedByteArray' and method_name.startswith('encode_') or method_name.startswith('decode_'): - continue# ignore decode/encode methods - return_type = m.find("return").attrib["type"] if m.find("return") != None else "void" - if return_type in TYPE_MAP: - return_type = TYPE_MAP[return_type] - arguments = [] - for arg in m.iter('param'): - dictArg = dict(arg.attrib) - if "dictArg" in dictArg: dictArg.pop("index") - dictArg["default_value"] = dictArg["default"] if "default" in dictArg else None - if "default" in dictArg: dictArg.pop("default") - type = dictArg['type'] - if type in TYPE_MAP: - type = TYPE_MAP[type] - arguments.append({ - 'type': type, - 'default_value': dictArg['default_value'], - 'has_default_value': "default" in dictArg - }) - methods.append({ - 'name': method_name, - 'native_method': method_name, - 'return': return_type, - 'arguments': arguments, - }) - if class_name.startswith("Packed") and class_name.endswith("Array"): - methods.append(METHOD_PACKED_ARRAY_GET) - # add operator methods - if class_name in OPERATOR_METHODS: - for em in OPERATOR_METHODS[class_name]: - operators.append(em) - - for c in (cls.find("constants") if cls.find("constants") is not None else []): - const_name = c.get("name") - if class_name in IGNORED_PROPS and const_name in IGNORED_PROPS[class_name]: - continue - constants.append(dict(c.attrib)) - return json.loads(apply_pattern(json.dumps(ret), { - 'class_name': class_name, - })) + class_name = cls.get("name") + ret = {"name": class_name} + members = [] + methods = [] + operators = [] + constants = [] + ret["properties"] = members + ret["methods"] = methods + ret["operators"] = operators + ret["constants"] = constants + ret["constructor_argc"] = MAX_CONSTRUCTOR_ARGC[class_name] + + for m in cls.find("members") if cls.find("members") is not None else []: + m_dict = dict(m.attrib) + type = m_dict["type"] + name = m_dict["name"] + if (class_name in IGNORED_PROPS) and (name in IGNORED_PROPS[class_name]): + continue + if type in TYPE_MAP: + type = TYPE_MAP[type] + native_prop = name + if class_name in PROPERTY_REMAP: + if name in PROPERTY_REMAP[class_name]: + native_prop = PROPERTY_REMAP[class_name][name] + members.append({"name": name, "type": type, "native": native_prop}) + + for m in cls.find("methods") if cls.find("methods") is not None else []: + m_dict = dict(m.attrib) + method_name = m_dict["name"] + if method_name == class_name: + continue # ignore constructors + if class_name in IGNORED_PROPS and method_name in IGNORED_PROPS[class_name]: + continue # ignored methods + if class_name == "PackedByteArray" and method_name.startswith("encode_") or method_name.startswith("decode_"): + continue # ignore decode/encode methods + return_type = m.find("return").attrib["type"] if m.find("return") != None else "void" + if return_type in TYPE_MAP: + return_type = TYPE_MAP[return_type] + arguments = [] + for arg in m.iter("param"): + dictArg = dict(arg.attrib) + if "dictArg" in dictArg: + dictArg.pop("index") + dictArg["default_value"] = dictArg["default"] if "default" in dictArg else None + if "default" in dictArg: + dictArg.pop("default") + type = dictArg["type"] + if type in TYPE_MAP: + type = TYPE_MAP[type] + arguments.append( + {"type": type, "default_value": dictArg["default_value"], "has_default_value": "default" in dictArg} + ) + methods.append( + { + "name": method_name, + "native_method": method_name, + "return": return_type, + "arguments": arguments, + } + ) + if class_name.startswith("Packed") and class_name.endswith("Array"): + methods.append(METHOD_PACKED_ARRAY_GET) + # add operator methods + if class_name in OPERATOR_METHODS: + for em in OPERATOR_METHODS[class_name]: + operators.append(em) + + for c in cls.find("constants") if cls.find("constants") is not None else []: + const_name = c.get("name") + if class_name in IGNORED_PROPS and const_name in IGNORED_PROPS[class_name]: + continue + constants.append(dict(c.attrib)) + return json.loads( + apply_pattern( + json.dumps(ret), + { + "class_name": class_name, + }, + ) + ) + def generate_api_json(MODULE_DIR): - DOCS_DIR = os.path.abspath(os.path.join(MODULE_DIR, "../../doc/classes")) - if not os.path.isdir(DOCS_DIR) and len(sys.argv) > 1: - DOCS_DIR = sys.argv[-1] - OUTPUT_FILE = os.path.join(MODULE_DIR, "builtin_api.gen.json") - - classes = [] - for cls in BUILTIN_CLASSES: - tree = ET.parse(open(os.path.join(DOCS_DIR, cls + '.xml'), 'r')) - data = tree.getroot() - classes.append(parse_class(data)) - json.dump(classes, open(OUTPUT_FILE, 'w'), ensure_ascii=False, indent=2, sort_keys=True) - + DOCS_DIR = os.path.abspath(os.path.join(MODULE_DIR, "../../doc/classes")) + if not os.path.isdir(DOCS_DIR) and len(sys.argv) > 1: + DOCS_DIR = sys.argv[-1] + OUTPUT_FILE = os.path.join(MODULE_DIR, "builtin_api.gen.json") + + classes = [] + for cls in BUILTIN_CLASSES: + tree = ET.parse(open(os.path.join(DOCS_DIR, cls + ".xml"), "r")) + data = tree.getroot() + classes.append(parse_class(data)) + json.dump(classes, open(OUTPUT_FILE, "w"), ensure_ascii=False, indent=2, sort_keys=True) + + if __name__ == "__main__": - generate_api_json() + generate_api_json(".") diff --git a/javascript.cpp b/javascript.cpp index 411965e3..e5f5ea4e 100644 --- a/javascript.cpp +++ b/javascript.cpp @@ -1,3 +1,33 @@ +/**************************************************************************/ +/* javascript.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.h" #include "core/config/engine.h" #include "core/io/file_access_encrypted.h" @@ -35,7 +65,6 @@ StringName JavaScript::get_instance_base_type() const { } ScriptInstance *JavaScript::instance_create(Object *p_this) { - JavaScriptBinder *binder = JavaScriptLanguage::get_thread_binder(Thread::get_caller_id()); ERR_FAIL_NULL_V_MSG(binder, NULL, "Cannot create instance from this thread"); const JavaScriptClassInfo *cls = NULL; @@ -195,7 +224,6 @@ bool JavaScript::get_property_default_value(const StringName &p_property, Varian } void JavaScript::update_exports() { - #ifdef TOOLS_ENABLED if (!javascript_class) return; @@ -324,8 +352,8 @@ JavaScriptModule::JavaScriptModule() { set_source_code("module.exports = {};" ENDL); } -Ref ResourceFormatLoaderJavaScriptModule::load(const String &p_path, const String &p_original_path, Error *r_error) { - return load_static(p_path, p_original_path, r_error); +Ref ResourceFormatLoaderJavaScriptModule::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode) { + return ResourceFormatLoaderJavaScriptModule::load_static(p_path, p_original_path, r_error); } void ResourceFormatLoaderJavaScriptModule::get_recognized_extensions(List *p_extensions) const { @@ -354,7 +382,8 @@ Ref ResourceFormatLoaderJavaScriptModule::load_static(const String &p_ module->set_script_path(p_path); if (p_path.ends_with("." EXT_JSMODULE) || p_path.ends_with("." EXT_JSCLASS) || p_path.ends_with("." EXT_JSON)) { String code = FileAccess::get_file_as_string(p_path, &err); - if (r_error) *r_error = err; + if (r_error) + *r_error = err; ERR_FAIL_COND_V_MSG(err != OK, Ref(), "Cannot load source code from file '" + p_path + "'."); module->set_source_code(code); } @@ -392,12 +421,13 @@ Ref ResourceFormatLoaderJavaScriptModule::load_static(const String &p_ } #endif - if (r_error) *r_error = err; + if (r_error) + *r_error = err; ERR_FAIL_COND_V(err != OK, Ref()); return module; } -Error ResourceFormatSaverJavaScriptModule::save(const String &p_path, const Ref &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverJavaScriptModule::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { Ref module = p_resource; ERR_FAIL_COND_V(module.is_null(), ERR_INVALID_PARAMETER); String source = module->get_source_code(); diff --git a/javascript.h b/javascript.h index 1ffbf1a3..51407c47 100644 --- a/javascript.h +++ b/javascript.h @@ -1,3 +1,33 @@ +/**************************************************************************/ +/* javascript.h */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + #ifndef JAVASCRIPT_H #define JAVASCRIPT_H @@ -125,7 +155,7 @@ class JavaScriptModule : public TextFile { class ResourceFormatLoaderJavaScriptModule : public ResourceFormatLoader { GDCLASS(ResourceFormatLoaderJavaScriptModule, ResourceFormatLoader) public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, ResourceFormatLoader::CacheMode p_cache_mode = CACHE_MODE_REUSE) override; virtual void get_recognized_extensions(List *p_extensions) const override; virtual void get_recognized_extensions_for_type(const String &p_type, List *p_extensions) const override; virtual bool handles_type(const String &p_type) const override; @@ -137,9 +167,9 @@ class ResourceFormatLoaderJavaScriptModule : public ResourceFormatLoader { class ResourceFormatSaverJavaScriptModule : public ResourceFormatSaver { GDCLASS(ResourceFormatSaverJavaScriptModule, ResourceFormatSaver) public: - virtual Error save(const String &p_path, const Ref &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; virtual bool recognize(const Ref &p_resource) const override; }; -#endif +#endif // JAVASCRIPT_H diff --git a/javascript_binder.h b/javascript_binder.h index ee296bbf..2d73e054 100644 --- a/javascript_binder.h +++ b/javascript_binder.h @@ -1,105 +1,135 @@ -#ifndef JAVASCRIPT_BINDING_HELPER_H -#define JAVASCRIPT_BINDING_HELPER_H - -#include "core/os/thread.h" -#include "javascript_gc_handler.h" - -typedef JavaScriptGCHandler JSMethodInfo; - -struct JavaScriptProperyInfo : public PropertyInfo { - Variant default_value; -}; - -struct JavaScriptError { - int line; - int column; - String message; - String file; - Vector stack; -}; - -struct BasicJavaScriptClassInfo { - bool tool; - StringName class_name; - String icon_path; - const ClassDB::ClassInfo *native_class; - HashMap signals; - HashMap methods; - HashMap properties; -}; - -struct JavaScriptClassInfo : public BasicJavaScriptClassInfo { - JavaScriptGCHandler constructor; - JavaScriptGCHandler prototype; -}; - -struct GlobalNumberConstant { - StringName name; - double_t value; -}; - -struct JavaScriptStackInfo { - int line; - String file; - String function; -}; - -class JavaScriptBinder { -protected: - // Path ==> JavaScript Class - HashMap javascript_classes; - HashMap frame_callbacks; - HashSet canceled_frame_callbacks; - static String BINDING_SCRIPT_CONTENT; - -public: - enum EvalType { - EVAL_TYPE_MODULE, - EVAL_TYPE_GLOBAL, - }; - - JavaScriptBinder() {} - virtual ~JavaScriptBinder(){}; - - virtual JavaScriptBinder *get_context_binder(void *p_context) = 0; - virtual Thread::ID get_thread_id() const = 0; - - virtual void clear_classes() { javascript_classes.clear(); } - - virtual void initialize() = 0; - virtual void uninitialize() = 0; - virtual void language_finalize() = 0; - virtual void frame() = 0; - - virtual JavaScriptGCHandler *alloc_object_binding_data(Object *p_object) = 0; - virtual void free_object_binding_data(JavaScriptGCHandler *p_gc_handle) = 0; - virtual void godot_refcount_incremented(JavaScriptGCHandler *p_gc_handle) = 0; - virtual bool godot_refcount_decremented(JavaScriptGCHandler *p_gc_handle) = 0; - - virtual Error eval_string(const String &p_source, EvalType type, const String &p_path, JavaScriptGCHandler &r_ret) = 0; - virtual Error safe_eval_text(const String &p_source, EvalType type, const String &p_path, String &r_error, JavaScriptGCHandler &r_ret) = 0; - virtual String error_to_string(const JavaScriptError &p_error) = 0; - virtual Error get_stacks(List &r_stacks) = 0; - virtual String get_backtrace_message(const List &stacks) = 0; - - virtual Error compile_to_bytecode(const String &p_code, const String &p_file, Vector &r_bytecode) = 0; - virtual Error load_bytecode(const Vector &p_bytecode, const String &p_file, JavaScriptGCHandler *r_module) = 0; - virtual const JavaScriptClassInfo *parse_javascript_class(const String &p_code, const String &p_path, bool ignore_cacehe, JavaScriptError *r_error) = 0; - virtual const JavaScriptClassInfo *parse_javascript_class(const Vector &p_bytecode, const String &p_path, bool ignore_cacehe, JavaScriptError *r_error) = 0; - - virtual JavaScriptGCHandler create_js_instance_for_godot_object(const JavaScriptClassInfo *p_class, Object *p_object) = 0; - virtual bool get_instance_property(const JavaScriptGCHandler &p_object, const StringName &p_name, Variant &r_ret) = 0; - virtual bool set_instance_property(const JavaScriptGCHandler &p_object, const StringName &p_name, const Variant &p_value) = 0; - virtual bool has_method(const JavaScriptGCHandler &p_object, const StringName &p_name) = 0; - virtual bool has_signal(const JavaScriptClassInfo *p_class, const StringName &p_signal) = 0; - virtual bool validate(const String &p_code, const String &p_path, JavaScriptError *r_error) = 0; - - virtual Variant call_method(const JavaScriptGCHandler &p_object, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0; - virtual Variant call(const JavaScriptGCHandler &p_fuction, const JavaScriptGCHandler &p_target, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0; - -#ifdef TOOLS_ENABLED - virtual const Dictionary &get_modified_api() const = 0; -#endif -}; - -#endif +/**************************************************************************/ +/* javascript_binder.h */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + +#ifndef JAVASCRIPT_BINDER_H +#define JAVASCRIPT_BINDER_H + +#include "core/os/thread.h" +#include "javascript_gc_handler.h" + +typedef JavaScriptGCHandler JSMethodInfo; + +struct JavaScriptProperyInfo : public PropertyInfo { + Variant default_value; +}; + +struct JavaScriptError { + int line; + int column; + String message; + String file; + Vector stack; +}; + +struct BasicJavaScriptClassInfo { + bool tool; + StringName class_name; + String icon_path; + const ClassDB::ClassInfo *native_class; + HashMap signals; + HashMap methods; + HashMap properties; +}; + +struct JavaScriptClassInfo : public BasicJavaScriptClassInfo { + JavaScriptGCHandler constructor; + JavaScriptGCHandler prototype; +}; + +struct GlobalNumberConstant { + StringName name; + double_t value; +}; + +struct JavaScriptStackInfo { + int line; + String file; + String function; +}; + +class JavaScriptBinder { +protected: + // Path ==> JavaScript Class + HashMap javascript_classes; + HashMap frame_callbacks; + HashSet canceled_frame_callbacks; + static String BINDING_SCRIPT_CONTENT; + +public: + enum EvalType { + EVAL_TYPE_MODULE, + EVAL_TYPE_GLOBAL, + }; + + JavaScriptBinder() {} + virtual ~JavaScriptBinder(){}; + + virtual JavaScriptBinder *get_context_binder(void *p_context) = 0; + virtual Thread::ID get_thread_id() const = 0; + + virtual void clear_classes() { javascript_classes.clear(); } + + virtual void initialize() = 0; + virtual void uninitialize() = 0; + virtual void language_finalize() = 0; + virtual void frame() = 0; + + virtual JavaScriptGCHandler *alloc_object_binding_data(Object *p_object) = 0; + virtual void free_object_binding_data(JavaScriptGCHandler *p_gc_handle) = 0; + virtual void godot_refcount_incremented(JavaScriptGCHandler *p_gc_handle) = 0; + virtual bool godot_refcount_decremented(JavaScriptGCHandler *p_gc_handle) = 0; + + virtual Error eval_string(const String &p_source, EvalType type, const String &p_path, JavaScriptGCHandler &r_ret) = 0; + virtual Error safe_eval_text(const String &p_source, EvalType type, const String &p_path, String &r_error, JavaScriptGCHandler &r_ret) = 0; + virtual String error_to_string(const JavaScriptError &p_error) = 0; + virtual Error get_stacks(List &r_stacks) = 0; + virtual String get_backtrace_message(const List &stacks) = 0; + + virtual Error compile_to_bytecode(const String &p_code, const String &p_file, Vector &r_bytecode) = 0; + virtual Error load_bytecode(const Vector &p_bytecode, const String &p_file, JavaScriptGCHandler *r_module) = 0; + virtual const JavaScriptClassInfo *parse_javascript_class(const String &p_code, const String &p_path, bool ignore_cacehe, JavaScriptError *r_error) = 0; + virtual const JavaScriptClassInfo *parse_javascript_class(const Vector &p_bytecode, const String &p_path, bool ignore_cacehe, JavaScriptError *r_error) = 0; + + virtual JavaScriptGCHandler create_js_instance_for_godot_object(const JavaScriptClassInfo *p_class, Object *p_object) = 0; + virtual bool get_instance_property(const JavaScriptGCHandler &p_object, const StringName &p_name, Variant &r_ret) = 0; + virtual bool set_instance_property(const JavaScriptGCHandler &p_object, const StringName &p_name, const Variant &p_value) = 0; + virtual bool has_method(const JavaScriptGCHandler &p_object, const StringName &p_name) = 0; + virtual bool has_signal(const JavaScriptClassInfo *p_class, const StringName &p_signal) = 0; + virtual bool validate(const String &p_code, const String &p_path, JavaScriptError *r_error) = 0; + + virtual Variant call_method(const JavaScriptGCHandler &p_object, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0; + virtual Variant call(const JavaScriptGCHandler &p_fuction, const JavaScriptGCHandler &p_target, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0; + +#ifdef TOOLS_ENABLED + virtual const Dictionary &get_modified_api() const = 0; +#endif +}; + +#endif // JAVASCRIPT_BINDER_H diff --git a/javascript_callable.h b/javascript_callable.h index e8ceb011..c2f99b3f 100644 --- a/javascript_callable.h +++ b/javascript_callable.h @@ -1,3 +1,33 @@ +/**************************************************************************/ +/* javascript_callable.h */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + #ifndef JAVASCRIPT_CALLABLE_H #define JAVASCRIPT_CALLABLE_H @@ -10,7 +40,8 @@ class JavaScriptCallable : public CallableCustom { public: JavaScriptCallable() {} - JavaScriptCallable(const JavaScriptGCHandler &p_function) : js_function(p_function) {} + JavaScriptCallable(const JavaScriptGCHandler &p_function) : + js_function(p_function) {} virtual ~JavaScriptCallable() {} }; diff --git a/javascript_gc_handler.h b/javascript_gc_handler.h index 0d88ffc4..a207d5c7 100644 --- a/javascript_gc_handler.h +++ b/javascript_gc_handler.h @@ -1,152 +1,182 @@ -#ifndef JAVASCRIPT_GC_HANDLER_H -#define JAVASCRIPT_GC_HANDLER_H - -#include "core/object/object.h" -#include "core/object/ref_counted.h" -#include "core/variant/variant.h" - -#define PROTOTYPE_LITERAL "prototype" -#define PROTO_LITERAL "__proto__" -#define TO_STRING_LITERAL "toString" -#define JS_CLASS_NAME_LITERAL "class_name" -#define GODOT_OBJECT_NAME "godot" - -struct JavaScriptGCHandler { - enum { - FLAG_NONE = 0, - FLAG_ATOMIC_VALUE = 1 << 1, - FLAG_BUILTIN_CLASS = 1 << 2, - FLAG_OBJECT = 1 << 3, - FLAG_REF_COUNTED = 1 << 4, - FLAG_FINALIZED = 1 << 5, - FLAG_TRANSFERABLE = 1 << 6, - }; - Variant::Type type; - uint8_t flags; - void *context; - void *javascript_object; - union { - Object *godot_object; - void *godot_builtin_object_ptr; - void *native_ptr; - }; - - _FORCE_INLINE_ Variant get_value() const { - switch (type) { - case Variant::OBJECT: - return godot_object; - case Variant::VECTOR2: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::RECT2: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::QUATERNION: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::COLOR: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::RID: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::TRANSFORM3D: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::TRANSFORM2D: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::BASIS: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::VECTOR3: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PLANE: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::AABB: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_INT32_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_INT64_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_BYTE_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_FLOAT32_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_FLOAT64_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_COLOR_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_STRING_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_VECTOR2_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - case Variant::PACKED_VECTOR3_ARRAY: - return *(static_cast(godot_builtin_object_ptr)); - default: - return Variant(); - } - return Variant(); - } - - _FORCE_INLINE_ Object *get_godot_object() { - if (flags & FLAG_OBJECT) { - return godot_object; - } - return nullptr; - } - - _FORCE_INLINE_ Vector2 *getVector2() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Rect2 *getRect2() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Color *getColor() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ AABB *getAABB() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Vector3 *getVector3() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Transform2D *getTransform2D() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Transform3D *getTransform3D() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Basis *getBasis() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ RID *getRID() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Plane *getPlane() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ Quaternion *getQuaternion() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedInt32Array *getPackedInt32Array() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedInt64Array *getPackedInt64Array() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedByteArray *getPackedByteArray() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedFloat32Array *getPackedFloat32Array() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedFloat64Array *getPackedFloat64Array() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedStringArray *getPackedStringArray() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedColorArray *getPackedColorArray() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedVector2Array *getPackedVector2Array() const { return static_cast(godot_builtin_object_ptr); } - _FORCE_INLINE_ PackedVector3Array *getPackedVector3Array() const { return static_cast(godot_builtin_object_ptr); } - - _FORCE_INLINE_ bool is_object() const { - return flags & FLAG_OBJECT; - } - - _FORCE_INLINE_ bool is_ref_counted() const { - return flags & FLAG_REF_COUNTED; - } - - _FORCE_INLINE_ bool is_transferable() const { - return flags & FLAG_TRANSFERABLE; - } - - _FORCE_INLINE_ bool is_atomic_type() const { - return flags & FLAG_ATOMIC_VALUE; - } - - _FORCE_INLINE_ bool is_finalized() const { - return flags & FLAG_FINALIZED; - } - - _FORCE_INLINE_ bool is_valid_javascript_object() const { - return context != NULL && javascript_object != NULL && !is_finalized(); - } - - _FORCE_INLINE_ void clear() { - type = Variant::NIL; - godot_object = NULL; - javascript_object = NULL; - context = NULL; - } - - JavaScriptGCHandler() { - type = Variant::NIL; - flags = FLAG_NONE; - godot_object = NULL; - javascript_object = NULL; - context = NULL; - } -}; - -#endif +/**************************************************************************/ +/* javascript_gc_handler.h */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + +#ifndef JAVASCRIPT_GC_HANDLER_H +#define JAVASCRIPT_GC_HANDLER_H + +#include "core/object/object.h" +#include "core/object/ref_counted.h" +#include "core/variant/variant.h" + +#define PROTOTYPE_LITERAL "prototype" +#define PROTO_LITERAL "__proto__" +#define TO_STRING_LITERAL "toString" +#define JS_CLASS_NAME_LITERAL "class_name" +#define GODOT_OBJECT_NAME "godot" + +struct JavaScriptGCHandler { + enum { + FLAG_NONE = 0, + FLAG_ATOMIC_VALUE = 1 << 1, + FLAG_BUILTIN_CLASS = 1 << 2, + FLAG_OBJECT = 1 << 3, + FLAG_REF_COUNTED = 1 << 4, + FLAG_FINALIZED = 1 << 5, + FLAG_TRANSFERABLE = 1 << 6, + }; + Variant::Type type; + uint8_t flags; + void *context; + void *javascript_object; + union { + Object *godot_object; + void *godot_builtin_object_ptr; + void *native_ptr; + }; + + _FORCE_INLINE_ Variant get_value() const { + switch (type) { + case Variant::OBJECT: + return godot_object; + case Variant::VECTOR2: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::RECT2: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::QUATERNION: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::COLOR: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::RID: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::TRANSFORM3D: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::TRANSFORM2D: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::BASIS: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::VECTOR3: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PLANE: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::AABB: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_INT32_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_INT64_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_BYTE_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_FLOAT32_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_FLOAT64_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_COLOR_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_STRING_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_VECTOR2_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + case Variant::PACKED_VECTOR3_ARRAY: + return *(static_cast(godot_builtin_object_ptr)); + default: + return Variant(); + } + return Variant(); + } + + _FORCE_INLINE_ Object *get_godot_object() { + if (flags & FLAG_OBJECT) { + return godot_object; + } + return nullptr; + } + + _FORCE_INLINE_ Vector2 *getVector2() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Rect2 *getRect2() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Color *getColor() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ AABB *getAABB() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Vector3 *getVector3() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Transform2D *getTransform2D() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Transform3D *getTransform3D() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Basis *getBasis() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ RID *getRID() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Plane *getPlane() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ Quaternion *getQuaternion() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedInt32Array *getPackedInt32Array() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedInt64Array *getPackedInt64Array() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedByteArray *getPackedByteArray() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedFloat32Array *getPackedFloat32Array() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedFloat64Array *getPackedFloat64Array() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedStringArray *getPackedStringArray() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedColorArray *getPackedColorArray() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedVector2Array *getPackedVector2Array() const { return static_cast(godot_builtin_object_ptr); } + _FORCE_INLINE_ PackedVector3Array *getPackedVector3Array() const { return static_cast(godot_builtin_object_ptr); } + + _FORCE_INLINE_ bool is_object() const { + return flags & FLAG_OBJECT; + } + + _FORCE_INLINE_ bool is_ref_counted() const { + return flags & FLAG_REF_COUNTED; + } + + _FORCE_INLINE_ bool is_transferable() const { + return flags & FLAG_TRANSFERABLE; + } + + _FORCE_INLINE_ bool is_atomic_type() const { + return flags & FLAG_ATOMIC_VALUE; + } + + _FORCE_INLINE_ bool is_finalized() const { + return flags & FLAG_FINALIZED; + } + + _FORCE_INLINE_ bool is_valid_javascript_object() const { + return context != NULL && javascript_object != NULL && !is_finalized(); + } + + _FORCE_INLINE_ void clear() { + type = Variant::NIL; + godot_object = NULL; + javascript_object = NULL; + context = NULL; + } + + JavaScriptGCHandler() { + type = Variant::NIL; + flags = FLAG_NONE; + godot_object = NULL; + javascript_object = NULL; + context = NULL; + } +}; + +#endif // JAVASCRIPT_GC_HANDLER_H diff --git a/javascript_instance.cpp b/javascript_instance.cpp index af0e67b8..6b48beb9 100644 --- a/javascript_instance.cpp +++ b/javascript_instance.cpp @@ -1,3 +1,33 @@ +/**************************************************************************/ +/* javascript_instance.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_instance.h" #include "javascript.h" #include "javascript_language.h" diff --git a/javascript_instance.h b/javascript_instance.h index 01220a47..32320dcd 100644 --- a/javascript_instance.h +++ b/javascript_instance.h @@ -1,10 +1,40 @@ +/**************************************************************************/ +/* javascript_instance.h */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + #ifndef JAVASCRIPT_INSTANCE_H #define JAVASCRIPT_INSTANCE_H -#include "javascript.h" -#include "javascript_binder.h" #include "core/object/script_language.h" #include "core/variant/callable.h" +#include "javascript.h" +#include "javascript_binder.h" class JavaScriptInstance : public ScriptInstance { friend class JavaScript; @@ -39,4 +69,4 @@ class JavaScriptInstance : public ScriptInstance { ~JavaScriptInstance(); }; -#endif +#endif // JAVASCRIPT_INSTANCE_H diff --git a/javascript_language.cpp b/javascript_language.cpp index cd2fe07a..17dd831f 100644 --- a/javascript_language.cpp +++ b/javascript_language.cpp @@ -1,357 +1,387 @@ -#include "javascript_language.h" -#include "core/object/class_db.h" -#include "core/io/file_access.h" -JavaScriptLanguage *JavaScriptLanguage::singleton = NULL; - -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