1use ion::function::Opt;
8use ion::{Context, Error, Function, Object, Result, Value, function_spec, js_fn};
9use mozjs::jsapi::JSFunctionSpec;
10use runtime::module::NativeModule;
11
12fn assert_internal(message: Option<String>) -> Result<()> {
13 let error = match message {
14 Some(msg) => format!("Assertion Failed: {msg}"),
15 None => String::from("Assertion Failed"),
16 };
17 Err(Error::new(error, None))
18}
19
20#[js_fn]
21fn ok(Opt(assertion): Opt<bool>, Opt(message): Opt<String>) -> Result<()> {
22 if let Some(true) = assertion {
23 Ok(())
24 } else {
25 assert_internal(message)
26 }
27}
28
29#[js_fn]
30fn equals(cx: &Context, actual: Value, expected: Value, Opt(message): Opt<String>) -> Result<()> {
31 if actual.is_same(cx, &expected) {
32 Ok(())
33 } else {
34 assert_internal(message)
35 }
36}
37
38#[js_fn]
39fn throws(cx: &Context, func: Function, Opt(message): Opt<String>) -> Result<()> {
40 if func.call(cx, &Object::global(cx), &[]).is_err() {
41 assert_internal(message)
42 } else {
43 Ok(())
44 }
45}
46
47#[js_fn]
48fn fail(Opt(message): Opt<String>) -> Result<()> {
49 assert_internal(message)
50}
51
52const FUNCTIONS: &[JSFunctionSpec] = &[
53 function_spec!(ok, 0),
54 function_spec!(equals, 2),
55 function_spec!(throws, 1),
56 function_spec!(fail, 0),
57 JSFunctionSpec::ZERO,
58];
59
60pub struct Assert;
61
62impl<'cx> NativeModule<'cx> for Assert {
63 const NAME: &'static str = "assert";
64 const VARIABLE_NAME: &'static str = "assert";
65 const SOURCE: &'static str = include_str!("assert.js");
66
67 fn module(&self, cx: &'cx Context) -> Option<Object<'cx>> {
68 let assert = Object::new(cx);
69 unsafe { assert.define_methods(cx, FUNCTIONS).then_some(assert) }
70 }
71}