pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/creatifcoding/mega/blob/master/DENO_SMOKE_TEST.md

ref="https://github.githubassets.com/assets/global-b40ec823a1a6a1af.css" /> mega/DENO_SMOKE_TEST.md at master · creatifcoding/mega · GitHub
Skip to content

Latest commit

 

History

History
261 lines (217 loc) · 7.07 KB

File metadata and controls

261 lines (217 loc) · 7.07 KB

Deno TypeScript Smoke Test Implementation Plan

Goal

Demonstrate TypeScript object passing through the complete Emacs-ng ↔ Deno interface stack.

Test Case

// hello-world.ts
interface Greeting {
  message: string;
  timestamp: number;
  metadata: {
    language: string;
    version: string;
  };
}

const hello: Greeting = {
  message: "Hello from TypeScript!",
  timestamp: Date.now(),
  metadata: {
    language: "TypeScript",
    version: "5.0"
  }
};

hello;  // Return to Lisp

Expected Elisp Result

(eval-ts "const hello = {
  message: 'Hello from TypeScript!',
  timestamp: Date.now(),
  metadata: {language: 'TypeScript', version: '5.0'}
}; hello")

;; Expected return value:
;; ((message . "Hello from TypeScript!")
;;  (timestamp . 1733358000000)
;;  (metadata . ((language . "TypeScript")
;;               (version . "5.0"))))

Implementation Steps

Step 1: Build System Prerequisites

Current Blocker: emacs-sys build requires src/globals.h generated by make globals.h

Resolution Options:

  1. Fix lib/ build errors preventing globals.h generation
  2. Use pre-generated bindings from a working build
  3. Commit generated bindings to repository for CI/development

Command to generate:

cd /home/runner/work/mega/mega
./autogen.sh
./configure --with-gnutls=ifavailable --without-x --without-dbus
make lib
cd src && make globals.h

Step 2: Update javascript.rs for Deno 0.371

File: crates/js/src/javascript.rs

Key Changes Needed:

// OLD (commented out):
// use deno::program_state::ProgramState;
// let program_state = ProgramState::build(flags).await?;
// let worker = create_main_worker(&program_state, main_module, permissions);

// NEW (for Deno 0.371):
use deno_runtime::worker::{MainWorker, WorkerOptions};
use deno_runtime::permissions::PermissionsContainer;
use deno_core::ModuleSpecifier;
use std::rc::Rc;

// Create worker options
let module_loader = Rc::new(deno_runtime::module_loader::FsModuleLoader);
let options = WorkerOptions {
    module_loader,
    ..Default::default()
};

// Bootstrap worker
let main_module = ModuleSpecifier::parse("file://github.com/main.js")?;
let mut worker = MainWorker::bootstrap_from_options(
    main_module.clone(),
    options,
);

Function to Update: eval_ts()

#[lisp_fn]
pub fn eval_ts(code: LispStringRef) -> LispObject {
    let runtime = unsafe { MAIN_JS_RUNTIME.as_mut() };
    
    // Get or create worker
    let worker = runtime.deno_worker.get_or_insert_with(|| {
        initialize_deno_worker()
    });
    
    // Execute TypeScript code
    let code_str = code.to_utf8();
    let result = runtime.tokio_runtime
        .as_ref()
        .unwrap()
        .block_on(async {
            // Use execute_script for inline code
            worker.execute_script(
                "<eval>",
                deno_core::FastString::from(code_str.as_str())
            )
        });
    
    match result {
        Ok(value) => {
            // Convert v8 Value to LispObject
            js_value_to_lisp(value, worker)
        }
        Err(e) => {
            // Return error to Lisp
            error!("TypeScript eval error: {}", e);
            LispObject::from(Qnil)
        }
    }
}

Helper: Convert JS Object to Lisp

fn js_value_to_lisp(value: v8::Global<v8::Value>, worker: &mut MainWorker) -> LispObject {
    let scope = &mut worker.js_runtime.handle_scope();
    let local = v8::Local::new(scope, value);
    
    if local.is_object() {
        let obj = local.to_object(scope).unwrap();
        let obj_str = v8::json::stringify(scope, obj).unwrap();
        let json_str = obj_str.to_rust_string_lossy(scope);
        
        // Parse JSON and convert to Lisp alist
        match serde_json::from_str::<serde_json::Value>(&json_str) {
            Ok(json_val) => json_to_lisp(&json_val),
            Err(_) => LispObject::from(Qnil)
        }
    } else if local.is_string() {
        let s = local.to_string(scope).unwrap();
        let rust_str = s.to_rust_string_lossy(scope);
        LispObject::from(rust_str.as_str())
    } else if local.is_number() {
        let num = local.number_value(scope).unwrap();
        LispObject::from(num as i64)
    } else {
        LispObject::from(Qnil)
    }
}

fn json_to_lisp(json: &serde_json::Value) -> LispObject {
    match json {
        serde_json::Value::Object(map) => {
            // Create alist: ((key1 . val1) (key2 . val2) ...)
            let mut list = LispObject::from(Qnil);
            for (key, val) in map.iter().rev() {
                let key_obj = LispObject::from(key.as_str());
                let val_obj = json_to_lisp(val);
                let pair = LispCons::new(key_obj, val_obj);
                list = LispCons::new(pair.into(), list).into();
            }
            list
        }
        serde_json::Value::Array(arr) => {
            let mut list = LispObject::from(Qnil);
            for item in arr.iter().rev() {
                let item_obj = json_to_lisp(item);
                list = LispCons::new(item_obj, list).into();
            }
            list
        }
        serde_json::Value::String(s) => LispObject::from(s.as_str()),
        serde_json::Value::Number(n) => {
            if let Some(i) = n.as_i64() {
                LispObject::from(i)
            } else if let Some(f) = n.as_f64() {
                LispObject::from(f)
            } else {
                LispObject::from(Qnil)
            }
        }
        serde_json::Value::Bool(b) => {
            if *b { LispObject::from(Qt) } else { LispObject::from(Qnil) }
        }
        serde_json::Value::Null => LispObject::from(Qnil),
    }
}

Step 3: Test Execution

Once build system works:

# Build with JS feature
cd /home/runner/work/mega/mega
cargo build --features javascript

# Or build entire project
make

# Test from Emacs
./src/emacs -Q --eval "(progn
  (require 'js)
  (js-initialize)
  (message \"%s\" (eval-ts \"const hello = {
    message: 'Hello from TypeScript!',
    timestamp: Date.now(),
    metadata: {language: 'TypeScript', version: '5.0'}
  }; hello\"))
  (kill-emacs))"

Step 4: Validation

The smoke test passes if:

  1. ✅ TypeScript code compiles without errors
  2. ✅ Object is created in JS/TS
  3. ✅ Object is serialized through v8 → Rust
  4. ✅ Object is converted to Lisp alist structure
  5. ✅ Lisp receives structured data (not just string)

Success output:

((message . "Hello from TypeScript!") (timestamp . 1733358293847) (metadata (language . "TypeScript") (version . "5.0")))

Current Status

  • ✅ Dependencies: deno_core 0.371, deno_runtime 0.229 ready
  • ✅ Rust toolchain: nightly (1.93.0-nightly)
  • ✅ Code patterns documented above
  • ❌ Build system: Blocked on globals.h generation
  • ❌ Implementation: Waiting for working build

Next Actions

  1. Resolve build blocker - Generate globals.h or use pre-built bindings
  2. Apply code changes - Update javascript.rs per patterns above
  3. Build and test - Compile with --features javascript
  4. Validate smoke test - Run TypeScript hello world
  5. Document results - Confirm object passing works end-to-end
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy