Skip to content

Commit

Permalink
Update js-sys with new features (#2824)
Browse files Browse the repository at this point in the history
* js-sys: add `String#matchAll`

* js-sys: add `String#replaceAll`

* js-sys: add `Promise#allSettled`

* js-sys: add `Promise#any`

* js-sys: add `.at()` for indexed collections

* js-sys: add `Object.hasOwn()`

* js-sys: add `Error` options and `cause`
  • Loading branch information
joshyrobot committed Mar 1, 2022
1 parent a608959 commit 26fee7f
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 0 deletions.
89 changes: 89 additions & 0 deletions crates/js-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ extern "C" {
#[wasm_bindgen(constructor)]
pub fn new_with_length(len: u32) -> Array;

/// Retrieves the element at the index, counting from the end if negative
/// (returns `undefined` if the index is out of range).
#[wasm_bindgen(method)]
pub fn at(this: &Array, index: i32) -> JsValue;

/// Retrieves the element at the index (returns `undefined` if the index is out of range).
#[wasm_bindgen(method, structural, indexing_getter)]
pub fn get(this: &Array, index: u32) -> JsValue;
Expand Down Expand Up @@ -1483,6 +1488,17 @@ extern "C" {
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
#[wasm_bindgen(constructor)]
pub fn new(message: &str) -> Error;
#[wasm_bindgen(constructor)]
pub fn new_with_options(message: &str, options: &Object) -> Error;

/// The cause property is the underlying cause of the error.
/// Usually this is used to add context to re-thrown errors.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#differentiate_between_similar_errors)
#[wasm_bindgen(method, getter, structural)]
pub fn cause(this: &Error) -> JsValue;
#[wasm_bindgen(method, setter, structural)]
pub fn set_cause(this: &Error, cause: &JsValue);

/// The message property is a human-readable description of the error.
///
Expand Down Expand Up @@ -3125,6 +3141,14 @@ extern "C" {
#[wasm_bindgen(method, js_name = hasOwnProperty)]
pub fn has_own_property(this: &Object, property: &JsValue) -> bool;

/// The `Object.hasOwn()` method returns a boolean indicating whether the
/// object passed in has the specified property as its own property (as
/// opposed to inheriting it).
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn)
#[wasm_bindgen(static_method_of = Object, js_name = hasOwn)]
pub fn has_own(instance: &Object, property: &JsValue) -> bool;

/// The `Object.is()` method determines whether two values are the same value.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
Expand Down Expand Up @@ -4304,6 +4328,14 @@ extern "C" {
#[wasm_bindgen(method, getter, structural)]
pub fn length(this: &JsString) -> u32;

/// The 'at()' method returns a new string consisting of the single UTF-16
/// code unit located at the specified offset into the string, counting from
/// the end if it's negative.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at)
#[wasm_bindgen(method, js_class = "String")]
pub fn at(this: &JsString, index: i32) -> Option<JsString>;

/// The String object's `charAt()` method returns a new string consisting of
/// the single UTF-16 code unit located at the specified offset into the
/// string.
Expand Down Expand Up @@ -4461,6 +4493,12 @@ extern "C" {
#[wasm_bindgen(method, js_class = "String", js_name = match)]
pub fn match_(this: &JsString, pattern: &RegExp) -> Option<Object>;

/// The `match_all()` method is similar to `match()`, but gives an iterator of `exec()` arrays, which preserve capture groups.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll)
#[wasm_bindgen(method, js_class = "String", js_name = matchAll)]
pub fn match_all(this: &JsString, pattern: &RegExp) -> Iterator;

/// The `normalize()` method returns the Unicode Normalization Form
/// of a given string (if the value isn't a string, it will be converted to one first).
///
Expand Down Expand Up @@ -4522,6 +4560,36 @@ extern "C" {
replacement: &Function,
) -> JsString;

/// The `replace_all()` method returns a new string with all matches of a pattern
/// replaced by a replacement. The pattern can be a string or a global RegExp, and
/// the replacement can be a string or a function to be called for each match.
///
/// Note: The original string will remain unchanged.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
pub fn replace_all(this: &JsString, pattern: &str, replacement: &str) -> JsString;

/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
pub fn replace_all_with_function(
this: &JsString,
pattern: &str,
replacement: &Function,
) -> JsString;

#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
pub fn replace_all_by_pattern(this: &JsString, pattern: &RegExp, replacement: &str)
-> JsString;

/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
pub fn replace_all_by_pattern_with_function(
this: &JsString,
pattern: &RegExp,
replacement: &Function,
) -> JsString;

/// The `search()` method executes a search for a match between
/// a regular expression and this String object.
///
Expand Down Expand Up @@ -5323,6 +5391,23 @@ extern "C" {
#[wasm_bindgen(static_method_of = Promise)]
pub fn all(obj: &JsValue) -> Promise;

/// The `Promise.allSettled(iterable)` method returns a single `Promise` that
/// resolves when all of the promises in the iterable argument have either
/// fulfilled or rejected or when the iterable argument contains no promises.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled)
#[wasm_bindgen(static_method_of = Promise, js_name = allSettled)]
pub fn all_settled(obj: &JsValue) -> Promise;

/// The `Promise.any(iterable)` method returns a single `Promise` that
/// resolves when any of the promises in the iterable argument have resolved
/// or when the iterable argument contains no promises. It rejects with an
/// `AggregateError` if all promises in the iterable rejected.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any)
#[wasm_bindgen(static_method_of = Promise)]
pub fn any(obj: &JsValue) -> Promise;

/// The `Promise.race(iterable)` method returns a promise that resolves or
/// rejects as soon as one of the promises in the iterable resolves or
/// rejects, with the value or reason from that promise.
Expand Down Expand Up @@ -5573,6 +5658,10 @@ macro_rules! arrays {
#[wasm_bindgen(method)]
pub fn set(this: &$name, src: &JsValue, offset: u32);

/// Gets the value at `idx`, counting from the end if negative.
#[wasm_bindgen(method)]
pub fn at(this: &$name, idx: i32) -> Option<$ty>;

/// Gets the value at `idx`, equivalent to the javascript `my_var = arr[idx]`.
#[wasm_bindgen(method, structural, indexing_getter)]
pub fn get_index(this: &$name, idx: u32) -> $ty;
Expand Down
26 changes: 26 additions & 0 deletions crates/js-sys/tests/wasm/Error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@ fn new() {
assert_eq!(JsValue::from(error.message()), "some message");
}

#[wasm_bindgen_test]
fn new_with_cause() {
let options = Object::new();
Reflect::set(
options.as_ref(),
&JsValue::from("cause"),
&JsValue::from("some cause"),
)
.unwrap();
let error = Error::new_with_options("some message", &options);
assert_eq!(error.cause(), "some cause");
}

#[wasm_bindgen_test]
fn empty_cause() {
let error = Error::new("test");
assert_eq!(error.cause(), JsValue::UNDEFINED);
}

#[wasm_bindgen_test]
fn set_cause() {
let error = Error::new("test");
error.set_cause(&JsValue::from("different"));
assert_eq!(error.cause(), "different");
}

#[wasm_bindgen_test]
fn set_message() {
let error = Error::new("test");
Expand Down
99 changes: 99 additions & 0 deletions crates/js-sys/tests/wasm/JsString.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ fn match_() {
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "T");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "I");

let re = RegExp::new("[A-Z]([a-z]*)", "g");
let result = JsString::from(s).match_(&re);
let obj = result.unwrap();

assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "The");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "It");

let result = JsString::from("foo").match_(&re);
assert!(result.is_none());

Expand All @@ -209,6 +216,66 @@ fn match_() {
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);
}

#[wasm_bindgen_test]
fn match_all() {
let s = "The quick brown fox jumped over the lazy dog. It barked.";
let re = RegExp::new("[A-Z]([a-z]*)", "g");
let result: Vec<_> = JsString::from(s)
.match_all(&re)
.into_iter()
.collect::<Result<_, _>>()
.unwrap();

let obj = &result[0];
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "The");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "he");

let obj = &result[1];
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "It");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "t");

let result: Vec<_> = JsString::from("foo")
.match_all(&re)
.into_iter()
.collect::<Result<_, _>>()
.unwrap();
assert_eq!(result.len(), 0);

let s = "For more information, see Chapter 3.4.5.1. Also see Chapter 3.1.4";
let re = RegExp::new("see (chapter \\d+(\\.\\d)*)", "gi");
let result: Vec<_> = JsString::from(s)
.match_all(&re)
.into_iter()
.collect::<Result<_, _>>()
.unwrap();

let obj = &result[0];
assert_eq!(
Reflect::get(obj.as_ref(), &"0".into()).unwrap(),
"see Chapter 3.4.5.1"
);
assert_eq!(
Reflect::get(obj.as_ref(), &"1".into()).unwrap(),
"Chapter 3.4.5.1"
);
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()).unwrap(), ".1");
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()).unwrap(), 22);
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);

