Skip to content

Commit

Permalink
Finish up clean up and linting of draft
Browse files Browse the repository at this point in the history
  • Loading branch information
nekevss committed Nov 21, 2023
1 parent 64bbfb8 commit 4f576a9
Show file tree
Hide file tree
Showing 16 changed files with 153 additions and 776 deletions.
117 changes: 14 additions & 103 deletions boa_engine/src/builtins/temporal/calendar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,12 +1140,22 @@ pub(crate) fn to_temporal_calendar_slot_value(
return Ok(calendar);
}
} else if calendar_like.is_plain_date_time() {
todo!()
// TODO
return Err(JsNativeError::range()
.with_message("Not yet implemented.")
.into());
} else if calendar_like.is_plain_year_month() {
todo!()
// TODO
return Err(JsNativeError::range()
.with_message("Not yet implemented.")
.into());
} else if calendar_like.is_plain_month_day() {
todo!()
// TODO
return Err(JsNativeError::range()
.with_message("Not yet implemented.")
.into());
} else if calendar_like.is_zoned_date_time() {
// TODO
return Err(JsNativeError::range()
.with_message("Not yet implemented.")
.into());
Expand Down Expand Up @@ -1187,6 +1197,7 @@ fn object_implements_calendar_protocol(calendar_like: &JsObject, context: &mut C
})
}

/// Utility function for taking a `JsValue` and converting it to a temporal library `CalendarDateLike` enum.
fn to_calendar_date_like(date_like: &JsValue, context: &mut Context) -> JsResult<CalendarDateLike> {
match date_like {
JsValue::Object(o) if o.is_plain_date_time() => {
Expand All @@ -1213,103 +1224,3 @@ fn to_calendar_date_like(date_like: &JsValue, context: &mut Context) -> JsResult
}
}
}

// ---------------------------- Native Abstract Calendar Methods ----------------------------
//
// The above refers to the functions in the Abstract Operations section of the Calendar
// spec takes either a calendar identifier or `Temporal.Calendar` and calls the a
// function that aligns with a method on `Temporal.Calendar`. These functions appear
// to be a second completely abstract builtin calendar implementation itself, so
// separating them from the other Abstract Operations seems both natural and will
// hopefully make any changes more maintainable.
//
// NOTE: Instead of creating temporal calendar it may be more efficient to retrieve
// the protocol and call the value directly in rust, something to consider.

/*
/// 12.2.2 `CalendarFields ( calendar, fieldNames )`
///
/// `CalendarFields` takes the input fields and adds the `extraFieldDescriptors` for
/// that specific calendar.
#[allow(unused)]
pub(crate) fn calendar_fields(
calendar: &JsValue,
field_names: Vec<JsValue>,
context: &mut Context,
) -> JsResult<Vec<JsValue>> {
let field_names = Array::create_array_from_list(field_names, context);
// 1. If calendar is a String, then
// a. Set calendar to ! CreateTemporalCalendar(calendar).
// b. Let fieldsArray be ? Call(%Temporal.Calendar.prototype.fields%, calendar, « CreateArrayFromList(fieldNames) »).
// c. Return ! CreateListFromArrayLike(fieldsArray, « String »).
// 2. Let fieldsArray be ? Invoke(calendar, "fields", « CreateArrayFromList(fieldNames) »).
let fields_array = call_method_on_abstract_calendar(
calendar,
&JsString::from("fields"),
&[field_names.into()],
context,
)?;
// 3. Let iteratorRecord be ? GetIterator(fieldsArray, sync).
let mut iterator_record = fields_array.get_iterator(context, Some(IteratorHint::Sync), None)?;
// 4. Return ? IteratorToListOfType(iteratorRecord, « String »).
super::iterator_to_list_of_types(&mut iterator_record, &[crate::value::Type::String], context)
}
/// 12.2.3 `CalendarMergeFields ( calendar, fields, additionalFields )`
///
/// Returns either a normal completion containing an Object, or a throw completion.
#[allow(unused)]
pub(crate) fn calendar_merge_fields(
calendar: &JsValue,
fields: &TemporalFields,
additional_fields: &JsValue,
context: &mut Context,
) -> JsResult<JsObject> {
// 1. If calendar is a String, then
// a. Set calendar to ! CreateTemporalCalendar(calendar).
// b. Return ? Call(%Temporal.Calendar.prototype.mergeFields%, calendar, « fields, additionalFields »).
// 2. Let result be ? Invoke(calendar, "mergeFields", « fields, additionalFields »).
let result = call_method_on_abstract_calendar(
calendar,
&JsString::from("mergeFields"),
&[fields.as_object(context)?.into(), additional_fields.clone()],
context,
)?;
// 3. If Type(result) is not Object, throw a TypeError exception.
// 4. Return result.
match result {
JsValue::Object(o) => Ok(o),
_ => Err(JsNativeError::typ()
.with_message("mergeFields must return an object")
.into()),
}
}
/// 12.2.24 `CalendarDateFromFields ( calendar, fields [ , options [ , dateFromFields ] ] )`
#[allow(unused)]
pub(crate) fn calendar_date_from_fields(
calendar: &JsValue,
_fields: &JsObject,
options: Option<&JsValue>,
_date_from_fields: Option<&JsObject>,
) -> JsResult<PlainDate> {
let _options = match options {
Some(o) => o.clone(),
_ => JsValue::undefined(),
};
// 1. If options is not present, set options to undefined.
// 2. If calendar is a String, then
// a. Set calendar to ! CreateTemporalCalendar(calendar).
// b. Return ? Call(%Temporal.Calendar.prototype.dateFromFields%, calendar, « fields, options »).
// 3. If dateFromFields is not present, set dateFromFields to ? GetMethod(calendar, "dateFromFields").
// 4. Let date be ? Call(calendar, dateFromFields, « fields, options »).
// 5. Perform ? RequireInternalSlot(date, [[InitializedTemporalDate]]).
// 6. Return date.
Err(JsNativeError::range()
.with_message("not yet implemented.")
.into())
}
*/
71 changes: 69 additions & 2 deletions boa_engine/src/builtins/temporal/calendar/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ impl CalendarProtocol for CustomRuntimeCalendar {
_overflow: ArithmeticOverflow,
_context: &mut dyn Any,
) -> TemporalResult<TemporalDate> {
todo!()
// TODO
Err(TemporalError::general("Not yet implemented."))
}

