Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delphi support? #1

Closed
edwinyzh opened this issue Aug 19, 2019 · 17 comments
Closed

Delphi support? #1

edwinyzh opened this issue Aug 19, 2019 · 17 comments

Comments

@edwinyzh
Copy link

This is a great project! Do you have a plan to support Delphi? Thanks.

@Coldzer0
Copy link
Owner

Thanks, Yes i'm working on it.
I will push the updates in the next few days.

@edwinyzh
Copy link
Author

edwinyzh commented Aug 19, 2019

Great!
BTW, I guess you know chakracore-delphi already, right? Would love to hear how do you compare QuickJS with Chakracore.
My initial thoughts:

  • Microsoft has abandoned ChakraCore
  • QuickJS must be simpler than ChakraCore
  • but the current status, delphi-ChakraCore has better support for integrating with the host (Delphi) program.

@Coldzer0
Copy link
Owner

Coldzer0 commented Aug 21, 2019

Great!
BTW, I guess you know chakracore-delphi already, right? Would love to hear how do you compare QuickJS with Chakracore.
My initial thoughts:

  • Microsoft has abandoned ChakraCore
  • QuickJS must be simpler than ChakraCore
  • but at the current status, delphi-ChakraCore as better support for integrating with the host (Delphi) program.

Yes i know about it, but first of all it's size is very big like 20 MB but QJS is like 1MB only

I agree with "Microsoft has abandoned ChakraCore" i think they don't care too much as they moved to chromium.

"QuickJS must be simpler than ChakraCore" it's the simplest implementation i've ever seen for a JS Engine

As Bellard says in the docs

Unlike other embedded Javascript engines, there is no implicit stack, so C functions get their parameters as normal C parameters. As a general rule, C functions take constant JSValues as parameters (so they don’t need to free them) and return a newly allocated (=live) JSValue.

Plus QJS Main Features is amazing with very small code and small memory

  • Small and easily embeddable: just a few C files, no external dependency, 190 KiB of x86 code for a simple hello world program.
  • Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
  • Almost complete ES2019 support including modules, asynchronous generators and full Annex B support (legacy web compatibility). Many features from the upcoming ES2020 specification are also supported.
  • Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features.
    Can compile Javascript sources to executables with no external dependency.
  • Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal.
  • Mathematical extensions: BigInt, BigFloat, operator overloading, bigint mode, math mode.
  • Command line interpreter with contextual colorization implemented in Javascript.
  • Small built-in standard library with C library wrappers.

"better support for integrating with the host (Delphi)"
I almost done with Delphi version maybe i'll push the update tomorrow or tomorrow after.

So i'm willing to support this project for long time, as i move from BESEN engine in my Cmulator project to QJS.
It's like 10x faster with ES2019 support 😄

Sorry for late reply i was very busy.

@edwinyzh
Copy link
Author

@Coldzer0 No need to be sorry about the late reply, and I really appreciate you answering my questions! I'm looking forward to the Delphi version so that I can have a look at it ;)

@Coldzer0
Copy link
Owner

@edwinyzh

I finished the Delphi Support 😄
Hope you find it helpful.

@edwinyzh
Copy link
Author

edwinyzh commented Aug 23, 2019

Great @Coldzer0 !
First thing - under XE4 to compile the demo project, I have to define the PUint32 type, can you add it to your code? Thanks.
interface

uses
...
{$IfNDef FPC}
  {$IF (CompilerVersion <= 25)}
  type
    PUint32 = ^Uint32; // PUint32 not defined in XE4
  {$IFEND}
{$ENDIF}

Will look further.

@edwinyzh
Copy link
Author

Is it normal that the demo console program outputs nothing? See attached screenshot.
2019-08-23_12h37_33

@edwinyzh
Copy link
Author

edwinyzh commented Aug 23, 2019

Oh I see, the compiled program must be run with a parameter which is the js file you want to run. My results of running apihook.js:

F:\>DelphiDemo examples\apihook.js


====================================================

API : kernel32.dll.ExitProcess
Hello From ExitProcess - 1337
OnCallBack return = 1
ExitProcess.args[0] :  1007
ExitProcess.args[1] :  2222

====================================================

API : user32.dll.MessageBox
Hello From MessageBox 1337
OnCallBack return = 0
MessageBox.args[0] :  hello
MessageBox.args[1] :  1010

