Skip to content

Commit f7dc8cd

Browse files
committed
Added Custom Array and Object Formatters
Improved IonObject;:keys to return keys as strings Added globals and microtask queue to eval subcommand Fixed underflow on u16 when counting brackets in REPL Replaced termcolor with colored Added .gitattributes
1 parent fc92938 commit f7dc8cd

File tree

25 files changed

+473
-192
lines changed

25 files changed

+473
-192
lines changed

.gitattributes

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
* text=auto eol=lf
2+
3+
*.rs text
4+
*.js text
5+
*.ts text
6+
*.js.flow text
7+
*.md text
8+
9+
*.toml text
10+
*.yml text
11+
12+
*.editorconfig text
13+
*.gitattributes text
14+
*.gitignore text
15+
16+
Cargo.lock text
17+
18+
*.bat text eol=crlf
19+
*.cmd text eol=crlf
20+
*.ps1 text eol=crlf
21+
*.sh text
22+
23+
*.gif binary
24+
*.ico binary
25+
*.png binary
26+
*.jpg binary
27+
*.jpeg binary
28+
*.svg text

Cargo.lock

Lines changed: 13 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ authors = ["Redfire <redfire75369@hotmail.com>"]
66
license = "MPL-2.0"
77

88
[dependencies]
9+
colored = "2.0.0"
910
structopt = "0.3.25"
1011
ion = { path = "../ion" }
1112
modules = { path = "../modules" }

cli/src/commands/eval.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
55
*/
66

7-
use runtime::globals::new_global;
7+
use runtime::globals::{init_globals, new_global};
8+
use runtime::microtask_queue::init_microtask_queue;
89
use runtime::new_runtime;
910

1011
use crate::evaluate::eval_inline;
1112

1213
pub fn eval_source(source: &str) {
1314
let (_engine, rt) = new_runtime();
14-
let (_global, _ac) = new_global(rt.cx());
15+
let (global, _ac) = new_global(rt.cx());
16+
17+
init_globals(rt.cx(), global);
18+
init_microtask_queue(rt.cx());
1519

1620
eval_inline(&rt, source);
1721
}

