1use std::path::Path;
8
9use mozjs::jsapi::{Compile, JS_ExecuteScript, JSScript};
10use mozjs::rust::{CompileOptionsWrapper, transform_u16_to_source_text};
11
12use crate::{Context, ErrorReport, Local, Value};
13
14#[derive(Debug)]
15pub struct Script<'cx> {
16 script: Local<'cx, *mut JSScript>,
17}
18
19impl Script<'_> {
20 pub fn compile<'cx>(cx: &'cx Context, path: &Path, script: &str) -> Result<Script<'cx>, ErrorReport> {
23 let script: Vec<u16> = script.encode_utf16().collect();
24 let mut source = transform_u16_to_source_text(script.as_slice());
25 let options = unsafe { CompileOptionsWrapper::new(cx.as_ptr(), path.to_str().unwrap(), 1) };
26
27 let script = unsafe { Compile(cx.as_ptr(), options.ptr, &raw mut source) };
28
29 if !script.is_null() {
30 Ok(Script { script: cx.root(script) })
31 } else {
32 Err(ErrorReport::new_with_exception_stack(cx)?.unwrap())
33 }
34 }
35
36 pub fn evaluate<'cx>(&self, cx: &'cx Context) -> Result<Value<'cx>, ErrorReport> {
39 let mut rval = Value::undefined(cx);
40
41 if unsafe { JS_ExecuteScript(cx.as_ptr(), self.script.handle().into(), rval.handle_mut().into()) } {
42 Ok(rval)
43 } else {
44 Err(ErrorReport::new_with_exception_stack(cx)?.unwrap())
45 }
46 }
47
48 pub fn compile_and_evaluate<'cx>(cx: &'cx Context, path: &Path, script: &str) -> Result<Value<'cx>, ErrorReport> {
51 match Script::compile(cx, path, script) {
52 Ok(s) => s.evaluate(cx),
53 Err(e) => Err(e),
54 }
55 }
56}
57
58impl<'s> From<Local<'s, *mut JSScript>> for Script<'s> {
59 fn from(script: Local<'s, *mut JSScript>) -> Script<'s> {
60 Script { script }
61 }
62}