And hello_module.js with error:

F:\>DelphiDemo examples\hello_module.js
ReferenceError: could not load module filename 'fib_module.js'

@Coldzer0
Copy link
Owner

Great @Coldzer0 !
First thing - under XE4 to compile the demo project, I have to define the PUint32 type, can you add it to your code? Thanks.
interface

uses
...
{$IfNDef FPC}
  {$IF (CompilerVersion <= 25)}
  type
    PUint32 = ^Uint32; // PUint32 not defined in XE4
  {$IFEND}
{$ENDIF}

Will look further.

Thanks for testing, that's very helpful.

Oh I see, the compiled program must be run with a parameter which is the js file you want to run. My results of running apihook.js:

F:\>DelphiDemo examples\apihook.js


====================================================

API : kernel32.dll.ExitProcess
Hello From ExitProcess - 1337
OnCallBack return = 1
ExitProcess.args[0] :  1007
ExitProcess.args[1] :  2222

====================================================

API : user32.dll.MessageBox
Hello From MessageBox 1337
OnCallBack return = 0
MessageBox.args[0] :  hello
MessageBox.args[1] :  1010

the result looks Ok 😄

And hello_module.js with error:

F:\>DelphiDemo examples\hello_modu
le.js
ReferenceError: could not load module filename 'fib_module.js'

this one happen on windows only, you need to write your own js_module_loader

the c implementation

JSModuleDef *js_module_loader(JSContext *ctx,
                              const char *module_name, void *opaque)
{
    JSModuleDef *m;

    if (has_suffix(module_name, ".so")) {
        m = js_module_loader_so(ctx, module_name);
    } else {
        size_t buf_len;
        uint8_t *buf;
        JSValue func_val;
    
        buf = js_load_file(ctx, &buf_len, module_name);
        if (!buf) {
            JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
                                   module_name);
            return NULL;
        }
        
        /* compile the module */
        func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
                           JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
        js_free(ctx, buf);
        if (JS_IsException(func_val))
            return NULL;
        /* the module is already referenced, so we must free it */
        m = JS_VALUE_GET_PTR(func_val);
        JS_FreeValue(ctx, func_val);
    }
    return m;
}

It's not hard to write your own one.
after implementing your own just change the js_module_loader with yours.

JS_SetModuleLoaderFunc(rt, nil, @js_module_loader, nil);

@edwinyzh
Copy link
Author

Thanks @Coldzer0 , it's useful.
When I actually start using it I might want to implement auto object binding using the good old RTTI (not the new but slow RTTI) to auto expose published methods of a Delphi object to JS.

@Coldzer0
Copy link
Owner

@edwinyzh

I already work on auto object binding for native classes
With the old RTTI and it works for both FPC & Delphi 😄

I finished the Register Native Class with published methods and properties.

I'll push it after some testing 👍

@edwinyzh
Copy link
Author

That's a great choice man! Looking forward to the new update :)

@Coldzer0
Copy link
Owner

can you add it to your code? Thanks.

I already did ^_^, in this commit.
Thanks.

@edwinyzh
Copy link
Author

can you add it to your code? Thanks.

I already did ^_^, in this commit.
Thanks.

I

@edwinyzh
Copy link
Author

Thanks, I noticed it. And the next part also makes me exciting ^_^

@edwinyzh

I already work on auto object binding for native classes
With the old RTTI and it works for both FPC & Delphi

I finished the Register Native Class with published methods and properties.

I'll push it after some testing

@edwinyzh
Copy link
Author

@edwinyzh

I already work on auto object binding for native classes
With the old RTTI and it works for both FPC & Delphi

I finished the Register Native Class with published methods and properties.

I'll push it after some testing

@Coldzer0,
Is this available yet? :)

@Coldzer0
Copy link
Owner

@Coldzer0,
Is this available yet? :)

@edwinyzh

I didn’t complete it yet because I stuck with some stuff like calling a published function from a class

QJS don’t know about the “Self” Param so it’s a bit harder to implement it without make changes in the QJS core

But it should work fine with any “class function”
Because it doesn’t have the self param

So we can declare all the native methods with class before it’s name

And if we need to use the self object i did make a work around by setting it to an property in the js object related to the class

But I’ll give it another try 👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants