|
|
|
@ -14,8 +14,7 @@ mod tests;
|
|
|
|
|
|
|
|
|
|
use crate::{ |
|
|
|
|
builtins::{ |
|
|
|
|
function::NativeFunctionData, |
|
|
|
|
object::{Object, ObjectKind, INSTANCE_PROTOTYPE, PROTOTYPE}, |
|
|
|
|
object::{Object, ObjectInternalMethods, ObjectKind, INSTANCE_PROTOTYPE, PROTOTYPE}, |
|
|
|
|
property::Property, |
|
|
|
|
value::{from_value, to_value, undefined, ResultValue, Value, ValueData}, |
|
|
|
|
}, |
|
|
|
@ -24,6 +23,7 @@ use crate::{
|
|
|
|
|
use gc::Gc; |
|
|
|
|
use std::borrow::Borrow; |
|
|
|
|
use std::cmp::{max, min}; |
|
|
|
|
use std::ops::Deref; |
|
|
|
|
|
|
|
|
|
/// Creates a new `Array` instance.
|
|
|
|
|
pub(crate) fn new_array(interpreter: &Interpreter) -> ResultValue { |
|
|
|
@ -97,7 +97,7 @@ pub(crate) fn add_to_array_object(array_ptr: &Value, add_values: &[Value]) -> Re
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Create a new array
|
|
|
|
|
pub fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn make_array(this: &mut Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
// Make a new Object which will internally represent the Array (mapping
|
|
|
|
|
// between indices and values): this creates an Object with no prototype
|
|
|
|
|
|
|
|
|
@ -157,7 +157,7 @@ pub fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.isarray
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
|
|
|
|
|
pub fn is_array(_this: &Value, args: &[Value], _interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn is_array(_this: &mut Value, args: &[Value], _interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
let value_true = Gc::new(ValueData::Boolean(true)); |
|
|
|
|
let value_false = Gc::new(ValueData::Boolean(false)); |
|
|
|
|
|
|
|
|
@ -167,7 +167,7 @@ pub fn is_array(_this: &Value, args: &[Value], _interpreter: &mut Interpreter) -
|
|
|
|
|
// 1.
|
|
|
|
|
ValueData::Object(ref obj) => { |
|
|
|
|
// 2.
|
|
|
|
|
if obj.borrow().kind == ObjectKind::Array { |
|
|
|
|
if (*obj).deref().borrow().kind == ObjectKind::Array { |
|
|
|
|
return Ok(value_true); |
|
|
|
|
} |
|
|
|
|
Ok(value_false) |
|
|
|
@ -192,7 +192,7 @@ pub fn is_array(_this: &Value, args: &[Value], _interpreter: &mut Interpreter) -
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.concat
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
|
|
|
|
|
pub fn concat(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn concat(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
// If concat is called with no arguments, it returns the original array
|
|
|
|
|
return Ok(this.clone()); |
|
|
|
@ -231,7 +231,7 @@ pub fn concat(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.push
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
|
|
|
|
|
pub fn push(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn push(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let new_array = add_to_array_object(this, args)?; |
|
|
|
|
Ok(new_array.get_field_slice("length")) |
|
|
|
|
} |
|
|
|
@ -246,7 +246,7 @@ pub fn push(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.pop
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
|
|
|
|
|
pub fn pop(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn pop(this: &mut Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let curr_length: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not convert argument to i32"); |
|
|
|
|
if curr_length < 1 { |
|
|
|
@ -269,7 +269,7 @@ pub fn pop(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.foreach
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
|
|
|
|
|
pub fn for_each(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn for_each(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Err(to_value( |
|
|
|
|
"Missing argument for Array.prototype.forEach".to_string(), |
|
|
|
@ -277,16 +277,16 @@ pub fn for_each(this: &Value, args: &[Value], interpreter: &mut Interpreter) ->
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let callback_arg = args.get(0).expect("Could not get `callbackFn` argument."); |
|
|
|
|
let this_arg = args.get(1).cloned().unwrap_or_else(undefined); |
|
|
|
|
let mut this_arg = args.get(1).cloned().unwrap_or_else(undefined); |
|
|
|
|
|
|
|
|
|
let length: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not get `length` property."); |
|
|
|
|
|
|
|
|
|
for i in 0..length { |
|
|
|
|
let element = this.get_field_slice(&i.to_string()); |
|
|
|
|
let arguments = vec![element.clone(), to_value(i), this.clone()]; |
|
|
|
|
let arguments = [element, to_value(i), this.clone()]; |
|
|
|
|
|
|
|
|
|
interpreter.call(callback_arg, &this_arg, arguments)?; |
|
|
|
|
interpreter.call(callback_arg, &mut this_arg, &arguments)?; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(Gc::new(ValueData::Undefined)) |
|
|
|
@ -304,7 +304,7 @@ pub fn for_each(this: &Value, args: &[Value], interpreter: &mut Interpreter) ->
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.join
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join
|
|
|
|
|
pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn join(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let separator = if args.is_empty() { |
|
|
|
|
String::from(",") |
|
|
|
|
} else { |
|
|
|
@ -334,7 +334,7 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.tostring
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString
|
|
|
|
|
pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn to_string(this: &mut Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let method_name = "join"; |
|
|
|
|
let mut arguments = vec![to_value(",")]; |
|
|
|
|
// 2.
|
|
|
|
@ -350,10 +350,10 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul
|
|
|
|
|
.get_field_slice("toString"); |
|
|
|
|
|
|
|
|
|
method = from_value(method).expect("failed to get Object.prototype.toString"); |
|
|
|
|
arguments = vec![]; |
|
|
|
|
arguments = Vec::new(); |
|
|
|
|
} |
|
|
|
|
// 4.
|
|
|
|
|
let join_result = _ctx.call(&method, this, arguments); |
|
|
|
|
let join_result = _ctx.call(&method, this, &arguments); |
|
|
|
|
let match_string = match join_result { |
|
|
|
|
Ok(v) => match *v { |
|
|
|
|
ValueData::String(ref s) => (*s).clone(), |
|
|
|
@ -376,7 +376,7 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.reverse
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
|
|
|
|
|
#[allow(clippy::else_if_without_else)] |
|
|
|
|
pub fn reverse(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn reverse(this: &mut Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let len: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not convert argument to i32"); |
|
|
|
|
let middle: i32 = len.wrapping_div(2); |
|
|
|
@ -415,7 +415,7 @@ pub fn reverse(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.shift
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
|
|
|
|
|
pub fn shift(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn shift(this: &mut Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let len: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not convert argument to i32"); |
|
|
|
|
|
|
|
|
@ -458,7 +458,7 @@ pub fn shift(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.unshift
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
|
|
|
|
|
pub fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn unshift(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let len: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not convert argument to i32"); |
|
|
|
|
let arg_c: i32 = args.len() as i32; |
|
|
|
@ -503,14 +503,14 @@ pub fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.every
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
|
|
|
|
|
pub fn every(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn every(this: &mut 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 { |
|
|
|
|
let mut this_arg = if args.len() > 1 { |
|
|
|
|
args[1].clone() |
|
|
|
|
} else { |
|
|
|
|
Gc::new(ValueData::Undefined) |
|
|
|
@ -520,8 +520,10 @@ pub fn every(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Res
|
|
|
|
|
let mut len = max_len; |
|
|
|
|
while i < len { |
|
|
|
|
let element = this.get_field_slice(&i.to_string()); |
|
|
|
|
let arguments = vec![element.clone(), to_value(i), this.clone()]; |
|
|
|
|
let result = interpreter.call(callback, &this_arg, arguments)?.is_true(); |
|
|
|
|
let arguments = [element, to_value(i), this.clone()]; |
|
|
|
|
let result = interpreter |
|
|
|
|
.call(callback, &mut this_arg, &arguments)? |
|
|
|
|
.is_true(); |
|
|
|
|
if !result { |
|
|
|
|
return Ok(to_value(false)); |
|
|
|
|
} |
|
|
|
@ -542,7 +544,7 @@ pub fn every(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Res
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.map
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
|
|
|
|
|
pub fn map(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn map(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Err(to_value( |
|
|
|
|
"missing argument 0 when calling function Array.prototype.map", |
|
|
|
@ -550,7 +552,7 @@ pub fn map(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resul
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let callback = args.get(0).cloned().unwrap_or_else(undefined); |
|
|
|
|
let this_val = args.get(1).cloned().unwrap_or_else(undefined); |
|
|
|
|
let mut this_val = args.get(1).cloned().unwrap_or_else(undefined); |
|
|
|
|
|
|
|
|
|
let length: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not get `length` property."); |
|
|
|
@ -560,11 +562,10 @@ pub fn map(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resul
|
|
|
|
|
let values = (0..length) |
|
|
|
|
.map(|idx| { |
|
|
|
|
let element = this.get_field_slice(&idx.to_string()); |
|
|
|
|
|
|
|
|
|
let args = vec![element, to_value(idx), new.clone()]; |
|
|
|
|
let args = [element, to_value(idx), new.clone()]; |
|
|
|
|
|
|
|
|
|
interpreter |
|
|
|
|
.call(&callback, &this_val, args) |
|
|
|
|
.call(&callback, &mut this_val, &args) |
|
|
|
|
.unwrap_or_else(|_| undefined()) |
|
|
|
|
}) |
|
|
|
|
.collect::<Vec<Value>>(); |
|
|
|
@ -591,7 +592,7 @@ pub fn map(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resul
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.indexof
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
|
|
|
|
|
pub fn index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn index_of(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
// If no arguments, return -1. Not described in spec, but is what chrome does.
|
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Ok(to_value(-1)); |
|
|
|
@ -646,7 +647,7 @@ pub fn index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValu
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.lastindexof
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf
|
|
|
|
|
pub fn last_index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn last_index_of(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
// If no arguments, return -1. Not described in spec, but is what chrome does.
|
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Ok(to_value(-1)); |
|
|
|
@ -695,14 +696,14 @@ pub fn last_index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> Resul
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.find
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
|
|
|
|
|
pub fn find(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn find(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Err(to_value( |
|
|
|
|
"missing callback when calling function Array.prototype.find".to_string(), |
|
|
|
|
)); |
|
|
|
|
} |
|
|
|
|
let callback = &args[0]; |
|
|
|
|
let this_arg = if args.len() > 1 { |
|
|
|
|
let mut this_arg = if args.len() > 1 { |
|
|
|
|
args[1].clone() |
|
|
|
|
} else { |
|
|
|
|
Gc::new(ValueData::Undefined) |
|
|
|
@ -710,8 +711,8 @@ pub fn find(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resu
|
|
|
|
|
let len: i32 = from_value(this.get_field_slice("length")).unwrap(); |
|
|
|
|
for i in 0..len { |
|
|
|
|
let element = this.get_field_slice(&i.to_string()); |
|
|
|
|
let arguments = vec![element.clone(), to_value(i), this.clone()]; |
|
|
|
|
let result = interpreter.call(callback, &this_arg, arguments)?; |
|
|
|
|
let arguments = [element.clone(), to_value(i), this.clone()]; |
|
|
|
|
let result = interpreter.call(callback, &mut this_arg, &arguments)?; |
|
|
|
|
if result.is_true() { |
|
|
|
|
return Ok(element); |
|
|
|
|
} |
|
|
|
@ -731,7 +732,7 @@ pub fn find(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resu
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.findindex
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
|
|
|
|
|
pub fn find_index(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn find_index(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Err(to_value( |
|
|
|
|
"Missing argument for Array.prototype.findIndex".to_string(), |
|
|
|
@ -740,7 +741,7 @@ pub fn find_index(this: &Value, args: &[Value], interpreter: &mut Interpreter) -
|
|
|
|
|
|
|
|
|
|
let predicate_arg = args.get(0).expect("Could not get `predicate` argument."); |
|
|
|
|
|
|
|
|
|
let this_arg = args |
|
|
|
|
let mut this_arg = args |
|
|
|
|
.get(1) |
|
|
|
|
.cloned() |
|
|
|
|
.unwrap_or_else(|| Gc::new(ValueData::Undefined)); |
|
|
|
@ -750,9 +751,9 @@ pub fn find_index(this: &Value, args: &[Value], interpreter: &mut Interpreter) -
|
|
|
|
|
|
|
|
|
|
for i in 0..length { |
|
|
|
|
let element = this.get_field_slice(&i.to_string()); |
|
|
|
|
let arguments = vec![element.clone(), to_value(i), this.clone()]; |
|
|
|
|
let arguments = [element, to_value(i), this.clone()]; |
|
|
|
|
|
|
|
|
|
let result = interpreter.call(predicate_arg, &this_arg, arguments)?; |
|
|
|
|
let result = interpreter.call(predicate_arg, &mut this_arg, &arguments)?; |
|
|
|
|
|
|
|
|
|
if result.is_true() { |
|
|
|
|
return Ok(Gc::new(ValueData::Rational(f64::from(i)))); |
|
|
|
@ -773,7 +774,7 @@ pub fn find_index(this: &Value, args: &[Value], interpreter: &mut Interpreter) -
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.fill
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
|
|
|
|
|
pub fn fill(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn fill(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let len: i32 = from_value(this.get_field_slice("length")).expect("Could not get argument"); |
|
|
|
|
let default_value = undefined(); |
|
|
|
|
let value = args.get(0).unwrap_or(&default_value); |
|
|
|
@ -812,7 +813,7 @@ pub fn fill(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.includes
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
|
|
|
|
|
pub fn includes_value(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn includes_value(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let search_element = args |
|
|
|
|
.get(0) |
|
|
|
|
.cloned() |
|
|
|
@ -846,7 +847,7 @@ pub fn includes_value(this: &Value, args: &[Value], _: &mut Interpreter) -> Resu
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.slice
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
|
|
|
|
|
pub fn slice(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn slice(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
let new_array = new_array(interpreter)?; |
|
|
|
|
let len: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not convert argument to i32"); |
|
|
|
@ -895,7 +896,7 @@ pub fn slice(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Res
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.filter
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
|
|
|
|
|
pub fn filter(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn filter(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Err(to_value( |
|
|
|
|
"missing argument 0 when calling function Array.prototype.filter", |
|
|
|
@ -903,7 +904,7 @@ pub fn filter(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Re
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let callback = args.get(0).cloned().unwrap_or_else(undefined); |
|
|
|
|
let this_val = args.get(1).cloned().unwrap_or_else(undefined); |
|
|
|
|
let mut this_val = args.get(1).cloned().unwrap_or_else(undefined); |
|
|
|
|
|
|
|
|
|
let length: i32 = |
|
|
|
|
from_value(this.get_field_slice("length")).expect("Could not get `length` property."); |
|
|
|
@ -914,10 +915,10 @@ pub fn filter(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Re
|
|
|
|
|
.filter_map(|idx| { |
|
|
|
|
let element = this.get_field_slice(&idx.to_string()); |
|
|
|
|
|
|
|
|
|
let args = vec![element.clone(), to_value(idx), new.clone()]; |
|
|
|
|
let args = [element.clone(), to_value(idx), new.clone()]; |
|
|
|
|
|
|
|
|
|
let callback_result = interpreter |
|
|
|
|
.call(&callback, &this_val, args) |
|
|
|
|
.call(&callback, &mut this_val, &args) |
|
|
|
|
.unwrap_or_else(|_| undefined()); |
|
|
|
|
|
|
|
|
|
if callback_result.is_true() { |
|
|
|
@ -946,14 +947,14 @@ pub fn filter(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Re
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.some
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
|
|
|
|
|
pub fn some(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
pub fn some(this: &mut Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue { |
|
|
|
|
if args.is_empty() { |
|
|
|
|
return Err(to_value( |
|
|
|
|
"missing callback when calling function Array.prototype.some".to_string(), |
|
|
|
|
)); |
|
|
|
|
} |
|
|
|
|
let callback = &args[0]; |
|
|
|
|
let this_arg = if args.len() > 1 { |
|
|
|
|
let mut this_arg = if args.len() > 1 { |
|
|
|
|
args[1].clone() |
|
|
|
|
} else { |
|
|
|
|
Gc::new(ValueData::Undefined) |
|
|
|
@ -963,8 +964,10 @@ pub fn some(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resu
|
|
|
|
|
let mut len = max_len; |
|
|
|
|
while i < len { |
|
|
|
|
let element = this.get_field_slice(&i.to_string()); |
|
|
|
|
let arguments = vec![element.clone(), to_value(i), this.clone()]; |
|
|
|
|
let result = interpreter.call(callback, &this_arg, arguments)?.is_true(); |
|
|
|
|
let arguments = [element, to_value(i), this.clone()]; |
|
|
|
|
let result = interpreter |
|
|
|
|
.call(callback, &mut this_arg, &arguments)? |
|
|
|
|
.is_true(); |
|
|
|
|
if result { |
|
|
|
|
return Ok(to_value(true)); |
|
|
|
|
} |
|
|
|
@ -977,14 +980,6 @@ pub fn some(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resu
|
|
|
|
|
|
|
|
|
|
/// Create a new `Array` object.
|
|
|
|
|
pub fn create_constructor(global: &Value) -> Value { |
|
|
|
|
// Create Constructor
|
|
|
|
|
let object_prototype = global.get_field_slice("Object").get_field_slice(PROTOTYPE); |
|
|
|
|
let mut array_constructor = Object::create(object_prototype); |
|
|
|
|
array_constructor.kind = ObjectKind::Function; |
|
|
|
|
array_constructor.set_internal_method("construct", make_array); |
|
|
|
|
// Todo: add call function
|
|
|
|
|
array_constructor.set_internal_method("call", make_array); |
|
|
|
|
|
|
|
|
|
// Create prototype
|
|
|
|
|
let array_prototype = ValueData::new_obj(None); |
|
|
|
|
let length = Property::default().value(to_value(0_i32)); |
|
|
|
@ -1011,10 +1006,9 @@ pub fn create_constructor(global: &Value) -> Value {
|
|
|
|
|
make_builtin_fn!(slice, named "slice", with length 2, of array_prototype); |
|
|
|
|
make_builtin_fn!(some, named "some", with length 2, of array_prototype); |
|
|
|
|
|
|
|
|
|
let array = to_value(array_constructor); |
|
|
|
|
let array = make_constructor_fn!(make_array, make_array, global, array_prototype); |
|
|
|
|
// Static Methods
|
|
|
|
|
make_builtin_fn!(is_array, named "isArray", with length 1, of array); |
|
|
|
|
array.set_field_slice(PROTOTYPE, to_value(array_prototype.clone())); |
|
|
|
|
|
|
|
|
|
array_prototype.set_field_slice("constructor", array.clone()); |
|
|
|
|
array |
|
|
|
|
} |
|
|
|
|