Browse Source

Rewrite some patterns with let-else and ok_or_else (#2404)

This Pull Request updates the codebase to the newest version of rustc (1.65.0).

It changes the following:

- Bumps `rust-version` to 1.65.0.
- Rewrites some snippets to use the new let else, ok_or_else and some other utils.
- Removes the `rustdoc::missing_doc_code_examples` allow lint from our codebase. (Context: https://github.com/rust-lang/rust/pull/101732)
pull/2406/head
José Julián Espina 2 years ago
parent
commit
91235c77fe
  1. 2
      Cargo.toml
  2. 6
      boa_ast/src/lib.rs
  3. 11
      boa_engine/src/bigint.rs
  4. 8
      boa_engine/src/builtins/array/mod.rs
  5. 62
      boa_engine/src/builtins/array_buffer/mod.rs
  6. 136
      boa_engine/src/builtins/date/mod.rs
  7. 10
      boa_engine/src/builtins/error/mod.rs
  8. 4
      boa_engine/src/builtins/eval/mod.rs
  9. 12
      boa_engine/src/builtins/function/mod.rs
  10. 12
      boa_engine/src/builtins/iterable/async_from_sync_iterator.rs
  11. 25
      boa_engine/src/builtins/iterable/mod.rs
  12. 12
      boa_engine/src/builtins/map/mod.rs
  13. 4
      boa_engine/src/builtins/object/mod.rs
  14. 20
      boa_engine/src/builtins/promise/mod.rs
  15. 30
      boa_engine/src/builtins/reflect/mod.rs
  16. 41
      boa_engine/src/builtins/regexp/mod.rs
  17. 23
      boa_engine/src/builtins/set/mod.rs
  18. 4
      boa_engine/src/builtins/string/mod.rs
  19. 4
      boa_engine/src/builtins/uri/mod.rs
  20. 29
      boa_engine/src/class.rs
  21. 1
      boa_engine/src/lib.rs
  22. 4
      boa_engine/src/object/internal_methods/arguments.rs
  23. 7
      boa_engine/src/object/internal_methods/global.rs
  24. 7
      boa_engine/src/object/internal_methods/mod.rs
  25. 78
      boa_engine/src/object/internal_methods/proxy.rs
  26. 29
      boa_engine/src/object/operations.rs
  27. 4
      boa_engine/src/string/mod.rs
  28. 6
      boa_engine/src/syntax/parser/expression/primary/object_initializer/mod.rs
  29. 28
      boa_engine/src/syntax/parser/statement/declaration/hoistable/mod.rs
  30. 68
      boa_engine/src/syntax/parser/statement/declaration/lexical.rs
  31. 60
      boa_engine/src/syntax/parser/statement/variable/mod.rs
  32. 22
      boa_engine/src/vm/opcode/iteration/for_await.rs
  33. 1
      boa_interner/src/lib.rs
  34. 1
      boa_tester/src/main.rs
  35. 3
      boa_unicode/src/lib.rs
  36. 3
      boa_wasm/src/lib.rs

2
Cargo.toml

@ -16,7 +16,7 @@ members = [
[workspace.package] [workspace.package]
edition = "2021" edition = "2021"
version = "0.16.0" version = "0.16.0"
rust-version = "1.64" rust-version = "1.65"
authors = ["boa-dev"] authors = ["boa-dev"]
repository = "https://github.com/boa-dev/boa" repository = "https://github.com/boa-dev/boa"
license = "Unlicense/MIT" license = "Unlicense/MIT"

6
boa_ast/src/lib.rs

@ -49,11 +49,7 @@
nonstandard_style, nonstandard_style,
missing_docs missing_docs
)] )]
#![allow( #![allow(clippy::module_name_repetitions, clippy::too_many_lines)]
clippy::module_name_repetitions,
clippy::too_many_lines,
rustdoc::missing_doc_code_examples
)]
mod position; mod position;
mod punctuator; mod punctuator;

11
boa_engine/src/bigint.rs

