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

Missing doc - how to use deno dependencies when running runtime from Rust? #27881

Open
renardeinside opened this issue Jan 30, 2025 · 3 comments
Labels
embedder Embedders using deno crates to build their own runtime rather than using Deno itself

Comments

@renardeinside
Copy link

renardeinside commented Jan 30, 2025

Assuming I have a project like so:

.
├── Cargo.lock
├── Cargo.toml
├── deno.json
├── deno.lock
├── example.js
└── src
    └── lib.rs

Where I've installed deno deps in deno.json:

{
  "imports": {
    "svelte": "npm:svelte@^5.19.5"
  }
}

And I have an example JS file:

console.log("Hello deno");
import {compile} from "svelte/compiler";

I'm running JS within Rust in a function closely copied from this example:

use std::rc::Rc;

use deno_runtime::deno_core::{self, error::CoreError};

#[allow(dead_code)]
async fn run_js(file_path: &str) -> Result<(), CoreError> {
    let main_module = deno_core::resolve_path(file_path, &std::env::current_dir()?).unwrap();

    let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
        module_loader: Some(Rc::new(deno_core::FsModuleLoader)),
        ..Default::default()
    });

    let mod_id = js_runtime.load_main_es_module(&main_module).await?;
    let result = js_runtime.mod_evaluate(mod_id);
    js_runtime.run_event_loop(Default::default()).await?;
    result.await
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn it_works() {
        let result = run_js("./example.js").await;
        // explicitly log the error and raise it
        if let Err(e) = result {
            eprintln!("{}", e);
            panic!("Error running JS");
        }
    }
}

And it cannot resolve the import, throwing unresolved:

Relative import path "svelte/compiler" not prefixed with / or ./ or ../ from "file:///Users/renarde/projects/schorle-lib/example.js"

How can I "point" deno to use its dependencies when running from Rust?

@marvinhagemeister marvinhagemeister added the embedder Embedders using deno crates to build their own runtime rather than using Deno itself label Jan 30, 2025
@renardeinside
Copy link
Author

My second try was to use the MainWorker with 0.196.0:

use std::rc::Rc;
use std::sync::Arc;

use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::npm::NpmResolver;

use deno_runtime::deno_core::url::Url;
use deno_runtime::deno_core::FsModuleLoader;
use deno_runtime::deno_fs::RealFs;


use deno_runtime::worker::MainWorker;
use deno_runtime::worker::WorkerOptions;
use deno_runtime::worker::WorkerServiceOptions;

use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::permissions::RuntimePermissionDescriptorParser;

pub fn prepare_worker(main_module: &Url) -> MainWorker {
    let fs = Arc::new(RealFs);
    let permission_desc_parser = Arc::new(RuntimePermissionDescriptorParser::new(
        sys_traits::impls::RealSys,
    ));
    let permissions = PermissionsContainer::allow_all(permission_desc_parser);

    let service_options = WorkerServiceOptions::<
        DenoInNpmPackageChecker,
        NpmResolver<sys_traits::impls::RealSys>,
        sys_traits::impls::RealSys,
    > {
        module_loader: Rc::new(FsModuleLoader),
        permissions: permissions,
        blob_store: Default::default(),
        broadcast_channel: Default::default(),
        feature_checker: Default::default(),
        node_services: Default::default(),
        npm_process_state_provider: Default::default(),
        root_cert_store_provider: Default::default(),
        fetch_dns_resolver: Default::default(),
        shared_array_buffer_store: Default::default(),
        compiled_wasm_module_store: Default::default(),
        v8_code_cache: Default::default(),
        fs,
    };

    let options = WorkerOptions {
        enable_stack_trace_arg_in_ops: true,
        ..Default::default()
    };

    return MainWorker::bootstrap_from_options(main_module, service_options, options);
}

#[cfg(test)]
mod tests {

    use deno_runtime::deno_core::resolve_path;

    use super::*;

    #[tokio::test]
    async fn it_works() {
        let current_dir = std::env::current_dir().unwrap();
        let main_module = resolve_path("./example.js", &current_dir);

        let main_module = match main_module {
            Ok(module) => module,
            Err(err) => {
                eprintln!("Error resolving main module path: {}", err);
                return;
            }
        };

        let mut prepared_worker = prepare_worker(&main_module);

        if let Err(e) = prepared_worker.execute_main_module(&main_module).await {
            eprintln!("Error executing main module: {}", e);
            return;
        }

        if let Err(e) = prepared_worker.run_event_loop(false).await {
            eprintln!("Error running event loop: {}", e);
            return;
        }
    }
}

Project structure:

.
├── Cargo.lock
├── Cargo.toml
├── deno.json
├── deno.lock
├── example.js
└── src
    └── lib.rs

Still fails though:

Error executing main module: Relative import path "svelte/compiler" not prefixed with / or ./ or ../ from "file:///Users/renarde/projects/schorle-lib/example.js"

@bartlomieju
Copy link
Member

Using deno_runtime is not enough. Executing code from npm or JSR is quite involved and requires most of the machinery available in deno_lib crate. There's no example of embedding a project like this right now.

@renardeinside
Copy link
Author

Hey @bartlomieju ,
Thanks for your reply.

This is for sure sad, but I'll try. Do I get it correctly that LibMainWorker in deno_lib is the closest to what I'm looking for?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
embedder Embedders using deno crates to build their own runtime rather than using Deno itself
Projects
None yet
Development

No branches or pull requests

3 participants