RuneR
Denoβ€’2y agoβ€’
2 replies
Rune

Parsing Typescript with deno_core and deno_ast fails on type annotations

Hey all, i'm trying to embed deno into my app so that users can write config file in typescript.

I got inspired by the "Roll your own JavaScript runtime" blog series, but they seem to be a bit outdated... The examples in the
deno_core
repo
are not perfect either.

I'm trying to write the following code:
((globalThis) => {
    globalThis.Math = {
        sum: (numbers: number[]): number => Deno.core.ops.op_sum(numbers),
        min: (numbers: number[]): number => Deno.core.ops.op_min(numbers)
    }
})(globalThis);


When running this as javascript, without type annotations, it works just fine.
However, when i try to add the ts loader from the example (with some slight modifications), it errors on the type annotations:
called `Result::unwrap()` on an `Err` value: Uncaught SyntaxError: Unexpected token ':'
    at [runjs:runtime.ts]:3:22


These are my dependencies:
deno_core = { version = "0.291", features = ["include_icu_data"] }
deno_ast = { version = "0.39", features = ["emit", "transpiling", "sourcemap", "typescript", "transforms", "compat"] }
anyhow = "1"


This is my main file
mod ts_loader;

use deno_core::error::AnyError;
use deno_core::*;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

const RUNTIME_SETUP: &str = include_str!("runtime.ts");
const EXAMPLE_SCRIPT: &str = include_str!("../example.ts");

#[op2]
fn op_sum(#[serde] nums: Vec<f64>) -> Result<f64, AnyError> {
    // Sum inputs
    let sum = nums.iter().fold(0.0, |a, v| a + v);
    // return as a Result<f64, AnyError>
    Ok(sum)
}

#[op2]
fn op_min(#[serde] nums: Vec<f64>) -> Result<f64, AnyError> {
    // Sum inputs
    let sum = nums.iter().min_by(|a, b| a.total_cmp(b));
    match sum {
        Some(x) => Ok(*x),
        None => Ok(f64::NAN),
    }
}

async fn run_js(script: String) -> Result<(), AnyError> {
    const SUM_EXT: OpDecl = op_sum();
    let sum_ext = Extension {
        name: "sum_ext",
        ops: std::borrow::Cow::Borrowed(&[SUM_EXT]),
        ..Default::default()
    };

    const MIN_EXT: OpDecl = op_min();
    let min_ext = Extension {
        name: "min_ext",
        ops: std::borrow::Cow::Borrowed(&[MIN_EXT]),
        ..Default::default()
    };

    let source_map_store = ts_loader::SourceMapStore(Rc::new(RefCell::new(HashMap::new())));

    // Initialize a runtime instance
    let mut runtime = JsRuntime::new(RuntimeOptions {
        extensions: vec![sum_ext, min_ext],
        module_loader: Some(Rc::new(ts_loader::TypescriptModuleLoader {
            source_maps: source_map_store.clone(),
        })),
        source_map_getter: Some(Rc::new(source_map_store)),
        ..Default::default()
    });

    runtime
        .execute_script("[runjs:runtime.ts]", RUNTIME_SETUP)
        .unwrap();
    runtime
        .execute_script("[evaluate_manifest]", script)
        .unwrap();

    Ok(())
}

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

    #[tokio::test]
    async fn it_works() {
        match run_js(EXAMPLE_SCRIPT.to_string()).await {
            Ok(_) => assert!(true),
            Err(reason) => assert!(false, "{}", reason),
        }
    }
}


The loader:
Was this page helpful?