@ -149,13 +149,10 @@ impl JsBigInt {
#[inline] #[inline]
pub fn pow(x: &Self, y: &Self) -> JsResult<Self> { pub fn pow(x: &Self, y: &Self) -> JsResult<Self> {
let y = if let Some(y) = y.inner.to_biguint() { let y = y
y .inner
} else { .to_biguint()
return Err(JsNativeError::range() .ok_or_else(|| JsNativeError::range().with_message("BigInt negative exponent"))?;
.with_message("BigInt negative exponent")
.into());
};
let num_bits = (x.inner.bits() as f64 let num_bits = (x.inner.bits() as f64
* y.to_f64().expect("Unable to convert from BigUInt to f64")) * y.to_f64().expect("Unable to convert from BigUInt to f64"))

8
boa_engine/src/builtins/array/mod.rs

@ -300,9 +300,7 @@ impl Array {
/// by `Array.prototype.concat`. /// by `Array.prototype.concat`.
fn is_concat_spreadable(o: &JsValue, context: &mut Context) -> JsResult<bool> { fn is_concat_spreadable(o: &JsValue, context: &mut Context) -> JsResult<bool> {
// 1. If Type(O) is not Object, return false. // 1. If Type(O) is not Object, return false.
let o = if let Some(o) = o.as_object() { let Some(o) = o.as_object() else {
o
} else {
return Ok(false); return Ok(false);
}; };
@ -461,9 +459,7 @@ impl Array {
let next = iterator_record.step(context)?; let next = iterator_record.step(context)?;
// iv. If next is false, then // iv. If next is false, then
let next = if let Some(next) = next { let Some(next) = next else {
next
} else {
// 1. Perform ? Set(A, "length", 𝔽(k), true). // 1. Perform ? Set(A, "length", 𝔽(k), true).
a.set("length", k, true, context)?; a.set("length", k, true, context)?;

62
boa_engine/src/builtins/array_buffer/mod.rs

@ -148,33 +148,25 @@ impl ArrayBuffer {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
let obj = if let Some(obj) = this.as_object() { let obj = this.as_object().ok_or_else(|| {
obj JsNativeError::typ().with_message("ArrayBuffer.byteLength called with non-object value")
} else { })?;
return Err(JsNativeError::typ()
.with_message("ArrayBuffer.byteLength called with non-object value")
.into());
};
let obj = obj.borrow(); let obj = obj.borrow();
let o = if let Some(o) = obj.as_array_buffer() { let buf = obj.as_array_buffer().ok_or_else(|| {
o JsNativeError::typ().with_message("ArrayBuffer.byteLength called with invalid object")
} else { })?;
return Err(JsNativeError::typ()
.with_message("ArrayBuffer.byteLength called with invalid object")
.into());
};
// TODO: Shared Array Buffer // TODO: Shared Array Buffer
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception. // 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
// 4. If IsDetachedBuffer(O) is true, return +0𝔽. // 4. If IsDetachedBuffer(O) is true, return +0𝔽.
if Self::is_detached_buffer(o) { if Self::is_detached_buffer(buf) {
return Ok(0.into()); return Ok(0.into());
} }
// 5. Let length be O.[[ArrayBufferByteLength]]. // 5. Let length be O.[[ArrayBufferByteLength]].
// 6. Return 𝔽(length). // 6. Return 𝔽(length).
Ok(o.array_buffer_byte_length.into()) Ok(buf.array_buffer_byte_length.into())
} }
/// `25.1.5.3 ArrayBuffer.prototype.slice ( start, end )` /// `25.1.5.3 ArrayBuffer.prototype.slice ( start, end )`
@ -186,34 +178,26 @@ impl ArrayBuffer {
fn slice(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> { fn slice(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
let obj = if let Some(obj) = this.as_object() { let obj = this.as_object().ok_or_else(|| {
obj JsNativeError::typ().with_message("ArrayBuffer.slice called with non-object value")
} else { })?;
return Err(JsNativeError::typ()
.with_message("ArrayBuffer.slice called with non-object value")
.into());
};
let obj_borrow = obj.borrow(); let obj_borrow = obj.borrow();
let o = if let Some(o) = obj_borrow.as_array_buffer() { let buf = obj_borrow.as_array_buffer().ok_or_else(|| {
o JsNativeError::typ().with_message("ArrayBuffer.slice called with invalid object")
} else { })?;
return Err(JsNativeError::typ()
.with_message("ArrayBuffer.slice called with invalid object")
.into());
};
// TODO: Shared Array Buffer // TODO: Shared Array Buffer
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception. // 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
// 4. If IsDetachedBuffer(O) is true, throw a TypeError exception. // 4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
if Self::is_detached_buffer(o) { if Self::is_detached_buffer(buf) {
return Err(JsNativeError::typ() return Err(JsNativeError::typ()
.with_message("ArrayBuffer.slice called with detached buffer") .with_message("ArrayBuffer.slice called with detached buffer")
.into()); .into());
} }
// 5. Let len be O.[[ArrayBufferByteLength]]. // 5. Let len be O.[[ArrayBufferByteLength]].
let len = o.array_buffer_byte_length as i64; let len = buf.array_buffer_byte_length as i64;
// 6. Let relativeStart be ? ToIntegerOrInfinity(start). // 6. Let relativeStart be ? ToIntegerOrInfinity(start).
let relative_start = args.get_or_undefined(0).to_integer_or_infinity(context)?; let relative_start = args.get_or_undefined(0).to_integer_or_infinity(context)?;
@ -298,14 +282,14 @@ impl ArrayBuffer {
// 22. NOTE: Side-effects of the above steps may have detached O. // 22. NOTE: Side-effects of the above steps may have detached O.
// 23. If IsDetachedBuffer(O) is true, throw a TypeError exception. // 23. If IsDetachedBuffer(O) is true, throw a TypeError exception.
if Self::is_detached_buffer(o) { if Self::is_detached_buffer(buf) {
return Err(JsNativeError::typ() return Err(JsNativeError::typ()
.with_message("ArrayBuffer detached while ArrayBuffer.slice was running") .with_message("ArrayBuffer detached while ArrayBuffer.slice was running")
.into()); .into());
} }
// 24. Let fromBuf be O.[[ArrayBufferData]]. // 24. Let fromBuf be O.[[ArrayBufferData]].
let from_buf = o let from_buf = buf
.array_buffer_data .array_buffer_data
.as_ref() .as_ref()
.expect("ArrayBuffer cannot be detached here"); .expect("ArrayBuffer cannot be detached here");
@ -389,13 +373,9 @@ impl ArrayBuffer {
// 2. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception. // 2. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception.
// 3. Let srcBlock be srcBuffer.[[ArrayBufferData]]. // 3. Let srcBlock be srcBuffer.[[ArrayBufferData]].
let src_block = if let Some(b) = &self.array_buffer_data { let src_block = self.array_buffer_data.as_deref().ok_or_else(|| {
b JsNativeError::syntax().with_message("Cannot clone detached array buffer")
} else { })?;
return Err(JsNativeError::syntax()
.with_message("Cannot clone detached array buffer")
.into());
};
{ {
// 4. Let targetBlock be targetBuffer.[[ArrayBufferData]]. // 4. Let targetBlock be targetBuffer.[[ArrayBufferData]].

136
boa_engine/src/builtins/date/mod.rs

@ -508,13 +508,9 @@ impl Date {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. If Type(O) is not Object, throw a TypeError exception. // 2. If Type(O) is not Object, throw a TypeError exception.
let o = if let Some(o) = this.as_object() { let o = this.as_object().ok_or_else(|| {
o JsNativeError::typ().with_message("Date.prototype[@@toPrimitive] called on non object")
} else { })?;
return Err(JsNativeError::typ()
.with_message("Date.prototype[@@toPrimitive] called on non object")
.into());
};
let hint = args.get_or_undefined(0); let hint = args.get_or_undefined(0);
@ -908,25 +904,13 @@ impl Date {
} }
// 3. Let y be ? ToNumber(year). // 3. Let y be ? ToNumber(year).
let y = args let y = args.get_or_undefined(0).to_number(context)?;
.get(0)
.cloned()
.unwrap_or_default()
.to_number(context)?;
// 4. If month is not present, let m be MonthFromTime(t); otherwise, let m be ? ToNumber(month). // 4. If month is not present, let m be MonthFromTime(t); otherwise, let m be ? ToNumber(month).
let m = if let Some(m) = args.get(1) { let m = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(m.to_number(context)?)
} else {
None
};
// 5. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date). // 5. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date).
let dt = if let Some(dt) = args.get(2) { let dt = args.get(2).map(|v| v.to_number(context)).transpose()?;
Some(dt.to_number(context)?)
} else {
None
};
// 6. Let newDate be MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)). // 6. Let newDate be MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)).
t.set_components(false, Some(y), m, dt, None, None, None, None); t.set_components(false, Some(y), m, dt, None, None, None, None);
@ -965,25 +949,13 @@ impl Date {
.to_number(context)?; .to_number(context)?;
// 3. If min is not present, let m be MinFromTime(t); otherwise, let m be ? ToNumber(min). // 3. If min is not present, let m be MinFromTime(t); otherwise, let m be ? ToNumber(min).
let m = if let Some(m) = args.get(1) { let m = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(m.to_number(context)?)
} else {
None
};
// 4. If sec is not present, let s be SecFromTime(t); otherwise, let s be ? ToNumber(sec). // 4. If sec is not present, let s be SecFromTime(t); otherwise, let s be ? ToNumber(sec).
let sec = if let Some(sec) = args.get(2) { let sec = args.get(2).map(|v| v.to_number(context)).transpose()?;
Some(sec.to_number(context)?)
} else {
None
};
// 5. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms). // 5. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms).
let milli = if let Some(milli) = args.get(3) { let milli = args.get(3).map(|v| v.to_number(context)).transpose()?;
Some(milli.to_number(context)?)
} else {
None
};
// 6. Let date be MakeDate(Day(t), MakeTime(h, m, s, milli)). // 6. Let date be MakeDate(Day(t), MakeTime(h, m, s, milli)).
t.set_components(false, None, None, None, Some(h), m, sec, milli); t.set_components(false, None, None, None, Some(h), m, sec, milli);
@ -1062,18 +1034,10 @@ impl Date {
.to_number(context)?; .to_number(context)?;
// 3. If sec is not present, let s be SecFromTime(t); otherwise, let s be ? ToNumber(sec). // 3. If sec is not present, let s be SecFromTime(t); otherwise, let s be ? ToNumber(sec).
let s = if let Some(s) = args.get(1) { let s = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(s.to_number(context)?)
} else {
None
};
// 4. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms). // 4. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms).
let milli = if let Some(milli) = args.get(2) { let milli = args.get(2).map(|v| v.to_number(context)).transpose()?;
Some(milli.to_number(context)?)
} else {
None
};
// 5. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)). // 5. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)).
t.set_components(false, None, None, None, None, Some(m), s, milli); t.set_components(false, None, None, None, None, Some(m), s, milli);
@ -1110,11 +1074,7 @@ impl Date {
.to_number(context)?; .to_number(context)?;
// 3. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date). // 3. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date).
let dt = if let Some(date) = args.get(1) { let dt = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(date.to_number(context)?)
} else {
None
};
// 4. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)). // 4. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)).
t.set_components(false, None, Some(m), dt, None, None, None, None); t.set_components(false, None, Some(m), dt, None, None, None, None);
@ -1155,11 +1115,7 @@ impl Date {
.to_number(context)?; .to_number(context)?;
// 3. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms). // 3. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms).
let milli = if let Some(milli) = args.get(1) { let milli = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(milli.to_number(context)?)
} else {
None
};
// 4. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)). // 4. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)).
t.set_components(false, None, None, None, None, None, Some(s), milli); t.set_components(false, None, None, None, None, None, Some(s), milli);
@ -1341,18 +1297,10 @@ impl Date {
.to_number(context)?; .to_number(context)?;
// 4. If month is not present, let m be MonthFromTime(t); otherwise, let m be ? ToNumber(month). // 4. If month is not present, let m be MonthFromTime(t); otherwise, let m be ? ToNumber(month).
let m = if let Some(m) = args.get(1) { let m = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(m.to_number(context)?)
} else {
None
};
// 5. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date). // 5. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date).
let dt = if let Some(dt) = args.get(2) { let dt = args.get(2).map(|v| v.to_number(context)).transpose()?;
Some(dt.to_number(context)?)
} else {
None
};
// 6. Let newDate be MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)). // 6. Let newDate be MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)).
t.set_components(true, Some(y), m, dt, None, None, None, None); t.set_components(true, Some(y), m, dt, None, None, None, None);
@ -1395,25 +1343,13 @@ impl Date {
.to_number(context)?; .to_number(context)?;
// 3. If min is not present, let m be MinFromTime(t); otherwise, let m be ? ToNumber(min). // 3. If min is not present, let m be MinFromTime(t); otherwise, let m be ? ToNumber(min).
let m = if let Some(m) = args.get(1) { let m = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(m.to_number(context)?)
} else {
None
};
// 4. If sec is not present, let s be SecFromTime(t); otherwise, let s be ? ToNumber(sec). // 4. If sec is not present, let s be SecFromTime(t); otherwise, let s be ? ToNumber(sec).
let sec = if let Some(s) = args.get(2) { let sec = args.get(2).map(|v| v.to_number(context)).transpose()?;
Some(s.to_number(context)?)
} else {
None
};
// 5. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms). // 5. If ms is not present, let milli be msFromTime(t); otherwise, let milli be ? ToNumber(ms).
let ms = if let Some(ms) = args.get(3) { let ms = args.get(3).map(|v| v.to_number(context)).transpose()?;
Some(ms.to_number(context)?)
} else {
None
};
// 6. Let newDate be MakeDate(Day(t), MakeTime(h, m, s, milli)). // 6. Let newDate be MakeDate(Day(t), MakeTime(h, m, s, milli)).
t.set_components(true, None, None, None, Some(h), m, sec, ms); t.set_components(true, None, None, None, Some(h), m, sec, ms);
@ -1493,21 +1429,13 @@ impl Date {
// 3. If sec is not present, let s be SecFromTime(t). // 3. If sec is not present, let s be SecFromTime(t).
// 4. Else, // 4. Else,
let s = if let Some(s) = args.get(1) { // a. Let s be ? ToNumber(sec).
// a. Let s be ? ToNumber(sec). let s = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(s.to_number(context)?)
} else {
None
};
// 5. If ms is not present, let milli be msFromTime(t). // 5. If ms is not present, let milli be msFromTime(t).
// 6. Else, // 6. Else,
let milli = if let Some(ms) = args.get(2) { // a. Let milli be ? ToNumber(ms).
// a. Let milli be ? ToNumber(ms). let milli = args.get(2).map(|v| v.to_number(context)).transpose()?;
Some(ms.to_number(context)?)
} else {
None
};
// 7. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)). // 7. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)).
t.set_components(true, None, None, None, None, Some(m), s, milli); t.set_components(true, None, None, None, None, Some(m), s, milli);
@ -1549,12 +1477,8 @@ impl Date {
// 3. If date is not present, let dt be DateFromTime(t). // 3. If date is not present, let dt be DateFromTime(t).
// 4. Else, // 4. Else,
let dt = if let Some(dt) = args.get(1) { // a. Let dt be ? ToNumber(date).
// a. Let dt be ? ToNumber(date). let dt = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(dt.to_number(context)?)
} else {
None
};
// 5. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)). // 5. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)).
t.set_components(true, None, Some(m), dt, None, None, None, None); t.set_components(true, None, Some(m), dt, None, None, None, None);
@ -1596,12 +1520,8 @@ impl Date {
// 3. If ms is not present, let milli be msFromTime(t). // 3. If ms is not present, let milli be msFromTime(t).
// 4. Else, // 4. Else,
let milli = if let Some(milli) = args.get(1) { // a. Let milli be ? ToNumber(ms).
// a. Let milli be ? ToNumber(ms). let milli = args.get(1).map(|v| v.to_number(context)).transpose()?;
Some(milli.to_number(context)?)
} else {
None
};
// 5. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)). // 5. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)).
t.set_components(true, None, None, None, None, None, Some(s), milli); t.set_components(true, None, None, None, None, None, Some(s), milli);
@ -1841,9 +1761,7 @@ impl Date {
// This method is implementation-defined and discouraged, so we just require the same format as the string // This method is implementation-defined and discouraged, so we just require the same format as the string
// constructor. // constructor.
let date = if let Some(arg) = args.get(0) { let Some(date) = args.get(0) else {
arg
} else {
return Ok(JsValue::nan()); return Ok(JsValue::nan());
}; };

10
boa_engine/src/builtins/error/mod.rs

@ -170,14 +170,10 @@ impl Error {
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let O be the this value. // 1. Let O be the this value.
let o = if let Some(o) = this.as_object() {
o
// 2. If Type(O) is not Object, throw a TypeError exception. // 2. If Type(O) is not Object, throw a TypeError exception.
} else { let o = this
return Err(JsNativeError::typ() .as_object()
.with_message("'this' is not an Object") .ok_or_else(|| JsNativeError::typ().with_message("'this' is not an Object"))?;
.into());
};
// 3. Let name be ? Get(O, "name"). // 3. Let name be ? Get(O, "name").
let name = o.get(js_string!("name"), context)?; let name = o.get(js_string!("name"), context)?;

4
boa_engine/src/builtins/eval/mod.rs

@ -77,9 +77,7 @@ impl Eval {
debug_assert!(direct || !strict); debug_assert!(direct || !strict);
// 2. If Type(x) is not String, return x. // 2. If Type(x) is not String, return x.
let x = if let Some(x) = x.as_string() { let Some(x) = x.as_string() else {
x.clone()
} else {
return Ok(x.clone()); return Ok(x.clone());
}; };

12
boa_engine/src/builtins/function/mod.rs

@ -841,15 +841,9 @@ impl BuiltInFunctionObject {
} }
}; };
let name = if let Some(name) = name { let name = name
if name.is_empty() { .filter(|n| !n.is_empty())
"anonymous".into() .unwrap_or_else(|| "anonymous".into());
} else {
name
}
} else {
"anonymous".into()
};
match function { match function {
Function::Native { .. } | Function::Closure { .. } | Function::Ordinary { .. } => { Function::Native { .. } | Function::Closure { .. } | Function::Ordinary { .. } => {

12
boa_engine/src/builtins/iterable/async_from_sync_iterator.rs

@ -233,10 +233,8 @@ impl AsyncFromSyncIterator {
// 10. IfAbruptRejectPromise(result, promiseCapability). // 10. IfAbruptRejectPromise(result, promiseCapability).
if_abrupt_reject_promise!(result, promise_capability, context); if_abrupt_reject_promise!(result, promise_capability, context);
// 11. If Type(result) is not Object, then let Some(result) = result.as_object() else {
let result = if let Some(result) = result.as_object() { // 11. If Type(result) is not Object, then
result
} else {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »). // a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
promise_capability promise_capability
.reject() .reject()
@ -333,10 +331,8 @@ impl AsyncFromSyncIterator {
// 10. IfAbruptRejectPromise(result, promiseCapability). // 10. IfAbruptRejectPromise(result, promiseCapability).
if_abrupt_reject_promise!(result, promise_capability, context); if_abrupt_reject_promise!(result, promise_capability, context);
// 11. If Type(result) is not Object, then let Some(result) = result.as_object() else {
let result = if let Some(result) = result.as_object() { // 11. If Type(result) is not Object, then
result
} else {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »). // a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
promise_capability promise_capability
.reject() .reject()

25
boa_engine/src/builtins/iterable/mod.rs

@ -353,13 +353,9 @@ impl IteratorRecord {
// Note: We check if iteratorRecord.[[NextMethod]] is callable here. // Note: We check if iteratorRecord.[[NextMethod]] is callable here.
// This check would happen in `Call` according to the spec, but we do not implement call for `JsValue`. // This check would happen in `Call` according to the spec, but we do not implement call for `JsValue`.
let next_method = if let Some(next_method) = self.next_method.as_callable() { let next_method = self.next_method.as_callable().ok_or_else(|| {
next_method JsNativeError::typ().with_message("iterable next method not a function")
} else { })?;
return Err(JsNativeError::typ()
.with_message("iterable next method not a function")
.into());
};
let result = if let Some(value) = value { let result = if let Some(value) = value {
// 2. Else, // 2. Else,
@ -373,13 +369,14 @@ impl IteratorRecord {
// 3. If Type(result) is not Object, throw a TypeError exception. // 3. If Type(result) is not Object, throw a TypeError exception.
// 4. Return result. // 4. Return result.
if let Some(o) = result.as_object() { result
Ok(IteratorResult { object: o.clone() }) .as_object()
} else { .map(|o| IteratorResult { object: o.clone() })
Err(JsNativeError::typ() .ok_or_else(|| {
.with_message("next value should be an object") JsNativeError::typ()
.into()) .with_message("next value should be an object")
} .into()
})
} }
/// `IteratorStep ( iteratorRecord )` /// `IteratorStep ( iteratorRecord )`

12
boa_engine/src/builtins/map/mod.rs

@ -540,16 +540,14 @@ pub(crate) fn add_entries_from_iterable(
// b. If next is false, return target. // b. If next is false, return target.
// c. Let nextItem be ? IteratorValue(next). // c. Let nextItem be ? IteratorValue(next).
let next_item = if let Some(next) = next { let Some(next_item) = next else {
next.value(context)?
} else {
return Ok(target.clone().into()); return Ok(target.clone().into());
}; };
let next_item = if let Some(obj) = next_item.as_object() { let next_item = next_item.value(context)?;
obj
// d. If Type(nextItem) is not Object, then let Some(next_item) = next_item.as_object() else {
} else { // d. If Type(nextItem) is not Object, then
// i. Let error be ThrowCompletion(a newly created TypeError object). // i. Let error be ThrowCompletion(a newly created TypeError object).
let err = Err(JsNativeError::typ() let err = Err(JsNativeError::typ()
.with_message("cannot get key and value from primitive item of `iterable`") .with_message("cannot get key and value from primitive item of `iterable`")

4
boa_engine/src/builtins/object/mod.rs

@ -635,9 +635,7 @@ impl Object {
} }
}; };
let obj = if let Some(obj) = o.as_object() { let Some(obj) = o.as_object() else {
obj
} else {
// 3. If Type(O) is not Object, return O. // 3. If Type(O) is not Object, return O.
return Ok(o); return Ok(o);
}; };

20
boa_engine/src/builtins/promise/mod.rs

@ -1268,23 +1268,21 @@ impl Promise {
return Ok(JsValue::Undefined); return Ok(JsValue::Undefined);
} }
let then = if let Some(resolution) = resolution.as_object() { let Some(then) = resolution.as_object() else {
// 9. Let then be Completion(Get(resolution, "then")).
resolution.get("then", context)
} else {
// 8. If Type(resolution) is not Object, then // 8. If Type(resolution) is not Object, then
// a. Perform FulfillPromise(promise, resolution). // a. Perform FulfillPromise(promise, resolution).
promise promise
.borrow_mut() .borrow_mut()
.as_promise_mut() .as_promise_mut()
.expect("Expected promise to be a Promise") .expect("Expected promise to be a Promise")
.fulfill_promise(resolution, context)?; .fulfill_promise(resolution, context)?;
// b. Return undefined. // b. Return undefined.
return Ok(JsValue::Undefined); return Ok(JsValue::Undefined);
}; };
let then_action = match then { // 9. Let then be Completion(Get(resolution, "then")).
let then_action = match then.get("then", context) {
// 10. If then is an abrupt completion, then // 10. If then is an abrupt completion, then
Err(e) => { Err(e) => {
// a. Perform RejectPromise(promise, then.[[Value]]). // a. Perform RejectPromise(promise, then.[[Value]]).
@ -1741,9 +1739,7 @@ impl Promise {
let promise = this; let promise = this;
// 2. If Type(promise) is not Object, throw a TypeError exception. // 2. If Type(promise) is not Object, throw a TypeError exception.
let promise_obj = if let Some(p) = promise.as_object() { let Some(promise_obj) = promise.as_object() else {
p
} else {
return Err(JsNativeError::typ() return Err(JsNativeError::typ()
.with_message("finally called with a non-object promise") .with_message("finally called with a non-object promise")
.into()); .into());

30
boa_engine/src/builtins/reflect/mod.rs

@ -113,13 +113,9 @@ impl Reflect {
let new_target = if let Some(new_target) = args.get(2) { let new_target = if let Some(new_target) = args.get(2) {
// 3. Else if IsConstructor(newTarget) is false, throw a TypeError exception. // 3. Else if IsConstructor(newTarget) is false, throw a TypeError exception.
if let Some(new_target) = new_target.as_constructor() { new_target.as_constructor().ok_or_else(|| {
new_target JsNativeError::typ().with_message("newTarget must be a constructor")
} else { })?
return Err(JsNativeError::typ()
.with_message("newTarget must be a constructor")
.into());
}
} else { } else {
// 2. If newTarget is not present, set newTarget to target. // 2. If newTarget is not present, set newTarget to target.
target target
@ -206,12 +202,11 @@ impl Reflect {
// 2. Let key be ? ToPropertyKey(propertyKey). // 2. Let key be ? ToPropertyKey(propertyKey).
let key = args.get_or_undefined(1).to_property_key(context)?; let key = args.get_or_undefined(1).to_property_key(context)?;
// 3. If receiver is not present, then // 3. If receiver is not present, then
let receiver = if let Some(receiver) = args.get(2).cloned() { // 3.a. Set receiver to target.
receiver let receiver = args
} else { .get(2)
// 3.a. Set receiver to target. .cloned()
target.clone().into() .unwrap_or_else(|| target.clone().into());
};
// 4. Return ? target.[[Get]](key, receiver). // 4. Return ? target.[[Get]](key, receiver).
target.__get__(&key, receiver, context) target.__get__(&key, receiver, context)
} }
@ -369,11 +364,10 @@ impl Reflect {
.ok_or_else(|| JsNativeError::typ().with_message("target must be an object"))?; .ok_or_else(|| JsNativeError::typ().with_message("target must be an object"))?;
let key = args.get_or_undefined(1).to_property_key(context)?; let key = args.get_or_undefined(1).to_property_key(context)?;
let value = args.get_or_undefined(2); let value = args.get_or_undefined(2);
let receiver = if let Some(receiver) = args.get(3).cloned() { let receiver = args
receiver .get(3)
} else { .cloned()
target.clone().into() .unwrap_or_else(|| target.clone().into());
};
Ok(target Ok(target
.__set__(key, value.clone(), receiver, context)? .__set__(key, value.clone(), receiver, context)?
.into()) .into())

41
boa_engine/src/builtins/regexp/mod.rs

@ -1045,13 +1045,10 @@ impl RegExp {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let rx be the this value. // 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception. // 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() { let rx = this.as_object().ok_or_else(|| {
rx JsNativeError::typ()
} else {
return Err(JsNativeError::typ()
.with_message("RegExp.prototype.match method called on incompatible value") .with_message("RegExp.prototype.match method called on incompatible value")
.into()); })?;
};
// 3. Let S be ? ToString(string). // 3. Let S be ? ToString(string).
let arg_str = args.get_or_undefined(0).to_string(context)?; let arg_str = args.get_or_undefined(0).to_string(context)?;
@ -1235,15 +1232,11 @@ impl RegExp {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let rx be the this value. // 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception. // 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() { let rx = this.as_object().ok_or_else(|| {
rx JsNativeError::typ().with_message(
} else { "RegExp.prototype[Symbol.replace] method called on incompatible value",
return Err(JsNativeError::typ() )
.with_message( })?;
"RegExp.prototype[Symbol.replace] method called on incompatible value",
)
.into());
};
// 3. Let S be ? ToString(string). // 3. Let S be ? ToString(string).
let arg_str = args.get_or_undefined(0).to_string(context)?; let arg_str = args.get_or_undefined(0).to_string(context)?;
@ -1457,13 +1450,10 @@ impl RegExp {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let rx be the this value. // 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception. // 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() { let rx = this.as_object().ok_or_else(|| {
rx JsNativeError::typ()
} else {
return Err(JsNativeError::typ()
.with_message("RegExp.prototype[Symbol.search] method called on incompatible value") .with_message("RegExp.prototype[Symbol.search] method called on incompatible value")
.into()); })?;
};
// 3. Let S be ? ToString(string). // 3. Let S be ? ToString(string).
let arg_str = args.get_or_undefined(0).to_string(context)?; let arg_str = args.get_or_undefined(0).to_string(context)?;
@ -1515,13 +1505,10 @@ impl RegExp {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// 1. Let rx be the this value. // 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception. // 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() { let rx = this.as_object().ok_or_else(|| {
rx JsNativeError::typ()
} else {
return Err(JsNativeError::typ()
.with_message("RegExp.prototype.split method called on incompatible value") .with_message("RegExp.prototype.split method called on incompatible value")
.into()); })?;
};
// 3. Let S be ? ToString(string). // 3. Let S be ? ToString(string).
let arg_str = args.get_or_undefined(0).to_string(context)?; let arg_str = args.get_or_undefined(0).to_string(context)?;

23
boa_engine/src/builtins/set/mod.rs

@ -281,21 +281,16 @@ impl Set {
pub(crate) fn delete(this: &JsValue, args: &[JsValue], _: &mut Context) -> JsResult<JsValue> { pub(crate) fn delete(this: &JsValue, args: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
let value = args.get_or_undefined(0); let value = args.get_or_undefined(0);
let res = if let Some(object) = this.as_object() { let mut object = this
if let Some(set) = object.borrow_mut().as_set_mut() { .as_object()
set.delete(value) .map(JsObject::borrow_mut)
} else { .ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Set"))?;
return Err(JsNativeError::typ()
.with_message("'this' is not a Set") let set = object
.into()); .as_set_mut()
} .ok_or_else(|| JsNativeError::typ().with_message("'this' is not a Set"))?;
} else {
return Err(JsNativeError::typ()
.with_message("'this' is not a Set")
.into());
};
Ok(res.into()) Ok(set.delete(value).into())
} }
/// `Set.prototype.entries( )` /// `Set.prototype.entries( )`

4
boa_engine/src/builtins/string/mod.rs

@ -952,9 +952,7 @@ impl String {
// 8. Let position be ! StringIndexOf(string, searchString, 0). // 8. Let position be ! StringIndexOf(string, searchString, 0).
// 9. If position is -1, return string. // 9. If position is -1, return string.
let position = if let Some(p) = this_str.index_of(&search_str, 0) { let Some(position) = this_str.index_of(&search_str, 0) else {
p
} else {
return Ok(this_str.into()); return Ok(this_str.into());
}; };

4
boa_engine/src/builtins/uri/mod.rs

@ -253,9 +253,7 @@ where
let cp = string.code_point_at(k); let cp = string.code_point_at(k);
// ii. If cp.[[IsUnpairedSurrogate]] is true, throw a URIError exception. // ii. If cp.[[IsUnpairedSurrogate]] is true, throw a URIError exception.
let ch = if let CodePoint::Unicode(ch) = cp { let CodePoint::Unicode(ch) = cp else {
ch
} else {
return Err(JsNativeError::uri() return Err(JsNativeError::uri()
.with_message("trying to encode an invalid string") .with_message("trying to encode an invalid string")
.into()); .into());

29
boa_engine/src/class.rs

@ -113,10 +113,8 @@ impl<T: Class> ClassConstructor for T {
.into()); .into());
} }
let class_constructor = context.global_object().clone().get(T::NAME, context)?; let class = context.global_object().clone().get(T::NAME, context)?;
let class_constructor = if let JsValue::Object(ref obj) = class_constructor { let JsValue::Object(ref class_constructor) = class else {
obj
} else {
return Err(JsNativeError::typ() return Err(JsNativeError::typ()
.with_message(format!( .with_message(format!(
"invalid constructor for native class `{}` ", "invalid constructor for native class `{}` ",
@ -124,28 +122,25 @@ impl<T: Class> ClassConstructor for T {
)) ))
.into()); .into());
}; };
let class_prototype =
if let JsValue::Object(ref obj) = class_constructor.get(PROTOTYPE, context)? { let JsValue::Object(ref class_prototype) = class_constructor.get(PROTOTYPE, context)? else {
obj.clone() return Err(JsNativeError::typ()
} else { .with_message(format!(
return Err(JsNativeError::typ() "invalid default prototype for native class `{}`",
.with_message(format!( T::NAME
"invalid default prototype for native class `{}`", ))
T::NAME .into());
)) };
.into());
};
let prototype = this let prototype = this
.as_object() .as_object()
.cloned()
.map(|obj| { .map(|obj| {
obj.get(PROTOTYPE, context) obj.get(PROTOTYPE, context)
.map(|val| val.as_object().cloned()) .map(|val| val.as_object().cloned())
}) })
.transpose()? .transpose()?
.flatten() .flatten()
.unwrap_or(class_prototype); .unwrap_or_else(|| class_prototype.clone());
let native_instance = Self::constructor(this, args, context)?; let native_instance = Self::constructor(this, args, context)?;
let object_instance = JsObject::from_proto_and_data( let object_instance = JsObject::from_proto_and_data(

1
boa_engine/src/lib.rs

@ -72,7 +72,6 @@
// Ignore because `write!(string, ...)` instead of `string.push_str(&format!(...))` can fail. // Ignore because `write!(string, ...)` instead of `string.push_str(&format!(...))` can fail.
// We only use it in `ToInternedString` where performance is not an issue. // We only use it in `ToInternedString` where performance is not an issue.
clippy::format_push_string, clippy::format_push_string,
rustdoc::missing_doc_code_examples
)] )]
extern crate static_assertions as sa; extern crate static_assertions as sa;

4
boa_engine/src/object/internal_methods/arguments.rs

@ -30,9 +30,7 @@ pub(crate) fn arguments_exotic_get_own_property(
) -> JsResult<Option<PropertyDescriptor>> { ) -> JsResult<Option<PropertyDescriptor>> {
// 1. Let desc be OrdinaryGetOwnProperty(args, P). // 1. Let desc be OrdinaryGetOwnProperty(args, P).
// 2. If desc is undefined, return desc. // 2. If desc is undefined, return desc.
let desc = if let Some(desc) = super::ordinary_get_own_property(obj, key, context)? { let Some(desc) = super::ordinary_get_own_property(obj, key, context)? else {
desc
} else {
return Ok(None); return Ok(None);
}; };

7
boa_engine/src/object/internal_methods/global.rs

@ -501,11 +501,8 @@ pub(crate) fn validate_and_apply_property_descriptor(
); );
// 1. Assert: If O is not undefined, then IsPropertyKey(P) is true. // 1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
let mut current = if let Some(own) = current { let Some(mut current) = current else {
own // 2. If current is undefined, then
}
// 2. If current is undefined, then
else {
// a. If extensible is false, return false. // a. If extensible is false, return false.
if !extensible { if !extensible {
return false; return false;

7
boa_engine/src/object/internal_methods/mod.rs

@ -794,11 +794,8 @@ pub(crate) fn validate_and_apply_property_descriptor(
Profiler::global().start_event("Object::validate_and_apply_property_descriptor", "object"); Profiler::global().start_event("Object::validate_and_apply_property_descriptor", "object");
// 1. Assert: If O is not undefined, then IsPropertyKey(P) is true. // 1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
let mut current = if let Some(own) = current { let Some(mut current) = current else {
own // 2. If current is undefined, then
}
// 2. If current is undefined, then
else {
// a. If extensible is false, return false. // a. If extensible is false, return false.
if !extensible { if !extensible {
return false; return false;

78
boa_engine/src/object/internal_methods/proxy.rs

@ -65,10 +65,8 @@ pub(crate) fn proxy_exotic_get_prototype_of(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
let trap = if let Some(trap) = handler.get_method("getPrototypeOf", context)? { let Some(trap) = handler.get_method("getPrototypeOf", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[GetPrototypeOf]](). // a. Return ? target.[[GetPrototypeOf]]().
return target.__get_prototype_of__(context); return target.__get_prototype_of__(context);
}; };
@ -130,10 +128,8 @@ pub(crate) fn proxy_exotic_set_prototype_of(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "setPrototypeOf"). // 5. Let trap be ? GetMethod(handler, "setPrototypeOf").
let trap = if let Some(trap) = handler.get_method("setPrototypeOf", context)? { let Some(trap) = handler.get_method("setPrototypeOf", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[SetPrototypeOf]](V). // a. Return ? target.[[SetPrototypeOf]](V).
return target.__set_prototype_of__(val, context); return target.__set_prototype_of__(val, context);
}; };
@ -193,10 +189,8 @@ pub(crate) fn proxy_exotic_is_extensible(obj: &JsObject, context: &mut Context)
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "isExtensible"). // 5. Let trap be ? GetMethod(handler, "isExtensible").
let trap = if let Some(trap) = handler.get_method("isExtensible", context)? { let Some(trap) = handler.get_method("isExtensible", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? IsExtensible(target). // a. Return ? IsExtensible(target).
return target.is_extensible(context); return target.is_extensible(context);
}; };
@ -242,10 +236,8 @@ pub(crate) fn proxy_exotic_prevent_extensions(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "preventExtensions"). // 5. Let trap be ? GetMethod(handler, "preventExtensions").
let trap = if let Some(trap) = handler.get_method("preventExtensions", context)? { let Some(trap) = handler.get_method("preventExtensions", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[PreventExtensions]](). // a. Return ? target.[[PreventExtensions]]().
return target.__prevent_extensions__(context); return target.__prevent_extensions__(context);
}; };
@ -291,10 +283,8 @@ pub(crate) fn proxy_exotic_get_own_property(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). // 5. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
let trap = if let Some(trap) = handler.get_method("getOwnPropertyDescriptor", context)? { let Some(trap) = handler.get_method("getOwnPropertyDescriptor", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[GetOwnProperty]](P). // a. Return ? target.[[GetOwnProperty]](P).
return target.__get_own_property__(key, context); return target.__get_own_property__(key, context);
}; };
@ -418,10 +408,8 @@ pub(crate) fn proxy_exotic_define_own_property(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "defineProperty"). // 5. Let trap be ? GetMethod(handler, "defineProperty").
let trap = if let Some(trap) = handler.get_method("defineProperty", context)? { let Some(trap) = handler.get_method("defineProperty", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[DefineOwnProperty]](P, Desc). // a. Return ? target.[[DefineOwnProperty]](P, Desc).
return target.__define_own_property__(key, desc, context); return target.__define_own_property__(key, desc, context);
}; };
@ -532,10 +520,8 @@ pub(crate) fn proxy_exotic_has_property(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "has"). // 5. Let trap be ? GetMethod(handler, "has").
let trap = if let Some(trap) = handler.get_method("has", context)? { let Some(trap) = handler.get_method("has", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[HasProperty]](P). // a. Return ? target.[[HasProperty]](P).
return target.has_property(key.clone(), context); return target.has_property(key.clone(), context);
}; };
@ -601,10 +587,8 @@ pub(crate) fn proxy_exotic_get(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "get"). // 5. Let trap be ? GetMethod(handler, "get").
let trap = if let Some(trap) = handler.get_method("get", context)? { let Some(trap) = handler.get_method("get", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[Get]](P, Receiver). // a. Return ? target.[[Get]](P, Receiver).
return target.__get__(key, receiver, context); return target.__get__(key, receiver, context);
}; };
@ -673,10 +657,8 @@ pub(crate) fn proxy_exotic_set(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "set"). // 5. Let trap be ? GetMethod(handler, "set").
let trap = if let Some(trap) = handler.get_method("set", context)? { let Some(trap) = handler.get_method("set", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[Set]](P, V, Receiver). // a. Return ? target.[[Set]](P, V, Receiver).
return target.__set__(key, value, receiver, context); return target.__set__(key, value, receiver, context);
}; };
@ -757,10 +739,8 @@ pub(crate) fn proxy_exotic_delete(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "deleteProperty"). // 5. Let trap be ? GetMethod(handler, "deleteProperty").
let trap = if let Some(trap) = handler.get_method("deleteProperty", context)? { let Some(trap) = handler.get_method("deleteProperty", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[Delete]](P). // a. Return ? target.[[Delete]](P).
return target.__delete__(key, context); return target.__delete__(key, context);
}; };
@ -826,10 +806,8 @@ pub(crate) fn proxy_exotic_own_property_keys(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "ownKeys"). // 5. Let trap be ? GetMethod(handler, "ownKeys").
let trap = if let Some(trap) = handler.get_method("ownKeys", context)? { let Some(trap) = handler.get_method("ownKeys", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? target.[[OwnPropertyKeys]](). // a. Return ? target.[[OwnPropertyKeys]]().
return target.__own_property_keys__(context); return target.__own_property_keys__(context);
}; };
@ -964,10 +942,8 @@ fn proxy_exotic_call(
.try_data()?; .try_data()?;
// 5. Let trap be ? GetMethod(handler, "apply"). // 5. Let trap be ? GetMethod(handler, "apply").
let trap = if let Some(trap) = handler.get_method("apply", context)? { let Some(trap) = handler.get_method("apply", context)? else {
trap // 6. If trap is undefined, then
// 6. If trap is undefined, then
} else {
// a. Return ? Call(target, thisArgument, argumentsList). // a. Return ? Call(target, thisArgument, argumentsList).
return target.call(this, args, context); return target.call(this, args, context);
}; };
@ -1009,10 +985,8 @@ fn proxy_exotic_construct(
assert!(target.is_constructor()); assert!(target.is_constructor());
// 6. Let trap be ? GetMethod(handler, "construct"). // 6. Let trap be ? GetMethod(handler, "construct").
let trap = if let Some(trap) = handler.get_method("construct", context)? { let Some(trap) = handler.get_method("construct", context)? else {
trap // 7. If trap is undefined, then
// 7. If trap is undefined, then
} else {
// a. Return ? Construct(target, argumentsList, newTarget). // a. Return ? Construct(target, argumentsList, newTarget).
return target.construct(args, Some(new_target), context); return target.construct(args, Some(new_target), context);
}; };

29
boa_engine/src/object/operations.rs

@ -502,13 +502,9 @@ impl JsObject {
} }
// 4. If Type(C) is not Object, throw a TypeError exception. // 4. If Type(C) is not Object, throw a TypeError exception.
let c = if let Some(c) = c.as_object() { let c = c.as_object().ok_or_else(|| {
c JsNativeError::typ().with_message("property 'constructor' is not an object")
} else { })?;
return Err(JsNativeError::typ()
.with_message("property 'constructor' is not an object")
.into());
};
// 5. Let S be ? Get(C, @@species). // 5. Let S be ? Get(C, @@species).
let s = c.get(WellKnownSymbols::species(), context)?; let s = c.get(WellKnownSymbols::species(), context)?;
@ -801,9 +797,7 @@ impl JsValue {
context: &mut Context, context: &mut Context,
) -> JsResult<bool> { ) -> JsResult<bool> {
// 1. If IsCallable(C) is false, return false. // 1. If IsCallable(C) is false, return false.
let function = if let Some(function) = function.as_callable() { let Some(function) = function.as_callable() else {
function
} else {
return Ok(false); return Ok(false);
}; };
@ -818,9 +812,7 @@ impl JsValue {
); );
} }
let mut object = if let Some(obj) = object.as_object() { let Some(mut object) = object.as_object().cloned() else {
obj.clone()
} else {
// 3. If Type(O) is not Object, return false. // 3. If Type(O) is not Object, return false.
return Ok(false); return Ok(false);
}; };
@ -828,14 +820,11 @@ impl JsValue {
// 4. Let P be ? Get(C, "prototype"). // 4. Let P be ? Get(C, "prototype").
let prototype = function.get("prototype", context)?; let prototype = function.get("prototype", context)?;
let prototype = if let Some(obj) = prototype.as_object() { // 5. If Type(P) is not Object, throw a TypeError exception.
obj let prototype = prototype.as_object().ok_or_else(|| {
} else { JsNativeError::typ()
// 5. If Type(P) is not Object, throw a TypeError exception.
return Err(JsNativeError::typ()
.with_message("function has non-object prototype in instanceof check") .with_message("function has non-object prototype in instanceof check")
.into()); })?;
};
// 6. Repeat, // 6. Repeat,
loop { loop {

4
boa_engine/src/string/mod.rs

@ -452,9 +452,7 @@ impl JsString {
pub(crate) fn to_number(&self) -> f64 { pub(crate) fn to_number(&self) -> f64 {
// 1. Let text be ! StringToCodePoints(str). // 1. Let text be ! StringToCodePoints(str).
// 2. Let literal be ParseText(text, StringNumericLiteral). // 2. Let literal be ParseText(text, StringNumericLiteral).
let string = if let Ok(string) = self.to_std_string() { let Ok(string) = self.to_std_string() else {
string
} else {
// 3. If literal is a List of errors, return NaN. // 3. If literal is a List of errors, return NaN.
return f64::NAN; return f64::NAN;
}; };

6
boa_engine/src/syntax/parser/expression/primary/object_initializer/mod.rs

@ -216,11 +216,7 @@ where
let (class_element_name, method) = let (class_element_name, method) =
AsyncMethod::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; AsyncMethod::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let property_name = if let property::ClassElementName::PropertyName(property_name) = let property::ClassElementName::PropertyName(property_name) = class_element_name else {
class_element_name
{
property_name
} else {
return Err(ParseError::general( return Err(ParseError::general(
"private identifiers not allowed in object literal", "private identifiers not allowed in object literal",
position, position,

28
boa_engine/src/syntax/parser/statement/declaration/hoistable/mod.rs

@ -143,24 +143,20 @@ fn parse_callable_declaration<R: Read, C: CallableDeclaration>(
cursor: &mut Cursor<R>, cursor: &mut Cursor<R>,
interner: &mut Interner, interner: &mut Interner,
) -> Result<(Identifier, FormalParameterList, StatementList), ParseError> { ) -> Result<(Identifier, FormalParameterList, StatementList), ParseError> {
let next_token = cursor.peek(0, interner)?; let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let name = if let Some(token) = next_token { let name = match next_token.kind() {
match token.kind() { TokenKind::Punctuator(Punctuator::OpenParen) => {
TokenKind::Punctuator(Punctuator::OpenParen) => { if !c.is_default() {
if !c.is_default() { return Err(ParseError::unexpected(
return Err(ParseError::unexpected( next_token.to_string(interner),
token.to_string(interner), next_token.span(),
token.span(), c.error_context(),
c.error_context(), ));
));
}
Sym::DEFAULT.into()
} }
_ => BindingIdentifier::new(c.name_allow_yield(), c.name_allow_await()) Sym::DEFAULT.into()
.parse(cursor, interner)?,
} }
} else { _ => BindingIdentifier::new(c.name_allow_yield(), c.name_allow_await())
return Err(ParseError::AbruptEnd); .parse(cursor, interner)?,
}; };
// Early Error: If BindingIdentifier is present and the source code matching BindingIdentifier is strict mode code, // Early Error: If BindingIdentifier is present and the source code matching BindingIdentifier is strict mode code,

68
boa_engine/src/syntax/parser/statement/declaration/lexical.rs

@ -261,20 +261,15 @@ where
let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if let Some(t) = cursor.peek(0, interner)? { let init = if cursor
if *t.kind() == TokenKind::Punctuator(Punctuator::Assign) { .peek(0, interner)?
Some( .filter(|t| *t.kind() == TokenKind::Punctuator(Punctuator::Assign))
Initializer::new( .is_some()
None, {
self.allow_in, Some(
self.allow_yield, Initializer::new(None, self.allow_in, self.allow_yield, self.allow_await)
self.allow_await,
)
.parse(cursor, interner)?, .parse(cursor, interner)?,
) )
} else {
None
}
} else { } else {
None None
}; };
@ -294,20 +289,15 @@ where
let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if let Some(t) = cursor.peek(0, interner)? { let init = if cursor
if *t.kind() == TokenKind::Punctuator(Punctuator::Assign) { .peek(0, interner)?
Some( .filter(|t| *t.kind() == TokenKind::Punctuator(Punctuator::Assign))
Initializer::new( .is_some()
None, {
self.allow_in, Some(
self.allow_yield, Initializer::new(None, self.allow_in, self.allow_yield, self.allow_await)
self.allow_await,
)
.parse(cursor, interner)?, .parse(cursor, interner)?,
) )
} else {
None
}
} else { } else {
None None
}; };
@ -334,20 +324,20 @@ where
))); )));
} }
let init = if let Some(t) = cursor.peek(0, interner)? { let init = if cursor
if *t.kind() == TokenKind::Punctuator(Punctuator::Assign) { .peek(0, interner)?
Some( .filter(|t| *t.kind() == TokenKind::Punctuator(Punctuator::Assign))
Initializer::new( .is_some()
Some(ident), {
self.allow_in, Some(
self.allow_yield, Initializer::new(
self.allow_await, Some(ident),
) self.allow_in,
.parse(cursor, interner)?, self.allow_yield,
self.allow_await,
) )
} else { .parse(cursor, interner)?,
None )
}
} else { } else {
None None
}; };

60
boa_engine/src/syntax/parser/statement/variable/mod.rs

@ -170,20 +170,15 @@ where
let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if let Some(t) = cursor.peek(0, interner)? { let init = if cursor
if *t.kind() == TokenKind::Punctuator(Punctuator::Assign) { .peek(0, interner)?
Some( .filter(|t| *t.kind() == TokenKind::Punctuator(Punctuator::Assign))
Initializer::new( .is_some()
None, {
self.allow_in, Some(
self.allow_yield, Initializer::new(None, self.allow_in, self.allow_yield, self.allow_await)
self.allow_await,
)
.parse(cursor, interner)?, .parse(cursor, interner)?,
) )
} else {
None
}
} else { } else {
None None
}; };
@ -194,20 +189,15 @@ where
let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if let Some(t) = cursor.peek(0, interner)? { let init = if cursor
if *t.kind() == TokenKind::Punctuator(Punctuator::Assign) { .peek(0, interner)?
Some( .filter(|t| *t.kind() == TokenKind::Punctuator(Punctuator::Assign))
Initializer::new( .is_some()
None, {
self.allow_in, Some(
self.allow_yield, Initializer::new(None, self.allow_in, self.allow_yield, self.allow_await)
self.allow_await,
)
.parse(cursor, interner)?, .parse(cursor, interner)?,
) )
} else {
None
}
} else { } else {
None None
}; };
@ -218,15 +208,15 @@ where
let ident = BindingIdentifier::new(self.allow_yield, self.allow_await) let ident = BindingIdentifier::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if let Some(t) = cursor.peek(0, interner)? { let init = if cursor
if *t.kind() == TokenKind::Punctuator(Punctuator::Assign) { .peek(0, interner)?
Some( .filter(|t| *t.kind() == TokenKind::Punctuator(Punctuator::Assign))
Initializer::new(Some(ident), true, self.allow_yield, self.allow_await) .is_some()
.parse(cursor, interner)?, {
) Some(
} else { Initializer::new(Some(ident), true, self.allow_yield, self.allow_await)
None .parse(cursor, interner)?,
} )
} else { } else {
None None
}; };

22
boa_engine/src/vm/opcode/iteration/for_await.rs

@ -23,13 +23,9 @@ impl Operation for ForAwaitOfLoopIterate {
.as_boolean() .as_boolean()
.expect("iterator [[Done]] was not a boolean"); .expect("iterator [[Done]] was not a boolean");
let next_method = context.vm.pop(); let next_method = context.vm.pop();
let next_method_object = if let Some(object) = next_method.as_callable() { let next_method_object = next_method.as_callable().ok_or_else(|| {
object JsNativeError::typ().with_message("iterable next method not a function")
} else { })?;
return Err(JsNativeError::typ()
.with_message("iterable next method not a function")
.into());
};
let iterator = context.vm.pop(); let iterator = context.vm.pop();
let next_result = next_method_object.call(&iterator, &[], context)?; let next_result = next_method_object.call(&iterator, &[], context)?;
context.vm.push(iterator); context.vm.push(iterator);
@ -54,13 +50,11 @@ impl Operation for ForAwaitOfLoopNext {
let address = context.vm.read::<u32>(); let address = context.vm.read::<u32>();
let next_result = context.vm.pop(); let next_result = context.vm.pop();
let next_result = if let Some(next_result) = next_result.as_object() { let next_result = next_result
IteratorResult::new(next_result.clone()) .as_object()
} else { .cloned()
return Err(JsNativeError::typ() .map(IteratorResult::new)
.with_message("next value should be an object") .ok_or_else(|| JsNativeError::typ().with_message("next value should be an object"))?;
.into());
};
if next_result.complete(context)? { if next_result.complete(context)? {
context.vm.frame_mut().pc = address as usize; context.vm.frame_mut().pc = address as usize;

1
boa_interner/src/lib.rs

@ -69,7 +69,6 @@
clippy::let_unit_value, clippy::let_unit_value,
// TODO deny once false positive is fixed (https://github.com/rust-lang/rust-clippy/issues/9626). // TODO deny once false positive is fixed (https://github.com/rust-lang/rust-clippy/issues/9626).
clippy::trait_duplication_in_bounds, clippy::trait_duplication_in_bounds,
rustdoc::missing_doc_code_examples,
)] )]
extern crate static_assertions as sa; extern crate static_assertions as sa;

1
boa_tester/src/main.rs

@ -60,7 +60,6 @@
clippy::missing_errors_doc, clippy::missing_errors_doc,
clippy::as_conversions, clippy::as_conversions,
clippy::let_unit_value, clippy::let_unit_value,
rustdoc::missing_doc_code_examples
)] )]
mod exec; mod exec;

3
boa_unicode/src/lib.rs

@ -63,8 +63,7 @@
clippy::must_use_candidate, clippy::must_use_candidate,
clippy::missing_errors_doc, clippy::missing_errors_doc,
clippy::as_conversions, clippy::as_conversions,
clippy::let_unit_value, clippy::let_unit_value
rustdoc::missing_doc_code_examples
)] )]
mod tables; mod tables;

3
boa_wasm/src/lib.rs

@ -55,8 +55,7 @@
clippy::must_use_candidate, clippy::must_use_candidate,
clippy::missing_errors_doc, clippy::missing_errors_doc,
clippy::as_conversions, clippy::as_conversions,
clippy::let_unit_value, clippy::let_unit_value
rustdoc::missing_doc_code_examples
)] )]
use boa_engine::Context; use boa_engine::Context;

Loading…
Cancel
Save