diff --git a/src/bin/bin.rs b/src/bin/bin.rs index 43e9cd1600..d628694f1e 100644 --- a/src/bin/bin.rs +++ b/src/bin/bin.rs @@ -12,7 +12,6 @@ pub fn main() { // Setup executor let expr = Parser::new(tokens).parse_all().unwrap(); - print!("{:#?}", expr); let mut engine: Interpreter = Executor::new(); let result = engine.run(&expr); diff --git a/src/lib/exec.rs b/src/lib/exec.rs index 49adc9a7d6..9743ad90ca 100644 --- a/src/lib/exec.rs +++ b/src/lib/exec.rs @@ -95,6 +95,9 @@ impl Executor for Interpreter { ExprDef::ConstExpr(Const::Undefined) => Ok(Gc::new(ValueData::Undefined)), ExprDef::ConstExpr(Const::Num(num)) => Ok(to_value(num)), ExprDef::ConstExpr(Const::Int(num)) => Ok(to_value(num)), + // we can't move String from Const into value, because const is a garbage collected value + // Which means Drop() get's called on Const, but str will be gone at that point. + // Do Const values need to be garbage collected? We no longer need them once we've generated Values ExprDef::ConstExpr(Const::String(ref str)) => Ok(to_value(str.to_owned())), ExprDef::ConstExpr(Const::Bool(val)) => Ok(to_value(val)), ExprDef::ConstExpr(Const::RegExp(_, _, _)) => Ok(to_value(None::<()>)), @@ -128,7 +131,6 @@ impl Executor for Interpreter { } ExprDef::GetConstFieldExpr(ref obj, ref field) => { let val_obj = self.run(obj)?; - println!("{:?}", val_obj.get_field(String::from("length"))); Ok(val_obj.borrow().get_field(field.clone())) } ExprDef::GetFieldExpr(ref obj, ref field) => { diff --git a/src/lib/js/value.rs b/src/lib/js/value.rs index 31d0dfe8ac..7e38969e38 100644 --- a/src/lib/js/value.rs +++ b/src/lib/js/value.rs @@ -55,6 +55,13 @@ impl ValueData { Gc::new(ValueData::Object(GcCell::new(obj))) } + /// Similar to `new_obj`, but you can pass a prototype to create from + pub fn new_obj_from_prototype(proto: Value) -> Value { + let mut obj: ObjectData = HashMap::new(); + obj.insert(INSTANCE_PROTOTYPE.to_string(), Property::new(proto)); + Gc::new(ValueData::Object(GcCell::new(obj))) + } + /// Returns true if the value is an object pub fn is_object(&self) -> bool { match *self { @@ -152,6 +159,13 @@ impl ValueData { /// Resolve the property in the object /// Returns a copy of the Property pub fn get_prop(&self, field: String) -> Option { + // handle length + // Spidermonkey has its own GetLengthProperty: https://searchfox.org/mozilla-central/source/js/src/vm/Interpreter-inl.h#154 + // TODO: Maybe we need a GetLengthProperty for value types + if let ValueData::String(ref s) = *self { + return Some(Property::new(to_value(s.len() as f64))) + } + let obj: ObjectData = match *self { ValueData::Object(ref obj) => { let hash = obj.clone(); diff --git a/tests/js/test.js b/tests/js/test.js index 4de96f523a..7e56815e02 100644 --- a/tests/js/test.js +++ b/tests/js/test.js @@ -1,2 +1,2 @@ -a = { a: 1 }; -a; \ No newline at end of file +var a = 'jabra888'; +a.length; \ No newline at end of file