ion/
script.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use 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	/// Compiles a script with a given filename and returns the compiled script.
21	/// Returns [Err] when script compilation fails.
22	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	/// Evaluates a script and returns its return value.
37	/// Returns [Err] when an exception occurs during script evaluation.
38	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	/// Compiles and evaluates a script with a given filename, and returns its return value.
49	/// Returns [Err] when script compilation fails or an exception occurs during script evaluation.
50	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}