Git Product home page Git Product logo

ecmascript's Issues

[Typescript] Generated declaration file expands INF and NAN incorrectly

Hello there, there seems to be an issue according to Typescript's compiler, tsc, with the following lines in the automatically-generated godot.d.ts:

image

This yields the following errors:

../godot.d.ts:2177:15 - error TS1005: ',' expected.

2177  const INF: 1.#INF;
                   ~~~~

../godot.d.ts:2182:15 - error TS1005: ',' expected.

2182  const NAN: 1.#QNAN;

Thankfully, the typescript file for my compiles just fine regardless.

Steps to reproduce:

  1. Create a new Godot project
  2. Select Project > Tools > ECMAScript > Generate Typescript Declaration File which generates godot.d.ts in res://
  3. Create a new Typescript file anywhere. In my case, it's res://src/ts/new_script.ts
  4. In res://src/ts/, create a subdirectory called godot and place godot.d.ts in it.
  5. At the top of new_script.ts, import the declarations by writing import "godot";
  6. Run tsc in the src/ts/ directory. It will then print the errors.

Can not compile on platform=javascript target=release_debug

Error log:

modules/ECMAScript/quickjs/quickjs/quickjs.c:16065:11: error: use of undeclared identifier 'debugger_dispatch_table'; did you mean 'active_dispatch_table'?
        ? debugger_dispatch_table : dispatch_table;
          ^~~~~~~~~~~~~~~~~~~~~~~
          active_dispatch_table
modules/ECMAScript/quickjs/quickjs/quickjs.c:16064:26: note: 'active_dispatch_table' declared here
    const void * const * active_dispatch_table = caller_ctx->rt->debugger_info.transport_close
                         ^
modules/ECMAScript/quickjs/quickjs/quickjs.c:16065:37: error: use of undeclared identifier 'dispatch_table'
        ? debugger_dispatch_table : dispatch_table;

is it possible to import es5 / es6 modules?

I tried to import typescript / javascript modules but it doesn't seem to like the module format I'm using.

godot generates an error:

E 0:00:00.514   reload: JavaScript Error    at <anonymous> (res://node_modules/of-range/range.js:2)
exports is not defined
  <C++ Source>  modules/ECMAScript/ecmascript.cpp:90 @ reload()

I have tried both node_modules and and files within my project directory. I think a way around this problem would be to use a bundler such-as webpack but I am hoping there is a simpler way to make this work.

Editor crashes when importing an ogg file

Try to import an ogg file or to open a project with an ogg file. This crahes the editor on my system (Window 10 professional) with the following error in the console:

Assertion failed: f->temp_offset == f->alloc.alloc_buffer_length_in_bytes, file thirdparty/misc/stb_vorbis.c, line 4160

exporting does not work

im getting this error:

ERROR: _load: No loader found for resource: res://Main.js.
At: core/io/resource_loader.cpp:280.
ERROR: poll: res://Main.tscn:3 - Parse Error: [ext_resource] referenced nonexistent resource at: res://Main.js
At: scene/resources/resource_format_text.cpp:440.
ERROR: load: Failed to load resource 'res://Main.tscn'.
At: core/io/resource_loader.cpp:208.
ERROR: _load: Failed loading resource: res://Main.tscn.
At: core/io/resource_loader.cpp:278.
ERROR: start: Failed loading scene: res://Main.tscn
At: main/main.cpp:1846.
WARNING: cleanup: ObjectDB Instances still exist!
At: core/object.cpp:2074.
ERROR: clear: Resources Still in use at Exit!
At: core/resource.cpp:473.

it works fine running from the editor
btw what export templates do i have to use with your builds
thx for your time developing this

Cannot attach node script

I am trying to use this in godot (tagged commit 3.1.2-stable) with ECMAScript (tagged commit godot3.1-duktape) and the Godot UI will not allow me to attach an ECMAScript to a Node2D. It seems like a form validation issue but maybe I'm doing something wrong?

image

I've tried using the alpha3 branch as well but that one won't build w/ godot 3.1.2-stable. I'm going to try more branches, but do you know what the issue might be?

Porting for multiplatform

Linux

  • GCC x64 debug
  • GCC x64 release
  • Clang x64 debug
  • Clang x64 release

Windows

  • MSVC x64 debug
  • MSVC x64 release
  • MSVC x86 debug
  • MSVC x86 debug

OSX

  • Clang x64 debug
  • Clang x64 release

export { default } from xxx lead to a crash

Example:
a.js

export default class A extends godot.Node {
}

b.js

export { default } from './a';

And this will also crash:
c.js

export class C extends godot.Node {
}

d.js

export { C as default } from './c';

signals on classes that aren't attached as a script are never registered

Suppose you have two source files, A and B, with A attached as a script to some node.

A:

import B from "./B.jsx"
export default class A extends godot.Node {
  @signal static readonly mysignal: string;
  _ready() {
    this.add_child(new B());
  }
}

B:

export default class B extends godot.Node {
  @signal static readonly mysignal: string;
}

A is loaded as a script so register_ecma_class is called and the signals property is used to register signals. B however only gets the signals property, but they don't get registered. I can look into a fix.

QuickJS is 20-100x slower than V8

I noticed you said in the read me:

It is also possible to replace the ECMAScript engine like V8 or SpiderMonkey but not in the near plan.

I'm guessing that you're already aware of the performance difference, but just in case, a few people mention benchmark results in this thread: https://news.ycombinator.com/item?id=20418602

[QuickJS] shows only 2~3% of V8 performance

[QuickJS is] still 2-3x slower than [the V8 interpreter], and 20-100x slower than [the V8 compiler].

Scores on V8 benchmark suite:
QuickJS: 445 424 633 271 771 180 923 1979 549
V8: 31083 51056 36692 63343 50309 7910 22964 35214 32307

Deno seems like it might be helpful, and will hit v1.0 in about 8 days. I've not mixed Rust and C++ before (I haven't done any C++ coding at all) but apparently Rust plays well with other languages: https://doc.rust-lang.org/1.5.0/book/rust-inside-other-languages.html

