CEF JavaScript binding "require/import" question

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

CEF JavaScript binding "require/import" question

Postby Devyre » Mon Jul 12, 2021 6:29 pm

Hello,

I'm trying to do JavaScript bindings and this is the syntax I have in mind to access native code:

Code: Select all
import { TestClass } from "sdk://test";
TestClass.doSomething();


I've gotten to the point where I register the sdk protocol handler, then thought I'd feed it this as a resource:

Code: Select all
export class TestClass {
    static doSomething() {
        native function doSomething();
        doSomething();
    }
};


But then I realized handlers can only be registered using CefRegisterExtension.
Now I would like to know how I could go with the above syntax, or something similar.
I am attempting to expose tons of classes to JavaScript and they can easily have 4-5 namespaces, and usage such as "sdk.namespace1.namespace2.namespace3.TestClass" would be a little bit annoying.

The import syntax seems much more neat.
One way I thought of doing is registering extensions with long names such as NativeProxy_SdkNamespace1Namespace2Namespace3TestClass
and then instead of using "native" in the above code snippet, I would just call these "NativeProxy_" functions.

Is there a better way to do this though? I've tried to search for this kind of thing, but it's very hard to find anything.
Devyre
Techie
 
Posts: 27
Joined: Fri Nov 20, 2020 8:31 pm

Re: CEF JavaScript binding "require/import" question

Postby magreenblatt » Mon Jul 12, 2021 6:35 pm

What do the JS functions do? Will they be executing logic in the browser process? If so, I suggest using async JS bindings instead.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: CEF JavaScript binding "require/import" question

Postby Devyre » Mon Jul 12, 2021 7:03 pm

Yes, they are supposed to run in the browser process.
They are mostly used to access data from the application.
At the moment, I am converting the function arguments to the CefProcessMessage arguments, then sending it to the browser process, and from there invoking the function with the corresponding instance, serializing the result, sending it back to the renderer process and invoking the resolve (or reject).
All of that pretty much works, i'm just a bit tied up on the syntax, as I would like to import what I need in my scripts for clarity (the import syntax easily shows what I'm using and what's available - that's why I prefer it).
Overall, I'm just wondering how it would be possible to import/require a module and letting that act the same as CefRegisterExtension (using a handler).
If that is not possible at this time, I will most likely fall back to what I said with using these "Proxy" functions that redirect to an extension.
Devyre
Techie
 
Posts: 27
Joined: Fri Nov 20, 2020 8:31 pm

Re: CEF JavaScript binding "require/import" question

Postby magreenblatt » Mon Jul 12, 2021 7:34 pm

Why do you want to use extensions? You can put your proxy objects in separate URLs and import them without using extensions. The proxy objects can communicate with the browser process using the generic message router or similar.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: CEF JavaScript binding "require/import" question

Postby Devyre » Mon Jul 12, 2021 7:59 pm

Mostly because I find extensions easier to understand, I haven't really found a way to add a global function using the CreateFunction way, since (from my understanding) you need to attach them to existing objects.
Is there any downside to using extensions (apart from my current struggle with attempting to import them of course)?
Devyre
Techie
 
Posts: 27
Joined: Fri Nov 20, 2020 8:31 pm

Re: CEF JavaScript binding "require/import" question

Postby magreenblatt » Mon Jul 12, 2021 8:09 pm

Extensions are harder to debug, and any errors during loading could crash the renderer process.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: CEF JavaScript binding "require/import" question

Postby Devyre » Thu Jul 15, 2021 7:44 pm

Hey, not sure if I should open a new thread for this, but I have an issue and I'm not sure why it happens.

So, I have the following HTML document (just to test some things because the renderer kept crashing in a 100ms interval callback after a while):
Code: Select all
<!DOCTYPE html>
<html>
    <head>

    </head>
    <script>
        setTimeout(async () => {
         while (true)
            NativeCall();
      }, 5000);
    </script>
    <body>
        <div>test</div>
    </body>
</html>


The function "NativeCall" is registered via extension and is returned as a Promise, similar to this:
Code: Select all
function NativeCall()
{
    return new Promise((resolve, reject) => {
        native function NativeCallCpp();
        NativeCallCpp(resolve, reject);
    });
}


In the corresponding V8Handler, I immediately return true, nothing else happens.
When I run this, the renderer process crashes with an "Out of memory" exception, even though the process has only 20-40 MB allocated.

I also tried to do this without using promises, which resulted in this entire issue to take a bit longer than before, but it still happened about a minute later (with a promise it happens in about 3-7 seconds).
I am using branch 4183 and running the process in 32 bit, but again, the allocated RAM when this crash happens is not more than 40 mb, and I made sure that Windows did not compress memory.

At first I thought this was because LARGEADDRESSAWARE was missing in my app, but turns out that's not the problem.
When taking a closer look at the exception and going up the callstack, it seems like chromium tries to allocate something with size -524289.

Any idea why this happens?
Devyre
Techie
 
Posts: 27
Joined: Fri Nov 20, 2020 8:31 pm

Re: CEF JavaScript binding "require/import" question

Postby magreenblatt » Thu Jul 15, 2021 8:23 pm

Are you looking at memory usage for the renderer process specifically? How are you measuring the memory usage? Tight loops may be keeping the JavaScript GC from running, or your native code (which you didn’t post) may be leaking memory.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: CEF JavaScript binding "require/import" question

Postby Devyre » Thu Jul 15, 2021 8:36 pm

There is no native code associated to the function, the V8 Handler returns true immediately, so I just register an extension with a handler that does absolutely nothing.
I measured the RAM usage with the Visual Studio debugger (attached to the right renderer process before it crashed) and by looking at the task manager, and to make sure that Windows did not compress it I created a memory dump (one of the right click options of the task manager processes).
This usually uncompresses all of the memory if compressed.

In more detail: I register the extension as suggested in OnWebKitInitialized() and allocate this V8Handler only once.
In the CefV8Handler::Execute function I return true immediately.

I will attempt this with the most recent branch and see if it is fixed there.
The reason I use the 4183 branch is because of shared texture support (and lots of commits from my end to make things viable for d3d9ex with shared textures).

Are you looking at memory usage for the renderer process specifically?

Yes, the 20-40 mb RAM is only the renderer process that is crashing.

Edit: Just tested it on the most recent branch (from spotify builds), happens there as well. I'm assuming what you are saying about the JavaScript GC is the problem. I am pretty sure that what I'm saying about the memory usage (it being less than 40 mb ram when it goes 'out of memory') is correct though. I will try this again with a 64 bit process and see how high the memory usage gets in a tight loop like this, and if it crashes at all.
Devyre
Techie
 
Posts: 27
Joined: Fri Nov 20, 2020 8:31 pm

Re: CEF JavaScript binding "require/import" question

Postby Devyre » Thu Jul 15, 2021 9:33 pm

I should have listened to you when you told me not to use extensions.
This issue is because of extensions, 100% confirmed.

I just added my NativeCall to the window object instead of registering an extension, and the exact same code, even the first one, now works perfectly fine.
It also seems to execute significantly faster than extensions.

Memory usage no longer increases to infinity, unless I use the first snippet (the tight while true loop).
But in that case, the JavaScript GC does its job and collects the garbage once I reach about 28MB ram.
Devyre
Techie
 
Posts: 27
Joined: Fri Nov 20, 2020 8:31 pm

Next

Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 37 guests