From d92da39299e8eb5810b2274eab9ab10dae2cbbe3 Mon Sep 17 00:00:00 2001 From: John Doneth Date: Sun, 8 Mar 2020 13:54:57 -0400 Subject: [PATCH] Add print & REPL functionality to CLI (#267) * Add basic REPL functionality * Add utility function to Realm * Rework flow to allow files to be loaded as well as open a shell * Remove shell option (not needed now its the default) * Update README.md & docs/debugging.md --- README.md | 14 ++++++++++++++ boa/src/realm.rs | 14 ++++++++++++-- boa_cli/src/main.rs | 29 ++++++++++++++++++++--------- docs/debugging.md | 7 ++++--- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 13672cc6705..e39cba5da7d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,20 @@ see [CHANGELOG](./CHANGELOG.md) - Run with `cargo run -- test.js` where `test.js` is an existing JS file - If any JS doesn't work then it's a bug. Please raise an issue! +## Command-line Options + +``` +USAGE: + boa_cli [FILE]... + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +ARGS: + ... The JavaScript file(s) to be evaluated +``` + ## Communication Feel free to contact us on Discord https://discord.gg/tUFFk9Y diff --git a/boa/src/realm.rs b/boa/src/realm.rs index 6f9fba0c3e1..e3931ac6217 100644 --- a/boa/src/realm.rs +++ b/boa/src/realm.rs @@ -5,8 +5,10 @@ //!A realm is represented in this implementation as a Realm struct with the fields specified from the spec use crate::{ builtins::{ - array, boolean, console, function, json, math, number, object, regexp, string, symbol, - value::{Value, ValueData}, + array, boolean, console, function, + function::NativeFunctionData, + json, math, number, object, regexp, string, symbol, + value::{ToValue, Value, ValueData}, }, environment::{ declarative_environment_record::DeclarativeEnvironmentRecord, @@ -65,6 +67,14 @@ impl Realm { global.set_field_slice("Symbol", symbol::create_constructor(global)); global.set_field_slice("console", console::create_constructor(global)); } + + /// Utility to add a function to the global object + pub fn register_global_func(self, func_name: &str, func: NativeFunctionData) -> Self { + self.global_obj + .set_field(func_name.to_value(), func.to_value()); + + self + } } // Similar to new_global_environment in lexical_environment, except we need to return a GlobalEnvirionment diff --git a/boa_cli/src/main.rs b/boa_cli/src/main.rs index baa72094b66..32a4614d512 100644 --- a/boa_cli/src/main.rs +++ b/boa_cli/src/main.rs @@ -2,29 +2,27 @@ #![warn(clippy::perf)] #![allow(clippy::cognitive_complexity)] +use boa::builtins::console::log; use boa::{exec::Executor, forward_val, realm::Realm}; +use std::io; use std::{fs::read_to_string, path::PathBuf}; use structopt::StructOpt; - /// CLI configuration for Boa. #[derive(Debug, StructOpt)] #[structopt(author, about)] struct Opt { - /// The javascript file to be evaluated. - #[structopt(name = "FILE", parse(from_os_str), default_value = "tests/js/test.js")] + /// The JavaScript file(s) to be evaluated. + #[structopt(name = "FILE", parse(from_os_str))] files: Vec, - /// Open a boa shell (WIP). - #[structopt(short, long)] - shell: bool, } - pub fn main() -> Result<(), std::io::Error> { let args = Opt::from_args(); - let realm = Realm::create(); + let realm = Realm::create().register_global_func("print", log); + let mut engine = Executor::new(realm); - for file in args.files { + for file in &args.files { let buffer = read_to_string(file)?; match forward_val(&mut engine, &buffer) { @@ -33,5 +31,18 @@ pub fn main() -> Result<(), std::io::Error> { } } + if args.files.is_empty() { + loop { + let mut buffer = String::new(); + + io::stdin().read_line(&mut buffer)?; + + match forward_val(&mut engine, buffer.trim_end()) { + Ok(v) => println!("{}", v.to_string()), + Err(v) => eprintln!("{}", v.to_string()), + } + } + } + Ok(()) } diff --git a/docs/debugging.md b/docs/debugging.md index 0c5f5d5aaef..1bf9e43812a 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -1,9 +1,10 @@ # Debugging -There are multiple ways to debug what Boa is doing. Or maybe you just want to know how it works under the hood. Or even test some javaScript. +There are multiple ways to debug what Boa is doing. Or maybe you just want to know how it works under the hood. Or even test some JavaScript. -The first thing i usually do is add some JS [here](../tests/js/test.js). -This file will be read if no arguments are provided. Then boa will begin to parse and execute that JS. +One way to do so is to create a file in the root of the repository. For example `test.js`. Then execute `cargo run -- test.js` to run the file with boa. + +You can also run boa interactively by simply calling `cargo run` without any arguments to start a shell to execute JS. These are added in order of how the code is read: