Skip to content

Commit

Permalink
Merge 4a52565 into 0dcf182
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwilliams authored May 22, 2021
2 parents 0dcf182 + 4a52565 commit 6cfef13
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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
12 changes: 12 additions & 0 deletions boa_examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "boa_examples"
version = "0.11.0"
authors = ["boa-dev"]
repository = "https://github.com/boa-dev/boa"
license = "Unlicense/MIT"
edition = "2018"

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

[dependencies]
Boa = { path = "../boa" }
14 changes: 14 additions & 0 deletions boa_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;
},
};
8 changes: 8 additions & 0 deletions boa_examples/scripts/calctest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//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 boa_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 boa_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 boa_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())));
}
38 changes: 38 additions & 0 deletions boa_examples/src/loadfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::fs::read_to_string;

use boa::{exec::Executable, parse, Context};

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

match read_to_string(js_file_path) {
Ok(src) => {
// Instantiate the execution context
let mut context = Context::new();

// Parse the source code
let expr = match parse(src, false) {
Ok(res) => res,
Err(e) => {
// Pretty print the error
eprintln!(
"Uncaught {}",
context
.throw_syntax_error(e.to_string())
.expect_err("interpreter.throw_syntax_error() did not return an error")
.display()
);

return;
}
};

// Execute the JS code read from the source file
match expr.run(&mut context) {
Ok(v) => println!("{}", v.display()),
Err(e) => eprintln!("Uncaught {}", e.display()),
}
}
Err(msg) => eprintln!("Error: {}", msg),
}
}
31 changes: 31 additions & 0 deletions boa_examples/src/loadstring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use boa::{exec::Executable, parse, Context};

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

// Instantiate the execution context
let mut context = Context::new();

// Parse the source code
let expr = match parse(js_code, false) {
Ok(res) => res,
Err(e) => {
// Pretty print the error
eprintln!(
"Uncaught {}",
context
.throw_syntax_error(e.to_string())
.expect_err("interpreter.throw_syntax_error() did not return an error")
.display()
);

return;
}
};

// Execute the JS code read from the source file
match expr.run(&mut context) {
Ok(v) => println!("{}", v.display()),
Err(e) => eprintln!("Uncaught {}", e.display()),
}
}
29 changes: 29 additions & 0 deletions boa_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");
}
66 changes: 66 additions & 0 deletions boa_examples/src/modulehandler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::fs::read_to_string;

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

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 engine 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;
}
}

0 comments on commit 6cfef13

Please sign in to comment.