From 3269c1b9016ff4503c8f935e81b580c3f8d20708 Mon Sep 17 00:00:00 2001 From: Halid Odat Date: Mon, 6 Dec 2021 21:18:10 +0000 Subject: [PATCH] Generic `JsResult` in `context.throw_` methods (#1734) Previously when we had the `context.throw_` methods (like `context.thtrow_type_error()`) they were limited as to where we could call them, e.i. a function that returned `JsResult`. So we had to call the `context.construct_` methods with an explicit `Err()` enum wrap to throw in functions that returned non-jsvalues (which happens a lot). Now, with this PR the throw methods have a generic `JsResult` return that can return in any `JsResult` returning function. Which cleans the API and makes the user experience a bit better. ```rust return Err(context.construct_type_error("...")); // to return context.throw_type_error("..."); ``` --- boa/src/bigint.rs | 8 +- boa/src/builtins/array/mod.rs | 10 +- boa/src/builtins/array_buffer/mod.rs | 2 +- boa/src/builtins/intl/mod.rs | 4 +- boa/src/builtins/iterable/mod.rs | 2 +- boa/src/builtins/json/mod.rs | 6 +- boa/src/builtins/number/mod.rs | 9 +- boa/src/builtins/regexp/mod.rs | 33 ++--- boa/src/builtins/typed_array/mod.rs | 113 +++++++++--------- boa/src/context.rs | 12 +- .../declarative_environment_record.rs | 10 +- .../environment/global_environment_record.rs | 8 +- .../environment/object_environment_record.rs | 2 +- boa/src/lib.rs | 11 +- boa/src/object/internal_methods/array.rs | 2 +- boa/src/object/internal_methods/proxy.rs | 101 +++++++--------- boa/src/object/jsobject.rs | 14 +-- boa/src/object/operations.rs | 25 ++-- boa/src/syntax/ast/node/declaration/mod.rs | 8 +- boa/src/value/mod.rs | 42 +++---- boa/src/value/operations.rs | 6 +- boa/src/vm/mod.rs | 20 ++-- boa_tester/src/exec/js262.rs | 2 +- boa_wasm/src/lib.rs | 5 +- 24 files changed, 197 insertions(+), 258 deletions(-) diff --git a/boa/src/bigint.rs b/boa/src/bigint.rs index 2e2bca1d58..504f74f40f 100644 --- a/boa/src/bigint.rs +++ b/boa/src/bigint.rs @@ -166,7 +166,7 @@ impl JsBigInt { let y = if let Some(y) = y.inner.to_biguint() { y } else { - return Err(context.construct_range_error("BigInt negative exponent")); + return context.throw_range_error("BigInt negative exponent"); }; let num_bits = (x.inner.bits() as f64 @@ -175,7 +175,7 @@ impl JsBigInt { + 1f64; if num_bits > 1_000_000_000f64 { - return Err(context.construct_range_error("Maximum BigInt size exceeded")); + return context.throw_range_error("Maximum BigInt size exceeded"); } Ok(Self::new(x.inner.as_ref().clone().pow(y))) @@ -192,7 +192,7 @@ impl JsBigInt { Ok(Self::new(inner)) } else { - Err(context.construct_range_error("Maximum BigInt size exceeded")) + context.throw_range_error("Maximum BigInt size exceeded") } } @@ -207,7 +207,7 @@ impl JsBigInt { Ok(Self::new(inner)) } else { - Err(context.construct_range_error("Maximum BigInt size exceeded")) + context.throw_range_error("Maximum BigInt size exceeded") } } diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index 7fc83a26e4..605392bcc3 100644 --- a/boa/src/builtins/array/mod.rs +++ b/boa/src/builtins/array/mod.rs @@ -165,7 +165,7 @@ impl Array { let int_len = len.to_u32(context).unwrap(); // ii. If SameValueZero(intLen, len) is false, throw a RangeError exception. if !JsValue::same_value_zero(&int_len.into(), len) { - return Err(context.construct_range_error("invalid array length")); + return context.throw_range_error("invalid array length"); } int_len }; @@ -210,7 +210,7 @@ impl Array { ) -> JsResult { // 1. If length > 2^32 - 1, throw a RangeError exception. if length > 2usize.pow(32) - 1 { - return Err(context.construct_range_error("array exceeded max size")); + return context.throw_range_error("array exceeded max size"); } // 7. Return A. // 2. If proto is not present, set proto to %Array.prototype%. @@ -365,7 +365,7 @@ impl Array { .unwrap(), ) } else { - Err(context.construct_type_error("Symbol.species must be a constructor")) + context.throw_type_error("Symbol.species must be a constructor") } } @@ -1669,8 +1669,8 @@ impl Array { } else { // 1. If targetIndex >= 2^53 - 1, throw a TypeError exception if target_index >= Number::MAX_SAFE_INTEGER as u64 { - return Err(context - .construct_type_error("Target index exceeded max safe integer value")); + return context + .throw_type_error("Target index exceeded max safe integer value"); } // 2. Perform ? CreateDataPropertyOrThrow(target, targetIndex, element) diff --git a/boa/src/builtins/array_buffer/mod.rs b/boa/src/builtins/array_buffer/mod.rs index 36597a5c7f..e61d433aee 100644 --- a/boa/src/builtins/array_buffer/mod.rs +++ b/boa/src/builtins/array_buffer/mod.rs @@ -363,7 +363,7 @@ impl ArrayBuffer { let src_block = if let Some(b) = &self.array_buffer_data { b } else { - return Err(context.construct_syntax_error("Cannot clone detached array buffer")); + return context.throw_syntax_error("Cannot clone detached array buffer"); }; { diff --git a/boa/src/builtins/intl/mod.rs b/boa/src/builtins/intl/mod.rs index 47ff367ef6..158bdd38fe 100644 --- a/boa/src/builtins/intl/mod.rs +++ b/boa/src/builtins/intl/mod.rs @@ -93,9 +93,7 @@ impl Intl { let k_value = o.get(k, context)?; // ii. If Type(kValue) is not String or Object, throw a TypeError exception. if !(k_value.is_object() || k_value.is_string()) { - return Err(context - .throw_type_error("locale should be a String or Object") - .unwrap_err()); + return context.throw_type_error("locale should be a String or Object"); } // iii. If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then // TODO: handle checks for InitializedLocale internal slot (there should be an if statement here) diff --git a/boa/src/builtins/iterable/mod.rs b/boa/src/builtins/iterable/mod.rs index 0624665e74..84f54329e9 100644 --- a/boa/src/builtins/iterable/mod.rs +++ b/boa/src/builtins/iterable/mod.rs @@ -149,7 +149,7 @@ impl JsValue { // 4. If Type(iterator) is not Object, throw a TypeError exception. if !iterator.is_object() { - return Err(context.construct_type_error("the iterator is not an object")); + return context.throw_type_error("the iterator is not an object"); } // 5. Let nextMethod be ? GetV(iterator, "next"). diff --git a/boa/src/builtins/json/mod.rs b/boa/src/builtins/json/mod.rs index 7e6124880b..0f3cbc42df 100644 --- a/boa/src/builtins/json/mod.rs +++ b/boa/src/builtins/json/mod.rs @@ -448,7 +448,7 @@ impl Json { // 10. If Type(value) is BigInt, throw a TypeError exception. if value.is_bigint() { - return Err(context.construct_type_error("cannot serialize bigint to JSON")); + return context.throw_type_error("cannot serialize bigint to JSON"); } // 11. If Type(value) is Object and IsCallable(value) is false, then @@ -531,7 +531,7 @@ impl Json { // 1. If state.[[Stack]] contains value, throw a TypeError exception because the structure is cyclical. let limiter = RecursionLimiter::new(value); if limiter.live { - return Err(context.construct_type_error("cyclic object value")); + return context.throw_type_error("cyclic object value"); } // 2. Append value to state.[[Stack]]. @@ -644,7 +644,7 @@ impl Json { // 1. If state.[[Stack]] contains value, throw a TypeError exception because the structure is cyclical. let limiter = RecursionLimiter::new(value); if limiter.live { - return Err(context.construct_type_error("cyclic object value")); + return context.throw_type_error("cyclic object value"); } // 2. Append value to state.[[Stack]]. diff --git a/boa/src/builtins/number/mod.rs b/boa/src/builtins/number/mod.rs index 5a63c6567b..3917e2e622 100644 --- a/boa/src/builtins/number/mod.rs +++ b/boa/src/builtins/number/mod.rs @@ -222,8 +222,8 @@ impl Number { let this_str_num = if let Some(precision) = precision { // 5. If f < 0 or f > 100, throw a RangeError exception. if !(0..=100).contains(&precision) { - return Err(context - .construct_range_error("toExponential() argument must be between 0 and 100")); + return context + .throw_range_error("toExponential() argument must be between 0 and 100"); } f64_to_exponential_with_precision(this_num, precision as usize) } else { @@ -256,9 +256,8 @@ impl Number { 0..=100 => n.to_integer(context)? as usize, // 4, 5. If f < 0 or f > 100, throw a RangeError exception. _ => { - return Err(context.construct_range_error( - "toFixed() digits argument must be between 0 and 100", - )) + return context + .throw_range_error("toFixed() digits argument must be between 0 and 100") } }, // 3. If fractionDigits is undefined, then f is 0. diff --git a/boa/src/builtins/regexp/mod.rs b/boa/src/builtins/regexp/mod.rs index f3d19a572f..15bdf69c84 100644 --- a/boa/src/builtins/regexp/mod.rs +++ b/boa/src/builtins/regexp/mod.rs @@ -332,8 +332,8 @@ impl RegExp { // 14. Set obj.[[RegExpMatcher]] to the Abstract Closure that evaluates parseResult by applying the semantics provided in 22.2.2 using patternCharacters as the pattern's List of SourceCharacter values and F as the flag parameters. let matcher = match Regex::with_flags(&p, f.as_ref()) { Err(error) => { - return Err(context - .construct_syntax_error(format!("failed to create matcher: {}", error.text))); + return context + .throw_syntax_error(format!("failed to create matcher: {}", error.text)); } Ok(val) => val, }; @@ -779,9 +779,7 @@ impl RegExp { // b. If Type(result) is neither Object nor Null, throw a TypeError exception. if !result.is_object() && !result.is_null() { - return Err( - context.construct_type_error("regexp exec returned neither object nor null") - ); + return context.throw_type_error("regexp exec returned neither object nor null"); } // c. Return result. @@ -790,7 +788,7 @@ impl RegExp { // 5. Perform ? RequireInternalSlot(R, [[RegExpMatcher]]). if !this.is_regexp() { - return Err(context.construct_type_error("RegExpExec called with invalid value")); + return context.throw_type_error("RegExpExec called with invalid value"); } // 6. Return ? RegExpBuiltinExec(R, S). @@ -814,9 +812,7 @@ impl RegExp { if let Some(rx) = obj.as_regexp() { rx.clone() } else { - return Err( - context.construct_type_error("RegExpBuiltinExec called with invalid value") - ); + return context.throw_type_error("RegExpBuiltinExec called with invalid value"); } }; @@ -870,9 +866,8 @@ impl RegExp { ) { Ok(s) => s.len(), Err(_) => { - return Err(context.construct_type_error( - "Failed to get byte index from utf16 encoded string", - )) + return context + .throw_type_error("Failed to get byte index from utf16 encoded string") } }; let r = matcher.find_from(&input, last_byte_index).next(); @@ -1046,9 +1041,8 @@ impl RegExp { let rx = if let Some(rx) = this.as_object() { rx } else { - return Err(context.construct_type_error( - "RegExp.prototype.match method called on incompatible value", - )); + return context + .throw_type_error("RegExp.prototype.match method called on incompatible value"); }; // 3. Let S be ? ToString(string). @@ -1495,9 +1489,9 @@ impl RegExp { let rx = if let Some(rx) = this.as_object() { rx } else { - return Err(context.construct_type_error( + return context.throw_type_error( "RegExp.prototype[Symbol.search] method called on incompatible value", - )); + ); }; // 3. Let S be ? ToString(string). @@ -1557,9 +1551,8 @@ impl RegExp { let rx = if let Some(rx) = this.as_object() { rx } else { - return Err(context.construct_type_error( - "RegExp.prototype.split method called on incompatible value", - )); + return context + .throw_type_error("RegExp.prototype.split method called on incompatible value"); }; // 3. Let S be ? ToString(string). diff --git a/boa/src/builtins/typed_array/mod.rs b/boa/src/builtins/typed_array/mod.rs index 23acfdd574..02fdf38e57 100644 --- a/boa/src/builtins/typed_array/mod.rs +++ b/boa/src/builtins/typed_array/mod.rs @@ -547,7 +547,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -682,7 +682,7 @@ impl TypedArray { // 2. Perform ? ValidateTypedArray(O). if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -747,7 +747,7 @@ impl TypedArray { // b. Let buffer be O.[[ViewedArrayBuffer]]. // c. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // d. Let typedArrayName be the String value of O.[[TypedArrayName]]. @@ -848,7 +848,7 @@ impl TypedArray { .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))? .is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Return CreateArrayIterator(O, key+value). @@ -876,7 +876,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -935,7 +935,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -980,7 +980,7 @@ impl TypedArray { // 14. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception. if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 15. Repeat, while k < final, @@ -1015,7 +1015,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1096,7 +1096,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1154,7 +1154,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1211,7 +1211,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1263,7 +1263,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1336,7 +1336,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1418,7 +1418,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1475,7 +1475,7 @@ impl TypedArray { .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))? .is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Return CreateArrayIterator(O, key). @@ -1503,7 +1503,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1606,7 +1606,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1664,7 +1664,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1741,7 +1741,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1821,7 +1821,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -1933,7 +1933,7 @@ impl TypedArray { // 1. Let targetBuffer be target.[[ViewedArrayBuffer]]. // 2. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception. if target_array.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } let target_buffer_obj = target_array .viewed_array_buffer() @@ -1945,7 +1945,7 @@ impl TypedArray { // 4. Let srcBuffer be source.[[ViewedArrayBuffer]]. // 5. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception. if source_array.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } let mut src_buffer_obj = source_array .viewed_array_buffer() @@ -1979,23 +1979,23 @@ impl TypedArray { let target_offset = match target_offset { IntegerOrInfinity::Integer(i) if i >= 0 => i as usize, IntegerOrInfinity::PositiveInfinity => { - return Err(context.construct_range_error("Target offset cannot be Infinity")) + return context.throw_range_error("Target offset cannot be Infinity"); } _ => unreachable!(), }; // 16. If srcLength + targetOffset > targetLength, throw a RangeError exception. if src_length + target_offset > target_length { - return Err(context.construct_range_error( + return context.throw_range_error( "Source typed array and target offset longer than target typed array", - )); + ); } // 17. If target.[[ContentType]] ≠ source.[[ContentType]], throw a TypeError exception. if target_name.content_type() != src_name.content_type() { - return Err(context.construct_type_error( + return context.throw_type_error( "Source typed array and target typed array have different content types", - )); + ); } // TODO: Shared Array Buffer @@ -2142,7 +2142,7 @@ impl TypedArray { // 1. Let targetBuffer be target.[[ViewedArrayBuffer]]. // 2. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception. if target_array.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let targetLength be target.[[ArrayLength]]. @@ -2167,7 +2167,7 @@ impl TypedArray { let target_offset = match target_offset { // 10. If targetOffset is +∞, throw a RangeError exception. IntegerOrInfinity::PositiveInfinity => { - return Err(context.construct_range_error("Target offset cannot be Infinity")) + return context.throw_range_error("Target offset cannot be Infinity") } IntegerOrInfinity::Integer(i) if i >= 0 => i as usize, _ => unreachable!(), @@ -2175,9 +2175,9 @@ impl TypedArray { // 11. If srcLength + targetOffset > targetLength, throw a RangeError exception. if src_length + target_offset > target_length { - return Err(context.construct_range_error( + return context.throw_range_error( "Source object and target offset longer than target typed array", - )); + ); } // 12. Let targetByteIndex be targetOffset × targetElementSize + targetByteOffset. @@ -2213,9 +2213,7 @@ impl TypedArray { // e. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception. if target_buffer.is_detached_buffer() { - return Err( - context.construct_type_error("Cannot set value on detached array buffer") - ); + return context.throw_type_error("Cannot set value on detached array buffer"); } // f. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, Unordered). @@ -2255,7 +2253,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -2304,7 +2302,7 @@ impl TypedArray { if count > 0 { // a. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception. if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // b. Let srcName be the String value of O.[[TypedArrayName]]. @@ -2419,7 +2417,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Let len be O.[[ArrayLength]]. @@ -2545,8 +2543,8 @@ impl TypedArray { .expect("Must be array buffer") .is_detached_buffer() { - return Err(context - .construct_type_error("Cannot sort typed array with detached buffer")); + return context + .throw_type_error("Cannot sort typed array with detached buffer"); } // c. If v is NaN, return +0𝔽. @@ -2770,7 +2768,7 @@ impl TypedArray { .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))? .is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. Return CreateArrayIterator(O, value). @@ -2848,8 +2846,8 @@ impl TypedArray { .content_type() != typed_array_name.content_type() { - return Err(context - .construct_type_error("New typed array has different context type than exemplar")); + return context + .throw_type_error("New typed array has different context type than exemplar"); } // 6. Return result. @@ -2879,7 +2877,7 @@ impl TypedArray { .as_typed_array() .ok_or_else(|| context.construct_type_error("Value is not a typed array object"))?; if o.is_detached() { - return Err(context.construct_type_error("Buffer of the typed array is detached")); + return context.throw_type_error("Buffer of the typed array is detached"); } // 3. If argumentList is a List of a single Number, then @@ -2887,8 +2885,8 @@ impl TypedArray { if let Some(number) = args[0].as_number() { // a. If newTypedArray.[[ArrayLength]] < ℝ(argumentList[0]), throw a TypeError exception. if (o.array_length() as f64) < number { - return Err(context - .construct_type_error("New typed array length is smaller than expected")); + return context + .throw_type_error("New typed array length is smaller than expected"); } } } @@ -3035,9 +3033,7 @@ impl TypedArray { // 1. Let srcData be srcArray.[[ViewedArrayBuffer]]. // 2. If IsDetachedBuffer(srcData) is true, throw a TypeError exception. if src_array.is_detached() { - return Err( - context.construct_type_error("Cannot initialize typed array from detached buffer") - ); + return context.throw_type_error("Cannot initialize typed array from detached buffer"); } let src_data_obj = src_array .viewed_array_buffer() @@ -3095,15 +3091,14 @@ impl TypedArray { // b. If IsDetachedBuffer(srcData) is true, throw a TypeError exception. if src_data.is_detached_buffer() { - return Err(context - .construct_type_error("Cannot initialize typed array from detached buffer")); + return context + .throw_type_error("Cannot initialize typed array from detached buffer"); } // c. If srcArray.[[ContentType]] ≠ O.[[ContentType]], throw a TypeError exception. if src_name.content_type() != constructor_name.content_type() { - return Err(context.construct_type_error( - "Cannot initialize typed array from different content type", - )); + return context + .throw_type_error("Cannot initialize typed array from different content type"); } // d. Let srcByteIndex be srcByteOffset. @@ -3188,7 +3183,7 @@ impl TypedArray { // 4. If offset modulo elementSize ≠ 0, throw a RangeError exception. if offset % constructor_name.element_size() != 0 { - return Err(context.construct_range_error("Invalid length for typed array")); + return context.throw_range_error("Invalid length for typed array"); } let buffer_byte_length = { @@ -3199,8 +3194,8 @@ impl TypedArray { // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. if buffer_array.is_detached_buffer() { - return Err(context - .construct_type_error("Cannot construct typed array from detached buffer")); + return context + .throw_type_error("Cannot construct typed array from detached buffer"); } // 7. Let bufferByteLength be buffer.[[ArrayBufferByteLength]]. @@ -3211,7 +3206,7 @@ impl TypedArray { let new_byte_length = if length.is_undefined() { // a. If bufferByteLength modulo elementSize ≠ 0, throw a RangeError exception. if buffer_byte_length % constructor_name.element_size() != 0 { - return Err(context.construct_range_error("Invalid length for typed array")); + return context.throw_range_error("Invalid length for typed array"); } // b. Let newByteLength be bufferByteLength - offset. @@ -3219,7 +3214,7 @@ impl TypedArray { // c. If newByteLength < 0, throw a RangeError exception. if new_byte_length < 0 { - return Err(context.construct_range_error("Invalid length for typed array")); + return context.throw_range_error("Invalid length for typed array"); } new_byte_length as usize @@ -3233,7 +3228,7 @@ impl TypedArray { // b. If offset + newByteLength > bufferByteLength, throw a RangeError exception. if offset + new_byte_length > buffer_byte_length { - return Err(context.construct_range_error("Invalid length for typed array")); + return context.throw_range_error("Invalid length for typed array"); } new_byte_length diff --git a/boa/src/context.rs b/boa/src/context.rs index 425ec47fe9..d39dc4a6ac 100644 --- a/boa/src/context.rs +++ b/boa/src/context.rs @@ -555,7 +555,7 @@ impl Context { /// Throws a `Error` with the specified message. #[inline] - pub fn throw_error(&mut self, message: M) -> JsResult + pub fn throw_error(&mut self, message: M) -> JsResult where M: Into>, { @@ -582,7 +582,7 @@ impl Context { /// Throws a `RangeError` with the specified message. #[inline] - pub fn throw_range_error(&mut self, message: M) -> JsResult + pub fn throw_range_error(&mut self, message: M) -> JsResult where M: Into>, { @@ -609,7 +609,7 @@ impl Context { /// Throws a `TypeError` with the specified message. #[inline] - pub fn throw_type_error(&mut self, message: M) -> JsResult + pub fn throw_type_error(&mut self, message: M) -> JsResult where M: Into>, { @@ -636,7 +636,7 @@ impl Context { /// Throws a `ReferenceError` with the specified message. #[inline] - pub fn throw_reference_error(&mut self, message: M) -> JsResult + pub fn throw_reference_error(&mut self, message: M) -> JsResult where M: Into>, { @@ -663,7 +663,7 @@ impl Context { /// Throws a `SyntaxError` with the specified message. #[inline] - pub fn throw_syntax_error(&mut self, message: M) -> JsResult + pub fn throw_syntax_error(&mut self, message: M) -> JsResult where M: Into>, { @@ -705,7 +705,7 @@ impl Context { } /// Throws a `EvalError` with the specified message. - pub fn throw_eval_error(&mut self, message: M) -> JsResult + pub fn throw_eval_error(&mut self, message: M) -> JsResult where M: Into>, { diff --git a/boa/src/environment/declarative_environment_record.rs b/boa/src/environment/declarative_environment_record.rs index c5419d777a..16714f8c2b 100644 --- a/boa/src/environment/declarative_environment_record.rs +++ b/boa/src/environment/declarative_environment_record.rs @@ -179,7 +179,7 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord { if self.env_rec.borrow().get(name).is_none() { // a. If S is true, throw a ReferenceError exception. if strict { - return Err(context.construct_reference_error(format!("{} not found", name))); + return context.throw_reference_error(format!("{} not found", name)); } // b. Perform envRec.CreateMutableBinding(N, true). @@ -204,9 +204,7 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord { // 3. If the binding for N in envRec has not yet been initialized, throw a ReferenceError exception. if binding_value_is_none { - return Err( - context.construct_reference_error(format!("{} has not been initialized", name)) - ); + return context.throw_reference_error(format!("{} has not been initialized", name)); // 4. Else if the binding for N in envRec is a mutable binding, change its bound value to V. } else if binding_mutable { let mut env_rec = self.env_rec.borrow_mut(); @@ -216,8 +214,8 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord { // a. Assert: This is an attempt to change the value of an immutable binding. // b. If S is true, throw a TypeError exception. } else if strict { - return Err(context - .construct_type_error(format!("Cannot mutate an immutable binding {}", name))); + return context + .throw_type_error(format!("Cannot mutate an immutable binding {}", name)); } // 6. Return NormalCompletion(empty). diff --git a/boa/src/environment/global_environment_record.rs b/boa/src/environment/global_environment_record.rs index df0432b3cd..5c21ecc7a5 100644 --- a/boa/src/environment/global_environment_record.rs +++ b/boa/src/environment/global_environment_record.rs @@ -300,9 +300,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord { // 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 2. If DclRec.HasBinding(N) is true, throw a TypeError exception. if !allow_name_reuse && self.declarative_record.has_binding(name, context)? { - return Err( - context.construct_type_error(format!("Binding already exists for {}", name)) - ); + return context.throw_type_error(format!("Binding already exists for {}", name)); } // 3. Return DclRec.CreateMutableBinding(N, D). @@ -325,9 +323,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord { // 1. Let DclRec be envRec.[[DeclarativeRecord]]. // 2. If DclRec.HasBinding(N) is true, throw a TypeError exception. if self.declarative_record.has_binding(name, context)? { - return Err( - context.construct_type_error(format!("Binding already exists for {}", name)) - ); + return context.throw_type_error(format!("Binding already exists for {}", name)); } // 3. Return DclRec.CreateImmutableBinding(N, S). diff --git a/boa/src/environment/object_environment_record.rs b/boa/src/environment/object_environment_record.rs index 40ccd06b17..d39cb62441 100644 --- a/boa/src/environment/object_environment_record.rs +++ b/boa/src/environment/object_environment_record.rs @@ -157,7 +157,7 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord { // 3. If stillExists is false and S is true, throw a ReferenceError exception. if !still_exists && strict { - return Err(context.construct_reference_error("Binding already exists")); + return context.throw_reference_error("Binding already exists"); } // 4. Return ? Set(bindingObject, N, V, S). diff --git a/boa/src/lib.rs b/boa/src/lib.rs index 841c70c7f2..59c1336cc2 100644 --- a/boa/src/lib.rs +++ b/boa/src/lib.rs @@ -108,10 +108,7 @@ pub(crate) fn forward>(context: &mut Context, src: T) -> String { Err(e) => { return format!( "Uncaught {}", - context - .throw_syntax_error(e.to_string()) - .expect_err("interpreter.throw_syntax_error() did not return an error") - .display() + context.construct_syntax_error(e.to_string()).display() ); } }; @@ -133,11 +130,7 @@ pub(crate) fn forward_val>(context: &mut Context, src: T) -> JsRe let src_bytes: &[u8] = src.as_ref(); // Setup executor let result = parse(src_bytes, false) - .map_err(|e| { - context - .throw_syntax_error(e.to_string()) - .expect_err("interpreter.throw_syntax_error() did not return an error") - }) + .map_err(|e| context.construct_syntax_error(e.to_string())) .and_then(|expr| expr.run(context)); // The main_timer needs to be dropped before the BoaProfiler is. diff --git a/boa/src/object/internal_methods/array.rs b/boa/src/object/internal_methods/array.rs index 3eeb4d684a..0002949ab4 100644 --- a/boa/src/object/internal_methods/array.rs +++ b/boa/src/object/internal_methods/array.rs @@ -62,7 +62,7 @@ pub(crate) fn array_exotic_define_own_property( // 5. If SameValueZero(newLen, numberLen) is false, throw a RangeError exception. #[allow(clippy::float_cmp)] if new_len as f64 != number_len { - return Err(context.construct_range_error("bad length for array")); + return context.throw_range_error("bad length for array"); } // 2. Let newLenDesc be a copy of Desc. diff --git a/boa/src/object/internal_methods/proxy.rs b/boa/src/object/internal_methods/proxy.rs index 136e86613f..633c41f53a 100644 --- a/boa/src/object/internal_methods/proxy.rs +++ b/boa/src/object/internal_methods/proxy.rs @@ -100,9 +100,7 @@ pub(crate) fn proxy_exotic_get_prototype_of( let handler_proto = match &handler_proto { JsValue::Object(obj) => Some(obj.clone()), JsValue::Null => None, - _ => { - return Err(context.construct_type_error("Proxy trap result is neither object nor null")) - } + _ => return context.throw_type_error("Proxy trap result is neither object nor null"), }; // 9. Let extensibleTarget be ? IsExtensible(target). @@ -116,7 +114,7 @@ pub(crate) fn proxy_exotic_get_prototype_of( // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception. if handler_proto != target_proto { - return Err(context.construct_type_error("Proxy trap returned unexpected prototype")); + return context.throw_type_error("Proxy trap returned unexpected prototype"); } // 13. Return handlerProto. @@ -181,7 +179,7 @@ pub(crate) fn proxy_exotic_set_prototype_of( // 12. If SameValue(V, targetProto) is false, throw a TypeError exception. if val != target_proto { - return Err(context.construct_type_error("Proxy trap failed to set prototype")); + return context.throw_type_error("Proxy trap failed to set prototype"); } // 13. Return true. @@ -225,7 +223,7 @@ pub(crate) fn proxy_exotic_is_extensible(obj: &JsObject, context: &mut Context) // 9. If SameValue(booleanTrapResult, targetResult) is false, throw a TypeError exception. if boolean_trap_result != target_result { - return Err(context.construct_type_error("Proxy trap returned unexpected extensible value")); + return context.throw_type_error("Proxy trap returned unexpected extensible value"); } // 10. Return booleanTrapResult. @@ -271,7 +269,7 @@ pub(crate) fn proxy_exotic_prevent_extensions( if boolean_trap_result && target.is_extensible(context)? { // a. Let extensibleTarget be ? IsExtensible(target). // b. If extensibleTarget is true, throw a TypeError exception. - return Err(context.construct_type_error("Proxy trap failed to set extensible")); + return context.throw_type_error("Proxy trap failed to set extensible"); } // 9. Return booleanTrapResult. @@ -318,9 +316,7 @@ pub(crate) fn proxy_exotic_get_own_property( // 8. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception. if !trap_result_obj.is_object() && !trap_result_obj.is_undefined() { - return Err( - context.construct_type_error("Proxy trap result is neither object nor undefined") - ); + return context.throw_type_error("Proxy trap result is neither object nor undefined"); } // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). @@ -331,17 +327,17 @@ pub(crate) fn proxy_exotic_get_own_property( if let Some(desc) = target_desc { // b. If targetDesc.[[Configurable]] is false, throw a TypeError exception. if !desc.expect_configurable() { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap result is undefined adn target result is not configurable", - )); + ); } // c. Let extensibleTarget be ? IsExtensible(target). // d. If extensibleTarget is false, throw a TypeError exception. if !target.is_extensible(context)? { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap result is undefined and target is not extensible", - )); + ); // e. Return undefined. } else { return Ok(None); @@ -368,7 +364,7 @@ pub(crate) fn proxy_exotic_get_own_property( result_desc.clone(), target_desc.clone(), ) { - return Err(context.construct_type_error("Proxy trap returned unexpected property")); + return context.throw_type_error("Proxy trap returned unexpected property"); } // 16. If resultDesc.[[Configurable]] is false, then @@ -380,17 +376,17 @@ pub(crate) fn proxy_exotic_get_own_property( if let Some(false) = result_desc.writable() { // i. If targetDesc.[[Writable]] is true, throw a TypeError exception. if desc.expect_writable() { - return Err( - context.construct_type_error("Proxy trap result is writable and not configurable while target result is not configurable") - ); + return + context.throw_type_error("Proxy trap result is writable and not configurable while target result is not configurable") + ; } } } // i. Throw a TypeError exception. _ => { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap result is not configurable and target result is undefined", - )) + ) } } } @@ -461,12 +457,12 @@ pub(crate) fn proxy_exotic_define_own_property( None => { // a. If extensibleTarget is false, throw a TypeError exception. if !extensible_target { - return Err(context.construct_type_error("Proxy trap failed to set property")); + return context.throw_type_error("Proxy trap failed to set property"); } // b. If settingConfigFalse is true, throw a TypeError exception. if setting_config_false { - return Err(context.construct_type_error("Proxy trap failed to set property")); + return context.throw_type_error("Proxy trap failed to set property"); } } // 15. Else, @@ -477,16 +473,14 @@ pub(crate) fn proxy_exotic_define_own_property( desc.clone(), Some(target_desc.clone()), ) { - return Err( - context.construct_type_error("Proxy trap set property to unexpected value") - ); + return context.throw_type_error("Proxy trap set property to unexpected value"); } // b. If settingConfigFalse is true and targetDesc.[[Configurable]] is true, throw a TypeError exception. if setting_config_false && target_desc.expect_configurable() { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap set property with unexpected configurable field", - )); + ); } // c. If IsDataDescriptor(targetDesc) is true, targetDesc.[[Configurable]] is false, and targetDesc.[[Writable]] is true, then @@ -497,9 +491,9 @@ pub(crate) fn proxy_exotic_define_own_property( // i. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, throw a TypeError exception. if let Some(writable) = desc.writable() { if !writable { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap set property with unexpected writable field", - )); + ); } } } @@ -559,13 +553,13 @@ pub(crate) fn proxy_exotic_has_property( if let Some(target_desc) = target_desc { // i. If targetDesc.[[Configurable]] is false, throw a TypeError exception. if !target_desc.expect_configurable() { - return Err(context.construct_type_error("Proxy trap returned unexpected property")); + return context.throw_type_error("Proxy trap returned unexpected property"); } // ii. Let extensibleTarget be ? IsExtensible(target). // iii. If extensibleTarget is false, throw a TypeError exception. if !target.is_extensible(context)? { - return Err(context.construct_type_error("Proxy trap returned unexpected property")); + return context.throw_type_error("Proxy trap returned unexpected property"); } } } @@ -623,8 +617,8 @@ pub(crate) fn proxy_exotic_get( if target_desc.is_data_descriptor() && !target_desc.expect_writable() { // i. If SameValue(trapResult, targetDesc.[[Value]]) is false, throw a TypeError exception. if !JsValue::same_value(&trap_result, target_desc.expect_value()) { - return Err(context - .construct_type_error("Proxy trap returned unexpected data descriptor")); + return context + .throw_type_error("Proxy trap returned unexpected data descriptor"); } } @@ -632,9 +626,8 @@ pub(crate) fn proxy_exotic_get( if target_desc.is_accessor_descriptor() && target_desc.expect_get().is_undefined() { // i. If trapResult is not undefined, throw a TypeError exception. if !trap_result.is_undefined() { - return Err(context.construct_type_error( - "Proxy trap returned unexpected accessor descriptor", - )); + return context + .throw_type_error("Proxy trap returned unexpected accessor descriptor"); } } } @@ -700,9 +693,7 @@ pub(crate) fn proxy_exotic_set( if target_desc.is_data_descriptor() && !target_desc.expect_writable() { // i. If SameValue(V, targetDesc.[[Value]]) is false, throw a TypeError exception. if !JsValue::same_value(&value, target_desc.expect_value()) { - return Err( - context.construct_type_error("Proxy trap set unexpected data descriptor") - ); + return context.throw_type_error("Proxy trap set unexpected data descriptor"); } } @@ -711,9 +702,8 @@ pub(crate) fn proxy_exotic_set( // i. If targetDesc.[[Set]] is undefined, throw a TypeError exception. match target_desc.set() { None | Some(&JsValue::Undefined) => { - return Err(context.construct_type_error( - "Proxy trap set unexpected accessor descriptor", - )); + return context + .throw_type_error("Proxy trap set unexpected accessor descriptor"); } _ => {} } @@ -776,7 +766,7 @@ pub(crate) fn proxy_exotic_delete( // 11. If targetDesc.[[Configurable]] is false, throw a TypeError exception. Some(target_desc) => { if !target_desc.expect_configurable() { - return Err(context.construct_type_error("Proxy trap failed to delete property")); + return context.throw_type_error("Proxy trap failed to delete property"); } } } @@ -784,7 +774,7 @@ pub(crate) fn proxy_exotic_delete( // 12. Let extensibleTarget be ? IsExtensible(target). // 13. If extensibleTarget is false, throw a TypeError exception. if !target.is_extensible(context)? { - return Err(context.construct_type_error("Proxy trap failed to delete property")); + return context.throw_type_error("Proxy trap failed to delete property"); } // 14. Return true. @@ -835,17 +825,17 @@ pub(crate) fn proxy_exotic_own_property_keys( match value { JsValue::String(s) => { if !unchecked_result_keys.insert(s.clone().into()) { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap result contains duplicate string property keys", - )); + ); } trap_result.push(s.clone().into()) } JsValue::Symbol(s) => { if !unchecked_result_keys.insert(s.clone().into()) { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap result contains duplicate symbol property keys", - )); + ); } trap_result.push(s.clone().into()) } @@ -895,9 +885,9 @@ pub(crate) fn proxy_exotic_own_property_keys( // a. If key is not an element of uncheckedResultKeys, throw a TypeError exception. // b. Remove key from uncheckedResultKeys. if !unchecked_result_keys.remove(&key) { - return Err(context.construct_type_error( + return context.throw_type_error( "Proxy trap failed to return all non-configurable property keys", - )); + ); } } @@ -911,15 +901,14 @@ pub(crate) fn proxy_exotic_own_property_keys( // a. If key is not an element of uncheckedResultKeys, throw a TypeError exception. // b. Remove key from uncheckedResultKeys. if !unchecked_result_keys.remove(&key) { - return Err(context.construct_type_error( - "Proxy trap failed to return all configurable property keys", - )); + return context + .throw_type_error("Proxy trap failed to return all configurable property keys"); } } // 22. If uncheckedResultKeys is not empty, throw a TypeError exception. if !unchecked_result_keys.is_empty() { - return Err(context.construct_type_error("Proxy trap failed to return all property keys")); + return context.throw_type_error("Proxy trap failed to return all property keys"); } // 23. Return trapResult. @@ -1014,9 +1003,7 @@ fn proxy_exotic_construct( // 10. If Type(newObj) is not Object, throw a TypeError exception. if !new_obj.is_object() { - return Err( - context.construct_type_error("Proxy trap constructor returned non-object value") - ); + return context.throw_type_error("Proxy trap constructor returned non-object value"); } // 11. Return newObj. diff --git a/boa/src/object/jsobject.rs b/boa/src/object/jsobject.rs index 4774edd110..d87c783e63 100644 --- a/boa/src/object/jsobject.rs +++ b/boa/src/object/jsobject.rs @@ -480,9 +480,7 @@ impl JsObject { // b. If IsCallable(getter) is false and getter is not undefined, throw a TypeError exception. // todo: extract IsCallable to be callable from Value if !getter.is_undefined() && getter.as_object().map_or(true, |o| !o.is_callable()) { - return Err( - context.construct_type_error("Property descriptor getter must be callable") - ); + return context.throw_type_error("Property descriptor getter must be callable"); } // c. Set desc.[[Get]] to getter. Some(getter) @@ -498,9 +496,7 @@ impl JsObject { // 14.b. If IsCallable(setter) is false and setter is not undefined, throw a TypeError exception. // todo: extract IsCallable to be callable from Value if !setter.is_undefined() && setter.as_object().map_or(true, |o| !o.is_callable()) { - return Err( - context.construct_type_error("Property descriptor setter must be callable") - ); + return context.throw_type_error("Property descriptor setter must be callable"); } // 14.c. Set desc.[[Set]] to setter. Some(setter) @@ -511,10 +507,10 @@ impl JsObject { // 15. If desc.[[Get]] is present or desc.[[Set]] is present, then ... // a. If desc.[[Value]] is present or desc.[[Writable]] is present, throw a TypeError exception. if get.as_ref().or_else(|| set.as_ref()).is_some() && desc.inner().is_data_descriptor() { - return Err(context.construct_type_error( + return context.throw_type_error( "Invalid property descriptor.\ - Cannot both specify accessors and a value or writable attribute", - )); +Cannot both specify accessors and a value or writable attribute", + ); } desc = desc.maybe_get(get).maybe_set(set); diff --git a/boa/src/object/operations.rs b/boa/src/object/operations.rs index c9981175bb..3e90002939 100644 --- a/boa/src/object/operations.rs +++ b/boa/src/object/operations.rs @@ -91,9 +91,7 @@ impl JsObject { let success = self.__set__(key.clone(), value.into(), self.clone().into(), context)?; // 5. If success is false and Throw is true, throw a TypeError exception. if !success && throw { - return Err( - context.construct_type_error(format!("cannot set non-writable property: {}", key)) - ); + return context.throw_type_error(format!("cannot set non-writable property: {}", key)); } // 6. Return success. Ok(success) @@ -152,7 +150,7 @@ impl JsObject { let success = self.create_data_property(key.clone(), value, context)?; // 4. If success is false, throw a TypeError exception. if !success { - return Err(context.construct_type_error(format!("cannot redefine property: {}", key))); + return context.throw_type_error(format!("cannot redefine property: {}", key)); } // 5. Return success. Ok(success) @@ -182,7 +180,7 @@ impl JsObject { let success = self.__define_own_property__(key.clone(), desc.into(), context)?; // 4. If success is false, throw a TypeError exception. if !success { - return Err(context.construct_type_error(format!("cannot redefine property: {}", key))); + return context.throw_type_error(format!("cannot redefine property: {}", key)); } // 5. Return success. Ok(success) @@ -206,7 +204,7 @@ impl JsObject { let success = self.__delete__(&key, context)?; // 4. If success is false, throw a TypeError exception. if !success { - return Err(context.construct_type_error(format!("cannot delete property: {}", key))); + return context.throw_type_error(format!("cannot delete property: {}", key)); } // 5. Return success. Ok(success) @@ -451,7 +449,7 @@ impl JsObject { // 4. If Type(C) is not Object, throw a TypeError exception. if !c.is_object() { - return Err(context.construct_type_error("property 'constructor' is not an object")); + return context.throw_type_error("property 'constructor' is not an object"); } // 5. Let S be ? Get(C, @@species). @@ -466,7 +464,7 @@ impl JsObject { // 8. Throw a TypeError exception. match s.as_object() { Some(obj) if obj.is_constructor() => Ok(obj.clone()), - _ => Err(context.construct_type_error("property 'constructor' is not a constructor")), + _ => context.throw_type_error("property 'constructor' is not a constructor"), } } @@ -555,8 +553,9 @@ impl JsObject { // 5. Return func. JsValue::Object(obj) if obj.is_callable() => Ok(Some(obj.clone())), // 4. If IsCallable(func) is false, throw a TypeError exception. - _ => Err(context - .construct_type_error("value returned for property of object is not a function")), + _ => { + context.throw_type_error("value returned for property of object is not a function") + } } } @@ -667,7 +666,7 @@ impl JsValue { let next = obj.get(index, context)?; // c. If Type(next) is not an element of elementTypes, throw a TypeError exception. if !types.contains(&next.get_type()) { - return Err(context.construct_type_error("bad type")); + return context.throw_type_error("bad type"); } // d. Append next as the last element of list. list.push(next.clone()); @@ -746,8 +745,8 @@ impl JsValue { obj } else { // 5. If Type(P) is not Object, throw a TypeError exception. - return Err(context - .construct_type_error("function has non-object prototype in instanceof check")); + return context + .throw_type_error("function has non-object prototype in instanceof check"); }; // 6. Repeat, diff --git a/boa/src/syntax/ast/node/declaration/mod.rs b/boa/src/syntax/ast/node/declaration/mod.rs index 1bcb3f3608..5a9bebe7fd 100644 --- a/boa/src/syntax/ast/node/declaration/mod.rs +++ b/boa/src/syntax/ast/node/declaration/mod.rs @@ -472,10 +472,10 @@ impl DeclarationPatternObject { }; if value.is_null() { - return Err(context.construct_type_error("Cannot destructure 'null' value")); + return context.throw_type_error("Cannot destructure 'null' value"); } if value.is_undefined() { - return Err(context.construct_type_error("Cannot destructure 'undefined' value")); + return context.throw_type_error("Cannot destructure 'undefined' value"); } // 1. Perform ? RequireObjectCoercible(value). @@ -685,10 +685,10 @@ impl DeclarationPatternArray { }; if value.is_null() { - return Err(context.construct_type_error("Cannot destructure 'null' value")); + return context.throw_type_error("Cannot destructure 'null' value"); } if value.is_undefined() { - return Err(context.construct_type_error("Cannot destructure 'undefined' value")); + return context.throw_type_error("Cannot destructure 'undefined' value"); } // 1. Let iteratorRecord be ? GetIterator(value). diff --git a/boa/src/value/mod.rs b/boa/src/value/mod.rs index 7c78eba1c8..ea3f99893c 100644 --- a/boa/src/value/mod.rs +++ b/boa/src/value/mod.rs @@ -374,7 +374,7 @@ impl JsValue { // 5. If success is false and Throw is true, throw a TypeError exception. // 6. Return success. if !success && throw { - return Err(context.construct_type_error("Cannot assign value to property")); + return context.throw_type_error("Cannot assign value to property"); } else { return Ok(value); } @@ -435,7 +435,7 @@ impl JsValue { // v. If Type(result) is not Object, return result. // vi. Throw a TypeError exception. return if result.is_object() { - Err(context.construct_type_error("Symbol.toPrimitive cannot return an object")) + context.throw_type_error("Symbol.toPrimitive cannot return an object") } else { Ok(result) }; @@ -465,33 +465,29 @@ impl JsValue { /// [spec]: https://tc39.es/ecma262/#sec-tobigint pub fn to_bigint(&self, context: &mut Context) -> JsResult { match self { - JsValue::Null => Err(context.construct_type_error("cannot convert null to a BigInt")), - JsValue::Undefined => { - Err(context.construct_type_error("cannot convert undefined to a BigInt")) - } + JsValue::Null => context.throw_type_error("cannot convert null to a BigInt"), + JsValue::Undefined => context.throw_type_error("cannot convert undefined to a BigInt"), JsValue::String(ref string) => { if let Some(value) = JsBigInt::from_string(string) { Ok(value) } else { - Err(context.construct_syntax_error(format!( + context.throw_syntax_error(format!( "cannot convert string '{}' to bigint primitive", string - ))) + )) } } JsValue::Boolean(true) => Ok(JsBigInt::one()), JsValue::Boolean(false) => Ok(JsBigInt::zero()), JsValue::Integer(_) | JsValue::Rational(_) => { - Err(context.construct_type_error("cannot convert Number to a BigInt")) + context.throw_type_error("cannot convert Number to a BigInt") } JsValue::BigInt(b) => Ok(b.clone()), JsValue::Object(_) => { let primitive = self.to_primitive(context, PreferredType::Number)?; primitive.to_bigint(context) } - JsValue::Symbol(_) => { - Err(context.construct_type_error("cannot convert Symbol to a BigInt")) - } + JsValue::Symbol(_) => context.throw_type_error("cannot convert Symbol to a BigInt"), } } @@ -522,9 +518,7 @@ impl JsValue { JsValue::Rational(rational) => Ok(Number::to_native_string(*rational).into()), JsValue::Integer(integer) => Ok(integer.to_string().into()), JsValue::String(string) => Ok(string.clone()), - JsValue::Symbol(_) => { - Err(context.construct_type_error("can't convert symbol to string")) - } + JsValue::Symbol(_) => context.throw_type_error("can't convert symbol to string"), JsValue::BigInt(ref bigint) => Ok(bigint.to_string().into()), JsValue::Object(_) => { let primitive = self.to_primitive(context, PreferredType::String)?; @@ -541,7 +535,7 @@ impl JsValue { pub fn to_object(&self, context: &mut Context) -> JsResult { match self { JsValue::Undefined | JsValue::Null => { - Err(context.construct_type_error("cannot convert 'null' or 'undefined' to object")) + context.throw_type_error("cannot convert 'null' or 'undefined' to object") } JsValue::Boolean(boolean) => { let prototype = context.standard_objects().boolean_object().prototype(); @@ -859,13 +853,11 @@ impl JsValue { let integer_index = self.to_integer(context)?; if integer_index < 0.0 { - return Err(context.construct_range_error("Integer index must be >= 0")); + return context.throw_range_error("Integer index must be >= 0"); } if integer_index > Number::MAX_SAFE_INTEGER { - return Err( - context.construct_range_error("Integer index must be less than 2**(53) - 1") - ); + return context.throw_range_error("Integer index must be less than 2**(53) - 1"); } Ok(integer_index as usize) @@ -922,12 +914,8 @@ impl JsValue { JsValue::String(ref string) => Ok(string.string_to_number()), JsValue::Rational(number) => Ok(number), JsValue::Integer(integer) => Ok(f64::from(integer)), - JsValue::Symbol(_) => { - Err(context.construct_type_error("argument must not be a symbol")) - } - JsValue::BigInt(_) => { - Err(context.construct_type_error("argument must not be a bigint")) - } + JsValue::Symbol(_) => context.throw_type_error("argument must not be a symbol"), + JsValue::BigInt(_) => context.throw_type_error("argument must not be a bigint"), JsValue::Object(_) => { let primitive = self.to_primitive(context, PreferredType::Number)?; primitive.to_number(context) @@ -962,7 +950,7 @@ impl JsValue { #[inline] pub fn require_object_coercible(&self, context: &mut Context) -> JsResult<&JsValue> { if self.is_null_or_undefined() { - Err(context.construct_type_error("cannot convert null or undefined to Object")) + context.throw_type_error("cannot convert null or undefined to Object") } else { Ok(self) } diff --git a/boa/src/value/operations.rs b/boa/src/value/operations.rs index 02f3bbfb56..87654d2ca9 100644 --- a/boa/src/value/operations.rs +++ b/boa/src/value/operations.rs @@ -398,10 +398,10 @@ impl JsValue { pub fn instance_of(&self, target: &JsValue, context: &mut Context) -> JsResult { // 1. If Type(target) is not Object, throw a TypeError exception. if !target.is_object() { - return Err(context.construct_type_error(format!( + return context.throw_type_error(format!( "right-hand side of 'instanceof' should be an object, got {}", target.type_of() - ))); + )); } // 2. Let instOfHandler be ? GetMethod(target, @@hasInstance). @@ -419,7 +419,7 @@ impl JsValue { } None => { // 4. If IsCallable(target) is false, throw a TypeError exception. - Err(context.construct_type_error("right-hand side of 'instanceof' is not callable")) + context.throw_type_error("right-hand side of 'instanceof' is not callable") } } } diff --git a/boa/src/vm/mod.rs b/boa/src/vm/mod.rs index 3caa96070d..7187cc575a 100644 --- a/boa/src/vm/mod.rs +++ b/boa/src/vm/mod.rs @@ -225,10 +225,10 @@ impl Context { let lhs = self.vm.pop(); if !rhs.is_object() { - return Err(self.construct_type_error(format!( + return self.throw_type_error(format!( "right-hand side of 'in' should be an object, got {}", rhs.type_of() - ))); + )); } let key = lhs.to_property_key(self)?; let value = self.has_property(&rhs, &key)?; @@ -634,7 +634,7 @@ impl Context { } Opcode::Call => { if self.vm.stack_size_limit <= self.vm.stack.len() { - return Err(self.construct_range_error("Maximum call stack size exceeded")); + return self.throw_range_error("Maximum call stack size exceeded"); } let argc = self.vm.read::(); let mut args = Vec::with_capacity(argc as usize); @@ -647,7 +647,7 @@ impl Context { let object = match func { JsValue::Object(ref object) if object.is_callable() => object.clone(), - _ => return Err(self.construct_type_error("not a callable function")), + _ => return self.throw_type_error("not a callable function"), }; let result = object.__call__(&this, &args, self)?; @@ -656,7 +656,7 @@ impl Context { } Opcode::CallWithRest => { if self.vm.stack_size_limit <= self.vm.stack.len() { - return Err(self.construct_range_error("Maximum call stack size exceeded")); + return self.throw_range_error("Maximum call stack size exceeded"); } let argc = self.vm.read::(); let mut args = Vec::with_capacity(argc as usize); @@ -680,7 +680,7 @@ impl Context { let object = match func { JsValue::Object(ref object) if object.is_callable() => object.clone(), - _ => return Err(self.construct_type_error("not a callable function")), + _ => return self.throw_type_error("not a callable function"), }; let result = object.__call__(&this, &args, self)?; @@ -689,7 +689,7 @@ impl Context { } Opcode::New => { if self.vm.stack_size_limit <= self.vm.stack.len() { - return Err(self.construct_range_error("Maximum call stack size exceeded")); + return self.throw_range_error("Maximum call stack size exceeded"); } let argc = self.vm.read::(); let mut args = Vec::with_capacity(argc as usize); @@ -707,7 +707,7 @@ impl Context { } Opcode::NewWithRest => { if self.vm.stack_size_limit <= self.vm.stack.len() { - return Err(self.construct_range_error("Maximum call stack size exceeded")); + return self.throw_range_error("Maximum call stack size exceeded"); } let argc = self.vm.read::(); let mut args = Vec::with_capacity(argc as usize); @@ -854,10 +854,10 @@ impl Context { Opcode::ValueNotNullOrUndefined => { let value = self.vm.pop(); if value.is_null() { - return Err(self.construct_type_error("Cannot destructure 'null' value")); + return self.throw_type_error("Cannot destructure 'null' value"); } if value.is_undefined() { - return Err(self.construct_type_error("Cannot destructure 'undefined' value")); + return self.throw_type_error("Cannot destructure 'undefined' value"); } self.vm.push(value); } diff --git a/boa_tester/src/exec/js262.rs b/boa_tester/src/exec/js262.rs index a42ec0b33b..a420fb0aa5 100644 --- a/boa_tester/src/exec/js262.rs +++ b/boa_tester/src/exec/js262.rs @@ -67,7 +67,7 @@ fn detach_array_buffer( // 3. If SameValue(arrayBuffer.[[ArrayBufferDetachKey]], key) is false, throw a TypeError exception. if !JsValue::same_value(&array_buffer.array_buffer_detach_key, key) { - return Err(context.construct_type_error("Cannot detach array buffer with different key")); + return context.throw_type_error("Cannot detach array buffer with different key"); } // 4. Set arrayBuffer.[[ArrayBufferData]] to null. diff --git a/boa_wasm/src/lib.rs b/boa_wasm/src/lib.rs index 1b90a1f54b..0a74c6eb8d 100644 --- a/boa_wasm/src/lib.rs +++ b/boa_wasm/src/lib.rs @@ -11,10 +11,7 @@ pub fn evaluate(src: &str) -> Result { Err(e) => { return Err(format!( "Uncaught {}", - context - .throw_syntax_error(e.to_string()) - .expect_err("interpreter.throw_syntax_error() did not return an error") - .display() + context.construct_syntax_error(e.to_string()).display() ) .into()); }