let obj = &result[1];
assert_eq!(
Reflect::get(obj.as_ref(), &"0".into()).unwrap(),
"see Chapter 3.1.4"
);
assert_eq!(
Reflect::get(obj.as_ref(), &"1".into()).unwrap(),
"Chapter 3.1.4"
);
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()).unwrap(), ".4");
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()).unwrap(), 48);
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);
}

#[wasm_bindgen_test]
fn normalize() {
let js = JsString::from("\u{1E9B}\u{0323}");
Expand Down Expand Up @@ -290,6 +357,38 @@ fn replace() {
assert_eq!(result, "border-top");
}

#[wasm_bindgen_test]
fn replace_all() {
let js = JsString::from(
"The quick brown fox jumped over the lazy dog. If the dog reacted, was it really lazy?",
);
let result = js.replace_all("dog", "ferret");

assert_eq!(
result,
"The quick brown fox jumped over the lazy ferret. If the ferret reacted, was it really lazy?"
);

let js = JsString::from("borderTopTest");
let result = js.replace_all_with_function("T", &get_replacer_function());

assert_eq!(result, "border-top-test");

let js = JsString::from(
"The quick brown fox jumped over the lazy dog. If the dog reacted, was it really lazy?",
);
let re = RegExp::new("dog", "g");
let result = js.replace_all_by_pattern(&re, "ferret");

assert_eq!(result, "The quick brown fox jumped over the lazy ferret. If the ferret reacted, was it really lazy?");

let js = JsString::from("borderTopTest");
let re = RegExp::new("[A-Z]", "g");
let result = js.replace_all_by_pattern_with_function(&re, &get_replacer_function());

assert_eq!(result, "border-top-test");
}

#[wasm_bindgen_test]
fn search() {
let js = JsString::from(
Expand Down
7 changes: 7 additions & 0 deletions crates/js-sys/tests/wasm/Object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ fn has_own_property() {
assert!(map_with_symbol_key().has_own_property(&symbol_key()));
}

#[wasm_bindgen_test]
fn has_own() {
assert!(Object::has_own(&foo_42(), &"foo".into()));
assert!(!Object::has_own(&foo_42(), &"bar".into()));
assert!(Object::has_own(&map_with_symbol_key(), &symbol_key()));
}

#[wasm_bindgen_test]
fn to_string() {
assert_eq!(Object::new().to_string(), "[object Object]");
Expand Down
12 changes: 12 additions & 0 deletions crates/js-sys/tests/wasm/TypedArray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ fn new_fill() {
each!(test_fill);
}

macro_rules! test_at {
($arr:ident) => {{
let arr = $arr::new(&2.into());
arr.set_index(1, 1 as _);
assert_eq!(arr.at(-1).unwrap() as f64, 1 as f64);
}};
}
#[wasm_bindgen_test]
fn new_at() {
each!(test_at);
}

macro_rules! test_get_set {
($arr:ident) => {{
let arr = $arr::new(&1.into());
Expand Down

0 comments on commit 26fee7f

Please sign in to comment.