servo/rust-mozjs

How to return string from JS?

Closed this issue · 2 comments

This makes me crazy((
All examples seems outdated and tests also didn't contain anything about strings...

Most closest way that I found is

#[macro_use]
extern crate mozjs;


use mozjs::jsapi::{ JS_NewGlobalObject, JS_EncodeStringToUTF8 };
use mozjs::jsapi::OnNewGlobalHookOption;
use mozjs::jsval::UndefinedValue;
use mozjs::rust::{ JSEngine, RealmOptions, Runtime, ToString, SIMPLE_GLOBAL_CLASS};

use std::ptr;
use std::ffi::CStr;
use std::str;



fn main() {
    println!("Hello, moz-js!");

    let engine = JSEngine::init().unwrap();
    let runtime = Runtime::new(engine);
    let context = runtime.cx();



    unsafe {
        let options = RealmOptions::default();
        let global = JS_NewGlobalObject(context, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
                               OnNewGlobalHookOption::FireOnNewGlobalHook,
                               &*options);
        rooted!(in(context) let global_root = global);
        let global = global_root.handle();  

        rooted!(in(context) let mut rval = UndefinedValue());
        let result = runtime.evaluate_script(global, "1 + 1", "test.js", 0, rval.handle_mut());


        rooted!(in(context) let str = unsafe {
            let str = ToString(context, rval.handle());
            assert!(!str.is_null(), "Error converting value to string.");
            str
        });

        let slice = unsafe {
            let bytes = JS_EncodeStringToUTF8(context, str.handle());
            assert!(!str.is_null(), "Error encoding string to UTF8.");
            CStr::from_ptr(bytes)
        };

        println!("result: {}", slice);
    }

}

but I've got errors😑

error[E0308]: mismatched types
  --> src/main.rs:44:56
   |
44 |             let bytes = JS_EncodeStringToUTF8(context, str.handle());
   |                                                        ^^^^^^^^^^^^ expected struct `mozjs::jsapi::Handle`, found struct `mozjs::rust::Handle`
   |
   = note: expected type `mozjs::jsapi::Handle<*mut mozjs::jsapi::JSString>`
              found type `mozjs::rust::Handle<'_, *mut mozjs::jsapi::JSString>`

error[E0308]: mismatched types
  --> src/main.rs:46:28
   |
46 |             CStr::from_ptr(bytes)
   |                            ^^^^^ expected *-ptr, found u64
   |
   = note: expected type `*const i8`
              found type `u64`

error[E0277]: `std::ffi::CStr` doesn't implement `std::fmt::Display`
  --> src/main.rs:49:32
   |
49 |         println!("result: {}", slice);
   |                                ^^^^^ `std::ffi::CStr` cannot be formatted with the default formatter

jdm commented

Thanks a lot.

Working snippet (without error handling)

#[macro_use]
extern crate mozjs;

use mozjs::conversions::ConversionResult;
use mozjs::conversions::FromJSValConvertible;
use mozjs::jsapi::{ JS_NewGlobalObject };
use mozjs::jsapi::OnNewGlobalHookOption;
use mozjs::jsval::UndefinedValue;
use mozjs::rust::{ JSEngine, RealmOptions, Runtime, SIMPLE_GLOBAL_CLASS};

use std::ptr;

fn main() {
    println!("Hello, moz-js!");

    let engine = JSEngine::init().unwrap();
    let runtime = Runtime::new(engine);
    let context = runtime.cx();

    unsafe {
        let options = RealmOptions::default();
        let global = JS_NewGlobalObject(context, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
                               OnNewGlobalHookOption::FireOnNewGlobalHook,
                               &*options);
        rooted!(in(context) let global_root = global);
        let global = global_root.handle();  

        rooted!(in(context) let mut rval = UndefinedValue());
        let _ = runtime.evaluate_script(global, "1 + 1", "test.js", 0, rval.handle_mut());

        let s = match String::from_jsval(context, rval.handle(), ()) {
            Ok(ConversionResult::Success(v)) => v,
            _ => String::from(""),
        };
        println!("SpiderMonkey says: {}", s);
    }
}