Anyway, I'll close this right away because I don't have anything extra to add here - just thought I'd add this note in case you weren't aware of how vast the performance difference is.

JSX/TSX file extension clashes with React/Hyperscript style file extensions

Great project and works fine as is just leaving this issue as the jsx/tsx file extensions used are pretty much exclusive to React/hyperscript.

It's a little weird to adopt these in this project and causes some extensions in editors such as VSCode to believe that the file you are editing is of a react type. While it doesn't break anything it'd be nice not to have to disable/configure extensions in my editor to avoid react exclusive code suggestions/linting.

I would like to suggest changing this requirement to js/ts as in theory they are normal JS files without any additional syntax added.

typescript doesn't understand the quickjs operator overloads for godot algebraic types

the following code yields an error:

const a = new godot.Vector2(1, 1);
const b = new godot.Vector2(1, 1);
const c = a + b;

The error is:

Argument of type 'number' is not assignable to parameter of type 'Vector2'.ts(2345)

it can be avoided like so:

const c = ((a as any) + (b as any) as any as godot.Vector2);

is there anyway to avoid this in typescript?

godot.Input.MOUSE_MODE_CONFINED is undefined (probably all enum members)

given the following code:

export default class A extends godot.Node2D {
  _ready() {
    console.log(godot.Input.MOUSE_MODE_CONFINED) // logs undefined
    console.log(godot.Input.MouseMode) // logs undefined
    godot.Input.set_mouse_mode(godot.Input.MOUSE_MODE_CONFINED)
  }
}

you can see that both the enum which typescript expects, as wells as the enum constants on the godot.Input class itself are undefined. The equivalent gdscript works:

extends Node
class_name A

func _ready():
  print(Input.MOUSE_MODE_CONFINED)  // prints 3
  Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED)

Here is a project containing the scripts:
ecmascript-mouse-mode-confined.zip

If the enum is not intended to be supported by the JS runtime, just typescript types, I would recommend making it a typescript const enum which would be replaced by 3 at typescript compile time so the JS runtime only needs to be aware of godot.Input.MOUSE_MODE_* not both that and godot.Input.MouseMode.MOUSE_MODE_*

generate strong types for engine signals and connections

is there any interest in generating strong types for connections such as:

(this is probably a poor example, I'd need to dig in and make a PR to do it correctly)

declare module godot {
  interface SceneTree implements MainLoop {
    //overload 1 for network_peer_connected signal
    function connect<T extends Object>(
      signal: "network_peer_connected",
      target: T,
      method: Extract<T, Function> | (...args: Parameters<onNetworkPeerConnected>) => void,  //could use e.g. MethodOf<T>,
      binds: Tail<Parameters<onNetworkPeerConnected>>,
      flags: number = 0,
    ): number;
    // more overloads, one per signal for discriminating union
  }
}

Cyclic imports cause stack overflow + segfault

Provided is a minimal reproduction of a bug (I'm not sure whether in QuickJS or these bindings) where cyclic imports cause a segmentation fault.

ecmascript-cyclicdep-mvr.zip

Cyclic imports don't really work in ECMAScript modules (they're often undefined) so I should probably work around them, and maybe it's not even a bug then, but perhaps having a warning in the documentation or even detecting it would be helpful. I'll try to reproduce in quickjs by itself to confirm if it's a bug here or in quickjs.

Here are the root 50 frames in gdb:

(gdb) bt -50
#37664 0x00000000004fc7bf in js_resolve_module (ctx=0x417b48f0, m=0x5405db30) at modules/ECMAScript/quickjs/quickjs/quickjs.c:27441
#37665 0x000000000050af7e in __JS_EvalInternal (ctx=0x417b48f0, this_obj=...,
    input=0x5405d150 "import TestA from \"./TestA\"\n\nclass TestB extends godot.Node2D {\n    _ready() {\n        testA.connect(TestA.my_signal, () => { godot.print(\"my_signal!\") })\n    }\n}\n\nexport default TestB\n",
    input_len=185, filename=0x5405ba70 "res://TestB.jsx", flags=33, scope_idx=-1) at modules/ECMAScript/quickjs/quickjs/quickjs.c:33094
