From dd0f9678eeca93958f02e907821bab8f379c778a Mon Sep 17 00:00:00 2001 From: HalidOdat Date: Wed, 29 Apr 2020 23:53:13 +0200 Subject: [PATCH] fix #209 "Calling Array with one argument" (#328) * fix issue 209 "Calling Array with one argument" * Update boa/src/builtins/array/mod.rs Co-Authored-By: Iban Eguia * Changed from unimplemented to panic in array Co-authored-by: Iban Eguia --- boa/src/builtins/array/mod.rs | 40 +++++++++++++++++++++++---------- boa/src/builtins/array/tests.rs | 22 ++++++++++++++++++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index 156cd617e6..eee445e76a 100644 --- a/boa/src/builtins/array/mod.rs +++ b/boa/src/builtins/array/mod.rs @@ -101,15 +101,6 @@ pub fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result // Make a new Object which will internally represent the Array (mapping // between indices and values): this creates an Object with no prototype - // Create length - let length = Property::new() - .value(to_value(args.len() as i32)) - .writable(true) - .configurable(false) - .enumerable(false); - - this.set_prop("length".to_string(), length); - // Set Prototype let array_prototype = ctx .realm @@ -122,11 +113,36 @@ pub fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result // to its Javascript Identifier (global constructor method name) this.set_kind(ObjectKind::Array); - // And finally add our arguments in - for (n, value) in args.iter().enumerate() { - this.set_field_slice(&n.to_string(), value.clone()); + // add our arguments in + let mut length = args.len() as i32; + match args.len() { + 1 if args[0].is_integer() => { + length = from_value::(args[0].clone()).expect("Could not convert argument to i32"); + // TODO: It should not create an array of undefineds, but an empty array ("holy" array in V8) with length `n`. + for n in 0..length { + this.set_field_slice(&n.to_string(), Gc::new(ValueData::Undefined)); + } + } + 1 if args[0].is_double() => { + // TODO: throw `RangeError`. + panic!("RangeError: invalid array length"); + } + _ => { + for (n, value) in args.iter().enumerate() { + this.set_field_slice(&n.to_string(), value.clone()); + } + } } + // finally create length property + let length = Property::new() + .value(to_value(length)) + .writable(true) + .configurable(false) + .enumerable(false); + + this.set_prop("length".to_string(), length); + Ok(this.clone()) } diff --git a/boa/src/builtins/array/tests.rs b/boa/src/builtins/array/tests.rs index a114fef293..3319aa94fa 100644 --- a/boa/src/builtins/array/tests.rs +++ b/boa/src/builtins/array/tests.rs @@ -791,3 +791,25 @@ fn some() { assert_eq!(del_array_length, "3"); assert_eq!(result, "true"); } + +#[test] +fn call_array_constructor_with_one_argument() { + let realm = Realm::create(); + let mut engine = Executor::new(realm); + let init = r#" + var empty = new Array(0); + + var five = new Array(5); + + var one = new Array("Hello, world!"); + "#; + forward(&mut engine, init); + let result = forward(&mut engine, "empty.length"); + assert_eq!(result, "0"); + + let result = forward(&mut engine, "five.length"); + assert_eq!(result, "5"); + + let result = forward(&mut engine, "one.length"); + assert_eq!(result, "1"); +}