Browse Source

working on stdlib

pull/5/head
Jason Williams 6 years ago
parent
commit
607a6b8521
  1. 112
      Cargo.lock
  2. 2
      Cargo.toml
  3. 17
      src/lib/js/array.rs
  4. 17
      src/lib/js/boolean.rs
  5. 34
      src/lib/js/console.rs
  6. 31
      src/lib/js/error.rs
  7. 46
      src/lib/js/function.rs
  8. 11
      src/lib/js/json.rs
  9. 195
      src/lib/js/math.rs
  10. 10
      src/lib/js/mod.rs
  11. 34
      src/lib/js/string.rs
  12. 3
      src/lib/lib.rs
  13. 7
      tests/value_test.rs

112
Cargo.lock generated

@ -4,9 +4,38 @@ version = "0.1.3"
dependencies = [ dependencies = [
"gc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gc_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gc_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "gc" name = "gc"
version = "0.3.2" version = "0.3.2"
@ -27,11 +56,46 @@ name = "itoa"
version = "0.4.3" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.3.15" version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "0.2.6" version = "0.2.6"
@ -39,7 +103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.79" version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -49,7 +113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -79,20 +143,62 @@ dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.0.4" version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "630b15fafc2270fc89de904da9ebb8b950642a5ed7bd99ec3f95558b0831ea9a" "checksum gc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "630b15fafc2270fc89de904da9ebb8b950642a5ed7bd99ec3f95558b0831ea9a"
"checksum gc_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2501c15cbaf28a0c2214617aa85351982a933161d7937fe6cd71c855364e0ea6" "checksum gc_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2501c15cbaf28a0c2214617aa85351982a933161d7937fe6cd71c855364e0ea6"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
"checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
"checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

2
Cargo.toml

@ -13,6 +13,8 @@ exclude = [".vscode/*", "Dockerfile", "Makefile", ".editorConfig"]
gc = "0.3.2" gc = "0.3.2"
gc_derive = "*" gc_derive = "*"
serde_json = "1.0" serde_json = "1.0"
rand = "0.5.5"
time = "0.1"
[lib] [lib]
name = "boa" name = "boa"

17
src/lib/js/array.rs

@ -0,0 +1,17 @@
use js::function::Function;
use js::value::{to_value, ResultValue, Value};
/// Create a new array
pub fn make_array(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
this.set_field_slice("length", to_value(0i32));
Ok(Value::undefined())
}
/// Create a new `Array` object
pub fn _create() -> Value {
let array = Function::make(make_array, &[]);
array
}
/// Initialise the global object with the `Array` object
pub fn init(global: Value) {
global.set_field_slice("Array", _create());
}

17
src/lib/js/boolean.rs

@ -0,0 +1,17 @@
use gc::Gc;
use js::value::{to_value, ResultValue, Value, ValueData};
/// Create a new boolean
pub fn make_boolean(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
Ok(Gc::new(ValueData::Undefined))
}
/// Create a new `Boolean` object
pub fn _create(global: Value) -> Value {
let boolean = to_value(make_boolean);
boolean
}
/// Initialise the global object with the `Error` object
pub fn init(global: Value) {
let global_ptr = global.borrow();
global_ptr.set_field_slice("Boolean", _create(global));
}

34
src/lib/js/console.rs

@ -0,0 +1,34 @@
use js::function::Function;
use js::value::{from_value, ResultValue, Value};
use std::iter::FromIterator;
use time::{now, strftime};
/// Print a javascript value to the standard output stream
pub fn log(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
let args: Vec<String> = FromIterator::from_iter(
args.iter()
.map(|x| from_value::<String>(x.clone()).unwrap()),
);
println!("{}: {}", strftime("%X", &now()).unwrap(), args.join(" "));
Ok(Value::undefined())
}
/// Print a javascript value to the standard error stream
pub fn error(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
let args: Vec<String> = FromIterator::from_iter(
args.iter()
.map(|x| from_value::<String>(x.clone()).unwrap()),
);
eprintln!("{}: {}", strftime("%X", &now()).unwrap(), args.join(" "));
Ok(Value::undefined())
}
/// Create a new `console` object
pub fn _create(global: Value) -> Value {
let console = Value::new_obj(Some(global));
console.set_field_slice("log", Function::make(log, &["object"]));
console.set_field_slice("error", Function::make(error, &["error"]));
console.set_field_slice("exception", Function::make(error, &["error"]));
console
}
/// Initialise the global object with the `console` object
pub fn init(global: Value) {
global.set_field_slice("console", _create(global.clone()));
}

31
src/lib/js/error.rs

@ -0,0 +1,31 @@
use js::function::Function;
use js::object::PROTOTYPE;
use js::value::{to_value, ResultValue, Value};
/// Create a new error
pub fn make_error(args: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
if args.len() >= 1 {
this.set_field_slice("message", to_value(args.get(0).unwrap().to_string()));
}
Ok(Value::undefined())
}
/// Get the string representation of the error
pub fn to_string(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
let name = this.get_field_slice("name");
let message = this.get_field_slice("message");
Ok(to_value(format!("{}: {}", name, message).to_string()))
}
/// Create a new `Error` object
pub fn _create(global: Value) -> Value {
let prototype = Value::new_obj(Some(global));
prototype.set_field_slice("message", to_value(""));
prototype.set_field_slice("name", to_value("Error"));
prototype.set_field_slice("toString", Function::make(to_string, &[]));
let error = Function::make(make_error, &["message"]);
error.set_field_slice(PROTOTYPE, prototype);
error
}
/// Initialise the global object with the `Error` object
pub fn init(global: Value) {
global.set_field_slice("Error", _create(global.clone()));
}

46
src/lib/js/function.rs

@ -1,5 +1,8 @@
use js::object::ObjectData; use gc::{Gc, GcCell};
use js::value::{ResultValue, Value}; use js::object::{ObjectData, Property};
use js::value::{to_value, ResultValue, Value, ValueData};
use std::collections::HashMap;
use std::iter::FromIterator;
pub type FunctionData = fn(Vec<Value>, Value, Value, Value) -> ResultValue; pub type FunctionData = fn(Vec<Value>, Value, Value, Value) -> ResultValue;
/// A Javascript function /// A Javascript function
@ -16,3 +19,42 @@ pub struct Function {
/// The argument names of the function /// The argument names of the function
pub args: Vec<String>, pub args: Vec<String>,
} }
impl Function {
/// Make a new function
pub fn new(repr: FunctionData, args: Vec<String>) -> Function {
let mut obj = HashMap::new();
obj.insert(
"arguments".to_string(),
Property::from_value(to_value(args.len() as i32)),
);
Function {
object: obj,
repr: repr,
args: args,
}
}
/// Create a function from function data and arguments
pub fn make(repr: FunctionData, args: &[&'static str]) -> Value {
Value {
ptr: Gc::new(ValueData::Function(GcCell::new(Function::new(
repr,
FromIterator::from_iter(args.iter().map(|arg| arg.to_string())),
)))),
}
}
/// Call with some args
pub fn call(&self, args: Vec<Value>, global: Value, scope: Value, this: Value) -> ResultValue {
(self.repr)(args, global, scope, this)
}
}
/// Create a new `Function` object
pub fn _create() -> Value {
let function: ObjectData = HashMap::new();
to_value(function)
}
/// Initialise the global object with the `Function` object
pub fn init(global: Value) {
global.set_field_slice("Function", _create());
}

11
src/lib/js/json.rs

@ -2,20 +2,21 @@
/// https://tc39.github.io/ecma262/#sec-json-object /// https://tc39.github.io/ecma262/#sec-json-object
use gc::GcCell; use gc::GcCell;
use js::value::{to_value, ResultValue, Value, ValueData}; use js::value::{to_value, ResultValue, Value, ValueData};
use serde_json;
/// Parse a JSON string into a Javascript object /// Parse a JSON string into a Javascript object
/// https://tc39.github.io/ecma262/#sec-json.parse /// https://tc39.github.io/ecma262/#sec-json.parse
pub fn parse(args: Vec<Value>) -> ResultValue { pub fn parse(args: Vec<Value>) -> ResultValue {
match serde_json::from_str(args.get(0).borrow().to_str().as_slice()) { match serde_json::from_str(&args.get(0).unwrap().clone().to_string()) {
Ok(json) => Ok(GcCell::new(ValueData::from_json(json))), Ok(json) => Ok(to_value(json)),
Err(err) => Err(GcCell::new(Value::String(err.to_str()))), Err(err) => Err(to_value(err.to_string())),
} }
} }
/// Process a Javascript object into a JSON string /// Process a Javascript object into a JSON string
pub fn stringify(args: Vec<Value>) -> ResultValue { pub fn stringify(args: Vec<Value>) -> ResultValue {
let obj = args.get(0); let obj = args.get(0);
let json = serde_json::to_string_pretty(obj.borrow()).unwrap(); let json = serde_json::to_string_pretty(obj.clone()).unwrap();
Ok(GcCell::new(Value::String(json.to_pretty_str()))) Ok(to_value(json.to_pretty_str()))
} }
/// Create a new `JSON` object /// Create a new `JSON` object

195
src/lib/js/math.rs

@ -0,0 +1,195 @@
use js::function::Function;
use js::value::{from_value, to_value, ResultValue, Value};
use rand::random;
use std::f64;
/// Get the absolute value of a number
pub fn abs(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().abs()
} else {
f64::NAN
}))
}
/// Get the arccos of a number
pub fn acos(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().acos()
} else {
f64::NAN
}))
}
/// Get the arcsine of a number
pub fn asin(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().asin()
} else {
f64::NAN
}))
}
/// Get the arctangent of a number
pub fn atan(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().atan()
} else {
f64::NAN
}))
}
/// Get the arctangent of a numbers
pub fn atan2(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0))
.unwrap()
.atan2(args.get(1).to_num())
} else {
f64::NAN
}))
}
/// Get the cubic root of a number
pub fn cbrt(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().cbrt()
} else {
f64::NAN
}))
}
/// Get lowest integer above a number
pub fn ceil(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().ceil()
} else {
f64::NAN
}))
}
/// Get the cosine of a number
pub fn cos(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().cos()
} else {
f64::NAN
}))
}
/// Get the power to raise the natural logarithm to get the number
pub fn exp(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().exp()
} else {
f64::NAN
}))
}
/// Get the highest integer below a number
pub fn floor(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().floor()
} else {
f64::NAN
}))
}
/// Get the natural logarithm of a number
pub fn log(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().log(f64::consts::E)
} else {
f64::NAN
}))
}
/// Get the maximum of several numbers
pub fn max(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
let mut max = f64::NEG_INFINITY;
for arg in args.iter() {
let num = arg.to_num();
max = max.max(num);
}
Ok(to_value(max))
}
/// Get the minimum of several numbers
pub fn min(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
let mut max = f64::INFINITY;
for arg in args.iter() {
let num = arg.to_num();
max = max.min(num);
}
Ok(to_value(max))
}
/// Raise a number to a power
pub fn pow(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 2 {
let num: f64 = from_value(*args.get(0)).unwrap();
let power: f64 = from_value(*args.get(1)).unwrap();
num.powf(power)
} else {
f64::NAN
}))
}
/// Generate a random floating-point number between 0 and 1
pub fn _random(_: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(random::<f64>()))
}
/// Round a number to the nearest integer
pub fn round(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().round()
} else {
f64::NAN
}))
}
/// Get the sine of a number
pub fn sin(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().sin()
} else {
f64::NAN
}))
}
/// Get the square root of a number
pub fn sqrt(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().sqrt()
} else {
f64::NAN
}))
}
/// Get the tangent of a number
pub fn tan(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(*args.get(0)).unwrap().tan()
} else {
f64::NAN
}))
}
/// Create a new `Math` object
pub fn _create(global: Value) -> Value {
let math = Value::new_obj(Some(global));
math.set_field_slice("E", to_value(f64::consts::E));
math.set_field_slice("LN2", to_value(f64::consts::LN_2));
math.set_field_slice("LN10", to_value(f64::consts::LN_10));
math.set_field_slice("LOG2E", to_value(f64::consts::LOG2_E));
math.set_field_slice("LOG10E", to_value(f64::consts::LOG10_E));
math.set_field_slice("SQRT1_2", to_value(0.5f64.sqrt()));
math.set_field_slice("SQRT2", to_value(f64::consts::SQRT2));
math.set_field_slice("PI", to_value(f64::consts::PI));
math.set_field_slice("abs", Function::make(abs, ["num1", "num2"]));
math.set_field_slice("acos", Function::make(acos, ["num1", "num2"]));
math.set_field_slice("asin", Function::make(asin, ["num1", "num2"]));
math.set_field_slice("atan", Function::make(atan, ["num1", "num2"]));
math.set_field_slice("atan2", Function::make(atan2, ["num1", "num2"]));
math.set_field_slice("cbrt", Function::make(cbrt, ["num1", "num2"]));
math.set_field_slice("ceil", Function::make(ceil, ["num1", "num2"]));
math.set_field_slice("cos", Function::make(cos, ["num1", "num2"]));
math.set_field_slice("exp", Function::make(exp, ["num1", "num2"]));
math.set_field_slice("floor", Function::make(floor, ["num"]));
math.set_field_slice("log", Function::make(log, ["num1", "num2"]));
math.set_field_slice("max", Function::make(max, ["num1", "num2"]));
math.set_field_slice("min", Function::make(min, ["num1", "num2"]));
math.set_field_slice("pow", Function::make(pow, ["num1", "num2"]));
math.set_field_slice("random", Function::make(_random, []));
math.set_field_slice("round", Function::make(round, ["num"]));
math.set_field_slice("sin", Function::make(sin, ["num"]));
math.set_field_slice("sqrt", Function::make(sqrt, ["num"]));
math.set_field_slice("tan", Function::make(tan, ["num"]));
math
}
/// Initialise the `Math` object on the global object
pub fn init(global: Value) {
global.set_field_slice("Math", _create(global));
}

