Skip to content

Commit 4c42492

Browse files
committed
refactor: extract Temporal this-type-check boilerplate into this_temporal_object! macro
Replace 163 occurrences of the 5-line this-type-check boilerplate across 8 Temporal builtin files with a single this_temporal_object! macro defined in temporal/mod.rs. The macro produces two let-bindings in the caller's scope: one for the owned JsObject (to keep it alive) and one for the downcast Ref<T>. Error messages standardized to: 'the this object must be a {Type} object.' Files changed: - temporal/mod.rs: macro definition - zoneddatetime/mod.rs: 47 replacements - plain_date_time/mod.rs: 37 replacements - plain_time/mod.rs: 16 replacements - plain_year_month/mod.rs: 15 replacements - plain_date/mod.rs: 15 replacements - duration/mod.rs: 13 replacements - instant/mod.rs: 12 replacements - plain_month_day/mod.rs: 8 replacements Net delta: +188 / -1145 lines
1 parent 66a1cd2 commit 4c42492

File tree

9 files changed

+188
-1145
lines changed

9 files changed

+188
-1145
lines changed

core/engine/src/builtins/temporal/duration/mod.rs

Lines changed: 13 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,7 @@ impl BuiltInConstructor for Duration {
331331
impl Duration {
332332
// Internal utility function for getting `Duration` field values.
333333
fn get_internal_field(this: &JsValue, field: &DateTimeValues) -> JsResult<JsValue> {
334-
let object = this.as_object();
335-
let duration = object
336-
.as_ref()
337-
.and_then(JsObject::downcast_ref::<Self>)
338-
.ok_or_else(|| {
339-
JsNativeError::typ().with_message("this value must be a Duration object.")
340-
})?;
334+
this_temporal_object!(duration = this, Self, "Duration");
341335

342336
let inner = &duration.inner;
343337

@@ -522,13 +516,7 @@ impl Duration {
522516
fn get_sign(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
523517
// 1. Let duration be the this value.
524518
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
525-
let object = this.as_object();
526-
let duration = object
527-
.as_ref()
528-
.and_then(JsObject::downcast_ref::<Self>)
529-
.ok_or_else(|| {
530-
JsNativeError::typ().with_message("this value must be a Duration object.")
531-
})?;
519+
this_temporal_object!(duration = this, Self, "Duration");
532520

533521
// 3. Return 𝔽(! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]],
534522
// duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]],
@@ -550,13 +538,7 @@ impl Duration {
550538
fn get_blank(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
551539
// 1. Let duration be the this value.
552540
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
553-
let object = this.as_object();
554-
let duration = object
555-
.as_ref()
556-
.and_then(JsObject::downcast_ref::<Self>)
557-
.ok_or_else(|| {
558-
JsNativeError::typ().with_message("this value must be a Duration object.")
559-
})?;
541+
this_temporal_object!(duration = this, Self, "Duration");
560542

561543
// 3. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]],
562544
// duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]],
@@ -642,13 +624,7 @@ impl Duration {
642624
) -> JsResult<JsValue> {
643625
// 1. Let duration be the this value.
644626
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
645-
let object = this.as_object();
646-
let duration = object
647-
.as_ref()
648-
.and_then(JsObject::downcast_ref::<Self>)
649-
.ok_or_else(|| {
650-
JsNativeError::typ().with_message("this value must be a Duration object.")
651-
})?;
627+
this_temporal_object!(duration = this, Self, "Duration");
652628

653629
// 3. Let temporalDurationLike be ? ToTemporalPartialDurationRecord(temporalDurationLike).
654630
let temporal_duration_like =
@@ -767,13 +743,7 @@ impl Duration {
767743
// 1. Let duration be the this value.
768744
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
769745
// 3. Return ! CreateNegatedTemporalDuration(duration).
770-
let object = this.as_object();
771-
let duration = object
772-
.as_ref()
773-
.and_then(JsObject::downcast_ref::<Self>)
774-
.ok_or_else(|| {
775-
JsNativeError::typ().with_message("this value must be a Duration object.")
776-
})?;
746+
this_temporal_object!(duration = this, Self, "Duration");
777747

778748
create_temporal_duration(duration.inner.negated(), None, context).map(Into::into)
779749
}
@@ -795,13 +765,7 @@ impl Duration {
795765
// 3. Return ! CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]),
796766
// abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]),
797767
// abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])).
798-
let object = this.as_object();
799-
let duration = object
800-
.as_ref()
801-
.and_then(JsObject::downcast_ref::<Self>)
802-
.ok_or_else(|| {
803-
JsNativeError::typ().with_message("this value must be a Duration object.")
804-
})?;
768+
this_temporal_object!(duration = this, Self, "Duration");
805769

806770
create_temporal_duration(duration.inner.abs(), None, context).map(Into::into)
807771
}
@@ -824,13 +788,7 @@ impl Duration {
824788
) -> JsResult<JsValue> {
825789
// 1.Let duration be the this value.
826790
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
827-
let object = this.as_object();
828-
let duration = object
829-
.as_ref()
830-
.and_then(JsObject::downcast_ref::<Self>)
831-
.ok_or_else(|| {
832-
JsNativeError::typ().with_message("this value must be a Duration object.")
833-
})?;
791+
this_temporal_object!(duration = this, Self, "Duration");
834792

835793
// 3. Return ? AddDurations(add, duration, other).
836794
let other = to_temporal_duration_record(args.get_or_undefined(0), context)?;
@@ -856,13 +814,7 @@ impl Duration {
856814
) -> JsResult<JsValue> {
857815
// 1.Let duration be the this value.
858816
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
859-
let object = this.as_object();
860-
let duration = object
861-
.as_ref()
862-
.and_then(JsObject::downcast_ref::<Self>)
863-
.ok_or_else(|| {
864-
JsNativeError::typ().with_message("this value must be a Duration object.")
865-
})?;
817+
this_temporal_object!(duration = this, Self, "Duration");
866818

867819
let other = to_temporal_duration_record(args.get_or_undefined(0), context)?;
868820

@@ -888,13 +840,7 @@ impl Duration {
888840
) -> JsResult<JsValue> {
889841
// 1. Let duration be the this value.
890842
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
891-
let object = this.as_object();
892-
let duration = object
893-
.as_ref()
894-
.and_then(JsObject::downcast_ref::<Self>)
895-
.ok_or_else(|| {
896-
JsNativeError::typ().with_message("this value must be a Duration object.")
897-
})?;
843+
this_temporal_object!(duration = this, Self, "Duration");
898844

899845
let round_to = match args.first().map(JsValue::variant) {
900846
// 3. If roundTo is undefined, then
@@ -991,13 +937,7 @@ impl Duration {
991937
) -> JsResult<JsValue> {
992938
// 1. Let duration be the this value.
993939
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
994-
let object = this.as_object();
995-
let duration = object
996-
.as_ref()
997-
.and_then(JsObject::downcast_ref::<Self>)
998-
.ok_or_else(|| {
999-
JsNativeError::typ().with_message("this value must be a Duration object.")
1000-
})?;
940+
this_temporal_object!(duration = this, Self, "Duration");
1001941

1002942
let total_of = args.get_or_undefined(0);
1003943

@@ -1067,13 +1007,7 @@ impl Duration {
10671007
args: &[JsValue],
10681008
context: &mut Context,
10691009
) -> JsResult<JsValue> {
1070-
let object = this.as_object();
1071-
let duration = object
1072-
.as_ref()
1073-
.and_then(JsObject::downcast_ref::<Self>)
1074-
.ok_or_else(|| {
1075-
JsNativeError::typ().with_message("this value must be a Duration object.")
1076-
})?;
1010+
this_temporal_object!(duration = this, Self, "Duration");
10771011

10781012
let options = get_options_object(args.get_or_undefined(0))?;
10791013
let precision = get_digits_option(&options, context)?;
@@ -1100,13 +1034,7 @@ impl Duration {
11001034
/// [spec]: https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.tojson
11011035
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toJSON
11021036
pub(crate) fn to_json(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
1103-
let object = this.as_object();
1104-
let duration = object
1105-
.as_ref()
1106-
.and_then(JsObject::downcast_ref::<Self>)
1107-
.ok_or_else(|| {
1108-
JsNativeError::typ().with_message("this value must be a Duration object.")
1109-
})?;
1037+
this_temporal_object!(duration = this, Self, "Duration");
11101038

11111039
let result = duration
11121040
.inner
@@ -1130,13 +1058,7 @@ impl Duration {
11301058
_: &mut Context,
11311059
) -> JsResult<JsValue> {
11321060
// TODO: Update for ECMA-402 compliance
1133-
let object = this.as_object();
1134-
let duration = object
1135-
.as_ref()
1136-
.and_then(JsObject::downcast_ref::<Self>)
1137-
.ok_or_else(|| {
1138-
JsNativeError::typ().with_message("this value must be a Duration object.")
1139-
})?;
1061+
this_temporal_object!(duration = this, Self, "Duration");
11401062

11411063
let result = duration
11421064
.inner

core/engine/src/builtins/temporal/instant/mod.rs

Lines changed: 12 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,7 @@ impl Instant {
286286
) -> JsResult<JsValue> {
287287
// 1. Let instant be the this value.
288288
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
289-
let object = this.as_object();
290-
let instant = object
291-
.as_ref()
292-
.and_then(JsObject::downcast_ref::<Self>)
293-
.ok_or_else(|| {
294-
JsNativeError::typ().with_message("the this object must be an instant object.")
295-
})?;
289+
this_temporal_object!(instant = this, Self, "Instant");
296290
// 3. Let ns be instant.[[Nanoseconds]].
297291
// 4. Let ms be floor(ℝ(ns) / 10^6).
298292
// 5. Return 𝔽(ms).
@@ -317,13 +311,7 @@ impl Instant {
317311
) -> JsResult<JsValue> {
318312
// 1. Let instant be the this value.
319313
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
320-
let object = this.as_object();
321-
let instant = object
322-
.as_ref()
323-
.and_then(JsObject::downcast_ref::<Self>)
324-
.ok_or_else(|| {
325-
JsNativeError::typ().with_message("the this object must be an instant object.")
326-
})?;
314+
this_temporal_object!(instant = this, Self, "Instant");
327315
// 3. Let ns be instant.[[Nanoseconds]].
328316
// 4. Return ns.
329317
Ok(JsBigInt::from(instant.inner.epoch_nanoseconds().as_i128()).into())
@@ -351,13 +339,7 @@ impl Instant {
351339
) -> JsResult<JsValue> {
352340
// 1. Let instant be the this value.
353341
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
354-
let object = this.as_object();
355-
let instant = object
356-
.as_ref()
357-
.and_then(JsObject::downcast_ref::<Self>)
358-
.ok_or_else(|| {
359-
JsNativeError::typ().with_message("the this object must be an instant object.")
360-
})?;
342+
this_temporal_object!(instant = this, Self, "Instant");
361343

362344
// 3. Return ? AddDurationToOrSubtractDurationFromInstant(add, instant, temporalDurationLike).
363345
let temporal_duration_like =
@@ -384,13 +366,7 @@ impl Instant {
384366
) -> JsResult<JsValue> {
385367
// 1. Let instant be the this value.
386368
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
387-
let object = this.as_object();
388-
let instant = object
389-
.as_ref()
390-
.and_then(JsObject::downcast_ref::<Self>)
391-
.ok_or_else(|| {
392-
JsNativeError::typ().with_message("the this object must be an instant object.")
393-
})?;
369+
this_temporal_object!(instant = this, Self, "Instant");
394370

395371
// 3. Return ? AddDurationToOrSubtractDurationFromInstant(subtract, instant, temporalDurationLike).
396372
let temporal_duration_like =
@@ -417,13 +393,7 @@ impl Instant {
417393
) -> JsResult<JsValue> {
418394
// 1. Let instant be the this value.
419395
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
420-
let object = this.as_object();
421-
let instant = object
422-
.as_ref()
423-
.and_then(JsObject::downcast_ref::<Self>)
424-
.ok_or_else(|| {
425-
JsNativeError::typ().with_message("the this object must be an instant object.")
426-
})?;
396+
this_temporal_object!(instant = this, Self, "Instant");
427397

428398
// 3. Return ? DifferenceTemporalInstant(until, instant, other, options).
429399
let other = to_temporal_instant(args.get_or_undefined(0), context)?;
@@ -453,13 +423,7 @@ impl Instant {
453423
) -> JsResult<JsValue> {
454424
// 1. Let instant be the this value.
455425
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
456-
let object = this.as_object();
457-
let instant = object
458-
.as_ref()
459-
.and_then(JsObject::downcast_ref::<Self>)
460-
.ok_or_else(|| {
461-
JsNativeError::typ().with_message("the this object must be an instant object.")
462-
})?;
426+
this_temporal_object!(instant = this, Self, "Instant");
463427

464428
// 3. Return ? DifferenceTemporalInstant(since, instant, other, options).
465429
let other = to_temporal_instant(args.get_or_undefined(0), context)?;
@@ -487,13 +451,7 @@ impl Instant {
487451
) -> JsResult<JsValue> {
488452
// 1. Let instant be the this value.
489453
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
490-
let object = this.as_object();
491-
let instant = object
492-
.as_ref()
493-
.and_then(JsObject::downcast_ref::<Self>)
494-
.ok_or_else(|| {
495-
JsNativeError::typ().with_message("the this object must be an instant object.")
496-
})?;
454+
this_temporal_object!(instant = this, Self, "Instant");
497455

498456
let round_to = match args.first().map(JsValue::variant) {
499457
// 3. If roundTo is undefined, then
@@ -589,13 +547,7 @@ impl Instant {
589547
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
590548
// 4. If instant.[[Nanoseconds]] ≠ other.[[Nanoseconds]], return false.
591549
// 5. Return true.
592-
let object = this.as_object();
593-
let instant = object
594-
.as_ref()
595-
.and_then(JsObject::downcast_ref::<Self>)
596-
.ok_or_else(|| {
597-
JsNativeError::typ().with_message("the this object must be an instant object.")
598-
})?;
550+
this_temporal_object!(instant = this, Self, "Instant");
599551

600552
// 3. Set other to ? ToTemporalInstant(other).
601553
let other = args.get_or_undefined(0);
@@ -619,14 +571,7 @@ impl Instant {
619571
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toString
620572
/// [temporal_rs-docs]: https://docs.rs/temporal_rs/latest/temporal_rs/struct.Instant.html#method.to_ixdtf_string
621573
fn to_string(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
622-
let object = this.as_object();
623-
let instant = object
624-
.as_ref()
625-
.and_then(JsObject::downcast_ref::<Self>)
626-
.ok_or_else(|| {
627-
JsNativeError::typ()
628-
.with_message("the this object must be a Temporal.Instant object.")
629-
})?;
574+
this_temporal_object!(instant = this, Self, "Instant");
630575

631576
let options = get_options_object(args.get_or_undefined(0))?;
632577

@@ -666,14 +611,7 @@ impl Instant {
666611
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toLocaleString
667612
fn to_locale_string(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
668613
// TODO: Update for ECMA-402 compliance
669-
let object = this.as_object();
670-
let instant = object
671-
.as_ref()
672-
.and_then(JsObject::downcast_ref::<Self>)
673-
.ok_or_else(|| {
674-
JsNativeError::typ()
675-
.with_message("the this object must be a Temporal.Instant object.")
676-
})?;
614+
this_temporal_object!(instant = this, Self, "Instant");
677615

678616
let ixdtf = instant.inner.to_ixdtf_string_with_provider(
679617
None,
@@ -693,14 +631,7 @@ impl Instant {
693631
/// [spec]: https://tc39.es/proposal-temporal/#sec-temporal.instant.tojson
694632
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toJSON
695633
fn to_json(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
696-
let object = this.as_object();
697-
let instant = object
698-
.as_ref()
699-
.and_then(JsObject::downcast_ref::<Self>)
700-
.ok_or_else(|| {
701-
JsNativeError::typ()
702-
.with_message("the this object must be a Temporal.Instant object.")
703-
})?;
634+
this_temporal_object!(instant = this, Self, "Instant");
704635

705636
let ixdtf = instant.inner.to_ixdtf_string_with_provider(
706637
None,
@@ -743,14 +674,7 @@ impl Instant {
743674
) -> JsResult<JsValue> {
744675
// 1. Let instant be the this value.
745676
// 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
746-
let object = this.as_object();
747-
let instant = object
748-
.as_ref()
749-
.and_then(JsObject::downcast_ref::<Self>)
750-
.ok_or_else(|| {
751-
JsNativeError::typ()
752-
.with_message("the this object must be a Temporal.Instant object.")
753-
})?;
677+
this_temporal_object!(instant = this, Self, "Instant");
754678

755679
// 3. Set timeZone to ? ToTemporalTimeZoneIdentifier(timeZone).
756680
let timezone = to_temporal_timezone_identifier(args.get_or_undefined(0), context)?;

0 commit comments

Comments
 (0)