Skip to content

Commit

Permalink
Added boa examples
Browse files Browse the repository at this point in the history
Added boa examples as per issue #446
  • Loading branch information
elasmojs authored and jasonwilliams committed Mar 7, 2021
1 parent 835acc9 commit 8f81f20
Show file tree
Hide file tree
Showing 12 changed files with 281 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"boa_wasm",
"boa_tester",
"boa_unicode",
"boa_examples"
]

# The release profile, used for `cargo build --release`.
Expand Down
10 changes: 10 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "boa-examples"
version = "0.1.0"
authors = ["elasmojs <66966290+elasmojs@users.noreply.github.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Boa = { path = "../boa", features = ["serde"] }
14 changes: 14 additions & 0 deletions examples/scripts/calc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
add: function(a, b){
return a + b;
},
subtract: function(a, b){
return a - b;
},
multiply: function(a, b){
return a * b;
},
divide: function(a, b){
return a/b;
}
}
9 changes: 9 additions & 0 deletions examples/scripts/calctest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

//load module
let calc = require('./scripts/calc.js');

console.log('Using calc module');
console.log('Add: ' + calc.add(3, 3));
console.log('Subtract: ' + calc.subtract(3, 3));
console.log('Multiply: ' + calc.multiply(3, 3));
console.log('Divide: ' + calc.divide(3, 3));
11 changes: 11 additions & 0 deletions examples/scripts/enhancedglobal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//access custom global variable
console.log("Custom global: " + customstring);

//call a custom global function with arguments
console.log("Custom function: " + rusty_hello("Boa! Boa!"));

//access a custom global object and call a member function of that object
let a = 5;
let b = 5;
let result = rusty_obj.add(a, b);
console.log("Custom object: Result from rusty_obj.add() : " + result);
1 change: 1 addition & 0 deletions examples/scripts/helloworld.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Hello World from JS file!");
59 changes: 59 additions & 0 deletions examples/src/enhancedglobal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::{fs::read_to_string};

use boa::{
exec::Interpreter,
forward,
realm::Realm,
builtins::value::Value,
builtins::value::ResultValue,
builtins::function::Function
};

pub fn run(){
let js_file_path = "./scripts/enhancedglobal.js";
let buffer = read_to_string(js_file_path);

if buffer.is_err(){
println!("Error: {}", buffer.unwrap_err());
return;
}

//Creating the execution context
let ctx = Realm::create();

//Adding a custom global variable
ctx.global_obj.set_field("customstring", "Hello! I am a custom global variable");

//Adding a custom global function
let rfn = Function::builtin(Vec::new(), rusty_hello);
ctx.global_obj.set_field("rusty_hello", Value::from_func(rfn));

//Adding s custom object
let gobj = Value::new_object(Some(&ctx.global_obj));
let addfn = Function::builtin(Vec::new(), add);
gobj.set_field("add", Value::from_func(addfn));
ctx.global_obj.set_field("rusty_obj", gobj);

//Instantiating the engien with the execution context
let mut engine = Interpreter::new(ctx);

//Loading, parsing and executing the JS code from the source file
let error_string = forward(&mut engine, &buffer.unwrap());
if error_string != "undefined"{
println!("Error parsing script: {}", error_string);
}
}

//Custom function callable from JS
fn rusty_hello(_:&Value, args:&[Value], _:&mut Interpreter) -> ResultValue{
let arg = args.get(0).unwrap();
let val = format!("Hello from Rust! You passed {}", arg);
return ResultValue::from(Ok(Value::from(val)));
}

//Function appended as property of a custom global object, callable from JS
fn add(_:&Value, args:&[Value], _engine:&mut Interpreter) -> ResultValue{
let arg0 = args.get(0).unwrap();
let arg1 = args.get(1).unwrap();
return ResultValue::from(Ok(Value::from(arg0.to_integer() + arg1.to_integer())));
}
29 changes: 29 additions & 0 deletions examples/src/loadfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::{fs::read_to_string};

use boa::{
exec::Interpreter,
forward,
realm::Realm
};

