Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addition of forEach() #268

Merged
merged 3 commits into from
Mar 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
"type": "lldb",
"request": "launch",
"name": "Launch",
"windows": {
"program": "${workspaceFolder}/target/debug/boa_cli.exe"
},
"program": "${workspaceFolder}/target/debug/boa_cli",
"args": ["${workspaceFolder}/tests/js/test.js"],
"sourceLanguages": ["rust"]
},
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"args": ["${workspaceFolder}/tests/js/test.js"],
"program": "${workspaceFolder}/target/debug/boa_cli.exe",
"cwd": "${workspaceFolder}",
"sourceFileMap": {
Expand Down
6 changes: 6 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"clear": true
}
},
{
Expand All @@ -23,6 +26,9 @@
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"clear": true
}
}
]
Expand Down
29 changes: 28 additions & 1 deletion boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,33 @@ pub fn pop(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(pop_value)
}

/// Array.prototype.forEach ( callbackFn [ , thisArg ] )
///
/// This method executes the provided callback function for each element in the array.
/// <https://tc39.es/ecma262/#sec-array.prototype.foreach>
pub fn for_each(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue {
if args.is_empty() {
return Err(to_value(
"Missing argument for Array.prototype.forEach".to_string(),
));
}

let callback_arg = args.get(0).expect("Could not get `callbackFn` argument.");
let 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()];

interpreter.call(callback_arg, &this_arg, arguments)?;
}

Ok(Gc::new(ValueData::Undefined))
}

/// Array.prototype.join ( separator )
///
/// The elements of the array are converted to Strings, and these Strings are
Expand Down Expand Up @@ -732,7 +759,7 @@ pub fn create_constructor(global: &Value) -> Value {
make_builtin_fn!(includes_value, named "includes", with length 1, of array_prototype);
make_builtin_fn!(map, named "map", with length 1, of array_prototype);
make_builtin_fn!(fill, named "fill", with length 1, of array_prototype);

make_builtin_fn!(for_each, named "forEach", with length 1, of array_prototype);
make_builtin_fn!(pop, named "pop", of array_prototype);
make_builtin_fn!(join, named "join", with length 1, of array_prototype);
make_builtin_fn!(to_string, named "toString", of array_prototype);
Expand Down
44 changes: 44 additions & 0 deletions boa/src/builtins/array/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,47 @@ fn slice() {
assert_eq!(forward(&mut engine, "many2.length"), "1");
assert_eq!(forward(&mut engine, "many3.length"), "0");
}

#[test]
fn for_each() {
let realm = Realm::create();
let mut engine = Executor::new(realm);
let init = r#"
var a = [2, 3, 4, 5];
var sum = 0;
var indexSum = 0;
var listLengthSum = 0;
function callingCallback(item, index, list) {
sum += item;
indexSum += index;
listLengthSum += list.length;
}
a.forEach(callingCallback);
"#;
forward(&mut engine, init);

assert_eq!(forward(&mut engine, "sum"), "14");
assert_eq!(forward(&mut engine, "indexSum"), "6");
assert_eq!(forward(&mut engine, "listLengthSum"), "16");
}

#[test]
fn for_each_push_value() {
let realm = Realm::create();
let mut engine = Executor::new(realm);
let init = r#"
var a = [1, 2, 3, 4];
function callingCallback(item, index, list) {
list.push(item * 2);
}
a.forEach(callingCallback);
"#;
forward(&mut engine, init);

// [ 1, 2, 3, 4, 2, 4, 6, 8 ]
assert_eq!(forward(&mut engine, "a.length"), "8");
assert_eq!(forward(&mut engine, "a[4]"), "2");
assert_eq!(forward(&mut engine, "a[5]"), "4");
assert_eq!(forward(&mut engine, "a[6]"), "6");
assert_eq!(forward(&mut engine, "a[7]"), "8");
}