From 58bc43cc72961fb5a26c1d3750aee6c50d067ced Mon Sep 17 00:00:00 2001 From: jhwgh1968 Date: Fri, 21 Feb 2020 19:20:12 -0600 Subject: [PATCH] Add crate docstring and two examples --- Cargo.toml | 5 ++++ examples/eval.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++ examples/minimal.rs | 52 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 17 +++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 examples/eval.rs create mode 100644 examples/minimal.rs diff --git a/Cargo.toml b/Cargo.toml index 4c448c448..e99d90f45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,11 @@ license = "MPL-2.0" [build-dependencies] cc = "1" +[[example]] +name = "minimal" +[[example]] +name = "eval" + [[test]] name = "callback" [[test]] diff --git a/examples/eval.rs b/examples/eval.rs new file mode 100644 index 000000000..b94ab113c --- /dev/null +++ b/examples/eval.rs @@ -0,0 +1,62 @@ +#![allow( + non_upper_case_globals, + non_camel_case_types, + non_snake_case, + improper_ctypes +)] + +//! # Running scripts +//! Here is the code under "Running scripts" in the MDN User Guide[1] translated into Rust. This +//! only shows the ``run()`` function's contents because the original does as well. +//! +//! The actual code that is run is designed to be testable, unlike the example given. +//! [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_User_Guide +//! + +use std::ptr; + +#[macro_use] +extern crate mozjs; +use mozjs::jsapi::*; +use mozjs::jsval::UndefinedValue; +use mozjs::rust::SIMPLE_GLOBAL_CLASS; +use mozjs::rust::{JSEngine, RealmOptions, Runtime}; + +fn run(rt: Runtime) { + let options = RealmOptions::default(); + rooted!(in(rt.cx()) let global = unsafe { + JS_NewGlobalObject(rt.cx(), &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &*options) + }); + + /* These should indicate source location for diagnostics. */ + let filename: &'static str = "inline.js"; + let lineno: u32 = 1; + + /* + * The return value comes back here. If it could be a GC thing, you must add it to the + * GC's "root set" with the rooted! macro. + */ + rooted!(in(rt.cx()) let mut rval = UndefinedValue()); + + /* + * Some example source in a string. This is equivalent to JS_EvaluateScript in C++. + */ + let source: &'static str = "40 + 2"; + + let res = rt.evaluate_script(global.handle(), source, filename, lineno, rval.handle_mut()); + + if res.is_ok() { + /* Should get a number back from the example source. */ + assert!(rval.get().is_int32()); + assert_eq!(rval.get().to_int32(), 42); + } +} + +fn main() { + let engine = JSEngine::init().expect("failed to initalize JS engine"); + let runtime = Runtime::new(engine.handle()); + assert!(!runtime.cx().is_null(), "failed to create JSContext"); + run(runtime); +} diff --git a/examples/minimal.rs b/examples/minimal.rs new file mode 100644 index 000000000..2d5284b46 --- /dev/null +++ b/examples/minimal.rs @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#![allow( + non_upper_case_globals, + non_camel_case_types, + non_snake_case, + improper_ctypes +)] + +//! # A minimal example +//! Here is the code under "A minimal example" in the MDN User Guide[1] translated into Rust. +//! [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_User_Guide + +use std::ptr; + +#[macro_use] +extern crate mozjs; +use mozjs::rust::SIMPLE_GLOBAL_CLASS; +use mozjs::{jsapi::*, rust::JSEngine, rust::RealmOptions, rust::Runtime}; + +fn main() { + // Initialize the JS engine. This handle must be kept alive in order to create new Runtimes. + let engine = JSEngine::init().expect("failed to initalize JS engine"); + + // Create a Runtime -- wraps a JSContext in the C++ API. + let runtime = Runtime::new(engine.handle()); + assert!(!runtime.cx().is_null(), "failed to create JSContext"); + + run(runtime); + + // There is no need for the shut down block in the C++, because rust destructors and Arc + // reference counts will clean up everything. +} + +fn run(rt: Runtime) { + let cx = rt.cx(); + // In addition to what the C++ interface requires, define a global scope for the code. + // + // This demonstrates the way Rust uses the C++ garbage collector: using the rooted! macro to + // indicate when the GC can collect them. + let options = RealmOptions::default(); + rooted!(in(cx) let _global = unsafe { + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &*options) + }); + + // Your application code here. This may include JSAPI calls to create your + // own custom JS objects and run scripts. +} diff --git a/src/lib.rs b/src/lib.rs index 9d6b010a4..f4fc5a3d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,23 @@ #![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, improper_ctypes)] +//! +//! This crate contains Rust bindings to the [SpiderMonkey Javascript engine][1] +//! developed by Mozilla. +//! +//! These bindings are designed to be a fairly straightforward translation to the C++ API, while +//! taking advantage of Rust's memory safety. For more about the Spidermonkey API, see the +//! [API Reference][2] and the [User Guide][3] on MDN, and the [embedding examples][4] on GitHub. +//! +//! The code from User Guide sections [A minimal example](../../../examples/minimal.rs) and +//! [Running scripts](../../../examples/eval.rs) are also included. +//! +//! [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey +//! [2]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference +//! [3]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_User_Guide +//! [4]: https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples/ +//! + #[macro_use] extern crate lazy_static; extern crate libc;