From 16d2c089bc48e1652c9effb3229ee362dc207283 Mon Sep 17 00:00:00 2001 From: nd419 <5161147+neeldug@users.noreply.github.com> Date: Tue, 29 Jun 2021 22:43:51 +0100 Subject: [PATCH 1/3] feat(boa): implements `at` method for string Closes #13 --- boa/src/builtins/string/mod.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index b2ee8972e0f..a37e4008247 100644 --- a/boa/src/builtins/string/mod.rs +++ b/boa/src/builtins/string/mod.rs @@ -134,6 +134,7 @@ impl BuiltIn for String { .method(Self::replace, "replace", 2) .method(Self::iterator, (symbol_iterator, "[Symbol.iterator]"), 0) .method(Self::search, "search", 1) + .method(Self::at, "at", 1) .build(); (Self::NAME, string_object.into(), Self::attribute()) @@ -266,6 +267,39 @@ impl String { } } + /// `String.prototype.at ( index )` + /// + /// This String object's at() method returns a String consisting of the single UTF-16 code unit located at the specified position. + /// Returns undefined if the given index cannot be found. + /// + /// More information: + /// - [ECMAScript reference][spec] + /// - [MDN documentation][mdn] + /// + /// [spec]: https://tc39.es/proposal-relative-indexing-method/#sec-string-prototype-additions + /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at + pub(crate) fn at(this: &Value, args: &[Value], context: &mut Context) -> Result { + let this = this.require_object_coercible(context)?; + let s = this.to_string(context)?; + let len = s.len(); + let relative_index = args + .get(0) + .cloned() + .expect("No index provided") + .to_integer(context)?; + let k = if relative_index < 0 as f64 { + len - (-relative_index as usize) + } else { + relative_index as usize + }; + + if let Some(utf16_val) = s.encode_utf16().nth(k) { + Ok(Value::from(from_u32(utf16_val as u32).unwrap())) + } else { + Ok(Value::undefined()) + } + } + /// `String.prototype.codePointAt( index )` /// /// The `codePointAt()` method returns an integer between `0` to `1114111` (`0x10FFFF`) representing the UTF-16 code unit at the given index. From ea985a5c96dc6581ff1719ea66b6e57bf8455eca Mon Sep 17 00:00:00 2001 From: nd419 <5161147+neeldug@users.noreply.github.com> Date: Wed, 30 Jun 2021 19:01:56 +0100 Subject: [PATCH 2/3] cleanup --- boa/src/builtins/string/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index a37e4008247..434e7dfedd7 100644 --- a/boa/src/builtins/string/mod.rs +++ b/boa/src/builtins/string/mod.rs @@ -276,7 +276,7 @@ impl String { /// - [ECMAScript reference][spec] /// - [MDN documentation][mdn] /// - /// [spec]: https://tc39.es/proposal-relative-indexing-method/#sec-string-prototype-additions + /// [spec]: https://tc39.es/proposal-relative-indexing-method/#sec-string.prototype.at /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at pub(crate) fn at(this: &Value, args: &[Value], context: &mut Context) -> Result { let this = this.require_object_coercible(context)?; @@ -285,7 +285,7 @@ impl String { let relative_index = args .get(0) .cloned() - .expect("No index provided") + .unwrap_or_default() .to_integer(context)?; let k = if relative_index < 0 as f64 { len - (-relative_index as usize) @@ -294,7 +294,9 @@ impl String { }; if let Some(utf16_val) = s.encode_utf16().nth(k) { - Ok(Value::from(from_u32(utf16_val as u32).unwrap())) + Ok(Value::from( + from_u32(u32::from(utf16_val)).expect("invalid utf-16 character"), + )) } else { Ok(Value::undefined()) } From 3b9806e20ec3447e77edcf3af327d9c2a531b569 Mon Sep 17 00:00:00 2001 From: nd419 <5161147+neeldug@users.noreply.github.com> Date: Wed, 30 Jun 2021 19:41:07 +0100 Subject: [PATCH 3/3] fix len --- boa/src/builtins/string/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index 434e7dfedd7..bb4bd9f5587 100644 --- a/boa/src/builtins/string/mod.rs +++ b/boa/src/builtins/string/mod.rs @@ -281,7 +281,7 @@ impl String { pub(crate) fn at(this: &Value, args: &[Value], context: &mut Context) -> Result { let this = this.require_object_coercible(context)?; let s = this.to_string(context)?; - let len = s.len(); + let len = s.encode_utf16().count(); let relative_index = args .get(0) .cloned()