How to return string from JS?
Closed this issue · 2 comments
caracal7 commented
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
- If you import
js::rust::wrappers::JS_EncodeStringToUtf8
instead ofjs::jsapi::JS_EncodeStringToUtf8
, that should address the first error. - to get a string from a JSVal, use the FromJSValConvertible implementation, String::from_jsval: https://github.com/servo/rust-mozjs/blob/master/src/conversions.rs#L494
caracal7 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);
}
}