10
src/lib/js/mod.rs

@ -1,7 +1,13 @@
/// The global `Array` object
pub mod array;
/// The global `console` object
pub mod console;
/// The global `Error` object
pub mod error;
/// The global `Function` object and function value representations /// The global `Function` object and function value representations
pub mod function; pub mod function;
// /// The global `JSON` object /// The global `JSON` object
// pub mod json; pub mod json;
/// The global `Object` object /// The global `Object` object
pub mod object; pub mod object;
/// Javascript values, utility methods and conversion between Javascript values and Rust values /// Javascript values, utility methods and conversion between Javascript values and Rust values

34
src/lib/js/string.rs

@ -0,0 +1,34 @@
use js::function::Function;
use js::object::{Property, PROTOTYPE};
use js::value::{from_value, to_value, ResultValue, Value};
/// Create new string
pub fn make_string(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
this.set_field_slice("length", to_value(0i32));
Ok(Value::undefined())
}
/// Get a string's length
pub fn get_string_length(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
let this_str: String = from_value(this).unwrap();
Ok(to_value::<i32>(this_str.len() as i32))
}
/// Create a new `String` object
pub fn _create(global: Value) -> Value {
let string = Function::make(make_string, ["string"]);
let proto = Value::new_obj(Some(global));
let prop = Property {
configurable: false,
enumerable: false,
writable: false,
value: Value::undefined(),
get: Function::make(get_string_length, []),
set: Value::undefined(),
};
proto.set_prop_slice("length", prop);
string.set_field_slice(PROTOTYPE, proto);
string
}
/// Initialise the `String` object on the global object
pub fn init(global: Value) {
global.set_field_slice("String", _create(global));
}

3
src/lib/lib.rs

@ -1,5 +1,8 @@
extern crate gc; extern crate gc;
extern crate rand;
extern crate serde_json; extern crate serde_json;
extern crate time;
#[macro_use] #[macro_use]
extern crate gc_derive; extern crate gc_derive;

7
tests/value_test.rs

@ -15,6 +15,13 @@ fn check_string_to_value() {
assert_eq!(v.is_null(), false); assert_eq!(v.is_null(), false);
} }
#[test]
fn check_undefined() {
let u = Value::undefined();
assert_eq!(u.get_type(), "undefined");
assert_eq!(u.to_string(), "undefined");
}
#[test] #[test]
fn check_get_set_field() { fn check_get_set_field() {
let obj = Value::new_obj(None); let obj = Value::new_obj(None);

Loading…
Cancel
Save