Skip to content

Commit 2fdc570

Browse files
committed
refactor: extract this-type-check boilerplate into require_internal_slot! macro
Replace the repeated as_object/downcast_ref/ok_or_else boilerplate with a single require_internal_slot! macro defined in builtins/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>. Uses the js_error! macro internally for error construction. Temporal modules (163 replacements): - zoneddatetime, plain_date_time, plain_time, plain_year_month, plain_date, duration, instant, plain_month_day Other builtins (32 replacements): - date (9), dataview (5), typed_array (4), array_buffer (4), shared_array_buffer (3), weak_map (2), intl/segmenter (2), intl/collator (1), weak_set (1), weak_ref (1)
1 parent 66a1cd2 commit 2fdc570

21 files changed

Lines changed: 221 additions & 1363 deletions

File tree

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

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -496,14 +496,7 @@ impl ArrayBuffer {
496496
// 1. Let O be the this value.
497497
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
498498
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
499-
let object = this.as_object();
500-
let buf = object
501-
.as_ref()
502-
.and_then(JsObject::downcast_ref::<Self>)
503-
.ok_or_else(|| {
504-
JsNativeError::typ()
505-
.with_message("get ArrayBuffer.prototype.byteLength called with invalid `this`")
506-
})?;
499+
require_internal_slot!(buf = this, Self, "ArrayBuffer");
507500

508501
// 4. If IsDetachedBuffer(O) is true, return +0𝔽.
509502
// 5. Let length be O.[[ArrayBufferByteLength]].
@@ -522,15 +515,7 @@ impl ArrayBuffer {
522515
// 1. Let O be the this value.
523516
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
524517
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
525-
let object = this.as_object();
526-
let buf = object
527-
.as_ref()
528-
.and_then(JsObject::downcast_ref::<Self>)
529-
.ok_or_else(|| {
530-
JsNativeError::typ().with_message(
531-
"get ArrayBuffer.prototype.maxByteLength called with invalid `this`",
532-
)
533-
})?;
518+
require_internal_slot!(buf = this, Self, "ArrayBuffer");
534519

535520
// 4. If IsDetachedBuffer(O) is true, return +0𝔽.
536521
let Some(data) = buf.bytes() else {
@@ -556,14 +541,7 @@ impl ArrayBuffer {
556541
// 1. Let O be the this value.
557542
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
558543
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
559-
let object = this.as_object();
560-
let buf = object
561-
.as_ref()
562-
.and_then(JsObject::downcast_ref::<Self>)
563-
.ok_or_else(|| {
564-
JsNativeError::typ()
565-
.with_message("get ArrayBuffer.prototype.resizable called with invalid `this`")
566-
})?;
544+
require_internal_slot!(buf = this, Self, "ArrayBuffer");
567545

568546
// 4. If IsFixedLengthArrayBuffer(O) is false, return true; otherwise return false.
569547
Ok(JsValue::from(!buf.is_fixed_len()))
@@ -581,14 +559,7 @@ impl ArrayBuffer {
581559
// 1. Let O be the this value.
582560
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
583561
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
584-
let object = this.as_object();
585-
let buf = object
586-
.as_ref()
587-
.and_then(JsObject::downcast_ref::<Self>)
588-
.ok_or_else(|| {
589-
JsNativeError::typ()
590-
.with_message("get ArrayBuffer.prototype.detached called with invalid `this`")
591-
})?;
562+
require_internal_slot!(buf = this, Self, "ArrayBuffer");
592563

593564
// 4. Return IsDetachedBuffer(O).
594565
Ok(buf.is_detached().into())

core/engine/src/builtins/array_buffer/shared.rs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,7 @@ impl SharedArrayBuffer {
225225
// 1. Let O be the this value.
226226
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
227227
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
228-
let object = this.as_object();
229-
let buf = object
230-
.as_ref()
231-
.and_then(JsObject::downcast_ref::<Self>)
232-
.ok_or_else(|| {
233-
JsNativeError::typ()
234-
.with_message("SharedArrayBuffer.byteLength called with invalid value")
235-
})?;
228+
require_internal_slot!(buf = this, Self, "SharedArrayBuffer");
236229

237230
// 4. Let length be ArrayBufferByteLength(O, seq-cst).
238231
let len = buf.bytes(Ordering::SeqCst).len() as u64;
@@ -252,14 +245,7 @@ impl SharedArrayBuffer {
252245
// 1. Let O be the this value.
253246
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
254247
// 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
255-
let object = this.as_object();
256-
let buf = object
257-
.as_ref()
258-
.and_then(JsObject::downcast_ref::<Self>)
259-
.ok_or_else(|| {
260-
JsNativeError::typ()
261-
.with_message("get SharedArrayBuffer.growable called with invalid `this`")
262-
})?;
248+
require_internal_slot!(buf = this, Self, "SharedArrayBuffer");
263249

264250
// 4. If IsFixedLengthArrayBuffer(O) is false, return true; otherwise return false.
265251
Ok(JsValue::from(!buf.is_fixed_len()))
@@ -276,14 +262,7 @@ impl SharedArrayBuffer {
276262
// 1. Let O be the this value.
277263
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
278264
// 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
279-
let object = this.as_object();
280-
let buf = object
281-
.as_ref()
282-
.and_then(JsObject::downcast_ref::<Self>)
283-
.ok_or_else(|| {
284-
JsNativeError::typ()
285-
.with_message("get SharedArrayBuffer.maxByteLength called with invalid value")
286-
})?;
265+
require_internal_slot!(buf = this, Self, "SharedArrayBuffer");
287266

288267
// 4. If IsFixedLengthArrayBuffer(O) is true, then
289268
// a. Let length be O.[[ArrayBufferByteLength]].

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

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,7 @@ impl DataView {
331331
) -> JsResult<JsValue> {
332332
// 1. Let O be the this value.
333333
// 2. Perform ? RequireInternalSlot(O, [[DataView]]).
334-
let object = this.as_object();
335-
let view = object
336-
.as_ref()
337-
.and_then(JsObject::downcast_ref::<Self>)
338-
.ok_or_else(|| JsNativeError::typ().with_message("`this` is not a DataView"))?;
334+
require_internal_slot!(view = this, Self, "DataView");
339335
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
340336
// 4. Let buffer be O.[[ViewedArrayBuffer]].
341337
let buffer = view.viewed_array_buffer.clone();
@@ -361,11 +357,7 @@ impl DataView {
361357
// 1. Let O be the this value.
362358
// 2. Perform ? RequireInternalSlot(O, [[DataView]]).
363359
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
364-
let object = this.as_object();
365-
let view = object
366-
.as_ref()
367-
.and_then(JsObject::downcast_ref::<Self>)
368-
.ok_or_else(|| JsNativeError::typ().with_message("`this` is not a DataView"))?;
360+
require_internal_slot!(view = this, Self, "DataView");
369361

370362
// 4. Let viewRecord be MakeDataViewWithBufferWitnessRecord(O, seq-cst).
371363
// 5. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
@@ -404,11 +396,7 @@ impl DataView {
404396
) -> JsResult<JsValue> {
405397
// 1. Let O be the this value.
406398
// 2. Perform ? RequireInternalSlot(O, [[DataView]]).
407-
let object = this.as_object();
408-
let view = object
409-
.as_ref()
410-
.and_then(JsObject::downcast_ref::<Self>)
411-
.ok_or_else(|| JsNativeError::typ().with_message("`this` is not a DataView"))?;
399+
require_internal_slot!(view = this, Self, "DataView");
412400

413401
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
414402
let buffer = view.viewed_array_buffer.as_buffer();
@@ -448,11 +436,7 @@ impl DataView {
448436
) -> JsResult<JsValue> {
449437
// 1. Perform ? RequireInternalSlot(view, [[DataView]]).
450438
// 2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
451-
let object = view.as_object();
452-
let view = object
453-
.as_ref()
454-
.and_then(JsObject::downcast_ref::<Self>)
455-
.ok_or_else(|| JsNativeError::typ().with_message("`this` is not a DataView"))?;
439+
require_internal_slot!(view = view, Self, "DataView");
456440

457441
// 3. Let getIndex be ? ToIndex(requestIndex).
458442
let get_index = request_index.to_index(context)?;
@@ -790,11 +774,7 @@ impl DataView {
790774
) -> JsResult<JsValue> {
791775
// 1. Perform ? RequireInternalSlot(view, [[DataView]]).
792776
// 2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
793-
let object = view.as_object();
794-
let view = object
795-
.as_ref()
796-
.and_then(JsObject::downcast_ref::<Self>)
797-
.ok_or_else(|| JsNativeError::typ().with_message("`this` is not a DataView"))?;
777+
require_internal_slot!(view = view, Self, "DataView");
798778

799779
// 3. Let getIndex be ? ToIndex(requestIndex).
800780
let get_index = request_index.to_index(context)?;

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

Lines changed: 9 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -850,11 +850,7 @@ impl Date {
850850
) -> JsResult<JsValue> {
851851
// 1. Let dateObject be the this value.
852852
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
853-
let object = this.as_object();
854-
let date = object
855-
.as_ref()
856-
.and_then(JsObject::downcast_ref::<Date>)
857-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
853+
require_internal_slot!(date = this, Date, "Date");
858854

859855
// 3. Let t be dateObject.[[DateValue]].
860856
let mut t = date.0;
@@ -920,11 +916,7 @@ impl Date {
920916
) -> JsResult<JsValue> {
921917
// 1. Let dateObject be the this value.
922918
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
923-
let object = this.as_object();
924-
let date = object
925-
.as_ref()
926-
.and_then(JsObject::downcast_ref::<Date>)
927-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
919+
require_internal_slot!(date = this, Date, "Date");
928920

929921
// 3. Let t be dateObject.[[DateValue]].
930922
let t = date.0;
@@ -1005,11 +997,7 @@ impl Date {
1005997
) -> JsResult<JsValue> {
1006998
// 1. Let dateObject be the this value.
1007999
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1008-
let object = this.as_object();
1009-
let date = object
1010-
.as_ref()
1011-
.and_then(JsObject::downcast_ref::<Date>)
1012-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1000+
require_internal_slot!(date = this, Date, "Date");
10131001

10141002
// 3. Let t be dateObject.[[DateValue]].
10151003
let mut t = date.0;
@@ -1089,11 +1077,7 @@ impl Date {
10891077
) -> JsResult<JsValue> {
10901078
// 1. Let dateObject be the this value.
10911079
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1092-
let object = this.as_object();
1093-
let date = object
1094-
.as_ref()
1095-
.and_then(JsObject::downcast_ref::<Date>)
1096-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1080+
require_internal_slot!(date = this, Date, "Date");
10971081

10981082
// 3. Let t be dateObject.[[DateValue]].
10991083
let mut t = date.0;
@@ -1163,11 +1147,7 @@ impl Date {
11631147
) -> JsResult<JsValue> {
11641148
// 1. Let dateObject be the this value.
11651149
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1166-
let object = this.as_object();
1167-
let date = object
1168-
.as_ref()
1169-
.and_then(JsObject::downcast_ref::<Date>)
1170-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1150+
require_internal_slot!(date = this, Date, "Date");
11711151

11721152
// 3. Let t be dateObject.[[DateValue]].
11731153
let mut t = date.0;
@@ -1242,11 +1222,7 @@ impl Date {
12421222
) -> JsResult<JsValue> {
12431223
// 1. Let dateObject be the this value.
12441224
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1245-
let object = this.as_object();
1246-
let date = object
1247-
.as_ref()
1248-
.and_then(JsObject::downcast_ref::<Date>)
1249-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1225+
require_internal_slot!(date = this, Date, "Date");
12501226

12511227
// 3. Let t be dateObject.[[DateValue]].
12521228
let mut t = date.0;
@@ -1317,11 +1293,7 @@ impl Date {
13171293
) -> JsResult<JsValue> {
13181294
// 1. Let dateObject be the this value.
13191295
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1320-
let object = this.as_object();
1321-
let date = object
1322-
.as_ref()
1323-
.and_then(JsObject::downcast_ref::<Date>)
1324-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1296+
require_internal_slot!(date = this, Date, "Date");
13251297

13261298
// 3. Let t be dateObject.[[DateValue]].
13271299
let mut t = date.0;
@@ -1399,11 +1371,7 @@ impl Date {
13991371
) -> JsResult<JsValue> {
14001372
// 1. Let dateObject be the this value.
14011373
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1402-
let object = this.as_object();
1403-
let date = object
1404-
.as_ref()
1405-
.and_then(JsObject::downcast_ref::<Date>)
1406-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1374+
require_internal_slot!(date = this, Date, "Date");
14071375

14081376
// 3. Let t be dateObject.[[DateValue]].
14091377
let t = date.0;
@@ -1466,11 +1434,7 @@ impl Date {
14661434
) -> JsResult<JsValue> {
14671435
// 1. Let dateObject be the this value.
14681436
// 2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
1469-
let object = this.as_object();
1470-
let date = object
1471-
.as_ref()
1472-
.and_then(JsObject::downcast_ref::<Date>)
1473-
.ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Date"))?;
1437+
require_internal_slot!(date = this, Date, "Date");
14741438

14751439
// 3. Let t be ? ToNumber(time).
14761440
let t = args.get_or_undefined(0).to_number(context)?;

core/engine/src/builtins/date/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn date_this_time_value() {
103103
run_test_actions([TestAction::assert_native_error(
104104
"({toString: Date.prototype.toString}).toString()",
105105
JsNativeErrorKind::Type,
106-
"'this' is not a Date",
106+
"the this object must be a Date object.",
107107
)]);
108108
}
109109

@@ -952,17 +952,17 @@ fn date_proto_to_locale_string_intl() {
952952
TestAction::assert_native_error(
953953
"Date.prototype.toLocaleString.call({})",
954954
JsNativeErrorKind::Type,
955-
"'this' is not a Date",
955+
"the this object must be a Date object.",
956956
),
957957
TestAction::assert_native_error(
958958
"Date.prototype.toLocaleDateString.call({})",
959959
JsNativeErrorKind::Type,
960-
"'this' is not a Date",
960+
"the this object must be a Date object.",
961961
),
962962
TestAction::assert_native_error(
963963
"Date.prototype.toLocaleTimeString.call({})",
964964
JsNativeErrorKind::Type,
965-
"'this' is not a Date",
965+
"the this object must be a Date object.",
966966
),
967967
TestAction::assert_eq("new Date(NaN).toLocaleString()", js_str!("Invalid Date")),
968968
TestAction::assert("typeof new Date(2020, 6, 8).toLocaleString() === 'string'"),

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,7 @@ impl Collator {
413413
fn resolved_options(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
414414
// 1. Let collator be the this value.
415415
// 2. Perform ? RequireInternalSlot(collator, [[InitializedCollator]]).
416-
let object = this.as_object();
417-
let collator = object
418-
.as_ref()
419-
.and_then(JsObject::downcast_ref::<Self>)
420-
.ok_or_else(|| {
421-
JsNativeError::typ()
422-
.with_message("`resolvedOptions` can only be called on a `Collator` object")
423-
})?;
416+
require_internal_slot!(collator = this, Self, "Collator");
424417

425418
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
426419
let options = context

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,7 @@ impl Segmenter {
262262
fn resolved_options(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
263263
// 1. Let segmenter be the this value.
264264
// 2. Perform ? RequireInternalSlot(segmenter, [[InitializedSegmenter]]).
265-
let object = this.as_object();
266-
let segmenter = object
267-
.as_ref()
268-
.and_then(JsObject::downcast_ref::<Self>)
269-
.ok_or_else(|| {
270-
JsNativeError::typ().with_message(
271-
"`resolved_options` can only be called on an `Intl.Segmenter` object",
272-
)
273-
})?;
265+
require_internal_slot!(segmenter = this, Self, "Segmenter");
274266

275267
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
276268
// 4. For each row of Table 19, except the header row, in table order, do

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,7 @@ impl Segments {
5555
fn containing(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
5656
// 1. Let segments be the this value.
5757
// 2. Perform ? RequireInternalSlot(segments, [[SegmentsSegmenter]]).
58-
let object = this.as_object();
59-
let segments = object
60-
.as_ref()
61-
.and_then(JsObject::downcast_ref::<Self>)
62-
.ok_or_else(|| {
63-
JsNativeError::typ()
64-
.with_message("`containing` can only be called on a `Segments` object")
65-
})?;
58+
require_internal_slot!(segments = this, Self, "Segments");
6659

6760
// 3. Let segmenter be segments.[[SegmentsSegmenter]].
6861
let segmenter = segments

0 commit comments

Comments
 (0)