#37666 0x000000000050b15b in JS_EvalInternal (ctx=0x417b48f0, this_obj=...,
    input=0x5405d150 "import TestA from \"./TestA\"\n\nclass TestB extends godot.Node2D {\n    _ready() {\n        testA.connect(TestA.my_signal, () => { godot.print(\"my_signal!\") })\n    }\n}\n\nexport default TestB\n",
    input_len=185, filename=0x5405ba70 "res://TestB.jsx", flags=33, scope_idx=-1) at modules/ECMAScript/quickjs/quickjs/quickjs.c:33119
#37667 0x000000000050b360 in JS_Eval (ctx=0x417b48f0,
    input=0x5405d150 "import TestA from \"./TestA\"\n\nclass TestB extends godot.Node2D {\n    _ready() {\n        testA.connect(TestA.my_signal, () => { godot.print(\"my_signal!\") })\n    }\n}\n\nexport default TestB\n",
    input_len=185, filename=0x5405ba70 "res://TestB.jsx", eval_flags=33) at modules/ECMAScript/quickjs/quickjs/quickjs.c:33149
#37668 0x0000000000463725 in QuickJSBinder::js_compile_module (this=0x415acc20, ctx=0x417b48f0, p_code=..., p_filename=..., r_error=0x254f8e00) at modules/ECMAScript/quickjs/quickjs_binder.cpp:639
#37669 0x00000000004630d3 in QuickJSBinder::js_module_loader (ctx=0x417b48f0, module_name=0x5405c0a0 "res://TestB", opaque=0x415acc20) at modules/ECMAScript/quickjs/quickjs_binder.cpp:574
#37670 0x00000000004fb66b in js_host_resolve_imported_module (ctx=0x417b48f0, base_module_name=13844, module_name1=13850) at modules/ECMAScript/quickjs/quickjs/quickjs.c:26993
#37671 0x00000000004fc7bf in js_resolve_module (ctx=0x417b48f0, m=0x5405b760) at modules/ECMAScript/quickjs/quickjs/quickjs.c:27441
#37672 0x000000000050af7e in __JS_EvalInternal (ctx=0x417b48f0, this_obj=...,
    input=0x5405b420 "import TestB from \"./TestB\";\n\nexport default class TestA extends godot.Area2D {\n    static my_signal = \"my_signal\"\n\n    _ready() {\n        this.add_child(new TestB())\n    }\n}\n\ngodot.register_signal(Te"..., input_len=221, filename=0x540098d0 "res://TestA.jsx", flags=33, scope_idx=-1) at modules/ECMAScript/quickjs/quickjs/quickjs.c:33094
#37673 0x000000000050b15b in JS_EvalInternal (ctx=0x417b48f0, this_obj=...,
    input=0x5405b420 "import TestB from \"./TestB\";\n\nexport default class TestA extends godot.Area2D {\n    static my_signal = \"my_signal\"\n\n    _ready() {\n        this.add_child(new TestB())\n    }\n}\n\ngodot.register_signal(Te"..., input_len=221, filename=0x540098d0 "res://TestA.jsx", flags=33, scope_idx=-1) at modules/ECMAScript/quickjs/quickjs/quickjs.c:33119
#37674 0x000000000050b360 in JS_Eval (ctx=0x417b48f0,
    input=0x5405b420 "import TestB from \"./TestB\";\n\nexport default class TestA extends godot.Area2D {\n    static my_signal = \"my_signal\"\n\n    _ready() {\n        this.add_child(new TestB())\n    }\n}\n\ngodot.register_signal(Te"..., input_len=221, filename=0x540098d0 "res://TestA.jsx", eval_flags=33) at modules/ECMAScript/quickjs/quickjs/quickjs.c:33149
