From 69a4a0f91e2b8eb4f82d16f8c3313976ad401013 Mon Sep 17 00:00:00 2001 From: cisen Date: Sun, 12 Jan 2020 22:23:13 +0800 Subject: [PATCH 1/7] feat: Implement Array.prototype.toString --- src/lib/builtins/array.rs | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index 48b1da2a779..56ca7eb1707 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -198,6 +198,28 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { Ok(to_value(elem_strs.join(&separator))) } +/// Array.prototype.toString ( separator ) +/// +/// The toString function is intentionally generic; it does not require that +/// its this value be an Array object. Therefore it can be transferred to +/// other kinds of objects for use as a method. +/// +pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { + let join_result = join(this, &[to_value("")], _ctx); + let match_string = match join_result { + Ok(v) => { + match *v { + ValueData::String(ref s) => { + (*s).clone() + }, + _ => "".to_string() + } + }, + Err(v) => format!("{}: {}", "error", v.to_string()), + }; + Ok(to_value(match_string)) +} + /// Array.prototype.reverse ( ) /// /// The elements of the array are rearranged so as to reverse their order. @@ -667,6 +689,7 @@ pub fn create_constructor(global: &Value) -> Value { 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); make_builtin_fn!(reverse, named "reverse", of array_prototype); make_builtin_fn!(shift, named "shift", of array_prototype); make_builtin_fn!(unshift, named "unshift", with length 1, of array_prototype); @@ -733,6 +756,27 @@ mod tests { assert_eq!(many, String::from("a.b.c")); } + #[test] + fn to_string() { + let realm = Realm::create(); + let mut engine = Executor::new(realm); + let init = r#" + var empty = [ ]; + var one = ["a"]; + var many = ["a", "b", "c"]; + "#; + forward(&mut engine, init); + // Empty + let empty = forward(&mut engine, "empty.toString()"); + assert_eq!(empty, String::from("")); + // One + let one = forward(&mut engine, "one.toString()"); + assert_eq!(one, String::from("a")); + // Many + let many = forward(&mut engine, "many.toString()"); + assert_eq!(many, String::from("a,b,c")); + } + #[test] fn every() { let realm = Realm::create(); From e080cbb7a12664843f12179f3f94540dc19b52b5 Mon Sep 17 00:00:00 2001 From: cisen Date: Sun, 12 Jan 2020 22:51:43 +0800 Subject: [PATCH 2/7] fix: fix the missing arguments for Array.prototype.toString's inner join --- src/lib/builtins/array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index 56ca7eb1707..bb44581a572 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -205,7 +205,7 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { /// other kinds of objects for use as a method. /// pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { - let join_result = join(this, &[to_value("")], _ctx); + let join_result = join(this, &[to_value(",")], _ctx); let match_string = match join_result { Ok(v) => { match *v { From faa91ae65866711d465424884e7bb4563a218e2f Mon Sep 17 00:00:00 2001 From: cisen Date: Sun, 12 Jan 2020 23:05:35 +0800 Subject: [PATCH 3/7] refactor: use fmt to beautify the code --- src/lib/builtins/array.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index bb44581a572..2a1c9d5b3aa 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -207,13 +207,9 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { let join_result = join(this, &[to_value(",")], _ctx); let match_string = match join_result { - Ok(v) => { - match *v { - ValueData::String(ref s) => { - (*s).clone() - }, - _ => "".to_string() - } + Ok(v) => match *v { + ValueData::String(ref s) => (*s).clone(), + _ => "".to_string(), }, Err(v) => format!("{}: {}", "error", v.to_string()), }; From dfcec219a2527675700027abff3204196e878471 Mon Sep 17 00:00:00 2001 From: cisen Date: Mon, 13 Jan 2020 23:19:08 +0800 Subject: [PATCH 4/7] =?UTF-8?q?refactor:=20Array.prototype.toString?= =?UTF-8?q?=E2=80=94=E2=80=94smplify=20error=20formating?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/builtins/array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index 2a1c9d5b3aa..516a977627c 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -211,7 +211,7 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul ValueData::String(ref s) => (*s).clone(), _ => "".to_string(), }, - Err(v) => format!("{}: {}", "error", v.to_string()), + Err(v) => format!("error: {}", v), }; Ok(to_value(match_string)) } From 8b06b25552385bc335f5e9b7be794fac94612069 Mon Sep 17 00:00:00 2001 From: cisen Date: Sun, 19 Jan 2020 00:05:06 +0800 Subject: [PATCH 5/7] fix: Array.prototype.toString should be called by ES value --- src/lib/builtins/array.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index 516a977627c..39296d2eb01 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -205,7 +205,33 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { /// other kinds of objects for use as a method. /// pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { - let join_result = join(this, &[to_value(",")], _ctx); + let method_name = "join"; + let arguments = vec![to_value(",")]; + // 2. + let method: Value = + from_value(this.get_field_slice(method_name)).expect("failed to get Object.prototype.join"); + // 3. + if !method.is_function() { + let mut object_to_string = _ctx + .realm + .global_obj + .get_field_slice("Object") + .get_field_slice(PROTOTYPE) + .get_field_slice("toString"); + + object_to_string = + from_value(object_to_string).expect("failed to get Object.prototype.toString"); + let fun_result = _ctx.call(&object_to_string, this, vec![]); + let match_string = match fun_result { + Ok(v) => match *v { + ValueData::String(ref s) => (*s).clone(), + _ => "".to_string(), + }, + Err(v) => format!("error: {}", v), + }; + return Ok(to_value(match_string)); + } + let join_result = _ctx.call(&method, this, arguments); let match_string = match join_result { Ok(v) => match *v { ValueData::String(ref s) => (*s).clone(), From 537872c49fa8a67630a6a3a1b25242f0c2df00b0 Mon Sep 17 00:00:00 2001 From: unknown <80275879@adc.com> Date: Mon, 20 Jan 2020 21:03:09 +0800 Subject: [PATCH 6/7] fix: fix the error message --- src/lib/builtins/array.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index 39296d2eb01..075c8a7ad75 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -209,7 +209,7 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul let arguments = vec![to_value(",")]; // 2. let method: Value = - from_value(this.get_field_slice(method_name)).expect("failed to get Object.prototype.join"); + from_value(this.get_field_slice(method_name)).expect("failed to get Array.prototype.join"); // 3. if !method.is_function() { let mut object_to_string = _ctx @@ -231,6 +231,7 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul }; return Ok(to_value(match_string)); } + // 4. let join_result = _ctx.call(&method, this, arguments); let match_string = match join_result { Ok(v) => match *v { From 0d4760d29493a7b2645f1975b3f55de0b1e6904a Mon Sep 17 00:00:00 2001 From: cisen Date: Mon, 27 Jan 2020 19:41:17 +0800 Subject: [PATCH 7/7] refactor: Array.prototype.toString remove the duplicated logic --- src/lib/builtins/array.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/lib/builtins/array.rs b/src/lib/builtins/array.rs index 075c8a7ad75..b46753e240b 100644 --- a/src/lib/builtins/array.rs +++ b/src/lib/builtins/array.rs @@ -206,30 +206,21 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { /// pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue { let method_name = "join"; - let arguments = vec![to_value(",")]; + let mut arguments = vec![to_value(",")]; // 2. - let method: Value = + let mut method: Value = from_value(this.get_field_slice(method_name)).expect("failed to get Array.prototype.join"); // 3. if !method.is_function() { - let mut object_to_string = _ctx + method = _ctx .realm .global_obj .get_field_slice("Object") .get_field_slice(PROTOTYPE) .get_field_slice("toString"); - object_to_string = - from_value(object_to_string).expect("failed to get Object.prototype.toString"); - let fun_result = _ctx.call(&object_to_string, this, vec![]); - let match_string = match fun_result { - Ok(v) => match *v { - ValueData::String(ref s) => (*s).clone(), - _ => "".to_string(), - }, - Err(v) => format!("error: {}", v), - }; - return Ok(to_value(match_string)); + method = from_value(method).expect("failed to get Object.prototype.toString"); + arguments = vec![]; } // 4. let join_result = _ctx.call(&method, this, arguments);