Browse Source

Add Array.prototype.every method fixes #163 (#157)

* Make Interpreter::call crate public

* Add Array.prototype.every method
pull/174/head
letmutx 5 years ago committed by Jason Williams
parent
commit
6038c32de9
  1. 81
      src/lib/js/array.rs

81
src/lib/js/array.rs

@ -271,6 +271,41 @@ pub fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue
Ok(to_value(temp))
}
/// Array.prototype.every ( callback, [ thisArg ] )
///
/// The every method executes the provided callback function once for each
/// element present in the array until it finds the one where callback returns
/// a falsy value. It returns `false` if it finds such element, otherwise it
/// returns `true`.
/// <https://tc39.es/ecma262/#sec-array.prototype.every/>
pub fn every(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue {
if args.is_empty() {
return Err(to_value(
"missing callback when calling function Array.prototype.every".to_string(),
));
}
let callback = &args[0];
let this_arg = if args.len() > 1 {
args[1].clone()
} else {
Gc::new(ValueData::Undefined)
};
let mut i = 0;
let max_len: i32 = from_value(this.get_field_slice("length")).unwrap();
let mut len = max_len;
while i < len {
let element = this.get_field(&i.to_string());
let arguments = vec![element.clone(), to_value(i), this.clone()];
let result = interpreter.call(callback, &this_arg, arguments)?.is_true();
if !result {
return Ok(to_value(false));
}
len = std::cmp::min(max_len, from_value(this.get_field_slice("length")).unwrap());
i += 1;
}
Ok(to_value(true))
}
/// Array.prototype.indexOf ( searchElement[, fromIndex ] )
///
///
@ -431,6 +466,7 @@ pub fn create_constructor(global: &Value) -> Value {
array_prototype.set_field_slice("reverse", to_value(reverse as NativeFunctionData));
array_prototype.set_field_slice("shift", to_value(shift as NativeFunctionData));
array_prototype.set_field_slice("unshift", to_value(unshift as NativeFunctionData));
array_prototype.set_field_slice("every", to_value(every as NativeFunctionData));
array_prototype.set_field_slice("find", to_value(find as NativeFunctionData));
array_prototype.set_field_slice("indexOf", index_of_func);
array_prototype.set_field_slice("lastIndexOf", last_index_of_func);
@ -493,6 +529,51 @@ mod tests {
assert_eq!(many, String::from("a.b.c"));
}
#[test]
fn every() {
let realm = Realm::create();
let mut engine = Executor::new(realm);
// taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
let init = r#"
let empty = [];
let array = [11, 23, 45];
function callback(element) {
return element > 10;
}
function callback2(element) {
return element < 10;
}
let appendArray = [1,2,3,4];
function appendingCallback(elem,index,arr) {
arr.push('new');
return elem !== "new";
}
let delArray = [1,2,3,4];
function deletingCallback(elem,index,arr) {
arr.pop()
return elem < 3;
}
"#;
forward(&mut engine, init);
let result = forward(&mut engine, "array.every(callback);");
assert_eq!(result, "true");
let result = forward(&mut engine, "empty.every(callback);");
assert_eq!(result, "true");
let result = forward(&mut engine, "array.every(callback2);");
assert_eq!(result, "false");
let result = forward(&mut engine, "appendArray.every(appendingCallback);");
assert_eq!(result, "true");
let result = forward(&mut engine, "delArray.every(deletingCallback);");
assert_eq!(result, "true");
}
#[test]
fn find() {
let realm = Realm::create();

Loading…
Cancel
Save