diff --git a/Cargo.toml b/Cargo.toml index 0d71706d9f..fa98be4787 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ repository = "https://github.com/jasonwilliams/boa" keywords = ["javascript", "compiler", "lexer", "parser", "js"] license = "Unlicense OR MIT" exclude = [".vscode/*", "Dockerfile", "Makefile", ".editorConfig"] +edition = "2018" [dependencies] gc = "0.3.2" diff --git a/src/lib/exec.rs b/src/lib/exec.rs index 9743ad90ca..8c8a495c86 100644 --- a/src/lib/exec.rs +++ b/src/lib/exec.rs @@ -1,13 +1,13 @@ use gc::{Gc, GcCell}; -use js::function::{Function, RegularFunction}; -use js::object::{INSTANCE_PROTOTYPE, PROTOTYPE}; -use js::value::{from_value, to_value, ResultValue, Value, ValueData}; -use js::{array, console, function, json, math, object, string}; +use crate::js::function::{Function, RegularFunction}; +use crate::js::object::{INSTANCE_PROTOTYPE, PROTOTYPE}; +use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData}; +use crate::js::{array, console, function, json, math, object, string}; use std::borrow::Borrow; use std::collections::HashMap; -use syntax::ast::constant::Const; -use syntax::ast::expr::{Expr, ExprDef}; -use syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, UnaryOp}; +use crate::syntax::ast::constant::Const; +use crate::syntax::ast::expr::{Expr, ExprDef}; +use crate::syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, UnaryOp}; /// A variable scope #[derive(Trace, Finalize, Clone, Debug)] pub struct Scope { @@ -188,32 +188,32 @@ impl Executor for Interpreter { Ok(result) } ExprDef::IfExpr(ref cond, ref expr, None) => { - Ok(if try!(self.run(cond)).borrow().is_true() { - try!(self.run(expr)) + Ok(if r#try!(self.run(cond)).borrow().is_true() { + r#try!(self.run(expr)) } else { Gc::new(ValueData::Undefined) }) } ExprDef::IfExpr(ref cond, ref expr, Some(ref else_e)) => { - Ok(if try!(self.run(cond)).borrow().is_true() { - try!(self.run(expr)) + Ok(if r#try!(self.run(cond)).borrow().is_true() { + r#try!(self.run(expr)) } else { - try!(self.run(else_e)) + r#try!(self.run(else_e)) }) } ExprDef::SwitchExpr(ref val_e, ref vals, ref default) => { - let val = try!(self.run(val_e)).clone(); + let val = r#try!(self.run(val_e)).clone(); let mut result = Gc::new(ValueData::Null); let mut matched = false; for tup in vals.iter() { let tup: &(Expr, Vec) = tup; let cond = &tup.0; let block = &tup.1; - if val == try!(self.run(cond)) { + if val == r#try!(self.run(cond)) { matched = true; let last_expr = block.last().unwrap(); for expr in block.iter() { - let e_result = try!(self.run(expr)); + let e_result = r#try!(self.run(expr)); if expr == last_expr { result = e_result; } @@ -221,14 +221,14 @@ impl Executor for Interpreter { } } if !matched && default.is_some() { - result = try!(self.run(default.as_ref().unwrap())); + result = r#try!(self.run(default.as_ref().unwrap())); } Ok(result) } ExprDef::ObjectDeclExpr(ref map) => { let obj = ValueData::new_obj(Some(self.global.clone())); for (key, val) in map.iter() { - obj.borrow().set_field(key.clone(), try!(self.run(val))); + obj.borrow().set_field(key.clone(), r#try!(self.run(val))); } Ok(obj) } @@ -236,7 +236,7 @@ impl Executor for Interpreter { let arr_map = ValueData::new_obj(Some(self.global.clone())); let mut index: i32 = 0; for val in arr.iter() { - let val = try!(self.run(val)); + let val = r#try!(self.run(val)); arr_map.borrow().set_field(index.to_string(), val); index += 1; } @@ -266,8 +266,8 @@ impl Executor for Interpreter { Ok(Gc::new(ValueData::Function(GcCell::new(function)))) } ExprDef::BinOpExpr(BinOp::Num(ref op), ref a, ref b) => { - let v_r_a = try!(self.run(a)); - let v_r_b = try!(self.run(b)); + let v_r_a = r#try!(self.run(a)); + let v_r_b = r#try!(self.run(b)); let v_a = (*v_r_a).clone(); let v_b = (*v_r_b).clone(); Ok(Gc::new(match *op { @@ -279,7 +279,7 @@ impl Executor for Interpreter { })) } ExprDef::UnaryOpExpr(ref op, ref a) => { - let v_r_a = try!(self.run(a)); + let v_r_a = r#try!(self.run(a)); let v_a = (*v_r_a).clone(); Ok(match *op { UnaryOp::Minus => to_value(-v_a.to_num()), @@ -289,8 +289,8 @@ impl Executor for Interpreter { }) } ExprDef::BinOpExpr(BinOp::Bit(ref op), ref a, ref b) => { - let v_r_a = try!(self.run(a)); - let v_r_b = try!(self.run(b)); + let v_r_a = r#try!(self.run(a)); + let v_r_b = r#try!(self.run(b)); let v_a = (*v_r_a).clone(); let v_b = (*v_r_b).clone(); Ok(Gc::new(match *op { @@ -302,8 +302,8 @@ impl Executor for Interpreter { })) } ExprDef::BinOpExpr(BinOp::Comp(ref op), ref a, ref b) => { - let v_r_a = try!(self.run(a)); - let v_r_b = try!(self.run(b)); + let v_r_a = r#try!(self.run(a)); + let v_r_b = r#try!(self.run(b)); let v_a = v_r_a.borrow(); let v_b = v_r_b.borrow(); Ok(to_value(match *op { @@ -322,18 +322,18 @@ impl Executor for Interpreter { })) } ExprDef::BinOpExpr(BinOp::Log(ref op), ref a, ref b) => { - let v_a = from_value::(try!(self.run(a))).unwrap(); - let v_b = from_value::(try!(self.run(b))).unwrap(); + let v_a = from_value::(r#try!(self.run(a))).unwrap(); + let v_b = from_value::(r#try!(self.run(b))).unwrap(); Ok(match *op { LogOp::And => to_value(v_a && v_b), LogOp::Or => to_value(v_a || v_b), }) } ExprDef::ConstructExpr(ref callee, ref args) => { - let func = try!(self.run(callee)); + let func = self.run(callee)?; let mut v_args = Vec::with_capacity(args.len()); for arg in args.iter() { - v_args.push(try!(self.run(arg))); + v_args.push(r#try!(self.run(arg))); } let this = Gc::new(ValueData::Object(GcCell::new(HashMap::new()))); this.borrow() @@ -342,7 +342,8 @@ impl Executor for Interpreter { ValueData::Function(ref func) => match func.clone().into_inner() { Function::NativeFunc(ref ntv) => { let func = ntv.data; - func(this, try!(self.run(callee)), v_args) + println!("{:#?}", this); + func(this, self.run(callee)?, v_args) } Function::RegularFunc(ref data) => { let scope = self.make_scope(this); @@ -364,9 +365,9 @@ impl Executor for Interpreter { Some(ref v) => self.run(v), None => Ok(Gc::new(ValueData::Undefined)), }, - ExprDef::ThrowExpr(ref ex) => Err(try!(self.run(ex))), + ExprDef::ThrowExpr(ref ex) => Err(r#try!(self.run(ex))), ExprDef::AssignExpr(ref ref_e, ref val_e) => { - let val = try!(self.run(val_e)); + let val = r#try!(self.run(val_e)); match ref_e.def { ExprDef::LocalExpr(ref name) => { self.scope() @@ -375,7 +376,7 @@ impl Executor for Interpreter { .set_field(name.clone(), val.clone()); } ExprDef::GetConstFieldExpr(ref obj, ref field) => { - let val_obj = try!(self.run(obj)); + let val_obj = r#try!(self.run(obj)); val_obj.borrow().set_field(field.clone(), val.clone()); } _ => (), @@ -388,7 +389,7 @@ impl Executor for Interpreter { for var in vars.iter() { let (name, value) = var.clone(); let val = match value { - Some(v) => try!(self.run(&v)), + Some(v) => r#try!(self.run(&v)), None => Gc::new(ValueData::Null), }; scope_vars_ptr.set_field(name.clone(), val); @@ -396,7 +397,7 @@ impl Executor for Interpreter { Ok(Gc::new(ValueData::Undefined)) } ExprDef::TypeOfExpr(ref val_e) => { - let val = try!(self.run(val_e)); + let val = r#try!(self.run(val_e)); Ok(to_value(match *val { ValueData::Undefined => "undefined", ValueData::Null | ValueData::Object(_) => "object", diff --git a/src/lib/js/array.rs b/src/lib/js/array.rs index 5457daf53b..54cf913b7f 100644 --- a/src/lib/js/array.rs +++ b/src/lib/js/array.rs @@ -1,6 +1,6 @@ use gc::Gc; -use js::function::NativeFunctionData; -use js::value::{to_value, ResultValue, Value, ValueData}; +use crate::js::function::NativeFunctionData; +use crate::js::value::{to_value, ResultValue, Value, ValueData}; /// Create a new array pub fn make_array(this: Value, _: Value, _: Vec) -> ResultValue { diff --git a/src/lib/js/console.rs b/src/lib/js/console.rs index 352153c403..f77fccad15 100644 --- a/src/lib/js/console.rs +++ b/src/lib/js/console.rs @@ -1,6 +1,6 @@ use gc::Gc; -use js::function::NativeFunctionData; -use js::value::{from_value, to_value, ResultValue, Value, ValueData}; +use crate::js::function::NativeFunctionData; +use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData}; use std::iter::FromIterator; use time::{now, strftime}; /// Print a javascript value to the standard output stream diff --git a/src/lib/js/error.rs b/src/lib/js/error.rs index 68123ac65c..b4efb94c9a 100644 --- a/src/lib/js/error.rs +++ b/src/lib/js/error.rs @@ -1,7 +1,7 @@ use gc::Gc; -use js::function::NativeFunctionData; -use js::object::PROTOTYPE; -use js::value::{to_value, ResultValue, Value, ValueData}; +use crate::js::function::NativeFunctionData; +use crate::js::object::PROTOTYPE; +use crate::js::value::{to_value, ResultValue, Value, ValueData}; /// Create a new error pub fn make_error(this: Value, _: Value, args: Vec) -> ResultValue { diff --git a/src/lib/js/function.rs b/src/lib/js/function.rs index 264e25ac52..8b367f6f2e 100644 --- a/src/lib/js/function.rs +++ b/src/lib/js/function.rs @@ -1,10 +1,12 @@ use gc::Gc; -use js::object::{ObjectData, Property}; -use js::value::{to_value, ResultValue, Value, ValueData}; +use crate::js::object::{ObjectData, Property}; +use crate::js::value::{to_value, ResultValue, Value, ValueData}; use std::collections::HashMap; -use syntax::ast::expr::Expr; +use crate::syntax::ast::expr::Expr; +/// fn(this, callee, arguments) pub type NativeFunctionData = fn(Value, Value, Vec) -> ResultValue; + /// A Javascript function /// A member of the Object type that may be invoked as a subroutine /// https://tc39.github.io/ecma262/#sec-terms-and-definitions-function diff --git a/src/lib/js/json.rs b/src/lib/js/json.rs index 584d086f95..b15c16947b 100644 --- a/src/lib/js/json.rs +++ b/src/lib/js/json.rs @@ -1,7 +1,7 @@ -use js::function::NativeFunctionData; +use crate::js::function::NativeFunctionData; /// The JSON Object /// https://tc39.github.io/ecma262/#sec-json-object -use js::value::{to_value, ResultValue, Value, ValueData}; +use crate::js::value::{to_value, ResultValue, Value, ValueData}; use serde_json::{self, to_string_pretty, Value as JSONValue}; /// Parse a JSON string into a Javascript object diff --git a/src/lib/js/math.rs b/src/lib/js/math.rs index b4366e9b1f..6d5574b426 100644 --- a/src/lib/js/math.rs +++ b/src/lib/js/math.rs @@ -1,5 +1,5 @@ -use js::function::NativeFunctionData; -use js::value::{from_value, to_value, ResultValue, Value, ValueData}; +use crate::js::function::NativeFunctionData; +use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData}; use rand::random; use std::f64; diff --git a/src/lib/js/object.rs b/src/lib/js/object.rs index 74d40cca7d..d6be01a95e 100644 --- a/src/lib/js/object.rs +++ b/src/lib/js/object.rs @@ -1,6 +1,6 @@ use gc::Gc; -use js::function::NativeFunctionData; -use js::value::{from_value, to_value, FromValue, ResultValue, ToValue, Value, ValueData}; +use crate::js::function::NativeFunctionData; +use crate::js::value::{from_value, to_value, FromValue, ResultValue, ToValue, Value, ValueData}; use std::collections::HashMap; pub static PROTOTYPE: &'static str = "prototype"; pub static INSTANCE_PROTOTYPE: &'static str = "__proto__"; diff --git a/src/lib/js/string.rs b/src/lib/js/string.rs index ed99a76278..fafda08630 100644 --- a/src/lib/js/string.rs +++ b/src/lib/js/string.rs @@ -1,12 +1,16 @@ use gc::Gc; -use js::function::NativeFunctionData; -use js::object::{Property, PROTOTYPE}; -use js::value::{from_value, to_value, ResultValue, Value, ValueData}; +use crate::js::function::NativeFunctionData; +use crate::js::object::{Property, PROTOTYPE}; +use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData}; /// Create new string -pub fn make_string(this: Value, _: Value, _: Vec) -> ResultValue { - this.set_field_slice("length", to_value(0i32)); - Ok(Gc::new(ValueData::Undefined)) +/// https://searchfox.org/mozilla-central/source/js/src/vm/StringObject.h#19 +pub fn make_string(this: Value, _: Value, args: Vec) -> ResultValue { + // If we're constructing a string, we should set the initial length + // To do this we need to convert the string back to a Rust String, then get the .len() + let a: String = from_value(args[0].clone()).unwrap(); + this.set_field_slice("length", to_value(a.len() as i32)); + Ok(this) } /// Get a string's length pub fn get_string_length(this: Value, _: Value, _: Vec) -> ResultValue { diff --git a/src/lib/js/value.rs b/src/lib/js/value.rs index 27835ead88..c8aa5bd665 100644 --- a/src/lib/js/value.rs +++ b/src/lib/js/value.rs @@ -1,6 +1,6 @@ use gc::{Gc, GcCell}; -use js::function::{Function, NativeFunction, NativeFunctionData}; -use js::object::{ObjectData, Property, INSTANCE_PROTOTYPE, PROTOTYPE}; +use crate::js::function::{Function, NativeFunction, NativeFunctionData}; +use crate::js::object::{ObjectData, Property, INSTANCE_PROTOTYPE, PROTOTYPE}; use serde_json::map::Map; use serde_json::Number as JSONNumber; use serde_json::Value as JSONValue; @@ -36,6 +36,7 @@ pub enum ValueData { /// `Number` - A 32-bit integer, such as `42` Integer(i32), /// `Object` - An object, such as `Math`, represented by a binary tree of string keys to Javascript values + /// Some Objects will need an internal slot to hold private values, so our second ObjectData is for that Object(GcCell), /// `Function` - A runnable block of code, such as `Math.sqrt`, which can take some variables and return a useful value or act upon an object Function(GcCell), @@ -160,7 +161,7 @@ impl ValueData { /// Returns a copy of the Property pub fn get_prop(&self, field: String) -> Option { // Spidermonkey has its own GetLengthProperty: https://searchfox.org/mozilla-central/source/js/src/vm/Interpreter-inl.h#154 - // TODO: Move this to a better place + // This is only for primitive strings, String() objects have their lengths calculated in string.rs if self.is_string() && field == "length" { if let ValueData::String(ref s) = *self { return Some(Property::new(to_value(s.len() as i32))) @@ -173,7 +174,10 @@ impl ValueData { hash.into_inner() } // Accesing .object on borrow() seems to automatically dereference it, so we don't need the * - // ValueData::Function(ref func) => func.clone().object, + ValueData::Function(ref func) => match func.clone().into_inner() { + Function::NativeFunc(ref func) => func.object.clone(), + Function::RegularFunc(ref func) => func.object.clone() + } _ => return None, }; match obj.get(&field) { @@ -332,13 +336,13 @@ impl Display for ValueData { } ), ValueData::Object(ref v) => { - try!(write!(f, "{}", "{")); + r#try!(write!(f, "{}", "{")); match v.borrow().iter().last() { Some((last_key, _)) => { for (key, val) in v.borrow().iter() { - try!(write!(f, "{}: {}", key, val.value.clone())); + r#try!(write!(f, "{}: {}", key, val.value.clone())); if key != last_key { - try!(write!(f, "{}", ", ")); + r#try!(write!(f, "{}", ", ")); } } } @@ -555,7 +559,7 @@ impl FromValue for Vec { let len = v.get_field_slice("length").to_int(); let mut vec = Vec::with_capacity(len as usize); for i in 0..len { - vec.push(try!(from_value(v.get_field(i.to_string())))) + vec.push(r#try!(from_value(v.get_field(i.to_string())))) } Ok(vec) } @@ -616,7 +620,7 @@ impl FromValue for Option { Ok(if value.is_null_or_undefined() { None } else { - Some(try!(FromValue::from_value(value))) + Some(r#try!(FromValue::from_value(value))) }) } } diff --git a/src/lib/syntax/ast/expr.rs b/src/lib/syntax/ast/expr.rs index 1687d15170..8f30d12ec4 100644 --- a/src/lib/syntax/ast/expr.rs +++ b/src/lib/syntax/ast/expr.rs @@ -1,7 +1,7 @@ use std::collections::btree_map::BTreeMap; use std::fmt::{Display, Formatter, Result}; -use syntax::ast::constant::Const; -use syntax::ast::op::{BinOp, Operator, UnaryOp}; +use crate::syntax::ast::constant::Const; +use crate::syntax::ast::op::{BinOp, Operator, UnaryOp}; #[derive(Clone, Trace, Finalize, Debug, PartialEq)] pub struct Expr { @@ -109,9 +109,9 @@ impl Display for ExprDef { return match *self { ExprDef::ConstExpr(ref c) => write!(f, "{}", c), ExprDef::BlockExpr(ref block) => { - try!(write!(f, "{}", "{")); + r#try!(write!(f, "{}", "{")); for expr in block.iter() { - try!(write!(f, "{};", expr)); + r#try!(write!(f, "{};", expr)); } write!(f, "{}", "}") } @@ -119,7 +119,7 @@ impl Display for ExprDef { ExprDef::GetConstFieldExpr(ref ex, ref field) => write!(f, "{}.{}", ex, field), ExprDef::GetFieldExpr(ref ex, ref field) => write!(f, "{}[{}]", ex, field), ExprDef::CallExpr(ref ex, ref args) => { - try!(write!(f, "{}(", ex)); + r#try!(write!(f, "{}(", ex)); let arg_strs: Vec = args.iter().map(|arg| arg.to_string()).collect(); write!(f, "{})", arg_strs.join(",")) } diff --git a/src/lib/syntax/ast/keyword.rs b/src/lib/syntax/ast/keyword.rs index 8866fa066e..67f2e8c9ff 100644 --- a/src/lib/syntax/ast/keyword.rs +++ b/src/lib/syntax/ast/keyword.rs @@ -2,7 +2,7 @@ use std::error; use std::fmt::Error; use std::fmt::{Display, Formatter}; use std::str::FromStr; -use syntax::ast::keyword::Keyword::*; +use crate::syntax::ast::keyword::Keyword::*; #[derive(Clone, PartialEq, Debug)] /// A Javascript Keyword diff --git a/src/lib/syntax/ast/token.rs b/src/lib/syntax/ast/token.rs index f1abfc7a5c..d1805e0328 100644 --- a/src/lib/syntax/ast/token.rs +++ b/src/lib/syntax/ast/token.rs @@ -1,7 +1,7 @@ use std::fmt::{Debug, Display, Formatter, Result}; -use syntax::ast::keyword::Keyword; -use syntax::ast::pos::Position; -use syntax::ast::punc::Punctuator; +use crate::syntax::ast::keyword::Keyword; +use crate::syntax::ast::pos::Position; +use crate::syntax::ast::punc::Punctuator; #[derive(Clone, PartialEq)] /// Represents a token diff --git a/src/lib/syntax/lexer.rs b/src/lib/syntax/lexer.rs index b5377b5e93..135b8c2d9a 100644 --- a/src/lib/syntax/lexer.rs +++ b/src/lib/syntax/lexer.rs @@ -8,8 +8,8 @@ use std::fmt; use std::iter::Peekable; use std::str::Chars; use std::str::FromStr; -use syntax::ast::punc::Punctuator; -use syntax::ast::token::{Token, TokenData}; +use crate::syntax::ast::punc::Punctuator; +use crate::syntax::ast::token::{Token, TokenData}; #[allow(unused)] macro_rules! vop { diff --git a/src/lib/syntax/parser.rs b/src/lib/syntax/parser.rs index b0bf8a474d..285114b227 100644 --- a/src/lib/syntax/parser.rs +++ b/src/lib/syntax/parser.rs @@ -1,10 +1,10 @@ use std::collections::btree_map::BTreeMap; -use syntax::ast::constant::Const; -use syntax::ast::expr::{Expr, ExprDef}; -use syntax::ast::keyword::Keyword; -use syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, Operator, UnaryOp}; -use syntax::ast::punc::Punctuator; -use syntax::ast::token::{Token, TokenData}; +use crate::syntax::ast::constant::Const; +use crate::syntax::ast::expr::{Expr, ExprDef}; +use crate::syntax::ast::keyword::Keyword; +use crate::syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, Operator, UnaryOp}; +use crate::syntax::ast::punc::Punctuator; +use crate::syntax::ast::token::{Token, TokenData}; macro_rules! mk ( ($this:expr, $def:expr) => { @@ -52,7 +52,7 @@ impl Parser { pub fn parse_all(&mut self) -> ParseResult { let mut exprs = Vec::new(); while self.pos < self.tokens.len() { - let result = try!(self.parse()); + let result = r#try!(self.parse()); exprs.push(result); } @@ -72,7 +72,7 @@ impl Parser { fn parse_struct(&mut self, keyword: Keyword) -> ParseResult { match keyword { Keyword::Throw => { - let thrown = try!(self.parse()); + let thrown = r#try!(self.parse()); Ok(mk!(self, ExprDef::ThrowExpr(Box::new(thrown)))) } Keyword::Var => { @@ -171,10 +171,10 @@ impl Parser { )) } Keyword::Switch => { - try!(self.expect_punc(Punctuator::OpenParen, "switch value")); + r#try!(self.expect_punc(Punctuator::OpenParen, "switch value")); let value = self.parse(); - try!(self.expect_punc(Punctuator::CloseParen, "switch value")); - try!(self.expect_punc(Punctuator::OpenBlock, "switch block")); + r#try!(self.expect_punc(Punctuator::CloseParen, "switch value")); + r#try!(self.expect_punc(Punctuator::OpenBlock, "switch block")); let mut cases = Vec::new(); let mut default = None; while self.pos + 1 < self.tokens.len() { @@ -184,26 +184,26 @@ impl Parser { TokenData::Keyword(Keyword::Case) => { let cond = self.parse(); let mut block = Vec::new(); - try!(self.expect_punc(Punctuator::Colon, "switch case")); + r#try!(self.expect_punc(Punctuator::Colon, "switch case")); loop { - match try!(self.get_token(self.pos)).data { + match r#try!(self.get_token(self.pos)).data { TokenData::Keyword(Keyword::Case) | TokenData::Keyword(Keyword::Default) => break, TokenData::Punctuator(Punctuator::CloseBlock) => break, - _ => block.push(try!(self.parse())), + _ => block.push(r#try!(self.parse())), } } cases.push((cond.unwrap(), block)); } TokenData::Keyword(Keyword::Default) => { let mut block = Vec::new(); - try!(self.expect_punc(Punctuator::Colon, "default switch case")); + r#try!(self.expect_punc(Punctuator::Colon, "default switch case")); loop { - match try!(self.get_token(self.pos)).data { + match r#try!(self.get_token(self.pos)).data { TokenData::Keyword(Keyword::Case) | TokenData::Keyword(Keyword::Default) => break, TokenData::Punctuator(Punctuator::CloseBlock) => break, - _ => block.push(try!(self.parse())), + _ => block.push(r#try!(self.parse())), } } default = Some(mk!(self, ExprDef::BlockExpr(block))); @@ -222,7 +222,7 @@ impl Parser { } } } - try!(self.expect_punc(Punctuator::CloseBlock, "switch block")); + r#try!(self.expect_punc(Punctuator::CloseBlock, "switch block")); Ok(mk!( self, ExprDef::SwitchExpr( @@ -237,7 +237,7 @@ impl Parser { } Keyword::Function => { // function [identifier] () { etc } - let tk = try!(self.get_token(self.pos)); + let tk = r#try!(self.get_token(self.pos)); let name = match tk.data { TokenData::Identifier(ref name) => { self.pos += 1; @@ -268,7 +268,7 @@ impl Parser { } } self.pos += 1; - if try!(self.get_token(self.pos)).data + if r#try!(self.get_token(self.pos)).data == TokenData::Punctuator(Punctuator::Comma) { self.pos += 1; @@ -291,13 +291,13 @@ impl Parser { if self.pos > self.tokens.len() { return Err(ParseError::AbruptEnd); } - let token = try!(self.get_token(self.pos)); + let token = r#try!(self.get_token(self.pos)); self.pos += 1; let expr: Expr = match token.data { TokenData::Punctuator(Punctuator::Semicolon) | TokenData::Comment(_) if self.pos < self.tokens.len() => { - try!(self.parse()) + r#try!(self.parse()) } TokenData::Punctuator(Punctuator::Semicolon) | TokenData::Comment(_) => { mk!(self, ExprDef::ConstExpr(Const::Undefined)) @@ -310,15 +310,15 @@ impl Parser { mk!(self, ExprDef::ConstExpr(Const::Undefined)) } TokenData::Identifier(s) => mk!(self, ExprDef::LocalExpr(s)), - TokenData::Keyword(keyword) => try!(self.parse_struct(keyword)), + TokenData::Keyword(keyword) => r#try!(self.parse_struct(keyword)), TokenData::Punctuator(Punctuator::OpenParen) => { - match try!(self.get_token(self.pos)).data { + match r#try!(self.get_token(self.pos)).data { TokenData::Punctuator(Punctuator::CloseParen) - if try!(self.get_token(self.pos + 1)).data + if r#try!(self.get_token(self.pos + 1)).data == TokenData::Punctuator(Punctuator::Arrow) => { self.pos += 2; - let expr = try!(self.parse()); + let expr = r#try!(self.parse()); mk!( self, ExprDef::ArrowFunctionDeclExpr(Vec::new(), Box::new(expr)), @@ -326,8 +326,8 @@ impl Parser { ) } _ => { - let next = try!(self.parse()); - let next_tok = try!(self.get_token(self.pos)); + let next = r#try!(self.parse()); + let next_tok = r#try!(self.get_token(self.pos)); self.pos += 1; match next_tok.data { TokenData::Punctuator(Punctuator::CloseParen) => next, @@ -338,7 +338,7 @@ impl Parser { ExprDef::LocalExpr(ref name) => (*name).clone(), _ => "".to_string(), }, - match try!(self.get_token(self.pos)).data { + match r#try!(self.get_token(self.pos)).data { TokenData::Identifier(ref id) => id.clone(), _ => "".to_string(), }, @@ -346,7 +346,7 @@ impl Parser { let mut expect_ident = true; loop { self.pos += 1; - let curr_tk = try!(self.get_token(self.pos)); + let curr_tk = r#try!(self.get_token(self.pos)); match curr_tk.data { TokenData::Identifier(ref id) if expect_ident => { args.push(id.clone()); @@ -380,11 +380,11 @@ impl Parser { } } } - try!(self.expect( + r#try!(self.expect( TokenData::Punctuator(Punctuator::Arrow), "arrow function" )); - let expr = try!(self.parse()); + let expr = r#try!(self.parse()); mk!( self, ExprDef::ArrowFunctionDeclExpr(args, Box::new(expr)), @@ -404,10 +404,10 @@ impl Parser { } TokenData::Punctuator(Punctuator::OpenBracket) => { let mut array: Vec = Vec::new(); - let mut expect_comma_or_end = try!(self.get_token(self.pos)).data + let mut expect_comma_or_end = r#try!(self.get_token(self.pos)).data == TokenData::Punctuator(Punctuator::CloseBracket); loop { - let token = try!(self.get_token(self.pos)); + let token = r#try!(self.get_token(self.pos)); if token.data == TokenData::Punctuator(Punctuator::CloseBracket) && expect_comma_or_end { @@ -432,7 +432,7 @@ impl Parser { "array declaration", )); } else { - let parsed = try!(self.parse()); + let parsed = r#try!(self.parse()); self.pos -= 1; array.push(parsed); expect_comma_or_end = true; @@ -442,7 +442,7 @@ impl Parser { mk!(self, ExprDef::ArrayDeclExpr(array), token) } TokenData::Punctuator(Punctuator::OpenBlock) - if try!(self.get_token(self.pos)).data + if r#try!(self.get_token(self.pos)).data == TokenData::Punctuator(Punctuator::CloseBlock) => { self.pos += 1; @@ -453,15 +453,15 @@ impl Parser { ) } TokenData::Punctuator(Punctuator::OpenBlock) - if try!(self.get_token(self.pos + 1)).data + if r#try!(self.get_token(self.pos + 1)).data == TokenData::Punctuator(Punctuator::Colon) => { let mut map = Box::new(BTreeMap::new()); - while try!(self.get_token(self.pos - 1)).data + while r#try!(self.get_token(self.pos - 1)).data == TokenData::Punctuator(Punctuator::Comma) || map.len() == 0 { - let tk = try!(self.get_token(self.pos)); + let tk = r#try!(self.get_token(self.pos)); let name = match tk.data { TokenData::Identifier(ref id) => id.clone(), TokenData::StringLiteral(ref str) => str.clone(), @@ -477,11 +477,11 @@ impl Parser { } }; self.pos += 1; - try!(self.expect( + r#try!(self.expect( TokenData::Punctuator(Punctuator::Colon), "object declaration" )); - let value = try!(self.parse()); + let value = r#try!(self.parse()); map.insert(name, value); self.pos += 1; } @@ -490,12 +490,12 @@ impl Parser { TokenData::Punctuator(Punctuator::OpenBlock) => { let mut exprs = Vec::new(); loop { - if try!(self.get_token(self.pos)).data + if r#try!(self.get_token(self.pos)).data == TokenData::Punctuator(Punctuator::CloseBlock) { break; } else { - exprs.push(try!(self.parse())); + exprs.push(r#try!(self.parse())); } } self.pos += 1; @@ -503,23 +503,23 @@ impl Parser { } TokenData::Punctuator(Punctuator::Sub) => mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::Minus, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::Minus, Box::new(r#try!(self.parse()))) ), TokenData::Punctuator(Punctuator::Add) => mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::Plus, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::Plus, Box::new(r#try!(self.parse()))) ), TokenData::Punctuator(Punctuator::Not) => mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::Not, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::Not, Box::new(r#try!(self.parse()))) ), TokenData::Punctuator(Punctuator::Inc) => mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::IncrementPre, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::IncrementPre, Box::new(r#try!(self.parse()))) ), TokenData::Punctuator(Punctuator::Dec) => mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::DecrementPre, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::DecrementPre, Box::new(r#try!(self.parse()))) ), _ => return Err(ParseError::Expected(Vec::new(), token.clone(), "script")), }; @@ -537,7 +537,7 @@ impl Parser { match next.data { TokenData::Punctuator(Punctuator::Dot) => { self.pos += 1; - let tk = try!(self.get_token(self.pos)); + let tk = r#try!(self.get_token(self.pos)); match tk.data { TokenData::Identifier(ref s) => { result = mk!( @@ -557,11 +557,11 @@ impl Parser { } TokenData::Punctuator(Punctuator::OpenParen) => { let mut args = Vec::new(); - let mut expect_comma_or_end = try!(self.get_token(self.pos + 1)).data + let mut expect_comma_or_end = r#try!(self.get_token(self.pos + 1)).data == TokenData::Punctuator(Punctuator::CloseParen); loop { self.pos += 1; - let token = try!(self.get_token(self.pos)); + let token = r#try!(self.get_token(self.pos)); if token.data == TokenData::Punctuator(Punctuator::CloseParen) && expect_comma_or_end { @@ -581,7 +581,7 @@ impl Parser { "function call arguments", )); } else { - let parsed = try!(self.parse()); + let parsed = r#try!(self.parse()); self.pos -= 1; args.push(parsed); expect_comma_or_end = true; @@ -591,9 +591,9 @@ impl Parser { } TokenData::Punctuator(Punctuator::Question) => { self.pos += 1; - let if_e = try!(self.parse()); - try!(self.expect(TokenData::Punctuator(Punctuator::Colon), "if expression")); - let else_e = try!(self.parse()); + let if_e = r#try!(self.parse()); + r#try!(self.expect(TokenData::Punctuator(Punctuator::Colon), "if expression")); + let else_e = r#try!(self.parse()); result = mk!( self, ExprDef::IfExpr(Box::new(expr), Box::new(if_e), Some(Box::new(else_e))) @@ -601,8 +601,8 @@ impl Parser { } TokenData::Punctuator(Punctuator::OpenBracket) => { self.pos += 1; - let index = try!(self.parse()); - try!(self.expect( + let index = r#try!(self.parse()); + r#try!(self.expect( TokenData::Punctuator(Punctuator::CloseBracket), "array index" )); @@ -613,7 +613,7 @@ impl Parser { } TokenData::Punctuator(Punctuator::Assign) => { self.pos += 1; - let next = try!(self.parse()); + let next = r#try!(self.parse()); result = mk!(self, ExprDef::AssignExpr(Box::new(expr), Box::new(next))); } TokenData::Punctuator(Punctuator::Arrow) => { @@ -623,79 +623,79 @@ impl Parser { ExprDef::LocalExpr(ref name) => args.push((*name).clone()), _ => return Err(ParseError::ExpectedExpr("identifier", result)), } - let next = try!(self.parse()); + let next = r#try!(self.parse()); result = mk!(self, ExprDef::ArrowFunctionDeclExpr(args, Box::new(next))); } TokenData::Punctuator(Punctuator::Add) => { - result = try!(self.binop(BinOp::Num(NumOp::Add), expr)) + result = r#try!(self.binop(BinOp::Num(NumOp::Add), expr)) } TokenData::Punctuator(Punctuator::Sub) => { - result = try!(self.binop(BinOp::Num(NumOp::Sub), expr)) + result = r#try!(self.binop(BinOp::Num(NumOp::Sub), expr)) } TokenData::Punctuator(Punctuator::Mul) => { - result = try!(self.binop(BinOp::Num(NumOp::Mul), expr)) + result = r#try!(self.binop(BinOp::Num(NumOp::Mul), expr)) } TokenData::Punctuator(Punctuator::Div) => { - result = try!(self.binop(BinOp::Num(NumOp::Div), expr)) + result = r#try!(self.binop(BinOp::Num(NumOp::Div), expr)) } TokenData::Punctuator(Punctuator::Mod) => { - result = try!(self.binop(BinOp::Num(NumOp::Mod), expr)) + result = r#try!(self.binop(BinOp::Num(NumOp::Mod), expr)) } TokenData::Punctuator(Punctuator::BoolAnd) => { - result = try!(self.binop(BinOp::Log(LogOp::And), expr)) + result = r#try!(self.binop(BinOp::Log(LogOp::And), expr)) } TokenData::Punctuator(Punctuator::BoolOr) => { - result = try!(self.binop(BinOp::Log(LogOp::Or), expr)) + result = r#try!(self.binop(BinOp::Log(LogOp::Or), expr)) } TokenData::Punctuator(Punctuator::And) => { - result = try!(self.binop(BinOp::Bit(BitOp::And), expr)) + result = r#try!(self.binop(BinOp::Bit(BitOp::And), expr)) } TokenData::Punctuator(Punctuator::Or) => { - result = try!(self.binop(BinOp::Bit(BitOp::Or), expr)) + result = r#try!(self.binop(BinOp::Bit(BitOp::Or), expr)) } TokenData::Punctuator(Punctuator::Xor) => { - result = try!(self.binop(BinOp::Bit(BitOp::Xor), expr)) + result = r#try!(self.binop(BinOp::Bit(BitOp::Xor), expr)) } TokenData::Punctuator(Punctuator::LeftSh) => { - result = try!(self.binop(BinOp::Bit(BitOp::Shl), expr)) + result = r#try!(self.binop(BinOp::Bit(BitOp::Shl), expr)) } TokenData::Punctuator(Punctuator::RightSh) => { - result = try!(self.binop(BinOp::Bit(BitOp::Shr), expr)) + result = r#try!(self.binop(BinOp::Bit(BitOp::Shr), expr)) } TokenData::Punctuator(Punctuator::Eq) => { - result = try!(self.binop(BinOp::Comp(CompOp::Equal), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::Equal), expr)) } TokenData::Punctuator(Punctuator::NotEq) => { - result = try!(self.binop(BinOp::Comp(CompOp::NotEqual), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::NotEqual), expr)) } TokenData::Punctuator(Punctuator::StrictEq) => { - result = try!(self.binop(BinOp::Comp(CompOp::StrictEqual), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::StrictEqual), expr)) } TokenData::Punctuator(Punctuator::StrictNotEq) => { - result = try!(self.binop(BinOp::Comp(CompOp::StrictNotEqual), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::StrictNotEqual), expr)) } TokenData::Punctuator(Punctuator::LessThan) => { - result = try!(self.binop(BinOp::Comp(CompOp::LessThan), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::LessThan), expr)) } TokenData::Punctuator(Punctuator::LessThanOrEq) => { - result = try!(self.binop(BinOp::Comp(CompOp::LessThanOrEqual), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::LessThanOrEqual), expr)) } TokenData::Punctuator(Punctuator::GreaterThan) => { - result = try!(self.binop(BinOp::Comp(CompOp::GreaterThan), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::GreaterThan), expr)) } TokenData::Punctuator(Punctuator::GreaterThanOrEq) => { - result = try!(self.binop(BinOp::Comp(CompOp::GreaterThanOrEqual), expr)) + result = r#try!(self.binop(BinOp::Comp(CompOp::GreaterThanOrEqual), expr)) } TokenData::Punctuator(Punctuator::Inc) => { result = mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::IncrementPost, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::IncrementPost, Box::new(r#try!(self.parse()))) ) } TokenData::Punctuator(Punctuator::Dec) => { result = mk!( self, - ExprDef::UnaryOpExpr(UnaryOp::DecrementPost, Box::new(try!(self.parse()))) + ExprDef::UnaryOpExpr(UnaryOp::DecrementPost, Box::new(r#try!(self.parse()))) ) } _ => carry_on = false, @@ -710,7 +710,7 @@ impl Parser { fn binop(&mut self, op: BinOp, orig: Expr) -> Result { let (precedence, assoc) = op.get_precedence_and_assoc(); self.pos += 1; - let next = try!(self.parse()); + let next = r#try!(self.parse()); Ok(match next.def { ExprDef::BinOpExpr(ref op2, ref a, ref b) => { let other_precedence = op2.get_precedence(); diff --git a/tests/js/test.js b/tests/js/test.js index a4bc5f3d8c..b71ec58ac8 100644 --- a/tests/js/test.js +++ b/tests/js/test.js @@ -1,2 +1,2 @@ -var a = 'jabrjjja888'; -a.length; \ No newline at end of file +var a = new String("test"); +a; \ No newline at end of file