From 5cfa527729482ffa077aeb3990cc0522235012c0 Mon Sep 17 00:00:00 2001 From: Lennart Buit <37534243+lennartbuit@users.noreply.github.com> Date: Fri, 28 Jun 2019 21:27:15 +0200 Subject: [PATCH] Add trim/trimStart/trimEnd to string prototype (#30) --- src/lib/js/string.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/lib/js/string.rs b/src/lib/js/string.rs index 4939173c81..135c119388 100644 --- a/src/lib/js/string.rs +++ b/src/lib/js/string.rs @@ -77,6 +77,42 @@ pub fn char_code_at(this: Value, _: Value, args: Vec) -> ResultValue { Ok(to_value(utf16_val as f64)) } +fn is_trimmable_whitespace(c: char) -> bool { + // The rust implementation of `trim` does not regard the same characters whitespace as ecma standard does + // + // Rust uses \p{White_Space} by default, which also includes: + // `\u{0085}' (next line) + // And does not include: + // '\u{FEFF}' (zero width non-breaking space) + match c { + // Explicit whitespace: https://tc39.es/ecma262/#sec-white-space + '\u{0009}' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true, + // Unicode Space_Seperator category + '\u{1680}' | '\u{2000}'..='\u{200A}' | '\u{202F}' | '\u{205F}' | '\u{3000}' => true, + // Line terminators: https://tc39.es/ecma262/#sec-line-terminators + '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}' => true, + _ => false, + } +} + +pub fn trim(this: Value, _: Value, _: Vec) -> ResultValue { + let this_str: String = + from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap(); + Ok(to_value(this_str.trim_matches(is_trimmable_whitespace))) +} + +pub fn trim_start(this: Value, _: Value, _: Vec) -> ResultValue { + let this_str: String = + from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap(); + Ok(to_value(this_str.trim_start_matches(is_trimmable_whitespace))) +} + +pub fn trim_end(this: Value, _: Value, _: Vec) -> ResultValue { + let this_str: String = + from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap(); + Ok(to_value(this_str.trim_end_matches(is_trimmable_whitespace))) +} + /// Create a new `String` object pub fn _create(global: &Value) -> Value { let string = to_value(make_string as NativeFunctionData); @@ -93,6 +129,9 @@ pub fn _create(global: &Value) -> Value { proto.set_field_slice("charAt", to_value(char_at as NativeFunctionData)); proto.set_field_slice("charCodeAt", to_value(char_code_at as NativeFunctionData)); proto.set_field_slice("toString", to_value(to_string as NativeFunctionData)); + proto.set_field_slice("trim", to_value(trim as NativeFunctionData)); + proto.set_field_slice("trimStart", to_value(trim_start as NativeFunctionData)); + proto.set_field_slice("trimEnd", to_value(trim_end as NativeFunctionData)); string.set_field_slice(PROTOTYPE, proto); string }