Skip to content

Commit 1848e23

Browse files
fix(builtins/intl, builtins/promise): convert panics to EngineError::Panic using js_expect (#5014)
Part of #3241. This removes several internal panic paths by replacing unwrap/downcast usage with proper error propagation using `js_expect()` and `JsResult`. It changes the following: * `core/engine/src/builtins/intl/segmenter/iterator.rs`: converted 1 panic to `js_expect().ok()?` * `core/engine/src/builtins/intl/segmenter/segments.rs`: converted 2 panics to `js_expect()?` * `core/engine/src/builtins/intl/collator/mod.rs`: converted 8 panics to `js_expect()?` * `core/engine/src/builtins/intl/list_format/mod.rs`: converted 7 panics to `js_expect()?` * `core/engine/src/builtins/intl/number_format/options.rs`: converted 2 panics to `js_expect()?` * `core/engine/src/builtins/intl/date_time_format/mod.rs`: converted 2 panics by propagating `JsResult` * `core/engine/src/builtins/promise/mod.rs`: converted 4 panics to `js_expect()?` Co-authored-by: José Julián Espina <jedel0124@gmail.com>
1 parent 15a6b94 commit 1848e23

File tree

7 files changed

+41
-37
lines changed

7 files changed

+41
-37
lines changed

core/engine/src/builtins/intl/collator/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use icu_collator::{
99
use icu_locale::{Locale, extensions::unicode};
1010

1111
use crate::{
12-
Context, JsArgs, JsData, JsNativeError, JsResult, JsString, JsValue,
12+
Context, JsArgs, JsData, JsExpect, JsNativeError, JsResult, JsString, JsValue,
1313
builtins::{
1414
BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject, OrdinaryObject,
1515
options::get_option,
@@ -362,7 +362,7 @@ impl Collator {
362362
// 2. Assert: Type(collator) is Object and collator has an [[InitializedCollator]] internal slot.
363363
let collator = collator
364364
.downcast_ref::<Self>()
365-
.expect("checked above that the object was a collator object");
365+
.js_expect("checked above that the object was a collator object")?;
366366

367367
// 3. If x is not provided, let x be undefined.
368368
// 5. Let X be ? ToString(x).
@@ -445,7 +445,7 @@ impl Collator {
445445
js_string!(collator.locale.to_string()),
446446
context,
447447
)
448-
.expect("operation must not fail per the spec");
448+
.js_expect("operation must not fail per the spec")?;
449449
options
450450
.create_data_property_or_throw(
451451
js_string!("usage"),
@@ -455,7 +455,7 @@ impl Collator {
455455
},
456456
context,
457457
)
458-
.expect("operation must not fail per the spec");
458+
.js_expect("operation must not fail per the spec")?;
459459
options
460460
.create_data_property_or_throw(
461461
js_string!("sensitivity"),
@@ -467,14 +467,14 @@ impl Collator {
467467
},
468468
context,
469469
)
470-
.expect("operation must not fail per the spec");
470+
.js_expect("operation must not fail per the spec")?;
471471
options
472472
.create_data_property_or_throw(
473473
js_string!("ignorePunctuation"),
474474
collator.ignore_punctuation,
475475
context,
476476
)
477-
.expect("operation must not fail per the spec");
477+
.js_expect("operation must not fail per the spec")?;
478478
options
479479
.create_data_property_or_throw(
480480
js_string!("collation"),
@@ -484,18 +484,18 @@ impl Collator {
484484
.unwrap_or(js_string!("default")),
485485
context,
486486
)
487-
.expect("operation must not fail per the spec");
487+
.js_expect("operation must not fail per the spec")?;
488488
options
489489
.create_data_property_or_throw(js_string!("numeric"), collator.numeric, context)
490-
.expect("operation must not fail per the spec");
490+
.js_expect("operation must not fail per the spec")?;
491491
if let Some(kf) = collator.case_first {
492492
options
493493
.create_data_property_or_throw(
494494
js_string!("caseFirst"),
495495
js_string!(kf.as_str()),
496496
context,
497497
)
498-
.expect("operation must not fail per the spec");
498+
.js_expect("operation must not fail per the spec")?;
499499
}
500500

501501
// 5. Return options.

core/engine/src/builtins/intl/date_time_format/mod.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! [spec]: https://tc39.es/ecma402/#datetimeformat-objects
99
1010
use crate::{
11-
Context, JsArgs, JsData, JsResult, JsString, JsValue, NativeFunction,
11+
Context, JsArgs, JsData, JsExpect, JsResult, JsString, JsValue, NativeFunction,
1212
builtins::{
1313
BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject,
1414
date::utils::{
@@ -272,7 +272,7 @@ impl DateTimeFormat {
272272

273273
let formatter = dtf.borrow().data().formatter.clone();
274274

275-
let dt = fields.to_formattable_datetime();
275+
let dt = fields.to_formattable_datetime()?;
276276
let tz_info = dtf.borrow().data().time_zone.to_time_zone_info();
277277
let tz_info_at_time = tz_info.at_date_time_iso(dt);
278278

@@ -482,13 +482,15 @@ impl ToLocalTime {
482482
})
483483
}
484484

485-
pub(crate) fn to_formattable_datetime(&self) -> DateTime<Iso> {
486-
DateTime {
485+
pub(crate) fn to_formattable_datetime(&self) -> JsResult<DateTime<Iso>> {
486+
Ok(DateTime {
487487
date: Date::try_new_iso(self.year, self.month, self.day)
488-
.expect("TimeClip insures valid range."),
488+
.ok()
489+
.js_expect("TimeClip insures valid range.")?,
489490
time: Time::try_new(self.hour, self.minute, self.second, self.subsecond)
490-
.expect("valid values"),
491-
}
491+
.ok()
492+
.js_expect("valid values")?,
493+
})
492494
}
493495
}
494496

core/engine/src/builtins/intl/list_format/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use icu_list::{
99
use icu_locale::Locale;
1010

1111
use crate::{
12-
Context, JsArgs, JsData, JsNativeError, JsResult, JsString, JsValue,
12+
Context, JsArgs, JsData, JsExpect, JsNativeError, JsResult, JsString, JsValue,
1313
builtins::{
1414
Array, BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject, OrdinaryObject,
1515
intl::options::EmptyPreferences,
@@ -374,7 +374,7 @@ impl ListFormat {
374374

375375
// 2. Let result be ! ArrayCreate(0).
376376
let result = Array::array_create(0, None, context)
377-
.expect("creating an empty array with default proto must not fail");
377+
.js_expect("creating an empty array with default proto must not fail")?;
378378

379379
// 3. Let n be 0.
380380
// 4. For each Record { [[Type]], [[Value]] } part in parts, do
@@ -388,16 +388,16 @@ impl ListFormat {
388388

389389
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
390390
o.create_data_property_or_throw(js_string!("type"), js_string!(part.typ()), context)
391-
.expect("operation must not fail per the spec");
391+
.js_expect("operation must not fail per the spec")?;
392392

393393
// c. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]).
394394
o.create_data_property_or_throw(js_string!("value"), js_string!(part.value()), context)
395-
.expect("operation must not fail per the spec");
395+
.js_expect("operation must not fail per the spec")?;
396396

397397
// d. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), O).
398398
result
399399
.create_data_property_or_throw(n, o, context)
400-
.expect("operation must not fail per the spec");
400+
.js_expect("operation must not fail per the spec")?;
401401

402402
// e. Increment n by 1.
403403
}
@@ -446,7 +446,7 @@ impl ListFormat {
446446
js_string!(lf.locale.to_string()),
447447
context,
448448
)
449-
.expect("operation must not fail per the spec");
449+
.js_expect("operation must not fail per the spec")?;
450450
options
451451
.create_data_property_or_throw(
452452
js_string!("type"),
@@ -457,7 +457,7 @@ impl ListFormat {
457457
},
458458
context,
459459
)
460-
.expect("operation must not fail per the spec");
460+
.js_expect("operation must not fail per the spec")?;
461461
options
462462
.create_data_property_or_throw(
463463
js_string!("style"),
@@ -469,7 +469,7 @@ impl ListFormat {
469469
},
470470
context,
471471
)
472-
.expect("operation must not fail per the spec");
472+
.js_expect("operation must not fail per the spec")?;
473473

474474
// 5. Return options.
475475
Ok(options.into())

core/engine/src/builtins/intl/number_format/options.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use icu_provider::{
1919
use tinystr::TinyAsciiStr;
2020

2121
use crate::{
22-
Context, JsNativeError, JsObject, JsResult, JsStr, JsString, JsValue,
22+
Context, JsExpect, JsNativeError, JsObject, JsResult, JsStr, JsString, JsValue,
2323
builtins::{
2424
intl::{
2525
ServicePreferences,
@@ -500,7 +500,7 @@ impl UnitFormatOptions {
500500
Style::Currency => {
501501
UnitFormatOptions::Currency {
502502
// a. Set intlObj.[[Currency]] to the ASCII-uppercase of currency.
503-
currency: currency.expect("asserted above that `currency` is not None"),
503+
currency: currency.js_expect("asserted above that `currency` is not None")?,
504504
// b. Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
505505
display: currency_display,
506506
// c. Set intlObj.[[CurrencySign]] to currencySign.
@@ -511,7 +511,7 @@ impl UnitFormatOptions {
511511
Style::Unit => {
512512
UnitFormatOptions::Unit {
513513
// a. Set intlObj.[[Unit]] to unit.
514-
unit: unit.expect("asserted above that `unit` is not None"),
514+
unit: unit.js_expect("asserted above that `unit` is not None")?,
515515
// b. Set intlObj.[[UnitDisplay]] to unitDisplay.
516516
display: unit_display,
517517
}

core/engine/src/builtins/intl/segmenter/iterator.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use icu_segmenter::{
55
};
66

77
use crate::{
8-
Context, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
8+
Context, JsData, JsExpect, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
99
builtins::{BuiltInBuilder, IntrinsicObject, iterable::create_iter_result_object},
1010
context::intrinsics::Intrinsics,
1111
js_string,
@@ -126,7 +126,8 @@ impl SegmentIterator {
126126
let segmenter = iter
127127
.segmenter
128128
.downcast_ref::<Segmenter>()
129-
.expect("segment iterator object should contain a segmenter");
129+
.js_expect("segment iterator object should contain a segmenter")
130+
.ok()?;
130131
let mut segments = segmenter.native.segment(string.variant());
131132
// the first elem is always 0.
132133
segments.next();

core/engine/src/builtins/intl/segmenter/segments.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use boa_gc::{Finalize, Trace};
22
use itertools::Itertools;
33

44
use crate::{
5-
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
5+
Context, JsArgs, JsData, JsExpect, JsNativeError, JsObject, JsResult, JsString, JsSymbol,
6+
JsValue,
67
builtins::{BuiltInBuilder, IntrinsicObject},
78
context::intrinsics::Intrinsics,
89
js_string,
@@ -67,7 +68,7 @@ impl Segments {
6768
let segmenter = segments
6869
.segmenter
6970
.downcast_ref::<Segmenter>()
70-
.expect("segments object should contain a segmenter");
71+
.js_expect("segments object should contain a segmenter")?;
7172

7273
// 4. Let string be segments.[[SegmentsString]].
7374
// 5. Let len be the length of string.
@@ -93,7 +94,7 @@ impl Segments {
9394
.tuple_windows()
9495
.find(|((i, _), (j, _))| (*i..*j).contains(&n))
9596
.map(|((i, _), (j, word))| ((i..j), word))
96-
.expect("string should have at least a length of 1, and `n` must be in range")
97+
.js_expect("string should have at least a length of 1, and `n` must be in range")?
9798
};
9899

99100
// 10. Return ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex).

core/engine/src/builtins/promise/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::{
88
iterable::{IteratorHint, IteratorRecord},
99
};
1010
use crate::{
11-
Context, JsArgs, JsError, JsResult, JsString,
11+
Context, JsArgs, JsError, JsExpect, JsResult, JsString,
1212
builtins::{Array, BuiltInObject},
1313
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
1414
error::JsNativeError,
@@ -915,15 +915,15 @@ impl Promise {
915915
js_string!("fulfilled"),
916916
context,
917917
)
918-
.expect("cannot fail per spec");
918+
.js_expect("cannot fail per spec")?;
919919

920920
// 11. Perform ! CreateDataPropertyOrThrow(obj, "value", x).
921921
obj.create_data_property_or_throw(
922922
js_string!("value"),
923923
args.get_or_undefined(0).clone(),
924924
context,
925925
)
926-
.expect("cannot fail per spec");
926+
.js_expect("cannot fail per spec")?;
927927

928928
// 12. Set values[index] to obj.
929929
captures.values.borrow_mut()[captures.index] = obj.into();
@@ -1005,15 +1005,15 @@ impl Promise {
10051005
js_string!("rejected"),
10061006
context,
10071007
)
1008-
.expect("cannot fail per spec");
1008+
.js_expect("cannot fail per spec")?;
10091009

10101010
// 11. Perform ! CreateDataPropertyOrThrow(obj, "reason", x).
10111011
obj.create_data_property_or_throw(
10121012
js_string!("reason"),
10131013
args.get_or_undefined(0).clone(),
10141014
context,
10151015
)
1016-
.expect("cannot fail per spec");
1016+
.js_expect("cannot fail per spec")?;
10171017

10181018
// 12. Set values[index] to obj.
10191019
captures.values.borrow_mut()[captures.index] = obj.into();

0 commit comments

Comments
 (0)