Skip to content

Commit

Permalink
Remove DateTimeStyleFormat implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
NorbertGarfield committed May 11, 2022
1 parent 0047ef8 commit 2676d0b
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 484 deletions.
273 changes: 0 additions & 273 deletions boa_engine/src/builtins/intl/date_time_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ use crate::{
use boa_gc::{Finalize, Trace};
use boa_profiler::Profiler;

#[cfg(test)]
use rustc_hash::FxHashMap;

/// JavaScript `Intl.DateTimeFormat` object.
#[derive(Debug, Clone, Trace, Finalize)]
pub struct DateTimeFormat {
Expand Down Expand Up @@ -226,273 +223,3 @@ pub(crate) fn to_date_time_options(
// 13. Return options.
Ok(options)
}

/// `DateTimeRangeFormat` type contains `rangePatterns` record represented as an object and may or
/// may not contain `rangePatterns12`, thus this field is declared optional.
#[cfg(test)]
pub(crate) struct DateTimeRangeFormat {
pub(crate) range_patterns: JsObject,
pub(crate) range_patterns12: Option<JsObject>,
}

/// `StylesRecord` type hash maps for `TimeFormat`, `DateFormat`, `DateTimeFormat` and
/// `DateTimeRangeFormat`. The key of these maps should be one of the following:
/// "full", "long", "medium" or "short". Map values contain formatting patterns like
/// "{year}-{month}-{day}"
#[cfg(test)]
pub(crate) struct StylesRecord {
pub(crate) time_format: FxHashMap<JsString, JsValue>,
pub(crate) date_format: FxHashMap<JsString, JsValue>,
pub(crate) date_time_format: FxHashMap<JsString, JsValue>,
pub(crate) date_time_range_format:
FxHashMap<JsString, FxHashMap<JsString, DateTimeRangeFormat>>,
}

/// The `DateTimeStyleFormat` abstract operation accepts arguments `dateStyle` and `timeStyle`,
/// which are each either undefined, "full", "long", "medium", or "short", at least one of which
/// is not undefined, and `styles`, which is a record from
/// %`DateTimeFormat`%.[[`LocaleData`]].[[<locale>]].[[styles]].[[<calendar>]] for some locale `locale`
/// and calendar `calendar`. It returns the appropriate format record for date time formatting
/// based on the parameters.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma402/#sec-date-time-style-format
#[cfg(test)]
pub(crate) fn date_time_style_format(
date_style: &JsValue,
time_style: &JsValue,
styles: &StylesRecord,
context: &mut Context,
) -> JsResult<JsValue> {
// 1. If timeStyle is not undefined, then
let time_format = if time_style.is_undefined() {
JsValue::undefined()
} else {
// a. Assert: timeStyle is one of "full", "long", "medium", or "short".
let available_time_styles = vec![
JsValue::String(JsString::new("full")),
JsValue::String(JsString::new("long")),
JsValue::String(JsString::new("medium")),
JsValue::String(JsString::new("short")),
];

if !available_time_styles
.iter()
.any(|style| style.eq(time_style))
{
return context.throw_type_error("DateTimeStyleFormat: unsupported time style");
}

// b. Let timeFormat be styles.[[TimeFormat]].[[<timeStyle>]].
let time_style_str = time_style
.to_string(context)
.unwrap_or_else(|_| JsString::empty());
let time_fmt = styles
.time_format
.get(&time_style_str)
.expect("Failed to get timeStyle from TimeFormat");
time_fmt.clone()
};

// 2. If dateStyle is not undefined, then
let date_format = if date_style.is_undefined() {
JsValue::undefined()
} else {
// a. Assert: dateStyle is one of "full", "long", "medium", or "short".
let available_date_styles = vec![
JsValue::String(JsString::new("full")),
JsValue::String(JsString::new("long")),
JsValue::String(JsString::new("medium")),
JsValue::String(JsString::new("short")),
];

if !available_date_styles
.iter()
.any(|style| style.eq(date_style))
{
return context.throw_type_error("DateTimeStyleFormat: unsupported date style");
}

// b. Let dateFormat be styles.[[DateFormat]].[[<dateStyle>]].
let date_style_str = date_style
.to_string(context)
.unwrap_or_else(|_| JsString::empty());
let date_fmt = styles
.date_format
.get(&date_style_str)
.expect("Failed to get dateStyle from DateFormat");
date_fmt.clone()
};

// 3. If dateStyle is not undefined and timeStyle is not undefined, then
if !date_style.is_undefined() && !time_style.is_undefined() {
// a. Let format be a new Record.
let format = JsObject::empty();

// b. Add to format all fields from dateFormat except [[pattern]] and [[rangePatterns]].
let date_format_obj = date_format
.to_object(context)
.expect("Failed to cast dateFormat to object");
let entries_list = date_format_obj.enumerable_own_property_names(
crate::property::PropertyNameKind::KeyAndValue,
context,
)?;

for entry in entries_list {
let entry_obj = entry.to_object(context)?;
let entry_key = entry_obj.get(0, context)?;
let entry_key_str = entry_key.to_string(context)?;
if entry_key_str.ne(&JsString::new("pattern"))
&& entry_key_str.ne(&JsString::new("rangePatterns"))
{
let entry_val = entry_obj.get(1, context)?;
format.set(entry_key_str, entry_val, true, context)?;
}
}

// c. Add to format all fields from timeFormat except
// [[pattern]], [[rangePatterns]], [[pattern12]], and [[rangePatterns12]], if present.
let time_format_obj = time_format
.to_object(context)
.expect("Failed to cast timeFormat to object");
let entries_list = time_format_obj.enumerable_own_property_names(
crate::property::PropertyNameKind::KeyAndValue,
context,
)?;
for entry in entries_list {
let entry_obj = entry.to_object(context)?;
let entry_key = entry_obj.get(0, context)?;
let entry_key_str = entry_key.to_string(context)?;
if entry_key_str.ne(&JsString::new("pattern"))
&& entry_key_str.ne(&JsString::new("rangePatterns"))
&& entry_key_str.ne(&JsString::new("pattern12"))
&& entry_key_str.ne(&JsString::new("rangePatterns12"))
{
let entry_val = entry_obj.get(1, context)?;
format.set(entry_key_str, entry_val, true, context)?;
}
}

// d. Let connector be styles.[[DateTimeFormat]].[[<dateStyle>]].
let date_style_str = date_style
.to_string(context)
.unwrap_or_else(|_| JsString::empty());
let connector = styles
.date_time_format
.get(&date_style_str)
.expect("Failed to get connector");
let connector_str = connector
.to_string(context)
.expect("Failed to cast connector to string");

// e. Let pattern be the string connector with the substring "{0}" replaced with
// timeFormat.[[pattern]] and the substring "{1}" replaced with dateFormat.[[pattern]].
let time_format_pattern = time_format_obj
.get("pattern", context)
.expect("Failed to get pattern");
let time_format_pattern = time_format_pattern
.to_string(context)
.expect("Failed to cast pattern to string");
let time_format_pattern = time_format_pattern.to_string();

let date_format_pattern = date_format_obj
.get("pattern", context)
.expect("Failed to get pattern");
let date_format_pattern = date_format_pattern
.to_string(context)
.expect("Failed to cast pattern to string");
let date_format_pattern = date_format_pattern.to_string();

let pattern = connector_str.replace("{0}", &time_format_pattern);
let pattern = pattern.replace("{1}", &date_format_pattern);

// f. Set format.[[pattern]] to pattern.
format.set(
"pattern",
JsValue::String(JsString::new(pattern)),
true,
context,
)?;

// g. If timeFormat has a [[pattern12]] field, then
let maybe_pattern12 = time_format_obj
.get("pattern12", context)
.unwrap_or_else(|_| JsValue::undefined());
if !maybe_pattern12.is_undefined() {
// i. Let pattern12 be the string connector with the substring "{0}"
// replaced with timeFormat.[[pattern12]] and the substring "{1}" replaced with
// dateFormat.[[pattern]].
let pattern12_str = maybe_pattern12
.to_string(context)
.unwrap_or_else(|_| JsString::empty());
let pattern12_str = pattern12_str.to_string();

let date_format_pattern = date_format_obj
.get("pattern", context)
.expect("Failed to get pattern");
let date_format_pattern = date_format_pattern
.to_string(context)
.expect("Failed to cast pattern to string");
let date_format_pattern = date_format_pattern.to_string();

let pattern12 = connector_str.replace("{0}", &pattern12_str);
let pattern12 = pattern12.replace("{1}", &date_format_pattern);

// ii. Set format.[[pattern12]] to pattern12.
format.set(
"pattern12",
JsValue::String(JsString::new(pattern12)),
true,
context,
)?;
}

// h. Let dateTimeRangeFormat be styles.[[DateTimeRangeFormat]].[[<dateStyle>]].[[<timeStyle>]].
let date_style_str = date_style
.to_string(context)
.unwrap_or_else(|_| JsString::empty());
let time_style_str = time_style
.to_string(context)
.unwrap_or_else(|_| JsString::empty());
let dtr_fmt_date_style = styles
.date_time_range_format
.get(&date_style_str)
.expect("Failed to get dateStyle");
let date_time_range_format = dtr_fmt_date_style
.get(&time_style_str)
.expect("Failed to get timeStyle");

// i. Set format.[[rangePatterns]] to dateTimeRangeFormat.[[rangePatterns]].
format.set(
"rangePatterns",
date_time_range_format.range_patterns.clone(),
true,
context,
)?;

// j. If dateTimeRangeFormat has a [[rangePatterns12]] field, then
if let Some(range_patterns12) = &date_time_range_format.range_patterns12 {
// i. Set format.[[rangePatterns12]] to dateTimeRangeFormat.[[rangePatterns12]].
format.set("rangePatterns12", range_patterns12.clone(), true, context)?;
}

// k. Return format.
return Ok(JsValue::Object(format));
}

// 4. If timeStyle is not undefined, then
if !time_style.is_undefined() {
// a. Return timeFormat.
return Ok(time_format);
}

// 5. Assert: dateStyle is not undefined.
if date_style.is_undefined() {
return context
.throw_type_error("DateTimeStyleFormat: date style must be defined at this point.");
}

Ok(date_format)
}
11 changes: 4 additions & 7 deletions boa_engine/src/builtins/intl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ pub(crate) fn get_number_option(
maximum: f64,
fallback: Option<f64>,
context: &mut Context,
) -> JsResult<f64> {
) -> JsResult<Option<f64>> {
// 1. Assert: Type(options) is Object.
// 2. Let value be ? Get(options, property).
let value = options.get(property, context)?;
Expand All @@ -751,13 +751,10 @@ pub(crate) fn default_number_option(
maximum: f64,
fallback: Option<f64>,
context: &mut Context,
) -> JsResult<f64> {
) -> JsResult<Option<f64>> {
// 1. If value is undefined, return fallback.
if value.is_undefined() {
match fallback {
Some(val_f64) => return Ok(val_f64),
None => return context.throw_type_error("DefaultNumberOption: no fallback provided"),
};
return Ok(fallback);
}

// 2. Set value to ? ToNumber(value).
Expand All @@ -769,5 +766,5 @@ pub(crate) fn default_number_option(
}

// 4. Return floor(value).
Ok(value.floor())
Ok(Some(value.floor()))
}
Loading

0 comments on commit 2676d0b

Please sign in to comment.