Skip to content

Commit

Permalink
Cleanup get_option and calls to the functioncar (#3355)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 authored Oct 5, 2023
1 parent 483fe02 commit c56a706
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 110 deletions.
39 changes: 17 additions & 22 deletions boa_engine/src/builtins/intl/collator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::{

use super::{
locale::{canonicalize_locale_list, resolve_locale, supported_locales, validate_extension},
options::{coerce_options_to_object, IntlOptions, LocaleMatcher},
options::{coerce_options_to_object, IntlOptions},
Service,
};

Expand Down Expand Up @@ -241,31 +241,28 @@ impl BuiltInConstructor for Collator {
// a. Let localeData be %Collator%.[[SortLocaleData]].
// 6. Else,
// a. Let localeData be %Collator%.[[SearchLocaleData]].
let usage =
get_option::<Usage>(&options, utf16!("usage"), false, context)?.unwrap_or_default();
let usage = get_option(&options, utf16!("usage"), context)?.unwrap_or_default();

// 7. Let opt be a new Record.
// 8. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
// 9. Set opt.[[localeMatcher]] to matcher.
let matcher =
get_option::<LocaleMatcher>(&options, utf16!("localeMatcher"), false, context)?
.unwrap_or_default();
let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default();

// 10. Let collation be ? GetOption(options, "collation", string, empty, undefined).
// 11. If collation is not undefined, then
// a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 12. Set opt.[[co]] to collation.
let collation = get_option::<Value>(&options, utf16!("collation"), false, context)?;
let collation = get_option(&options, utf16!("collation"), context)?;

// 13. Let numeric be ? GetOption(options, "numeric", boolean, empty, undefined).
// 14. If numeric is not undefined, then
// a. Let numeric be ! ToString(numeric).
// 15. Set opt.[[kn]] to numeric.
let numeric = get_option::<bool>(&options, utf16!("numeric"), false, context)?;
let numeric = get_option(&options, utf16!("numeric"), context)?;

// 16. Let caseFirst be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined).
// 17. Set opt.[[kf]] to caseFirst.
let case_first = get_option::<CaseFirst>(&options, utf16!("caseFirst"), false, context)?;
let case_first = get_option(&options, utf16!("caseFirst"), context)?;

let mut intl_options = IntlOptions {
matcher,
Expand Down Expand Up @@ -314,22 +311,20 @@ impl BuiltInConstructor for Collator {

// 26. Let sensitivity be ? GetOption(options, "sensitivity", string, « "base", "accent", "case", "variant" », undefined).
// 28. Set collator.[[Sensitivity]] to sensitivity.
let sensitivity =
get_option::<Sensitivity>(&options, utf16!("sensitivity"), false, context)?
// 27. If sensitivity is undefined, then
// a. If usage is "sort", then
// i. Let sensitivity be "variant".
// b. Else,
// i. Let dataLocale be r.[[dataLocale]].
// ii. Let dataLocaleData be localeData.[[<dataLocale>]].
// iii. Let sensitivity be dataLocaleData.[[sensitivity]].
.or_else(|| (usage == Usage::Sort).then_some(Sensitivity::Variant));
let sensitivity = get_option(&options, utf16!("sensitivity"), context)?
// 27. If sensitivity is undefined, then
// a. If usage is "sort", then
// i. Let sensitivity be "variant".
// b. Else,
// i. Let dataLocale be r.[[dataLocale]].
// ii. Let dataLocaleData be localeData.[[<dataLocale>]].
// iii. Let sensitivity be dataLocaleData.[[sensitivity]].
.or_else(|| (usage == Usage::Sort).then_some(Sensitivity::Variant));

// 29. Let ignorePunctuation be ? GetOption(options, "ignorePunctuation", boolean, empty, false).
// 30. Set collator.[[IgnorePunctuation]] to ignorePunctuation.
let ignore_punctuation =
get_option::<bool>(&options, utf16!("ignorePunctuation"), false, context)?
.unwrap_or_default();
let ignore_punctuation: bool =
get_option(&options, utf16!("ignorePunctuation"), context)?.unwrap_or_default();

let (strength, case_level) = sensitivity.map(Sensitivity::to_collator_options).unzip();

Expand Down
12 changes: 4 additions & 8 deletions boa_engine/src/builtins/intl/list_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{

use super::{
locale::{canonicalize_locale_list, resolve_locale, supported_locales},
options::{IntlOptions, LocaleMatcher},
options::IntlOptions,
Service,
};

Expand Down Expand Up @@ -111,9 +111,7 @@ impl BuiltInConstructor for ListFormat {

// 5. Let opt be a new Record.
// 6. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
let matcher =
get_option::<LocaleMatcher>(&options, utf16!("localeMatcher"), false, context)?
.unwrap_or_default();
let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default();

// 7. Set opt.[[localeMatcher]] to matcher.
// 8. Let localeData be %ListFormat%.[[LocaleData]].
Expand All @@ -130,13 +128,11 @@ impl BuiltInConstructor for ListFormat {

// 11. Let type be ? GetOption(options, "type", string, « "conjunction", "disjunction", "unit" », "conjunction").
// 12. Set listFormat.[[Type]] to type.
let typ = get_option::<ListFormatType>(&options, utf16!("type"), false, context)?
.unwrap_or_default();
let typ = get_option(&options, utf16!("type"), context)?.unwrap_or_default();

// 13. Let style be ? GetOption(options, "style", string, « "long", "short", "narrow" », "long").
// 14. Set listFormat.[[Style]] to style.
let style = get_option::<ListLength>(&options, utf16!("style"), false, context)?
.unwrap_or(ListLength::Wide);
let style = get_option(&options, utf16!("style"), context)?.unwrap_or(ListLength::Wide);

// 15. Let dataLocale be r.[[dataLocale]].
// 16. Let dataLocaleData be localeData.[[<dataLocale>]].
Expand Down
63 changes: 23 additions & 40 deletions boa_engine/src/builtins/intl/locale/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use boa_profiler::Profiler;
use icu_collator::CaseFirst;
use icu_datetime::options::preferences::HourCycle;
use icu_locid::{
extensions::unicode::Value,
extensions_unicode_key as key, extensions_unicode_value as value,
subtags::{Language, Region, Script},
extensions::unicode::Value, extensions_unicode_key as key, extensions_unicode_value as value,
};

#[cfg(test)]
Expand Down Expand Up @@ -237,27 +235,18 @@ impl BuiltInConstructor for Locale {
// 3. If ! IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
// 4. Let language be ? GetOption(options, "language", string, empty, undefined).
// 5. If language is not undefined, then
let language = get_option::<JsString>(options, utf16!("language"), false, context)?
// a. If language does not match the unicode_language_subtag production, throw a RangeError exception.
.map(|s| s.to_std_string_escaped().parse::<Language>())
.transpose()
.map_err(|e| JsNativeError::range().with_message(e.to_string()))?;
// a. If language does not match the unicode_language_subtag production, throw a RangeError exception.
let language = get_option(options, utf16!("language"), context)?;

// 6. Let script be ? GetOption(options, "script", string, empty, undefined).
// 7. If script is not undefined, then
let script = get_option::<JsString>(options, utf16!("script"), false, context)?
.map(|s| s.to_std_string_escaped().parse::<Script>())
.transpose()
// a. If script does not match the unicode_script_subtag production, throw a RangeError exception.
.map_err(|e| JsNativeError::range().with_message(e.to_string()))?;
// a. If script does not match the unicode_script_subtag production, throw a RangeError exception.
let script = get_option(options, utf16!("script"), context)?;

// 8. Let region be ? GetOption(options, "region", string, empty, undefined).
// 9. If region is not undefined, then
let region = get_option::<JsString>(options, utf16!("region"), false, context)?
.map(|s| s.to_std_string_escaped().parse::<Region>())
.transpose()
// a. If region does not match the unicode_region_subtag production, throw a RangeError exception.
.map_err(|e| JsNativeError::range().with_message(e.to_string()))?;
// a. If region does not match the unicode_region_subtag production, throw a RangeError exception.
let region = get_option(options, utf16!("region"), context)?;

// 10. Set tag to ! CanonicalizeUnicodeLocaleId(tag).
context.icu().locale_canonicalizer().canonicalize(&mut tag);
Expand Down Expand Up @@ -299,42 +288,36 @@ impl BuiltInConstructor for Locale {
// 14. If calendar is not undefined, then
// 15. Set opt.[[ca]] to calendar.
// a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
let ca = get_option::<Value>(options, utf16!("calendar"), false, context)?;
let ca = get_option(options, utf16!("calendar"), context)?;

// 16. Let collation be ? GetOption(options, "collation", string, empty, undefined).
// 17. If collation is not undefined, then
// 18. Set opt.[[co]] to collation.
// a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
let co = get_option::<Value>(options, utf16!("collation"), false, context)?;
let co = get_option(options, utf16!("collation"), context)?;

// 19. Let hc be ? GetOption(options, "hourCycle", string, « "h11", "h12", "h23", "h24" », undefined).
// 20. Set opt.[[hc]] to hc.
let hc =
get_option::<HourCycle>(options, utf16!("hourCycle"), false, context)?.map(
|hc| match hc {
HourCycle::H24 => value!("h24"),
HourCycle::H23 => value!("h23"),
HourCycle::H12 => value!("h12"),
HourCycle::H11 => value!("h11"),
},
);
let hc = get_option(options, utf16!("hourCycle"), context)?.map(|hc| match hc {
HourCycle::H24 => value!("h24"),
HourCycle::H23 => value!("h23"),
HourCycle::H12 => value!("h12"),
HourCycle::H11 => value!("h11"),
});

// 21. Let kf be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined).
// 22. Set opt.[[kf]] to kf.
let kf =
get_option::<CaseFirst>(options, utf16!("caseFirst"), false, context)?.map(
|kf| match kf {
CaseFirst::UpperFirst => value!("upper"),
CaseFirst::LowerFirst => value!("lower"),
CaseFirst::Off => value!("false"),
_ => unreachable!(),
},
);
let kf = get_option(options, utf16!("caseFirst"), context)?.map(|kf| match kf {
CaseFirst::UpperFirst => value!("upper"),
CaseFirst::LowerFirst => value!("lower"),
CaseFirst::Off => value!("false"),
_ => unreachable!(),
});

// 23. Let kn be ? GetOption(options, "numeric", boolean, empty, undefined).
// 24. If kn is not undefined, set kn to ! ToString(kn).
// 25. Set opt.[[kn]] to kn.
let kn = get_option::<bool>(options, utf16!("numeric"), false, context)?.map(|b| {
let kn = get_option(options, utf16!("numeric"), context)?.map(|b| {
if b {
value!("true")
} else {
Expand All @@ -346,7 +329,7 @@ impl BuiltInConstructor for Locale {
// 27. If numberingSystem is not undefined, then
// 28. Set opt.[[nu]] to numberingSystem.
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
let nu = get_option::<Value>(options, utf16!("numberingSystem"), false, context)?;
let nu = get_option(options, utf16!("numberingSystem"), context)?;

// 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys).
// 30. Set locale.[[Locale]] to r.[[locale]].
Expand Down
48 changes: 39 additions & 9 deletions boa_engine/src/builtins/intl/locale/options.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
use icu_locid::extensions::unicode::Value;
use icu_locid::{
extensions::unicode::Value,
subtags::{Language, Region, Script},
};

use crate::{builtins::options::OptionType, Context, JsNativeError};

impl OptionType for Value {
fn from_value(value: crate::JsValue, context: &mut Context<'_>) -> crate::JsResult<Self> {
let val = value
.to_string(context)?
.to_std_string_escaped()
.parse::<Self>()
.map_err(|e| JsNativeError::range().with_message(e.to_string()))?;
let val = value.to_string(context)?.to_std_string_escaped();

if val.as_tinystr_slice().is_empty() {
if val.len() < 3 {
return Err(JsNativeError::range()
.with_message("Unicode Locale Identifier `type` cannot be empty")
.with_message("nonterminal `type` must be at least 3 characters long")
.into());
}

Ok(val)
val.parse::<Self>()
.map_err(|e| JsNativeError::range().with_message(e.to_string()).into())
}
}

impl OptionType for Language {
fn from_value(value: crate::JsValue, context: &mut Context<'_>) -> crate::JsResult<Self> {
value
.to_string(context)?
.to_std_string_escaped()
.parse::<Self>()
.map_err(|e| JsNativeError::range().with_message(e.to_string()).into())
}
}

impl OptionType for Script {
fn from_value(value: crate::JsValue, context: &mut Context<'_>) -> crate::JsResult<Self> {
value
.to_string(context)?
.to_std_string_escaped()
.parse::<Self>()
.map_err(|e| JsNativeError::range().with_message(e.to_string()).into())
}
}

impl OptionType for Region {
fn from_value(value: crate::JsValue, context: &mut Context<'_>) -> crate::JsResult<Self> {
value
.to_string(context)?
.to_std_string_escaped()
.parse::<Self>()
.map_err(|e| JsNativeError::range().with_message(e.to_string()).into())
}
}
3 changes: 1 addition & 2 deletions boa_engine/src/builtins/intl/locale/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,7 @@ where
let options = coerce_options_to_object(options, context)?;

// 2. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
let matcher = get_option::<LocaleMatcher>(&options, utf16!("localeMatcher"), false, context)?
.unwrap_or_default();
let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default();

let elements = match matcher {
// 4. Else,
Expand Down
7 changes: 3 additions & 4 deletions boa_engine/src/builtins/intl/number_format/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) fn get_digit_format_options(

// 7. Let roundingPriority be ? GetOption(options, "roundingPriority", string, « "auto", "morePrecision", "lessPrecision" », "auto").
let mut rounding_priority =
get_option(options, utf16!("roundingPriority"), false, context)?.unwrap_or_default();
get_option(options, utf16!("roundingPriority"), context)?.unwrap_or_default();

// 8. Let roundingIncrement be ? GetNumberOption(options, "roundingIncrement", 1, 5000, 1).
// 9. If roundingIncrement is not in « 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 », throw a RangeError exception.
Expand All @@ -58,12 +58,11 @@ pub(crate) fn get_digit_format_options(
}

// 10. Let roundingMode be ? GetOption(options, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand").
let rounding_mode =
get_option(options, utf16!("roundingMode"), false, context)?.unwrap_or_default();
let rounding_mode = get_option(options, utf16!("roundingMode"), context)?.unwrap_or_default();

// 11. Let trailingZeroDisplay be ? GetOption(options, "trailingZeroDisplay", string, « "auto", "stripIfInteger" », "auto").
let trailing_zero_display =
get_option(options, utf16!("trailingZeroDisplay"), false, context)?.unwrap_or_default();
get_option(options, utf16!("trailingZeroDisplay"), context)?.unwrap_or_default();

// 12. NOTE: All fields required by SetNumberFormatDigitOptions have now been read from options. The remainder of this AO interprets the options and may throw exceptions.

Expand Down
10 changes: 4 additions & 6 deletions boa_engine/src/builtins/intl/plural_rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use super::{
f64_to_formatted_fixed_decimal, get_digit_format_options, DigitFormatOptions, Extrema,
Notation,
},
options::{coerce_options_to_object, IntlOptions, LocaleMatcher},
options::{coerce_options_to_object, IntlOptions},
Service,
};

Expand Down Expand Up @@ -113,14 +113,12 @@ impl BuiltInConstructor for PluralRules {
// 3. Let opt be a new Record.
// 4. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
// 5. Set opt.[[localeMatcher]] to matcher.
let matcher =
get_option::<LocaleMatcher>(&options, utf16!("localeMatcher"), false, context)?
.unwrap_or_default();
let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default();

// 6. Let t be ? GetOption(options, "type", string, « "cardinal", "ordinal" », "cardinal").
// 7. Set pluralRules.[[Type]] to t.
let rule_type = get_option::<PluralRuleType>(&options, utf16!("type"), false, context)?
.unwrap_or(PluralRuleType::Cardinal);
let rule_type =
get_option(&options, utf16!("type"), context)?.unwrap_or(PluralRuleType::Cardinal);

// 8. Perform ? SetNumberFormatDigitOptions(pluralRules, options, +0𝔽, 3𝔽, "standard").
let format_options = get_digit_format_options(&options, 0, 3, Notation::Standard, context)?;
Expand Down
10 changes: 3 additions & 7 deletions boa_engine/src/builtins/intl/segmenter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub(crate) use segments::*;

use super::{
locale::{canonicalize_locale_list, resolve_locale, supported_locales},
options::{IntlOptions, LocaleMatcher},
options::IntlOptions,
Service,
};

Expand Down Expand Up @@ -133,9 +133,7 @@ impl BuiltInConstructor for Segmenter {

// 6. Let opt be a new Record.
// 7. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
let matcher =
get_option::<LocaleMatcher>(&options, utf16!("localeMatcher"), false, context)?
.unwrap_or_default();
let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default();

// 8. Set opt.[[localeMatcher]] to matcher.
// 9. Let localeData be %Segmenter%.[[LocaleData]].
Expand All @@ -151,9 +149,7 @@ impl BuiltInConstructor for Segmenter {
);

// 12. Let granularity be ? GetOption(options, "granularity", string, « "grapheme", "word", "sentence" », "grapheme").
let granularity =
get_option::<Granularity>(&options, utf16!("granularity"), false, context)?
.unwrap_or_default();
let granularity = get_option(&options, utf16!("granularity"), context)?.unwrap_or_default();
// 13. Set segmenter.[[SegmenterGranularity]] to granularity.

let native = match granularity {
Expand Down
Loading

0 comments on commit c56a706

Please sign in to comment.