Skip to content

Commit

Permalink
fixes #10 (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwilliams authored Sep 25, 2019
1 parent 83616ef commit 27178e1
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 8 deletions.
15 changes: 14 additions & 1 deletion src/lib/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crate::{
},
};
use gc::{Gc, GcCell};
use std::{borrow::Borrow, ops::Deref};
use std::{
borrow::Borrow,
ops::{Deref, DerefMut},
};

/// An execution engine
pub trait Executor {
Expand Down Expand Up @@ -470,7 +473,17 @@ impl Default for InterpreterBuilder {
impl Interpreter {
/// https://tc39.es/ecma262/#sec-call
fn call(&mut self, f: &Value, v: &Value, arguments_list: Vec<Value>) -> ResultValue {
// All functions should be objects, and eventually will be.
// During this transition call will support both native functions and function objects
match (*f).deref() {
ValueData::Object(ref obj) => {
let func: Value = obj.borrow_mut().deref_mut().get_internal_slot("call");
if !func.is_undefined() {
return self.call(&func, v, arguments_list);
}
// TODO: error object should be here
Err(Gc::new(ValueData::Undefined))
}
ValueData::Function(ref inner_func) => match *inner_func.deref().borrow() {
Function::NativeFunc(ref ntv) => {
let func = ntv.data;
Expand Down
16 changes: 16 additions & 0 deletions src/lib/js/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,22 @@ mod tests {
assert_eq!(boolean_constructor.is_function(), true);
}

#[test]
/// Test the correct type is returned from call and construct
fn construct_and_call() {
let mut engine = Executor::new();
let init = r#"
const one = new Boolean(1);
const zero = Boolean(0);
"#;
forward(&mut engine, init);
let one = forward_val(&mut engine, "one").unwrap();
let zero = forward_val(&mut engine, "zero").unwrap();

assert_eq!(one.is_object(), true);
assert_eq!(zero.is_boolean(), true);
}

#[test]
fn constructor_gives_true_instance() {
let mut engine = Executor::new();
Expand Down
38 changes: 35 additions & 3 deletions src/lib/js/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use crate::{
value::{from_value, to_value, ResultValue, Value, ValueData},
},
};
use gc::Gc;
use std::{
cmp::{max, min},
f64::NAN,
};

/// Create new string
/// Create new string [[Construct]]
/// <https://searchfox.org/mozilla-central/source/js/src/vm/StringObject.h#19>
// This gets called when a new String() is created, it's called by exec:346
pub fn make_string(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
Expand All @@ -33,6 +34,21 @@ pub fn make_string(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultV
Ok(this.clone())
}

/// Call new string [[Call]]
/// https://tc39.es/ecma262/#sec-string-constructor-string-value
pub fn call_string(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let arg = match args.get(0) {
Some(v) => v.clone(),
None => Gc::new(ValueData::Undefined),
};

if arg.is_undefined() {
return Ok(to_value(""));
}

Ok(to_value(arg.to_string()))
}

/// Get a string's length
pub fn get_string_length(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
let this_str = ctx.value_to_rust_string(this);
Expand Down Expand Up @@ -654,7 +670,7 @@ pub fn create_constructor(global: &Value) -> Value {
string_constructor.set_internal_method("construct", make_string);
// Todo: add call internal method (should be easy)
// Currently call points to the constructor function, this is wrong
string_constructor.set_internal_method("call", make_string);
string_constructor.set_internal_method("call", call_string);

// Create prototype
let proto = ValueData::new_obj(Some(global));
Expand Down Expand Up @@ -697,7 +713,7 @@ pub fn init(global: &Value) {
mod tests {
use super::*;
use crate::exec::Executor;
use crate::forward;
use crate::{forward, forward_val};

#[test]
fn check_string_constructor_is_function() {
Expand Down Expand Up @@ -747,6 +763,22 @@ mod tests {
//assert_eq!(b, String::from("Hello, world! Have a nice day."));
}

#[test]
/// Test the correct type is returned from call and construct
fn construct_and_call() {
let mut engine = Executor::new();
let init = r#"
const hello = new String('Hello');
const world = String('world');
"#;
forward(&mut engine, init);
let hello = forward_val(&mut engine, "hello").unwrap();
let world = forward_val(&mut engine, "world").unwrap();

assert_eq!(hello.is_object(), true);
assert_eq!(world.is_string(), true);
}

#[test]
fn repeat() {
let mut engine = Executor::new();
Expand Down
8 changes: 8 additions & 0 deletions src/lib/js/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ impl ValueData {
}
}

/// Returns true if the value is a boolean
pub fn is_boolean(&self) -> bool {
match *self {
ValueData::Boolean(_) => true,
_ => false,
}
}

/// Returns true if the value is true
/// [toBoolean](https://tc39.github.io/ecma262/#sec-toboolean)
pub fn is_true(&self) -> bool {
Expand Down
6 changes: 2 additions & 4 deletions tests/js/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
function jason(a, b) {
return arguments[0];
}
const val = jason(100, 6);
let a = Boolean(0);
typeof a;

0 comments on commit 27178e1

Please sign in to comment.