Skip to content

Commit 26fee7f

Browse files
author
joshyrobot
authored
Update js-sys with new features (#2824)
* 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`
1 parent a608959 commit 26fee7f

File tree

5 files changed

+233
-0
lines changed

5 files changed

+233
-0
lines changed

crates/js-sys/src/lib.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@ extern "C" {
306306
#[wasm_bindgen(constructor)]
307307
pub fn new_with_length(len: u32) -> Array;
308308

309+
/// Retrieves the element at the index, counting from the end if negative
310+
/// (returns `undefined` if the index is out of range).
311+
#[wasm_bindgen(method)]
312+
pub fn at(this: &Array, index: i32) -> JsValue;
313+
309314
/// Retrieves the element at the index (returns `undefined` if the index is out of range).
310315
#[wasm_bindgen(method, structural, indexing_getter)]
311316
pub fn get(this: &Array, index: u32) -> JsValue;
@@ -1483,6 +1488,17 @@ extern "C" {
14831488
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
14841489
#[wasm_bindgen(constructor)]
14851490
pub fn new(message: &str) -> Error;
1491+
#[wasm_bindgen(constructor)]
1492+
pub fn new_with_options(message: &str, options: &Object) -> Error;
1493+
1494+
/// The cause property is the underlying cause of the error.
1495+
/// Usually this is used to add context to re-thrown errors.
1496+
///
1497+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#differentiate_between_similar_errors)
1498+
#[wasm_bindgen(method, getter, structural)]
1499+
pub fn cause(this: &Error) -> JsValue;
1500+
#[wasm_bindgen(method, setter, structural)]
1501+
pub fn set_cause(this: &Error, cause: &JsValue);
14861502

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

3144+
/// The `Object.hasOwn()` method returns a boolean indicating whether the
3145+
/// object passed in has the specified property as its own property (as
3146+
/// opposed to inheriting it).
3147+
///
3148+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn)
3149+
#[wasm_bindgen(static_method_of = Object, js_name = hasOwn)]
3150+
pub fn has_own(instance: &Object, property: &JsValue) -> bool;
3151+
31283152
/// The `Object.is()` method determines whether two values are the same value.
31293153
///
31303154
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
@@ -4304,6 +4328,14 @@ extern "C" {
43044328
#[wasm_bindgen(method, getter, structural)]
43054329
pub fn length(this: &JsString) -> u32;
43064330

4331+
/// The 'at()' method returns a new string consisting of the single UTF-16
4332+
/// code unit located at the specified offset into the string, counting from
4333+
/// the end if it's negative.
4334+
///
4335+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at)
4336+
#[wasm_bindgen(method, js_class = "String")]
4337+
pub fn at(this: &JsString, index: i32) -> Option<JsString>;
4338+
43074339
/// The String object's `charAt()` method returns a new string consisting of
43084340
/// the single UTF-16 code unit located at the specified offset into the
43094341
/// string.
@@ -4461,6 +4493,12 @@ extern "C" {
44614493
#[wasm_bindgen(method, js_class = "String", js_name = match)]
44624494
pub fn match_(this: &JsString, pattern: &RegExp) -> Option<Object>;
44634495

4496+
/// The `match_all()` method is similar to `match()`, but gives an iterator of `exec()` arrays, which preserve capture groups.
4497+
///
4498+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll)
4499+
#[wasm_bindgen(method, js_class = "String", js_name = matchAll)]
4500+
pub fn match_all(this: &JsString, pattern: &RegExp) -> Iterator;
4501+
44644502
/// The `normalize()` method returns the Unicode Normalization Form
44654503
/// of a given string (if the value isn't a string, it will be converted to one first).
44664504
///
@@ -4522,6 +4560,36 @@ extern "C" {
45224560
replacement: &Function,
45234561
) -> JsString;
45244562

4563+
/// The `replace_all()` method returns a new string with all matches of a pattern
4564+
/// replaced by a replacement. The pattern can be a string or a global RegExp, and
4565+
/// the replacement can be a string or a function to be called for each match.
4566+
///
4567+
/// Note: The original string will remain unchanged.
4568+
///
4569+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)
4570+
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
4571+
pub fn replace_all(this: &JsString, pattern: &str, replacement: &str) -> JsString;
4572+
4573+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)
4574+
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
4575+
pub fn replace_all_with_function(
4576+
this: &JsString,
4577+
pattern: &str,
4578+
replacement: &Function,
4579+
) -> JsString;
4580+
4581+
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
4582+
pub fn replace_all_by_pattern(this: &JsString, pattern: &RegExp, replacement: &str)
4583+
-> JsString;
4584+
4585+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)
4586+
#[wasm_bindgen(method, js_class = "String", js_name = replaceAll)]
4587+
pub fn replace_all_by_pattern_with_function(
4588+
this: &JsString,
4589+
pattern: &RegExp,
4590+
replacement: &Function,
4591+
) -> JsString;
4592+
45254593
/// The `search()` method executes a search for a match between
45264594
/// a regular expression and this String object.
45274595
///
@@ -5323,6 +5391,23 @@ extern "C" {
53235391
#[wasm_bindgen(static_method_of = Promise)]
53245392
pub fn all(obj: &JsValue) -> Promise;
53255393

5394+
/// The `Promise.allSettled(iterable)` method returns a single `Promise` that
5395+
/// resolves when all of the promises in the iterable argument have either
5396+
/// fulfilled or rejected or when the iterable argument contains no promises.
5397+
///
5398+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled)
5399+
#[wasm_bindgen(static_method_of = Promise, js_name = allSettled)]
5400+
pub fn all_settled(obj: &JsValue) -> Promise;
5401+
5402+
/// The `Promise.any(iterable)` method returns a single `Promise` that
5403+
/// resolves when any of the promises in the iterable argument have resolved
5404+
/// or when the iterable argument contains no promises. It rejects with an
5405+
/// `AggregateError` if all promises in the iterable rejected.
5406+
///
5407+
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any)
5408+
#[wasm_bindgen(static_method_of = Promise)]
5409+
pub fn any(obj: &JsValue) -> Promise;
5410+
53265411
/// The `Promise.race(iterable)` method returns a promise that resolves or
53275412
/// rejects as soon as one of the promises in the iterable resolves or
53285413
/// rejects, with the value or reason from that promise.
@@ -5573,6 +5658,10 @@ macro_rules! arrays {
55735658
#[wasm_bindgen(method)]
55745659
pub fn set(this: &$name, src: &JsValue, offset: u32);
55755660

5661+
/// Gets the value at `idx`, counting from the end if negative.
5662+
#[wasm_bindgen(method)]
5663+
pub fn at(this: &$name, idx: i32) -> Option<$ty>;
5664+
55765665
/// Gets the value at `idx`, equivalent to the javascript `my_var = arr[idx]`.
55775666
#[wasm_bindgen(method, structural, indexing_getter)]
55785667
pub fn get_index(this: &$name, idx: u32) -> $ty;

crates/js-sys/tests/wasm/Error.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,32 @@ fn new() {
99
assert_eq!(JsValue::from(error.message()), "some message");
1010
}
1111

12+
#[wasm_bindgen_test]
13+
fn new_with_cause() {
14+
let options = Object::new();
15+
Reflect::set(
16+
options.as_ref(),
17+
&JsValue::from("cause"),
18+
&JsValue::from("some cause"),
19+
)
20+
.unwrap();
21+
let error = Error::new_with_options("some message", &options);
22+
assert_eq!(error.cause(), "some cause");
23+
}
24+
25+
#[wasm_bindgen_test]
26+
fn empty_cause() {
27+
let error = Error::new("test");
28+
assert_eq!(error.cause(), JsValue::UNDEFINED);
29+
}
30+
31+
#[wasm_bindgen_test]
32+
fn set_cause() {
33+
let error = Error::new("test");
34+
error.set_cause(&JsValue::from("different"));
35+
assert_eq!(error.cause(), "different");
36+
}
37+
1238
#[wasm_bindgen_test]
1339
fn set_message() {
1440
let error = Error::new("test");

crates/js-sys/tests/wasm/JsString.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ fn match_() {
188188
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "T");
189189
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "I");
190190

191+
let re = RegExp::new("[A-Z]([a-z]*)", "g");
192+
let result = JsString::from(s).match_(&re);
193+
let obj = result.unwrap();
194+
195+
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "The");
196+
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "It");
197+
191198
let result = JsString::from("foo").match_(&re);
192199
assert!(result.is_none());
193200

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

219+
#[wasm_bindgen_test]
220+
fn match_all() {
221+
let s = "The quick brown fox jumped over the lazy dog. It barked.";
222+
let re = RegExp::new("[A-Z]([a-z]*)", "g");
223+
let result: Vec<_> = JsString::from(s)
224+
.match_all(&re)
225+
.into_iter()
226+
.collect::<Result<_, _>>()
227+
.unwrap();
228+
229+
let obj = &result[0];
230+
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "The");
231+
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "he");
232+
233+
let obj = &result[1];
234+
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "It");
235+
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "t");
236+
237+
let result: Vec<_> = JsString::from("foo")
238+
.match_all(&re)
239+
.into_iter()
240+
.collect::<Result<_, _>>()
241+
.unwrap();
242+
assert_eq!(result.len(), 0);
243+
244+
let s = "For more information, see Chapter 3.4.5.1. Also see Chapter 3.1.4";
245+
let re = RegExp::new("see (chapter \\d+(\\.\\d)*)", "gi");
246+
let result: Vec<_> = JsString::from(s)
247+
.match_all(&re)
248+
.into_iter()
249+
.collect::<Result<_, _>>()
250+
.unwrap();
251+
252+
let obj = &result[0];
253+
assert_eq!(
254+
Reflect::get(obj.as_ref(), &"0".into()).unwrap(),
255+
"see Chapter 3.4.5.1"
256+
);
257+
assert_eq!(
258+
Reflect::get(obj.as_ref(), &"1".into()).unwrap(),
259+
"Chapter 3.4.5.1"
260+
);
261+
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()).unwrap(), ".1");
262+
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()).unwrap(), 22);
263+
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);
264+
265+
let obj = &result[1];
266+
assert_eq!(
267+
Reflect::get(obj.as_ref(), &"0".into()).unwrap(),
268+
"see Chapter 3.1.4"
269+
);
270+
assert_eq!(
271+
Reflect::get(obj.as_ref(), &"1".into()).unwrap(),
272+
"Chapter 3.1.4"
273+
);
274+
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()).unwrap(), ".4");
275+
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()).unwrap(), 48);
276+
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);
277+
}
278+
212279
#[wasm_bindgen_test]
213280
fn normalize() {
214281
let js = JsString::from("\u{1E9B}\u{0323}");
@@ -290,6 +357,38 @@ fn replace() {
290357
assert_eq!(result, "border-top");
291358
}
292359

360+
#[wasm_bindgen_test]
361+
fn replace_all() {
362+
let js = JsString::from(
363+
"The quick brown fox jumped over the lazy dog. If the dog reacted, was it really lazy?",
364+
);
365+
let result = js.replace_all("dog", "ferret");
366+
367+
assert_eq!(
368+
result,
369+
"The quick brown fox jumped over the lazy ferret. If the ferret reacted, was it really lazy?"
370+
);
371+
372+
let js = JsString::from("borderTopTest");
373+
let result = js.replace_all_with_function("T", &get_replacer_function());
374+
375+
assert_eq!(result, "border-top-test");
376+
377+
let js = JsString::from(
378+
"The quick brown fox jumped over the lazy dog. If the dog reacted, was it really lazy?",
379+
);
380+
let re = RegExp::new("dog", "g");
381+
let result = js.replace_all_by_pattern(&re, "ferret");
382+
383+
assert_eq!(result, "The quick brown fox jumped over the lazy ferret. If the ferret reacted, was it really lazy?");
384+
385+
let js = JsString::from("borderTopTest");
386+
let re = RegExp::new("[A-Z]", "g");
387+
let result = js.replace_all_by_pattern_with_function(&re, &get_replacer_function());
388+
389+
assert_eq!(result, "border-top-test");
390+
}
391+
293392
#[wasm_bindgen_test]
294393
fn search() {
295394
let js = JsString::from(

crates/js-sys/tests/wasm/Object.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,13 @@ fn has_own_property() {
191191
assert!(map_with_symbol_key().has_own_property(&symbol_key()));
192192
}
193193

194+
#[wasm_bindgen_test]
195+
fn has_own() {
196+
assert!(Object::has_own(&foo_42(), &"foo".into()));
197+
assert!(!Object::has_own(&foo_42(), &"bar".into()));
198+
assert!(Object::has_own(&map_with_symbol_key(), &symbol_key()));
199+
}
200+
194201
#[wasm_bindgen_test]
195202
fn to_string() {
196203
assert_eq!(Object::new().to_string(), "[object Object]");

crates/js-sys/tests/wasm/TypedArray.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ fn new_fill() {
8989
each!(test_fill);
9090
}
9191

92+
macro_rules! test_at {
93+
($arr:ident) => {{
94+
let arr = $arr::new(&2.into());
95+
arr.set_index(1, 1 as _);
96+
assert_eq!(arr.at(-1).unwrap() as f64, 1 as f64);
97+
}};
98+
}
99+
#[wasm_bindgen_test]
100+
fn new_at() {
101+
each!(test_at);
102+
}
103+
92104
macro_rules! test_get_set {
93105
($arr:ident) => {{
94106
let arr = $arr::new(&1.into());

0 commit comments

Comments
 (0)