fn date_until(
Expand All @@ -217,7 +218,8 @@ impl CalendarProtocol for CustomRuntimeCalendar {
_largest_unit: boa_temporal::options::TemporalUnit,
_context: &mut dyn Any,
) -> TemporalResult<Duration> {
todo!()
// TODO
Err(TemporalError::general("Not yet implemented."))
}

fn era(&self, _: &CalendarDateLike, _: &mut dyn Any) -> TemporalResult<Option<TinyStr8>> {
Expand Down Expand Up @@ -248,6 +250,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("year must return a number."));
};
Expand Down Expand Up @@ -285,6 +293,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("month must return a number."));
};
Expand Down Expand Up @@ -354,6 +368,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("day must return a number."));
};
Expand Down Expand Up @@ -395,6 +415,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("DayOfWeek must return a number."));
};
Expand Down Expand Up @@ -438,6 +464,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("dayOfYear must return a number."));
};
Expand Down Expand Up @@ -481,6 +513,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("weekOfYear must return a number."));
};
Expand Down Expand Up @@ -524,6 +562,11 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("yearOfWeek must return a number."));
};
Expand Down Expand Up @@ -561,6 +604,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("daysInWeek must return a number."));
};
Expand Down Expand Up @@ -603,6 +652,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("daysInMonth must return a number."));
};
Expand Down Expand Up @@ -648,6 +703,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("daysInYear must return a number."));
};
Expand Down Expand Up @@ -691,6 +752,12 @@ impl CalendarProtocol for CustomRuntimeCalendar {
.call(&method, &[date_like], context)
.map_err(|err| TemporalError::general(err.to_string()))?;

// Validate the return value.
// 3. If Type(result) is not Number, throw a TypeError exception.
// 4. If IsIntegralNumber(result) is false, throw a RangeError exception.
// 5. If result < 1𝔽, throw a RangeError exception.
// 6. Return ℝ(result).

let Some(number) = val.as_number() else {
return Err(TemporalError::r#type().with_message("monthsInYear must return a number."));
};
Expand Down
1 change: 0 additions & 1 deletion boa_engine/src/builtins/temporal/duration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,6 @@ pub(crate) fn create_temporal_duration(
}

/// Equivalent to 7.5.13 `ToTemporalPartialDurationRecord ( temporalDurationLike )`
///
pub(crate) fn to_temporal_partial_duration(
duration_like: &JsValue,
context: &mut Context,
Expand Down
8 changes: 5 additions & 3 deletions boa_engine/src/builtins/temporal/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ pub(crate) fn prepare_temporal_fields(
// iv. If value is not a String, throw a TypeError exception.
FieldValue::String(primitive.to_string(context)?.to_std_string_escaped())
}
_ => unreachable!("todo need to implement conversion handling for tz."),
FieldConversion::None => {
unreachable!("todo need to implement conversion handling for tz.")
}
};

// 3. Perform ! CreateDataPropertyOrThrow(result, property, value).
result
.set_field_value(field.to_std_string_escaped(), converted_value)
.set_field_value(&field.to_std_string_escaped(), &converted_value)
.expect("FieldConversion enforces the appropriate type");
// iii. Else if requiredFields is a List, then
} else if !partial {
Expand All @@ -126,7 +128,7 @@ pub(crate) fn prepare_temporal_fields(
// 2. If property is in the Property column of Table 17, then
// a. Set value to the corresponding Default value of the same row.
// 3. Perform ! CreateDataPropertyOrThrow(result, property, value).
result.require_field(field.to_std_string_escaped());
result.require_field(&field.to_std_string_escaped());
}
// c. Else if duplicateBehaviour is throw, then
} else if dup_option.to_std_string_escaped() == "throw" {
Expand Down
Loading

0 comments on commit 4f576a9

Please sign in to comment.