servo / rust-mozjs

DEPRECATED - moved to servo/mozjs instead.
Mozilla Public License 2.0
293 stars 122 forks source link

How to return string from JS? #473

Closed caracal7 closed 5 years ago

caracal7 commented 5 years ago

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 5 years ago
caracal7 commented 5 years ago

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);
    }
}