#37675 0x0000000000463725 in QuickJSBinder::js_compile_module (this=0x415acc20, ctx=0x417b48f0, p_code=..., p_filename=..., r_error=0x254f94a0) at modules/ECMAScript/quickjs/quickjs_binder.cpp:639
#37676 0x000000000046e4e5 in QuickJSBinder::parse_ecma_class (this=0x415acc20, p_code=..., p_path=..., r_error=0x254f94a0) at modules/ECMAScript/quickjs/quickjs_binder.cpp:2003
#37677 0x0000000000459e7a in ECMAScript::reload (this=0x5405aea0, p_keep_state=true) at modules/ECMAScript/ecmascript.cpp:92
#37678 0x000000000045aaf7 in ResourceFormatLoaderECMAScript::load (this=0x415ab810, p_path=..., p_original_path=..., r_error=0x0) at modules/ECMAScript/ecmascript.cpp:256
#37679 0x0000000001a181e6 in ResourceLoader::_load (p_path=..., p_original_path=..., p_type_hint=..., p_no_cache=false, r_error=0x0) at core/io/resource_loader.cpp:270
#37680 0x0000000001a18ca3 in ResourceLoader::load (p_path=..., p_type_hint=..., p_no_cache=false, r_error=0x0) at core/io/resource_loader.cpp:401
#37681 0x0000000001616d8f in ResourceInteractiveLoaderText::poll (this=0x540692e0) at scene/resources/resource_format_text.cpp:433
#37682 0x0000000001a168ff in ResourceFormatLoader::load (this=0x34c6bcb0, p_path=..., p_original_path=..., r_error=0x254fa25c) at core/io/resource_loader.cpp:197
#37683 0x0000000001a181e6 in ResourceLoader::_load (p_path=..., p_original_path=..., p_type_hint=..., p_no_cache=true, r_error=0x254fa25c) at core/io/resource_loader.cpp:270
#37684 0x0000000001a18ca3 in ResourceLoader::load (p_path=..., p_type_hint=..., p_no_cache=true, r_error=0x254fa25c) at core/io/resource_loader.cpp:401
#37685 0x0000000000b52fd6 in EditorNode::load_scene (this=0x43fc5060, p_scene=..., p_ignore_broken_deps=false, p_set_inherited=false, p_clear_errors=true, p_force_open_imported=false) at editor/editor_node.cpp:3371
#37686 0x0000000000b53e20 in EditorNode::open_request (this=0x43fc5060, p_path=...) at editor/editor_node.cpp:3488
#37687 0x0000000000c10687 in FileSystemDock::_select_file (this=0x5cb42880, p_path=..., p_select_in_favorites=false) at editor/filesystem_dock.cpp:832
#37688 0x0000000000c1091a in FileSystemDock::_tree_activate_file (this=0x5cb42880) at editor/filesystem_dock.cpp:851
#37689 0x00000000022be420 in MethodBind0::call (this=0x415a3890, p_object=0x5cb42880, p_args=0x254fa9b0, p_arg_count=0, r_error=...) at ./core/method_bind.gen.inc:59
#37690 0x00000000018c5549 in Object::call (this=0x5cb42880, p_method=..., p_args=0x254fa9b0, p_argcount=0, r_error=...) at core/object.cpp:922
#37691 0x00000000018c7184 in Object::emit_signal (this=0x5cb57a60, p_name=..., p_args=0x254fa9b0, p_argcount=0) at core/object.cpp:1249
#37692 0x00000000018c780d in Object::emit_signal (this=0x5cb57a60, p_name=..., p_arg1=..., p_arg2=..., p_arg3=..., p_arg4=..., p_arg5=...) at core/object.cpp:1306
#37693 0x0000000001317cb3 in Tree::_gui_input (this=0x5cb57a60, p_event=...) at scene/gui/tree.cpp:2727
#37694 0x00000000022c031b in MethodBind1<Ref<InputEvent> >::call (this=0x34d7a610, p_object=0x5cb57a60, p_args=0x254fb590, p_arg_count=1, r_error=...) at ./core/method_bind.gen.inc:775
#37695 0x00000000018c4b0b in Object::call_multilevel (this=0x5cb57a60, p_method=..., p_args=0x254fb590, p_argcount=1) at core/object.cpp:764
#37696 0x00000000018c524d in Object::call_multilevel (this=0x5cb57a60, p_name=..., p_arg1=..., p_arg2=..., p_arg3=..., p_arg4=..., p_arg5=...) at core/object.cpp:864
#37697 0x00000000011bde80 in Viewport::_gui_call_input (this=0x43f67520, p_control=0x5cb57a60, p_input=...) at scene/main/viewport.cpp:1669
#37698 0x00000000011bf128 in Viewport::_gui_input_event (this=0x43f67520, p_event=...) at scene/main/viewport.cpp:1979
#37699 0x00000000011c3ae0 in Viewport::input (this=0x43f67520, p_event=...) at scene/main/viewport.cpp:2825
#37700 0x00000000011bcc98 in Viewport::_vp_input (this=0x43f67520, p_ev=...) at scene/main/viewport.cpp:1446
#37701 0x00000000022fc3db in MethodBind1<Ref<InputEvent> const&>::call (this=0x34c86540, p_object=0x43f67520, p_args=0x254fc2c0, p_arg_count=1, r_error=...) at ./core/method_bind.gen.inc:775
#37702 0x00000000018c5549 in Object::call (this=0x43f67520, p_method=..., p_args=0x254fc2c0, p_argcount=1, r_error=...) at core/object.cpp:922
#37703 0x00000000018c519e in Object::call (this=0x43f67520, p_name=..., p_arg1=..., p_arg2=..., p_arg3=..., p_arg4=..., p_arg5=...) at core/object.cpp:848
#37704 0x00000000011a2f95 in SceneTree::call_group_flags (this=0x43f671d0, p_call_flags=2, p_group=..., p_function=..., p_arg1=..., p_arg2=..., p_arg3=..., p_arg4=..., p_arg5=...) at scene/main/scene_tree.cpp:275
#37705 0x00000000011a3bfd in SceneTree::input_event (this=0x43f671d0, p_event=...) at scene/main/scene_tree.cpp:431
#37706 0x0000000000416fed in InputDefault::_parse_input_event_impl (this=0x2a350d00, p_event=..., p_is_emulated=false) at main/input_default.cpp:442
#37707 0x0000000000416060 in InputDefault::parse_input_event (this=0x2a350d00, p_event=...) at main/input_default.cpp:259
#37708 0x0000000000418081 in InputDefault::flush_accumulated_events (this=0x2a350d00) at main/input_default.cpp:678
#37709 0x000000000040bc2e in OS_Windows::process_events (this=0x254fc910) at platform/windows/os_windows.cpp:2598
#37710 0x00000000004100a4 in OS_Windows::run (this=0x254fc910) at platform/windows/os_windows.cpp:3396
#37711 0x00000000004019da in widechar_main (argc=2, argv=0x256cc710) at platform/windows/godot_windows.cpp:161
#37712 0x0000000000401af3 in _main () at platform/windows/godot_windows.cpp:184
#37713 0x0000000000401b28 in main (_argc=2, _argv=0x1e8f80) at platform/windows/godot_windows.cpp:201

