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

destruction of context causes unbinds all the native modules from JsRuntime #364

Open
dream-1ab opened this issue Sep 22, 2024 · 4 comments

Comments

@dream-1ab
Copy link

dream-1ab commented Sep 22, 2024

what I want is create a single JsRuntime for my entire application, bind all the necessary native modules, and reuse this runtime on each JsContext, but the problem is that destruction of first JsContext will causes unbind all the native modules registered to JsRuntime so if I create a second JsContext with that JsRuntime I cannot access my native module binding unless rebind all the native modules to JsRuntime again before creating second JsContext.

is this correct behavior or I have misunderstanding to use JsRuntime, JsContext?
if yes what is the correct way to use native modules on single JsRuntime with multiple JsContext?

your native module example works fine because it only create only one JsContext and program will end after simple javascript execution, but if you create multiple JsContext in your example I assume it will not work in second JsContext unless you rebind all the native modules.

and I cannot access my class in javascript registered by rust side, it is can't be work at all, there is no example, nor documentation.

I mean is thank you for making this crate for us but you may face less github issue if you would spend few hours of time to make documentation and more example, I believe a lot of developers struggling the same issue as me.

thank you and have a nice day :)

@DelSkayn
Copy link
Owner

DelSkayn commented Oct 10, 2024

Modules are loaded within a Context not within a Runtime. The runtime only stores the method by which modules are loaded it doesn't store the context themselves. So when a context is dropped all the modules within it are also unloaded.

The runtime stores the GC, allocator and other stuff which is specific to the javascript engine functionality. The context stores all the javascript state.

If you want to reuse the modules you would need to reuse the context.

@dream-1ab
Copy link
Author

thank you for explaining, now that is a littie bit clear to me.
but if modules are loaded within a context how we can register native modules using JsRuntime.set_loader(resolver, loader) even JsContext is not created yet?

if modules are loaded within JsContext rather than JsRuntime why we don't register modules on JsContext? (e.g. my_js_context.set_loader(xxx, yyy) rather than my_js_runtime.set_loader(xxx, yyy))

here is my JsRuntime initialization code:

fn initialize_js_engine(&mut self) {
        let resolver = (
            BuiltinResolver::default()
                .with_module("designer")
                .with_module("designer/egui"),
            FileResolver::default()
                // .with_path("")
        );
        let designer_module_source = include_str!("../assets/js_modules/build/designer.js");
        let loader = (
            BuiltinLoader::default().with_module("designer", designer_module_source), //some js module
            ModuleLoader::default().with_module("designer/egui", MyEguiNativeModule {}), // and native module
            ScriptLoader::default(),
        );

        self.js_engine_runtime.set_loader(resolver, loader)
    }

this initialize_js_engine function only calling once during program startup, and this single JsRuntime instance shared to all the JsContext, this is my current approach (and I think this is the approach usually other developers does.), the problem is that if I drop firstly created JsContext then all the other contexts on same JsRuntime are unable to use the modules registered via JsRuntime.

so should I always re-register modules by calling js_engine_runtime.set_loader(resolver, loader) for each JsContext after they are created?

@DelSkayn
Copy link
Owner

Modules aren't registered in the runtime just the loading function. set_loader defines a loading function; a method by which modules can be loaded. This can be from a file but also, in the case of native modules, just a predefined module. When a context then needs to load a module it calls that loader function and uses it to create the module for that context.

I see that the provided loaders have a slightly strange behavior where they remove a module once it is loaded preventing it from being loaded again once a new context is created. This should probably be changed. In the mean time you can implement your own loader by implementing the Loader trait. You can look at the implementation of the existing BuiltinLoader and ModuleLoader to see how to do that.

@dream-1ab
Copy link
Author

Modules aren't registered in the runtime just the loading function. set_loader defines a loading function; a method by which modules can be loaded. This can be from a file but also, in the case of native modules, just a predefined module. When a context then needs to load a module it calls that loader function and uses it to create the module for that context.

I see that the provided loaders have a slightly strange behavior where they remove a module once it is loaded preventing it from being loaded again once a new context is created. This should probably be changed. In the mean time you can implement your own loader by implementing the Loader trait. You can look at the implementation of the existing BuiltinLoader and ModuleLoader to see how to do that.

Thank you sir, thnaks for your reply :)

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