cli/src/commands/repl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn start_repl() {
2727
loop {
2828
let mut input = String::new();
2929
let mut lines = 0;
30-
let mut multiline: (u16, u16, u16) = (0, 0, 0); // (), [], {}
30+
let mut multiline: (i16, i16, i16) = (0, 0, 0); // (), [], {}
3131
loop {
3232
let mut line = String::new();
3333

cli/src/evaluate.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ use std::path::Path;
99

1010
use mozjs::rust::Runtime;
1111

12+
use ion::format::config::Config;
13+
use ion::format::format_value;
1214
use ion::script::IonScript;
13-
use ion::types::string::to_string;
1415
use modules::init_modules;
1516
use runtime::globals::{init_globals, new_global};
1617
use runtime::microtask_queue::init_microtask_queue;
@@ -19,7 +20,7 @@ use runtime::new_runtime;
1920

2021
pub fn eval_inline(rt: &Runtime, source: &str) {
2122
match IonScript::compile_and_evaluate(rt.cx(), "inline.js", source) {
22-
Ok(v) => println!("{}", to_string(rt.cx(), v)),
23+
Ok(v) => println!("{}", format_value(rt.cx(), Config::default().quoted(true), v)),
2324
Err(e) => e.print(),
2425
}
2526
}
@@ -33,7 +34,7 @@ pub fn eval_script(path: &Path) {
3334

3435
let script = read_script(path).expect("");
3536
match IonScript::compile_and_evaluate(rt.cx(), &path.file_name().unwrap().to_str().unwrap(), &script) {
36-
Ok(v) => println!("{}", to_string(rt.cx(), v)),
37+
Ok(v) => println!("{}", format_value(rt.cx(), Config::default().quoted(true), v)),
3738
Err(e) => e.print(),
3839
}
3940
}

cli/src/main.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use runtime::config::{Config, CONFIG, LogLevel};
1010

1111
use crate::commands::{repl, run};
1212
use crate::commands::eval;
13-
use crate::Commands::{Eval, Repl, Run};
1413

1514
mod commands;
1615
pub mod evaluate;
@@ -19,11 +18,11 @@ pub mod evaluate;
1918
#[structopt(name = "spiderfire", about = "JavaScript Runtime")]
2019
struct Cli {
2120
#[structopt(subcommand)]
22-
commands: Option<Commands>,
21+
command: Option<Command>,
2322
}
2423

2524
#[derive(StructOpt)]
26-
pub enum Commands {
25+
pub enum Command {
2726
#[structopt(about = "Evaluates a line of JavaScript")]
2827
Eval {
2928
#[structopt(required(true), about = "Line of JavaScript to be evaluated")]
@@ -35,13 +34,13 @@ pub enum Commands {
3534

3635
#[structopt(about = "Runs a JavaScript file")]
3736
Run {
38-
#[structopt(about = "The JavaScript file to run. Default: 'main.js'", required(false), default_value = "main.js")]
37+
#[structopt(about = "The JavaScript file to run, Default: 'main.js'", required(false), default_value = "main.js")]
3938
path: String,
4039

41-
#[structopt(about = "Sets logging level, Default: ERROR", short, long, required(false), default_value = "error")]
40+
#[structopt(about = "Sets logging level, Default: ERROR", short, long, required(false), default_value = "ERROR")]
4241
log_level: String,
4342

44-
#[structopt(about = "Sets logging level to DEBUG.", short, long)]
43+
#[structopt(about = "Sets logging level to DEBUG", short, long)]
4544
debug: bool,
4645

4746
#[structopt(about = "Disables ES Modules Features", short, long)]
@@ -52,23 +51,27 @@ pub enum Commands {
5251
fn main() {
5352
let args = Cli::from_args();
5453

55-
match args.commands {
56-
Some(Eval { source }) => {
54+
#[cfg(windows)]
55+
{
56+
colored::control::set_virtual_terminal(true).unwrap();
57+
}
58+
59+
match args.command {
60+
Some(Command::Eval { source }) => {
5761
CONFIG
5862
.set(Config::default().log_level(LogLevel::Debug).script(true))
5963
.expect("Config Initialisation Failed");
6064
eval::eval_source(&source);
6165
}
6266

63-
Some(Run {
67+
Some(Command::Run {
6468
path,
6569
log_level,
6670
debug,
6771
script,
6872
}) => {
69-
7073
let log_lev = if debug {
71-
LogLevel::Debug
74+
LogLevel::Debug
7275
} else {
7376
match log_level.to_uppercase().as_str() {
7477
"NONE" => LogLevel::None,
@@ -86,7 +89,7 @@ fn main() {
8689
run::run(&path);
8790
}
8891

89-
Some(Repl) | None => {
92+
Some(Command::Repl) | None => {
9093
CONFIG
9194
.set(Config::default().log_level(LogLevel::Debug).script(true))
9295
.expect("Config Initialisation Failed");

ion/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ license = "MPL-2.0"
77

88
[dependencies]
99
chrono = "0.4.19"
10-
futures = { version = "0.3.17", features = ["executor"]}
10+
colored = "2.0.0"
11+
futures = { version = "0.3.17", features = ["executor"] }
1112
ion-proc = { path = "../ion-proc" }
1213
libffi = "2.0.0"
1314
mozjs = { package = "mozjs", git = "https://github.com/servo/rust-mozjs" }
1415
mozjs_sys = { package = "mozjs_sys", git = "https://github.com/servo/mozjs", rev = "de147f0cf52da9c84fa95edf09c5f9f84695088c" }
15-
termcolor = "1.1.2"
1616

1717
[features]
1818
debugmozjs = ["mozjs/debugmozjs"]

ion/src/format/array.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
5+
*/
6+
7+
use colored::Colorize;
8+
9+
use crate::format::{format_value, INDENT, NEWLINE};
10+
use crate::format::config::Config;
11+
use crate::IonContext;
12+
use crate::objects::array::IonArray;
13+
14+
/// Formats an [IonArray] to a [String] using the given configuration options
15+
pub fn format_array(cx: IonContext, cfg: Config, array: IonArray) -> String {
16+
let color = cfg.colors.array;
17+
if cfg.depth < 5 {
18+
unsafe {
19+
let vec = array.to_vec(cx);
20+
let vec_length = vec.len();
21+
22+
if vec_length == 0 {
23+
"[]".color(color).to_string()
24+
} else {
25+
let mut string = format!("[{}", NEWLINE).color(color).to_string();
26+
let length = vec_length.clamp(0, 100);
27+
let remaining = vec_length - length;
28+
29+
let inner_indent = INDENT.repeat((cfg.indentation + cfg.depth + 1) as usize);
30+
let outer_indent = INDENT.repeat((cfg.indentation + cfg.depth) as usize);
31+
for i in 0..length {
32+
let value = vec[i];
33+
let value_string = format_value(cx, cfg.depth(cfg.depth + 1).quoted(true), value);
34+
string.push_str(&inner_indent);
35+
string.push_str(&value_string);
36+
37+
if i != vec_length - 1 {
38+
string.push_str(&format!(",{}", NEWLINE).color(color).to_string());
39+
} else {
40+
string.push_str(NEWLINE);
41+
}
42+
}
43+
44+
if remaining > 0 {
45+
string.push_str(&inner_indent);
46+
if remaining == 1 {
47+
string.push_str(&"... 1 more item".color(color).to_string());
48+
} else if remaining > 1 {
49+
string.push_str(&format!("... {} more items", remaining).color(color).to_string());
50+
}
51+
}
52+
53+
string.push_str(&outer_indent);
54+
string.push_str(&"]".color(color).to_string());
55+
string
56+
}
57+
}
58+
} else {
59+
"[Array]".color(color).to_string()
60+
}
61+
}

ion/src/format/boxed.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
5+
*/
6+
7+
use mozjs::jsapi::js::{ESClass, Unbox};
8+
9+
use crate::format::config::Config;
10+
use crate::format::primitive::format_primitive;
11+
use crate::IonContext;
12+
use crate::objects::object::{IonObject, IonRawObject};
13+
14+
/// Formats a boxed object to a [String] using the given configuration options
15+
/// Supported types are `Boolean`, `Number`, `String` and `BigInt`
16+
pub fn format_boxed(cx: IonContext, cfg: Config, object: IonRawObject, class: ESClass) -> String {
17+
rooted!(in(cx) let robj = object);
18+
rooted!(in(cx) let mut unboxed = IonObject::new(cx).to_value());
19+
20+
unsafe {
21+
if Unbox(cx, robj.handle().into(), unboxed.handle_mut().into()) {
22+
use ESClass::*;
23+
match class {
24+
Boolean | Number | String => format_primitive(cx, cfg, unboxed.get()),
25+
BigInt => format!("Unimplemented Formatting: {}", "BigInt"),
26+
_ => unreachable!(),
27+
}
28+
} else {
29+
String::from("Boxed Value")
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)