Are Singleton / Autoload supported ? How ?

Hello the GodotExplorer ECMAScript Team !

First: Thank you, this is awesome !
Second: the question in the title, so "Are Singleton / Autoload supported ? How ?"

Thank you !

Godot 4.0 Branch

Hi, thanks for the great module getting JS support in Godot! I was wondering if you were looking at supporting Godot 4.0 in a separate branch.

Godot 4.0 (currently pre-alpha / in development on master branch of godot repository) has a number of breaking API changes, I was experimenting with some of these changes in https://github.com/Flux159/ECMAScript/tree/godot_4.0, but ran into some issues with how PackedArrays were being used differently from PooledArrays along with a number of other C++ errors during compilation.

Thoughts on prebuilt binaries

Hi, do you have thoughts on providing prebuilt binaries of Godot with the ECMAScript module already installed?

Specifically, making the builds as mentioned in the README

Compilation
Clone the source code of godot
Clone this module and put it into godot/modules/ and make sure the folder name of this module is ECMAScript
Recompile the godot engine (Only MinGW is supported on Windows for now!)

is a significant burden to getting started with the project (not to mention making binaries w/out tools for exporting published games). I was wondering if it makes sense to provide prebuilt binaries (or setup a CI/CD pipeline with Github Actions to build & publish them as part of the repo).

QuickJS Error when trying to get World Space for raycasting

Hello, first of thanks for this great implementation of ES for Godot. It helps me alot getting started.

i ran into an issue when trying to get the world space state, in order to cast an ray between two Spatials. (i want to copy the Y position of the element below the player)

export default class Example extends godot.KinematicBody {
  _physics_process(delta) {
    var world = this.get_world()
    var spaceState = world.get_direct_space_state() // this line throws the error
  }
}
E 0:00:01.516   variant_to_var: Parameter ' data->ecma_object ' is null.
  <C++-Quellcode>modules/ECMAScript/quickjs/quickjs_binder.cpp:132 @ variant_to_var()

This method of ray casting is recommendet in http://docs.godotengine.org/en/3.2/tutorials/physics/ray-casting.html

My Godot Built is based on

  • Godot e707b712e8 (3.2 branch)
  • ECMAScript ec69d88 (maybe a bit outdated)

Two issues with Worker demo

  1. fib.js default export is fib function and not a godot class, so every time the file is loaded i get an error message "modules/ECMAScript/ecmascript.cpp:92 - JavaScript Error". Is this how it is supposed to be right now (work in progress)? So for now to avoid this message on every save one should export some empty class inheriting godot.Object?

  2. This one is less straightforward. When i press "Calculate in Worker" the playing scene just exits without any error ("Calculate in Main Thread" works fine). I tested different things and it seems like there is a stack overflow in worker thread on my machine when N is higher than 26. Even when fib is a simple function as (n) => n < 2 ? n : fib( n - 1 ). With 26 or lower worker is fine. Any clues what this might be caused by? What is the maximum N on your machine if you use the provided simple function?

Won't build on Windows 10 x64

Spawns next error log:

UnicodeEncodeError: 'charmap' codec can't encode character '\xd7' in position 24610: character maps to <undefined>:
  File "C:\Users\Teashrock\Documents\Development\Not-Mine\godot-3.2-stable\SConstruct", line 518:
    SConscript("modules/SCsub")
  File "c:\users\teashrock\envs\py3.7.4\lib\site-packages\scons\SCons\Script\SConscript.py", line 668:
    return method(*args, **kw)
  File "c:\users\teashrock\envs\py3.7.4\lib\site-packages\scons\SCons\Script\SConscript.py", line 605:
    return _SConscript(self.fs, *files, **subst_kw)
  File "c:\users\teashrock\envs\py3.7.4\lib\site-packages\scons\SCons\Script\SConscript.py", line 286:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "C:\Users\Teashrock\Documents\Development\Not-Mine\godot-3.2-stable\modules\SCsub", line 17:
    SConscript(x + "/SCsub")
  File "c:\users\teashrock\envs\py3.7.4\lib\site-packages\scons\SCons\Script\SConscript.py", line 668:
    return method(*args, **kw)
  File "c:\users\teashrock\envs\py3.7.4\lib\site-packages\scons\SCons\Script\SConscript.py", line 605:
    return _SConscript(self.fs, *files, **subst_kw)
  File "c:\users\teashrock\envs\py3.7.4\lib\site-packages\scons\SCons\Script\SConscript.py", line 286:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "C:\Users\Teashrock\Documents\Development\Not-Mine\godot-3.2-stable\modules\ECMAScript\SCsub", line 63:
    f.write(text.replace('${source}', dump_text_file_to_cpp("misc/godot.d.ts")))
  File "C:\Users\Teashrock\Envs\Py3.7.4\lib\encodings\cp1251.py", line 19:
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]