pub fn run(){
let js_file_path = "./scripts/helloworld.js";
let buffer = read_to_string(js_file_path);

if buffer.is_err(){
println!("Error: {}", buffer.unwrap_err());
return;
}

//Create the execution context
let ctx = Realm::create();

//Instantiate the engien with the execution context
let mut engine = Interpreter::new(ctx);

//Load, parse and execute the JS code read from the source file
let error_string = forward(&mut engine, &buffer.unwrap());
if error_string != "undefined"{
println!("Error parsing script: {}", error_string);
}
}
21 changes: 21 additions & 0 deletions examples/src/loadstring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use boa::{
exec::Interpreter,
forward,
realm::Realm
};

pub fn run(){
let js_code = "console.log('Hello World from a JS code string!')";

//Create the execution context
let ctx = Realm::create();

//Instantiate the engien with the execution context
let mut engine = Interpreter::new(ctx);

//Load, parse and execute the given JS String
let error_string = forward(&mut engine, js_code);
if error_string != "undefined"{
println!("Error parsing script: {}", error_string);
}
}
29 changes: 29 additions & 0 deletions examples/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mod loadstring;
mod loadfile;
mod returnval;
mod enhancedglobal;
mod modulehandler;

fn main() {
println!("\r\n");

//example that loads, parses and executs a JS code string
loadstring::run();
println!("\r\n");

//example that loads, parses and executs JS code from a source file (./scripts/helloworld.js)
loadfile::run();
println!("\r\n");

//example that loads, parses and executs JS code and uses the return value
returnval::run();
println!("\r\n");

//example that enhances the global object with custom values, objects, functions
enhancedglobal::run();
println!("\r\n");

//example that implements a custom module handler which mimics (require / module.exports) pattern
modulehandler::run();
println!("\r\n");
}
65 changes: 65 additions & 0 deletions examples/src/modulehandler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::fs::read_to_string;

use boa::{
exec::Interpreter,
forward,
realm::Realm,
builtins::value::Value,
builtins::value::ResultValue,
builtins::function::Function
};

pub fn run(){
let js_file_path = "./scripts/calctest.js";
let buffer = read_to_string(js_file_path);

if buffer.is_err(){
println!("Error: {}", buffer.unwrap_err());
return;
}

//Creating the execution context
let ctx = Realm::create();

//Adding custom implementation that mimics 'require'
let requirefn = Function::builtin(Vec::new(), require);
ctx.global_obj.set_field("require", Value::from_func(requirefn));

//Addming custom object that mimics 'module.exports'
let moduleobj = Value::new_object(Some(&ctx.global_obj));
moduleobj.set_field("exports", Value::from(" "));
ctx.global_obj.set_field("module", moduleobj);

//Instantiating the engien with the execution context
let mut engine = Interpreter::new(ctx);

//Loading, parsing and executing the JS code from the source file
let error_string = forward(&mut engine, &buffer.unwrap());
if error_string != "undefined"{
println!("Error parsing script: {}", error_string);
}
}

//Custom implementation that mimics 'require' module loader
fn require(_:&Value, args:&[Value], engine:&mut Interpreter) -> ResultValue{
let arg = args.get(0).unwrap();

//BUG: Dev branch seems to be passing string arguments along with quotes
let libfile = arg.to_string().replace("\"", "");

//Read the module source file
println!("Loading: {}", libfile);
let buffer = read_to_string(libfile);
if buffer.is_err(){
println!("Error: {}", buffer.unwrap_err());
return ResultValue::from(Ok(Value::from(-1)));
}else{
//Load and parse the module source
forward(engine, &buffer.unwrap());

//Access module.exports and return as ResultValue
let module_exports = engine.realm.global_obj.get_field("module").get_field("exports");
let return_value = ResultValue::from(Ok(Value::from(module_exports)));
return return_value;
}
}
32 changes: 32 additions & 0 deletions examples/src/returnval.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use boa::{
exec::Interpreter,
forward_val,
realm::Realm
};

pub fn run(){
let js_string = r"
function add(a, b){
return a + b;
}
let a = 3;
let b = 3;
add(a,b);
";

//Create the execution context
let ctx = Realm::create();

//Instantiate the engien with the execution context
let mut engine = Interpreter::new(ctx);

//Load, parse, execute the given JS String and returns the result of the execution as a Boa Value
match forward_val(&mut engine, js_string){
Ok(v) => {
println!("Script returned: {}", v);
},
Err(e) =>{
println!("Script error: {}", e);
}
}
}

0 comments on commit 8f81f20

Please sign in to comment.