add generic argument for cast for get_node

Similar to C#'s GetNode<Label>(), add a generic argument to the $ and get_node types.

Something like:

interface Node {
  $<T extends godot.Node>(path: string): T;
}

If there's no reason against it, I could submit a PR once I read up on the repository.

"Cannot parse source code" issue

Hello!

I'm facing a weird issue, every time I try to create a script and attach it to a node I get an error. Here is the error when I tried to attach a script to a sprite. Obviously, the script exists and the code is correct (didn't change the template).

E 0:00:00.531   parse_ecma_class_from_module: Condition "p_module == __null || p_module->module == __null" is true. Returned: __null <Source C++>  modules/ECMAScript/quickjs/quickjs_binder.cpp:1630 @ parse_ecma_class_from_module()
E 0:00:00.531   reload: JavaScript Error    at res://SpriteTest.js:1
stack overflow
  <Source C++>  modules/ECMAScript/ecmascript.cpp:92 @ reload()
E 0:00:00.531   load: Cannot parse source code from file 'res://SpriteTest.js'.
  <Source C++>  modules/ECMAScript/ecmascript.cpp:267 @ load()

Missing gdscript functions

I notice we're missing some print functions that are in gdscript. Namely prints, printt, print_debug, and print-stack.

When writing gdscript I use prints in every situation (as it inserts spaces between arguments, just like console.log in JavaScript), so I noticed it quickly when trying this project.

Also I'm not sure that print is working as expected. It is supposed to accept and print any number of arguments, but in my testing it only prints the first:

// this prints: "a"
godot.print("a", "b", "c")

The typings for print seem correct though:

function godot.print(...args: any[]): void

Suggested improvements to async workflow

With Javascript being very async heavy, and ECMAScript not having to completely match how GDScript implements its features, there's potentially to provide slight usability improvements to the workflow with regards to Godot coroutines and signals workflow. These do not need to be implemented at a low level and may just be shims that wrap existing behavior

  • Support async/await against GDScript yielded functions
#gdscript Player
func jump():
  var anim = $AnimationPlayer
  anim.play("jump")
  yield($AnimationPlayer, "animation_finished")

// javascript
async function() {
  const player = get_node("Player");
  const result = await player.jump();
}
  • Support for closures or literal function references in place of Godot funcref/method-name binding functions
node.connect("my_signal", (param) => { console.log(param) });
node.connect("my_signal", this.mySignalHandler);
  • Convenience method to wrap one-shot signal connections in Promises
// with async/await
const async_result = await godot.OnSignal(node, "my_signal")
do_stuff(async_result);

// or with promises
godot.OnSignal(node, "my_signal")
  .then((result) => { do_stuff(result) })

If developers want to have a more advance version of the signalling, they could write a custom wrapper using RxJS where results get piped into an Observable.

Socket.io NPM

Has anyone had any luck with getting socket.io-client npm functional with this? It seems that it does not read npm module entry properly for me.

E 0:03:17.602   resolve_module_file: Module entry does not exists: node_modules/socket.io-client/./lib/index.js
  <C++ Error>   Condition "!FileAccess::exists(entry)" is true. Returned: ""
  <C++ Source>  modules/ECMAScript/quickjs/quickjs_binder.cpp:631 @ resolve_module_file()

resolution of node_modules

In resolve_module_file requested CommonJS module with require('$name') is expected to have a package at node_modules/$name/package.json at root of a godot project.

  • What if one want to move all js files (with node_modules) into a subfolder, like /js?

  • What if packages installed like this - nodule_modules/a/node_modules/b? Package a requires package b and they might be positioned in such way if some other package requires package b with a different version.

  • What if one want to require node_modules/a/b.js by require('a/b')? If b is not exported in index of package a.

prefer package.json + node_modules to current godot.d.ts generation workflow

Imo, more idiomatic typescript development (this might change with deno) practices call for the godot.d.ts and decorators.ts files to be a dependency, rather than generated by the editor. A combination of both could work, but I think the current workflow:

Run the menu command Project > Tools > ECMAScript > Generate TypeScript Project from the godot editor to generate a TypeScript project

would be better done by generating a package.json that depends on some godot-ecmascript package on npm that would be maintained by this group.

I wouldn't mind contributing this, but I think it warrants discussion.

Other benefits I can think of:

  • versioning the godot binding types
  • updating the godot binding types without updating the ECMAScript engine module
  • can use a npm-style project's .gitignore, in my project using this (awesome) binding set, I manually ignore the generated files because I prefer it that way

node_modules, gdignore and export

Currently godot scans and exports all files in node_modules folder, which is no good as it is notorious for becoming big in size. (Typescript folder is more than 50MB.)

There is .gdignore for that. Can be added automatically with some script in package.json:

"postinstall": "touch ./node_modules/.gdignore"

(Should be something else on windows - there is no touch there.)

Problem is - it will prevent needed files from being included in export too...

But previous two issues (#50 and #51) make me think that it might be easier to delegate work with node_modules to some other tool.

For example - you create a file index.js through which you export all cjs used by godot scripts and then build it with webpack. And you get a single script that contains only requested packages, which then is required by godot scripts with a relative path.

It removes all the problems associated with node_modules.

Thoughts?

godot.randi() can return negative numbers

According to the documentation, randi() should return a random integer between 0 and 2^32-1 which should make it trivial to get a random number in an interval via modulo.
godot.randi() can return negative values (I would assume between -2^16 and 2^16-1?) which forces you to wrap calls with godot.floor().

[BUG] object with signal that has more than one connection deletes arguments between the calls

I haven't set up a minimal viable reproduction yet, but I have a script class (A) with a signal, and then two nodes (both of class B) connect to the node of class A. When A emits its signal, the first node of class B gets the emitted arguments with the call:

emit_signal('signal_of_a', {ARGUMENT: "something"})

But the second node of class B gets an undefined argument instead, and because the bad argument is never set in QuickJSBinder::call, an uninitialized value is used to index the array of arguments which often leads to segfaults.

I also noticed that it happens while the code is in the JS_Call in QuickJSBinder::call_method, but I'm going to sleep for tonight. I will investigate more later. I have a suspicion since it occurs in the JS runtime that the variant_to_var is missing a reference count or something, but I don't know.

Add iterator implementation to the Pool*Array types

I'm not sure this is possible, but for now I have to do:

const bytes: PoolByteArray = godot.var2bytes({"hello": "world"});
for(let i = 0; i < bytes.size(); i++) {
  const byte = bytes.get(i);

I may be able to do this myself by attaching a Symbol.iterator property to the prototype which I will try, and can submit a PR for when done. Which might still take some time considering the codebase I'm converting.

Document advanced property support

Right now it's very difficult to figure out how to actually 'export' (in the Godot meaning of that) NodePaths and other types. I saw the latest release notes and figured out that support has been added for something like as the 'default value':

{
    type: godot.VariantType.TYPE_NODE_PATH,
    name: 'Tile Map',
}

But only after crashing the editor a few times by trying to set default value to something like new godot.TileMap() .

Would be great to have this documented along with all the valid usages. I can pick this one up and improve the documentation but I'd like to learn more first about everything before I do so to make sure I document it correctly.

Porting to QuickJS

I will wait until quickjs is more stable at least the debugger is implemented.

Export godot symbols to script

  • Refactor the ECMAScriptGCHandler to improve the binding process
  • Export godot Object types godot.Object godot.Reference
    • Constants and enumerations
    • Methods
    • Properties
    • Indexed properties and theme properties
    • Signals
  • Export global symbols of godot
    • Builtin functions godot.sin godot.randi
    • Builtin constants and enumerations
  • Export builtin types godot.Vector2 godot.Color
    • Implement the way to bind builtin types efficently
    • Script to generate binding code
    • Operator override
    • Properties and constants
    • Mannually bind overrided methods
    • Mannually bind constructor initializers
    • Mannually bind virtual properties of builtin types Rect2.end, Color.r8

Register script classes to godot

  • Implement godot.register_class to register classes form JS
  • Modules
    • ES6 module support
    • Register ECMAClass with export default ClassFunction syntax
    • Preload resources with module
  • Export properties from JS to godot inspector
  • Register signals from JS
  • Update the plugin to dump api
  • Tooled script support
  • Class icon support
  • Named class to allow create customer node write in javascript in the editor create dialog

Exporting

  • Allow exporting javascript scripts
  • Support compile script to bytecode when exporting
  • Support export script with encryption key
  • Implement script dependence dectection to allow only export required scripts

Optional Plans

  • Refactor the abstract binding helper to make it easier to port to other script engines
  • Refactor the ECMAScript resource workflow to allow attach javascript files to nodes
  • Allow passing function object for Object.connect, Object.disconnect and Object.is_connected
  • Override more methods which using method name as paramaters to using function object
  • Add await support for signals
  • Add plugin for better using of TypeScript
  • Add multi-thread support with Worker API
  • Add api to convert data between godot pool array with javascript typed arrays
  • Operator override for builtin classes
  • Add debugger support
  • Optimize the Performance
    • Profile from the fork of bunnymark
    • Optimize the performance for builtin types
    • Add allocator for binding object ECMAScriptGCHandler
    • More work to improve the performance for container types Array Dictionary

Crashes if _input or _unhandled_input is present

On my machine playing scene crashes if i have a js class with _input or _unhandled_input.

Reproduction: create empty project, create some root node, attach new ecma script to it and add _input(event) {} or _unhandled_input(even) {}. Play the scene and move a mouse few seconds.

Without those methods everything is working, as soon as i add them, crashes appear. On crashes i can see messages about malloc in terminal with godot editor process.

Is this reproducible on your machine?

QuickJs vs V8

Please excuse my ignorance in complexity of these things but I was wonder the following.
Since V8 is in orders of magnitude faster than quickjs, why not use V8 as the js engine?

Not possible to manipulate x or y of built-in vectors

Create something with a Position, like Area2D. Now try to manipulate only x or only y of the position:

export default class Player extends godot.Area2D {
    constructor() {
        this.velocity = new godot.Vector2();
    }
    _process() {
        this.velocity.x++; //this works!
        this.position.x++; //this should work but doesn't!
        this.position = new godot.Vector2(this.position.x + 1, this.position.y); //this works!
    }
}

I tried with position and scale, I assume all built-in vecors might behave the same.

Announce godot support for ECMAScript when completing these tasks

Major binding process

  • Export godot builtin classes into ECMAScript
  • Export global functions in@GDScript into ECMAScript
  • Export godot Object classes (All classes extend from Object) into ECMAScript
  • Export constants and enumerations into ECMAScript
  • Instance godot Object classes from ECMAScript
  • Call C++ methods from ECMAScript side
  • Export singleton objects (OS, ResourceLoader ... ) into ECMAScript
    • Export constants and enumerations for singletons
  • Register classes from ECMAScript
  • Instance ECMAScript classes in godot
  • Call ECMAScript methods from C++ side
  • Register signals from ECMAScript
  • Register exported properties (which can be modified by the editor inspector) from ECMAScript classes
  • Implement tooled script to make it possiable to run ECMAScript code in godot editor
  • Automatic gernerate Scripts that can attach to godot Objects
  • Implement a way to preload script libraries when starting project

Tools and editor plugins

  • Write tool to generate C++ code for binding builtin classes with Scons
  • Make a godot plugin to browser classes registed in ECMAScript
  • Reload ecmascript files in godot editor
  • Make a godot plugin to export ECMAScript API and documentations into a Declaration file

Maybe in the future

  • Implement a way to excute ECMAScript code in a seperated thread
  • Script import process to compile TypeScript/ES6 script within godot
  • Enhanced external editor workflow
  • Implement debugger client

Autoload scripts break after multithread support commit (35505d14417c3a5)

I merged the upstream changes, and all of my auto load scripts now cause the following:

Godot Engine v3.2.3.beta.custom_build.63cd61ce4 - https://godotengine.org
OpenGL ES 3.0 Renderer: Quadro P2000/PCIe/SSE2
                                                                                                                                                                                          "mike-HP-ZBook-15-G5" 14:21 15-Aug-20
ERROR: get_parent_class: Cannot get class 'JSEnvBootstrapper'.
   At: core/class_db.cpp:343.
ERROR: start: Script does not inherit a Node: res://js-extensions/JSEnvBootstrapper.jsx
   At: main/main.cpp:1758.
ERROR: get_parent_class: Cannot get class 'SteamManager'.
   At: core/class_db.cpp:343.
ERROR: start: Script does not inherit a Node: res://core/network/SteamManager.jsx
   At: main/main.cpp:1758.
ERROR: object_method: Parameter "bind" is null.
   At: modules/ECMAScript/quickjs/quickjs_binder.cpp:117.
ERROR: godot_load: Condition "argc < 1 || !JS_IsString(argv[0])" is true. Returned: JS_ThrowTypeError(ctx, "string expected for %s.%s", "godot", "load")
   At: modules/ECMAScript/quickjs/quickjs_binder.cpp:451.
ERROR: object_method: Parameter "bind" is null.
   At: modules/ECMAScript/quickjs/quickjs_binder.cpp:117.
ERROR: get_parent_class: Cannot get class 'GameState'.
   At: core/class_db.cpp:343.
ERROR: start: Script does not inherit a Node: res://core/GameState.jsx
   At: main/main.cpp:1758.

I'm sorry for the vague issue, but I used git bisect to find that the multi threaded classes commit broke it:

commit 35505d14417c3a5ef37eaf5d76977b1cd9d3c302 (refs/bisect/bad)
Author: Geequlim <[email protected]>
Date:   Sat Aug 8 12:38:37 2020 +0800

    ECMAScript class with multi-thread support

And I thought you might know what happened, faster than I can dig in.

godot.InputEvent pressed property doesn't work, but is_pressed getter does

Here's a reproduction:
ecmascript-pressed.zip

Here's the running script:

export default class A extends godot.Node2D {
  _input(evt) {
    if (evt.button_index === godot.ButtonList.BUTTON_RIGHT && evt.is_pressed())
      godot.print('right click!')
    if (evt.button_index === godot.ButtonList.BUTTON_LEFT && evt.pressed)
      godot.print('left click!')
  }
}

Notice that the right click triggers the print, but not the left.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.