diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2020-06-09 22:48:01 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-06-11 07:46:20 +0200 |
commit | 78155a66686b03a18eec1ea189ec43b06c51b51a (patch) | |
tree | df71a780992a3827f8de5f3950d92c186f2db7e9 | |
parent | 9940a7f6def5c3c03412fd0540f238d5413bb90a (diff) | |
download | serenity-78155a66686b03a18eec1ea189ec43b06c51b51a.zip |
LibJS: Consolidate error messages into ErrorTypes.h
Now, exceptions can be thrown with
interpreter.throw_exception<T>(ErrorType:TYPE, "format", "args",
"here").
63 files changed, 439 insertions, 223 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 4f6bdbd19d..8a7d05eedb 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -120,15 +120,15 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj auto call_type = is_new_expression() ? "constructor" : "function"; if (m_callee->is_identifier() || m_callee->is_member_expression()) { String expression_string; - if (m_callee->is_identifier()) + if (m_callee->is_identifier()) { expression_string = static_cast<const Identifier&>(*m_callee).string(); - else + } else { expression_string = static_cast<const MemberExpression&>(*m_callee).to_string_approximation(); - error_message = String::format("%s is not a %s (evaluated from '%s')", callee.to_string_without_side_effects().characters(), call_type, expression_string.characters()); + } + return interpreter.throw_exception<TypeError>(ErrorType::IsNotAEvaluatedFrom, callee.to_string_without_side_effects().characters(), call_type, expression_string.characters()); } else { - error_message = String::format("%s is not a %s", callee.to_string_without_side_effects().characters(), call_type); + return interpreter.throw_exception<TypeError>(ErrorType::IsNotA, callee.to_string_without_side_effects().characters(), call_type); } - return interpreter.throw_exception<TypeError>(error_message); } auto& function = callee.as_function(); @@ -156,7 +156,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj for (auto ch : static_cast<const StringObject&>(value.as_object()).primitive_string().string()) arguments.append(Value(js_string(interpreter, String::format("%c", ch)))); } else { - interpreter.throw_exception<TypeError>(String::format("%s is not iterable", value.to_string_without_side_effects().characters())); + interpreter.throw_exception<TypeError>(ErrorType::NotIterable, value.to_string_without_side_effects().characters()); } } else { arguments.append(value); @@ -412,7 +412,7 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj // FIXME: We need to properly implement the iterator protocol auto is_iterable = rhs_result.is_array() || rhs_result.is_string() || (rhs_result.is_object() && rhs_result.as_object().is_string_object()); if (!is_iterable) - return interpreter.throw_exception<TypeError>("for..of right-hand side must be iterable"); + return interpreter.throw_exception<TypeError>(ErrorType::ForOfNotIterable); size_t index = 0; auto next = [&]() -> Optional<Value> { @@ -985,7 +985,7 @@ Value Identifier::execute(Interpreter& interpreter, GlobalObject& global_object) { auto value = interpreter.get_variable(string(), global_object); if (value.is_empty()) - return interpreter.throw_exception<ReferenceError>(String::format("'%s' not known", string().characters())); + return interpreter.throw_exception<ReferenceError>(ErrorType::UnknownIdentifier, string().characters()); return value; } @@ -1107,7 +1107,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob return {}; if (reference.is_unresolvable()) - return interpreter.throw_exception<ReferenceError>("Invalid left-hand side in assignment"); + return interpreter.throw_exception<ReferenceError>(ErrorType::InvalidLeftHandAssignment); update_function_name(rhs_result, reference.name().as_string()); reference.put(interpreter, rhs_result); @@ -1523,7 +1523,7 @@ Value ArrayExpression::execute(Interpreter& interpreter, GlobalObject& global_ob array->indexed_properties().append(js_string(interpreter, string_to_spread.substring(i, 1))); continue; } - interpreter.throw_exception<TypeError>(String::format("%s is not iterable", value.to_string_without_side_effects().characters())); + interpreter.throw_exception<TypeError>(ErrorType::NotIterable, value.to_string_without_side_effects().characters()); return {}; } } @@ -1573,7 +1573,7 @@ Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& glo if (interpreter.exception()) return {}; if (!tag.is_function()) { - interpreter.throw_exception<TypeError>(String::format("%s is not a function", tag.to_string_without_side_effects().characters())); + interpreter.throw_exception<TypeError>(ErrorType::NotAFunction, tag.to_string_without_side_effects().characters()); return {}; } auto& tag_function = tag.as_function(); diff --git a/Libraries/LibJS/CMakeLists.txt b/Libraries/LibJS/CMakeLists.txt index e2de6c97b4..b033360350 100644 --- a/Libraries/LibJS/CMakeLists.txt +++ b/Libraries/LibJS/CMakeLists.txt @@ -27,6 +27,7 @@ set(SOURCES Runtime/ErrorConstructor.cpp Runtime/Error.cpp Runtime/ErrorPrototype.cpp + Runtime/ErrorTypes.cpp Runtime/Exception.cpp Runtime/FunctionConstructor.cpp Runtime/Function.cpp diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index 7894c53f59..3c4eceeb57 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -156,7 +156,7 @@ void Interpreter::set_variable(const FlyString& name, Value value, GlobalObject& auto possible_match = environment->get(name); if (possible_match.has_value()) { if (!first_assignment && possible_match.value().declaration_kind == DeclarationKind::Const) { - throw_exception<TypeError>("Assignment to constant variable"); + throw_exception<TypeError>(ErrorType::InvalidAssignToConst); return; } diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index 1a65eb2696..a4b6a4640f 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -35,6 +35,7 @@ #include <LibJS/Console.h> #include <LibJS/Forward.h> #include <LibJS/Heap/Heap.h> +#include <LibJS/Runtime/ErrorTypes.h> #include <LibJS/Runtime/Exception.h> #include <LibJS/Runtime/LexicalEnvironment.h> #include <LibJS/Runtime/MarkedValueList.h> @@ -175,6 +176,12 @@ public: return throw_exception(heap().allocate<Exception>(value)); } + template<typename T, typename... Args> + Value throw_exception(ErrorType type, Args&&... args) + { + return throw_exception(T::create(global_object(), String::format(type.message(), forward<Args>(args)...))); + } + Value last_value() const { return m_last_value; } bool underscore_is_last_value() const { return m_underscore_is_last_value; } diff --git a/Libraries/LibJS/Runtime/Array.cpp b/Libraries/LibJS/Runtime/Array.cpp index 70ee69c077..fdd2e0ac03 100644 --- a/Libraries/LibJS/Runtime/Array.cpp +++ b/Libraries/LibJS/Runtime/Array.cpp @@ -55,7 +55,7 @@ Array* array_from(Interpreter& interpreter, GlobalObject& global_object) if (!this_object) return {}; if (!this_object->is_array()) { - interpreter.throw_exception<TypeError>("Not an Array"); + interpreter.throw_exception<TypeError>(ErrorType::NotAn, "Array"); return nullptr; } return static_cast<Array*>(this_object); @@ -78,7 +78,7 @@ void Array::length_setter(Interpreter& interpreter, Value value) if (interpreter.exception()) return; if (length.is_nan() || length.is_infinity() || length.as_double() < 0) { - interpreter.throw_exception<RangeError>("Invalid array length"); + interpreter.throw_exception<RangeError>(ErrorType::ArrayInvalidLength); return; } array->indexed_properties().set_array_like_size(length.as_double()); diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 800a386836..1f9a788ede 100644 --- a/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -59,7 +59,7 @@ Value ArrayConstructor::call(Interpreter& interpreter) if (interpreter.argument_count() == 1 && interpreter.argument(0).is_number()) { auto array_length_value = interpreter.argument(0); if (!array_length_value.is_integer() || array_length_value.as_i32() < 0) { - interpreter.throw_exception<TypeError>("Invalid array length"); + interpreter.throw_exception<TypeError>(ErrorType::ArrayInvalidLength); return {}; } auto* array = Array::create(interpreter.global_object()); diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp index ed5d7a3611..199c2df72b 100644 --- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -80,12 +80,12 @@ ArrayPrototype::~ArrayPrototype() static Function* callback_from_args(Interpreter& interpreter, const String& name) { if (interpreter.argument_count() < 1) { - interpreter.throw_exception<TypeError>(String::format("Array.prototype.%s() requires at least one argument", name.characters())); + interpreter.throw_exception<TypeError>(ErrorType::ArrayPrototypeOneArg, name.characters()); return nullptr; } auto callback = interpreter.argument(0); if (!callback.is_function()) { - interpreter.throw_exception<TypeError>(String::format("%s is not a function", callback.to_string_without_side_effects().characters())); + interpreter.throw_exception<TypeError>(ErrorType::NotAFunction, callback.to_string_without_side_effects().characters()); return nullptr; } return &callback.as_function(); @@ -194,7 +194,7 @@ Value ArrayPrototype::push(Interpreter& interpreter) auto argument_count = interpreter.argument_count(); auto new_length = length + argument_count; if (new_length > MAX_ARRAY_LIKE_INDEX) - return interpreter.throw_exception<TypeError>("Maximum array size exceeded"); + return interpreter.throw_exception<TypeError>(ErrorType::ArrayMaxSize); for (size_t i = 0; i < argument_count; ++i) { this_object->put(length + i, interpreter.argument(i)); if (interpreter.exception()) @@ -467,7 +467,7 @@ Value ArrayPrototype::reduce(Interpreter& interpreter) start += 1; } if (!start_found) { - interpreter.throw_exception<TypeError>("Reduce of empty array with no initial value"); + interpreter.throw_exception<TypeError>(ErrorType::ReduceNoInitial); return {}; } } @@ -526,7 +526,7 @@ Value ArrayPrototype::reduce_right(Interpreter& interpreter) start -= 1; } if (!start_found) { - interpreter.throw_exception<TypeError>("Reduce of empty array with no initial value"); + interpreter.throw_exception<TypeError>(ErrorType::ReduceNoInitial); return {}; } } @@ -734,7 +734,7 @@ Value ArrayPrototype::splice(Interpreter& interpreter) size_t new_length = initial_length + insert_count - actual_delete_count; if (new_length > MAX_ARRAY_LIKE_INDEX) - return interpreter.throw_exception<TypeError>("Maximum array size exceeded"); + return interpreter.throw_exception<TypeError>(ErrorType::ArrayMaxSize); auto removed_elements = Array::create(interpreter.global_object()); diff --git a/Libraries/LibJS/Runtime/BigIntConstructor.cpp b/Libraries/LibJS/Runtime/BigIntConstructor.cpp index 4dfb543f22..9dd20b9c05 100644 --- a/Libraries/LibJS/Runtime/BigIntConstructor.cpp +++ b/Libraries/LibJS/Runtime/BigIntConstructor.cpp @@ -56,7 +56,7 @@ Value BigIntConstructor::call(Interpreter& interpreter) return {}; if (primitive.is_number()) { if (!primitive.is_integer()) { - interpreter.throw_exception<RangeError>("BigInt argument must be an integer"); + interpreter.throw_exception<RangeError>(ErrorType::BigIntIntArgument); return {}; } return js_bigint(interpreter, Crypto::SignedBigInteger { primitive.as_i32() }); @@ -69,7 +69,7 @@ Value BigIntConstructor::call(Interpreter& interpreter) Value BigIntConstructor::construct(Interpreter& interpreter) { - interpreter.throw_exception<TypeError>("BigInt is not a constructor"); + interpreter.throw_exception<TypeError>(ErrorType::NotACtor, "BigInt"); return {}; } diff --git a/Libraries/LibJS/Runtime/BigIntPrototype.cpp b/Libraries/LibJS/Runtime/BigIntPrototype.cpp index 9a4498ec38..e36cefc1f7 100644 --- a/Libraries/LibJS/Runtime/BigIntPrototype.cpp +++ b/Libraries/LibJS/Runtime/BigIntPrototype.cpp @@ -51,7 +51,7 @@ static BigIntObject* bigint_object_from(Interpreter& interpreter, GlobalObject& if (!this_object) return nullptr; if (!this_object->is_bigint_object()) { - interpreter.throw_exception<TypeError>("Not a BigInt object"); + interpreter.throw_exception<TypeError>(ErrorType::NotA, "BigInt"); return nullptr; } return static_cast<BigIntObject*>(this_object); diff --git a/Libraries/LibJS/Runtime/BooleanPrototype.cpp b/Libraries/LibJS/Runtime/BooleanPrototype.cpp index 1fbf50742c..3129bd579b 100644 --- a/Libraries/LibJS/Runtime/BooleanPrototype.cpp +++ b/Libraries/LibJS/Runtime/BooleanPrototype.cpp @@ -48,7 +48,7 @@ Value BooleanPrototype::to_string(Interpreter& interpreter) return js_string(interpreter.heap(), this_object.as_bool() ? "true" : "false"); } if (!this_object.is_object() || !this_object.as_object().is_boolean()) { - interpreter.throw_exception<TypeError>("Not a Boolean"); + interpreter.throw_exception<TypeError>(ErrorType::NotA, "Boolean"); return {}; } @@ -63,7 +63,7 @@ Value BooleanPrototype::value_of(Interpreter& interpreter) return this_object; } if (!this_object.is_object() || !this_object.as_object().is_boolean()) { - interpreter.throw_exception<TypeError>("Not a Boolean"); + interpreter.throw_exception<TypeError>(ErrorType::NotA, "Boolean"); return {}; } diff --git a/Libraries/LibJS/Runtime/DatePrototype.cpp b/Libraries/LibJS/Runtime/DatePrototype.cpp index e112be27c0..7492a0de9d 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -42,7 +42,7 @@ static Date* this_date_from_interpreter(Interpreter& interpreter) if (!this_object) return nullptr; if (!this_object->is_date()) { - interpreter.throw_exception<TypeError>("object must be of type Date"); + interpreter.throw_exception<TypeError>(ErrorType::NotA, "Date"); return nullptr; } return static_cast<Date*>(this_object); diff --git a/Libraries/LibJS/Runtime/ErrorPrototype.cpp b/Libraries/LibJS/Runtime/ErrorPrototype.cpp index e6f0e14434..781c0ab32f 100644 --- a/Libraries/LibJS/Runtime/ErrorPrototype.cpp +++ b/Libraries/LibJS/Runtime/ErrorPrototype.cpp @@ -54,7 +54,7 @@ Value ErrorPrototype::name_getter(Interpreter& interpreter) if (!this_object) return {}; if (!this_object->is_error()) - return interpreter.throw_exception<TypeError>("Not an Error object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotAn, "Error"); return js_string(interpreter, static_cast<const Error*>(this_object)->name()); } @@ -64,7 +64,7 @@ void ErrorPrototype::name_setter(Interpreter& interpreter, Value value) if (!this_object) return; if (!this_object->is_error()) { - interpreter.throw_exception<TypeError>("Not an Error object"); + interpreter.throw_exception<TypeError>(ErrorType::NotAn, "Error"); return; } auto name = value.to_string(interpreter); @@ -79,14 +79,14 @@ Value ErrorPrototype::message_getter(Interpreter& interpreter) if (!this_object) return {}; if (!this_object->is_error()) - return interpreter.throw_exception<TypeError>("Not an Error object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotAn, "Error"); return js_string(interpreter, static_cast<const Error*>(this_object)->message()); } Value ErrorPrototype::to_string(Interpreter& interpreter) { if (!interpreter.this_value(interpreter.global_object()).is_object()) - return interpreter.throw_exception<TypeError>("Not an object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotAnObject, interpreter.this_value(interpreter.global_object()).to_string_without_side_effects().characters()); auto& this_object = interpreter.this_value(interpreter.global_object()).as_object(); String name = "Error"; diff --git a/Libraries/LibJS/Runtime/ErrorTypes.cpp b/Libraries/LibJS/Runtime/ErrorTypes.cpp new file mode 100644 index 0000000000..ac73e7b05e --- /dev/null +++ b/Libraries/LibJS/Runtime/ErrorTypes.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <LibJS/Runtime/ErrorTypes.h> + +namespace JS { + +#define __ENUMERATE_JS_ERROR(name, message) \ +const ErrorType ErrorType::name = ErrorType(message); + JS_ENUMERATE_ERROR_TYPES(__ENUMERATE_JS_ERROR) +#undef __ENUMERATE_JS_ERROR + +} diff --git a/Libraries/LibJS/Runtime/ErrorTypes.h b/Libraries/LibJS/Runtime/ErrorTypes.h new file mode 100644 index 0000000000..8d263b01c6 --- /dev/null +++ b/Libraries/LibJS/Runtime/ErrorTypes.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#define JS_ENUMERATE_ERROR_TYPES(M) \ + M(ArrayInvalidLength, "Invalid array length") \ + M(ArrayMaxSize, "Maximum array size exceeded") \ + M(ArrayPrototypeOneArg, "Array.prototype.%s() requires at least one argument") \ + M(AccessorBadField, "Accessor descriptor's '%s' field must be a function or undefined") \ + M(AccessorValueOrWritable, "Accessor property descriptor cannot specify a value or writable key") \ + M(BigIntBadOperator, "Cannot use %s operator with BigInt") \ + M(BigIntBadOperatorOtherType, "Cannot use %s operator with BigInt and other type") \ + M(BigIntIntArgument, "BigInt argument must be an integer") \ + M(BigIntInvalidValue, "Invalid value for BigInt: %s") \ + M(Convert, "Cannot convert %s to %s") \ + M(ConvertUndefinedToObject, "Cannot convert undefined to object") \ + M(DescChangeNonConfigurable, "Cannot change attributes of non-configurable property '%s'") \ + M(ForOfNotIterable, "for..of right-hand side must be iterable") \ + M(FunctionArgsNotObject, "Argument array must be an object") \ + M(InOperatorWithObject, "'in' operator must be used on an object") \ + M(InstanceOfOperatorBadPrototype, "Prototype property of %s is not an object") \ + M(InvalidAssignToConst, "Invalid assignment to const variable") \ + M(InvalidLeftHandAssignment, "Invalid left-hand side in assignment") \ + M(IsNotA, "%s is not a %s") \ + M(IsNotAEvaluatedFrom, "%s is not a %s (evaluated from '%s')") \ + M(NotA, "Not a %s object") \ + M(NotACtor, "%s is not a constructor") \ + M(NotAFunction, "%s is not a function") \ + M(NotAFunctionNoParam, "Not a function") \ + M(NotAn, "Not an %s object") \ + M(NotAnObject, "%s is not an object") \ + M(NotASymbol, "%s is not a symbol") \ + M(NotIterable, "%s is not iterable") \ + M(NonExtensibleDefine, "Cannot define property %s on non-extensible object") \ + M(ObjectDefinePropertyReturnedFalse, "Object's [[DefineProperty]] method returned false") \ + M(ObjectSetPrototypeOfReturnedFalse, "Object's [[SetPrototypeOf]] method returned false") \ + M(ObjectSetPrototypeOfTwoArgs, "Object.setPrototypeOf requires at least two arguments") \ + M(ObjectPreventExtensionsReturnedFalse, "Object's [[PreventExtensions]] method returned false") \ + M(ObjectPrototypeWrongType, "Prototype must be an object or null") \ + M(ProxyCallWithNew, "Proxy must be called with the 'new' operator") \ + M(ProxyConstructorBadType, "Expected %s argument of Proxy constructor to be object, got %s") \ + M(ProxyDefinePropExistingConfigurable, "Proxy handler's defineProperty trap violates " \ + "invariant: a property cannot be defined as non-configurable if it already exists on the " \ + "target object as a configurable property") \ + M(ProxyDefinePropIncompatibleDescriptor, "Proxy handler's defineProperty trap violates " \ + "invariant: the new descriptor is not compatible with the existing descriptor of the " \ + "property on the target") \ + M(ProxyDefinePropNonConfigurableNonExisting, "Proxy handler's defineProperty trap " \ + "violates invariant: a property cannot be defined as non-configurable if it does not " \ + "already exist on the target object") \ + M(ProxyDefinePropNonExtensible, "Proxy handler's defineProperty trap violates invariant: " \ + "a property cannot be reported as being defined if the property does not exist on " \ + "the target and the target is non-extensible") \ + M(ProxyDeleteNonConfigurable, "Proxy handler's deleteProperty trap violates invariant: " \ + "cannot report a non-configurable own property of the target as deleted") \ + M(ProxyGetImmutableDataProperty, "Proxy handler's get trap violates invariant: the " \ + "returned value must match the value on the target if the property exists on the " \ + "target as a non-writable, non-configurable own data property") \ + M(ProxyGetNonConfigurableAccessor, "Proxy handler's get trap violates invariant: the " \ + "returned value must be undefined if the property exists on the target as a " \ + "non-configurable accessor property with an undefined get attribute") \ + M(ProxyGetOwnDescriptorExistingConfigurable, "Proxy handler's getOwnPropertyDescriptor " \ + "trap violates invariant: a property cannot be defined as non-configurable if it " \ + "already exists on the target object as a configurable property") \ + M(ProxyGetOwnDescriptorInvalidDescriptor, "Proxy handler's getOwnPropertyDescriptor trap " \ + "violates invariant: invalid property descriptor for existing property on the target") \ + M(ProxyGetOwnDescriptorInvalidNonConfig, "Proxy handler's getOwnPropertyDescriptor trap " \ + "violates invariant: cannot report target's property as non-configurable if the " \ + "property does not exist, or if it is configurable") \ + M(ProxyGetOwnDescriptorNonConfigurable, "Proxy handler's getOwnPropertyDescriptor trap " \ + "violates invariant: cannot return undefined for a property on the target which is " \ + "a non-configurable property") \ + M(ProxyGetOwnDescriptorReturn, "Proxy handler's getOwnPropertyDescriptor trap violates " \ + "invariant: must return an object or undefined") \ + M(ProxyGetOwnDescriptorUndefReturn, "Proxy handler's getOwnPropertyDescriptor trap " \ + "violates invariant: cannot report a property as being undefined if it exists as an " \ + "own property of the target and the target is non-extensible") \ + M(ProxyGetPrototypeOfNonExtensible, "Proxy handler's getPrototypeOf trap violates " \ + "invariant: cannot return a different prototype object for a non-extensible target") \ + M(ProxyGetPrototypeOfReturn, "Proxy handler's getPrototypeOf trap violates invariant: " \ + "must return an object or null") \ + M(ProxyHasExistingNonConfigurable, "Proxy handler's has trap violates invariant: a " \ + "property cannot be reported as non-existent if it exists on the target as a " \ + "non-configurable property") \ + M(ProxyHasExistingNonExtensible, "Proxy handler's has trap violates invariant: a property " \ + "cannot be reported as non-existent if it exists on the target and the target is " \ + "non-extensible") \ + M(ProxyInvalidTrap, "Proxy handler's %s trap wasn't undefined, null, or callable") \ + M(ProxyIsExtensibleReturn, "Proxy handler's isExtensible trap violates invariant: " \ + "return value must match the target's extensibility") \ + M(ProxyPreventExtensionsReturn, "Proxy handler's preventExtensions trap violates " \ + "invariant: cannot return true if the target object is extensible") \ + M(ProxyRevoked, "An operation was performed on a revoked Proxy object") \ + M(ProxySetImmutableDataProperty, "Proxy handler's set trap violates invariant: cannot " \ + "return true for a property on the target which is a non-configurable, non-writable " \ + "own data property") \ + M(ProxySetNonConfigurableAccessor, "Proxy handler's set trap violates invariant: cannot " \ + "return true for a property on the target which is a non-configurable own accessor " \ + "property with an undefined set attribute") \ + M(ProxySetPrototypeOfNonExtensible, "Proxy handler's setPrototypeOf trap violates " \ + "invariant: the argument must match the prototype of the target if the " \ + "target is non-extensible") \ + M(ProxyTwoArguments, "Proxy constructor requires at least two arguments") \ + M(ReduceNoInitial, "Reduce of empty array with no initial value") \ + M(ReferencePrimitiveAssignment, "Cannot assign property %s to primitive value") \ + M(ReferenceUnresolvable, "Unresolvable reference") \ + M(ReflectArgumentMustBeAFunction, "First argument of Reflect.%s() must be a function") \ + M(ReflectArgumentMustBeAnObject, "First argument of Reflect.%s() must be an object") \ + M(ReflectBadArgumentsList, "Arguments list must be an object") \ + M(ReflectBadNewTarget, "Optional third argument of Reflect.construct() must be a constructor") \ + M(ReflectBadDescriptorArgument, "Descriptor argument is not an object") \ + M(StringRawCannotConvert, "Cannot convert property 'raw' to object from %s") \ + M(StringRepeatCountMustBe, "repeat count must be a %s number") \ + M(ToObjectNullOrUndef, "ToObject on null or undefined") \ + M(UnknownIdentifier, "'%s' is not defined") \ + /* LibWeb bindings */ \ + M(BadArgCountOne, "%s() needs one argument") \ + M(BadArgCountAtLeastOne, "%s() needs at least one argument") \ + M(BadArgCountMany, "%s() needs %s arguments") \ + M(DrawImageArgumentCount, "drawImage() needs three arguments") \ + M(FillBadWindingRule, "fill() winding rule must be either 'nonzero' or 'evenodd'") \ + M(FillNonString, "fill() called with non-string") \ + M(ImageIsAn, "Image is not an HTMLImageElement, it's an %s") \ + M(PutImageDataBadCall, "putImageData() called with non-ImageData") \ + + +namespace JS { + +class ErrorType { +public: +#define __ENUMERATE_JS_ERROR(name, message) \ + static const ErrorType name; + JS_ENUMERATE_ERROR_TYPES(__ENUMERATE_JS_ERROR) +#undef __ENUMERATE_JS_ERROR + + const char* message() const { return m_message; }; + +private: + explicit ErrorType(const char* message) + : m_message(message) + { + } + + const char* m_message; +}; + +} + diff --git a/Libraries/LibJS/Runtime/FunctionPrototype.cpp b/Libraries/LibJS/Runtime/FunctionPrototype.cpp index dea52b19ef..0fcef2453d 100644 --- a/Libraries/LibJS/Runtime/FunctionPrototype.cpp +++ b/Libraries/LibJS/Runtime/FunctionPrototype.cpp @@ -64,14 +64,14 @@ Value FunctionPrototype::apply(Interpreter& interpreter) if (!this_object) return {}; if (!this_object->is_function()) - return interpreter.throw_exception<TypeError>("Not a Function object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotA, "Function"); auto& function = static_cast<Function&>(*this_object); auto this_arg = interpreter.argument(0); auto arg_array = interpreter.argument(1); if (arg_array.is_null() || arg_array.is_undefined()) return interpreter.call(function, this_arg); if (!arg_array.is_object()) - return interpreter.throw_exception<TypeError>("argument array must be an object"); + return interpreter.throw_exception<TypeError>(ErrorType::FunctionArgsNotObject); auto length_property = arg_array.as_object().get("length"); if (interpreter.exception()) return {}; @@ -94,7 +94,7 @@ Value FunctionPrototype::bind(Interpreter& interpreter) if (!this_object) return {}; if (!this_object->is_function()) - return interpreter.throw_exception<TypeError>("Not a Function object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotA, "Function"); auto& this_function = static_cast<Function&>(*this_object); auto bound_this_arg = interpreter.argument(0); @@ -114,7 +114,7 @@ Value FunctionPrototype::call(Interpreter& interpreter) if (!this_object) return {}; if (!this_object->is_function()) - return interpreter.throw_exception<TypeError>("Not a Function object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotA, "Function"); auto& function = static_cast<Function&>(*this_object); auto this_arg = interpreter.argument(0); MarkedValueList arguments(interpreter.heap()); @@ -131,7 +131,7 @@ Value FunctionPrototype::to_string(Interpreter& interpreter) if (!this_object) return {}; if (!this_object->is_function()) - return interpreter.throw_exception<TypeError>("Not a Function object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotA, "Function"); String function_name = static_cast<Function*>(this_object)->name(); String function_parameters = ""; diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index dff49c1706..ab79d1005c 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -352,7 +352,7 @@ bool Object::define_property(const FlyString& property_name, const Object& descr if (is_accessor_property) { if (descriptor.has_property("value") || descriptor.has_property("writable")) { if (throw_exceptions) - interpreter().throw_exception<TypeError>("Accessor property descriptors cannot specify a value or writable key"); + interpreter().throw_exception<TypeError>(ErrorType::AccessorValueOrWritable); return false; } @@ -369,14 +369,14 @@ bool Object::define_property(const FlyString& property_name, const Object& descr if (getter.is_function()) { getter_function = &getter.as_function(); } else if (!getter.is_undefined()) { - interpreter().throw_exception<TypeError>("Accessor descriptor's 'get' field must be a function or undefined"); + interpreter().throw_exception<TypeError>(ErrorType::AccessorBadField, "get"); return false; } if (setter.is_function()) { setter_function = &setter.as_function(); } else if (!setter.is_undefined()) { - interpreter().throw_exception<TypeError>("Accessor descriptor's 'set' field must be a function or undefined"); + interpreter().throw_exception<TypeError>(ErrorType::AccessorBadField, "set"); return false; } @@ -424,7 +424,7 @@ bool Object::put_own_property(Object& this_object, const FlyString& property_nam if (!is_extensible()) { dbg() << "Disallow define_property of non-extensible object"; if (throw_exceptions && interpreter().in_strict_mode()) - interpreter().throw_exception<TypeError>(String::format("Cannot define property %s on non-extensible object", property_name.characters())); + interpreter().throw_exception<TypeError>(ErrorType::NonExtensibleDefine, property_name.characters()); return false; } @@ -459,7 +459,7 @@ bool Object::put_own_property(Object& this_object, const FlyString& property_nam if (!new_property && mode == PutOwnPropertyMode::DefineProperty && !metadata.value().attributes.is_configurable() && attributes != metadata.value().attributes) { dbg() << "Disallow reconfig of non-configurable property"; if (throw_exceptions) - interpreter().throw_exception<TypeError>(String::format("Cannot change attributes of non-configurable property '%s'", property_name.characters())); + interpreter().throw_exception<TypeError>(ErrorType::DescChangeNonConfigurable, property_name.characters()); return false; } @@ -498,7 +498,7 @@ bool Object::put_own_property_by_index(Object& this_object, u32 property_index, if (!is_extensible()) { dbg() << "Disallow define_property of non-extensible object"; if (throw_exceptions && interpreter().in_strict_mode()) - interpreter().throw_exception<TypeError>(String::format("Cannot define property %d on non-extensible object", property_index)); + interpreter().throw_exception<TypeError>(ErrorType::NonExtensibleDefine, property_index); return false; } @@ -517,7 +517,7 @@ bool Object::put_own_property_by_index(Object& this_object, u32 property_index, if (!new_property && mode == PutOwnPropertyMode::DefineProperty && !existing_attributes.is_configurable() && attributes != existing_attributes) { dbg() << "Disallow reconfig of non-configurable property"; if (throw_exceptions) - interpreter().throw_exception<TypeError>(String::format("Cannot change attributes of non-configurable property %d", property_index)); + interpreter().throw_exception<TypeError>(ErrorType::DescChangeNonConfigurable, property_index); return false; } @@ -778,7 +778,7 @@ Value Object::to_string() const auto& interpreter = const_cast<Object*>(this)->interpreter(); auto to_string_result = interpreter.call(to_string_function, const_cast<Object*>(this)); if (to_string_result.is_object()) - interpreter.throw_exception<TypeError>("Cannot convert object to string"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "object", "string"); if (interpreter.exception()) return {}; auto* string = to_string_result.to_primitive_string(interpreter); @@ -796,7 +796,7 @@ Value Object::invoke(const FlyString& property_name, Optional<MarkedValueList> a if (interpreter.exception()) return {}; if (!property.is_function()) { - interpreter.throw_exception<TypeError>(String::format("%s is not a function", property.to_string_without_side_effects().characters())); + interpreter.throw_exception<TypeError>(ErrorType::NotAFunction, property.to_string_without_side_effects().characters()); return {}; } return interpreter.call(property.as_function(), this, move(arguments)); diff --git a/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Libraries/LibJS/Runtime/ObjectConstructor.cpp index 979b26a980..9c651cc840 100644 --- a/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -98,7 +98,7 @@ Value ObjectConstructor::get_prototype_of(Interpreter& interpreter) Value ObjectConstructor::set_prototype_of(Interpreter& interpreter) { if (interpreter.argument_count() < 2) - return interpreter.throw_exception<TypeError>("Object.setPrototypeOf requires at least two arguments"); + return interpreter.throw_exception<TypeError>(ErrorType::ObjectSetPrototypeOfTwoArgs); auto* object = interpreter.argument(0).to_object(interpreter); if (interpreter.exception()) return {}; @@ -109,12 +109,12 @@ Value ObjectConstructor::set_prototype_of(Interpreter& interpreter) } else if (prototype_value.is_object()) { prototype = &prototype_value.as_object(); } else { - interpreter.throw_exception<TypeError>("Prototype must be null or object"); + interpreter.throw_exception<TypeError>(ErrorType::ObjectPrototypeWrongType); return {}; } if (!object->set_prototype(prototype)) { if (!interpreter.exception()) - interpreter.throw_exception<TypeError>("Object's setPrototypeOf method returned false"); + interpreter.throw_exception<TypeError>(ErrorType::ObjectSetPrototypeOfReturnedFalse); return {}; } return object; @@ -135,7 +135,7 @@ Value ObjectConstructor::prevent_extensions(Interpreter& interpreter) return argument; if (!argument.as_object().prevent_extensions()) { if (!interpreter.exception()) - interpreter.throw_exception<TypeError>("Proxy preventExtensions handler returned false"); + interpreter.throw_exception<TypeError>(ErrorType::ObjectPreventExtensionsReturnedFalse); return {}; } return argument; @@ -155,9 +155,9 @@ Value ObjectConstructor::get_own_property_descriptor(Interpreter& interpreter) Value ObjectConstructor::define_property_(Interpreter& interpreter) { if (!interpreter.argument(0).is_object()) - return interpreter.throw_exception<TypeError>("Object argument is not an object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotAnObject, "Object argument"); if (!interpreter.argument(2).is_object()) - return interpreter.throw_exception<TypeError>("Descriptor argument is not an object"); + return interpreter.throw_exception<TypeError>(ErrorType::NotAnObject, "Descriptor argument"); auto& object = interpreter.argument(0).as_object(); auto property_key = interpreter.argument(1).to_string(interpreter); if (interpreter.exception()) @@ -166,9 +166,9 @@ Value ObjectConstructor::define_property_(Interpreter& interpreter) if (!object.define_property(property_key, descriptor)) { if (!interpreter.exception()) { if (object.is_proxy_object()) { - interpreter.throw_exception<TypeError>("Proxy handler's defineProperty method returned false"); + interpreter.throw_exception<TypeError>(ErrorType::ObjectDefinePropertyReturnedFalse); } else { - interpreter.throw_exception<TypeError>("Unable to define property on non-extensible object"); + interpreter.throw_exception<TypeError>(ErrorType::NonExtensibleDefine, property_key.characters()); } } return {}; @@ -184,7 +184,7 @@ Value ObjectConstructor::is(Interpreter& interpreter) Value ObjectConstructor::keys(Interpreter& interpreter) { if (!interpreter.argument_count()) - return interpreter.throw_exception<TypeError>("Can't convert undefined to object"); + return interpreter.throw_exception<TypeError>(ErrorType::ConvertUndefinedToObject); auto* obj_arg = interpreter.argument(0).to_object(interpreter); if (interpreter.exception()) @@ -196,7 +196,7 @@ Value ObjectConstructor::keys(Interpreter& interpreter) Value ObjectConstructor::values(Interpreter& interpreter) { if (!interpreter.argument_count()) - return interpreter.throw_exception<TypeError>("Can't convert undefined to object"); + return interpreter.throw_exception<TypeError>(ErrorType::ConvertUndefinedToObject); auto* obj_arg = interpreter.argument(0).to_object(interpreter); if (interpreter.exception()) @@ -208,7 +208,7 @@ Value ObjectConstructor::values(Interpreter& interpreter) Value ObjectConstructor::entries(Interpreter& interpreter) { if (!interpreter.argument_count()) - return interpreter.throw_exception<TypeError>("Can't convert undefined to object"); + return interpreter.throw_exception<TypeError>(ErrorType::ConvertUndefinedToObject); auto* obj_arg = interpreter.argument(0).to_object(interpreter); if (interpreter.exception()) diff --git a/Libraries/LibJS/Runtime/ProxyConstructor.cpp b/Libraries/LibJS/Runtime/ProxyConstructor.cpp index 1d03959705..3bd89190f8 100644 --- a/Libraries/LibJS/Runtime/ProxyConstructor.cpp +++ b/Libraries/LibJS/Runtime/ProxyConstructor.cpp @@ -46,21 +46,21 @@ ProxyConstructor::~ProxyConstructor() Value ProxyConstructor::call(Interpreter& interpreter) { - return interpreter.throw_exception<TypeError>("Proxy must be called with the \"new\" operator"); + return interpreter.throw_exception<TypeError>(ErrorType::ProxyCallWithNew); } Value ProxyConstructor::construct(Interpreter& interpreter) { if (interpreter.argument_count() < 2) - return interpreter.throw_exception<TypeError>("Proxy requires at least two arguments"); + return interpreter.throw_exception<TypeError>(ErrorType::ProxyTwoArguments); auto target = interpreter.argument(0); auto handler = interpreter.argument(1); if (!target.is_object()) - return interpreter.throw_exception<TypeError>(String::format("Expected target argument of Proxy constructor to be object, got %s", target.to_string_without_side_effects().characters())); + return interpreter.throw_exception<TypeError>(ErrorType::ProxyConstructorBadType, "target", target.to_string_without_side_effects().characters()); if (!handler.is_object()) - return interpreter.throw_exception<TypeError>(String::format("Expected handler argument of Proxy constructor to be object, got %s", handler.to_string_without_side_effects().characters())); + return interpreter.throw_exception<TypeError>(ErrorType::ProxyConstructorBadType, "handler", handler.to_string_without_side_effects().characters()); return ProxyObject::create(global_object(), target.as_object(), handler.as_object()); } diff --git a/Libraries/LibJS/Runtime/ProxyObject.cpp b/Libraries/LibJS/Runtime/ProxyObject.cpp index 9d83de5475..2df848c4ee 100644 --- a/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -76,7 +76,7 @@ ProxyObject::~ProxyObject() Object* ProxyObject::prototype() { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return nullptr; } auto trap = m_handler.get("getPrototypeOf"); @@ -85,7 +85,7 @@ Object* ProxyObject::prototype() if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.prototype(); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's getPrototypeOf trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "getPrototypeOf"); return nullptr; } MarkedValueList arguments(interpreter().heap()); @@ -94,7 +94,7 @@ Object* ProxyObject::prototype() if (interpreter().exception()) return nullptr; if (!trap_result.is_object() && !trap_result.is_null()) { - interpreter().throw_exception<TypeError>("Proxy handler's getPrototypeOf trap violates invariant: must return an object or null"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetPrototypeOfReturn); return nullptr; } if (m_target.is_extensible()) { @@ -108,7 +108,7 @@ Object* ProxyObject::prototype() if (interpreter().exception()) return nullptr; if (!same_value(interpreter(), trap_result, Value(target_proto))) { - interpreter().throw_exception<TypeError>("Proxy handler's getPrototypeOf trap violates invariant: cannot return a different prototype object for a non-extensible target"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetPrototypeOfNonExtensible); return nullptr; } return &trap_result.as_object(); @@ -117,7 +117,7 @@ Object* ProxyObject::prototype() const Object* ProxyObject::prototype() const { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return nullptr; } return const_cast<const Object*>(const_cast<ProxyObject*>(this)->prototype()); @@ -126,7 +126,7 @@ const Object* ProxyObject::prototype() const bool ProxyObject::set_prototype(Object* object) { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("setPrototypeOf"); @@ -135,7 +135,7 @@ bool ProxyObject::set_prototype(Object* object) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.set_prototype(object); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's setPrototypeOf trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "setPrototypeOf"); return false; } MarkedValueList arguments(interpreter().heap()); @@ -150,7 +150,7 @@ bool ProxyObject::set_prototype(Object* object) if (interpreter().exception()) return false; if (!same_value(interpreter(), Value(object), Value(target_proto))) { - interpreter().throw_exception<TypeError>("Proxy handler's setPrototypeOf trap violates invariant: the argument must match the prototype of the target if the target is non-extensible"); + interpreter().throw_exception<TypeError>(ErrorType::ProxySetPrototypeOfNonExtensible); return false; } return true; @@ -159,7 +159,7 @@ bool ProxyObject::set_prototype(Object* object) bool ProxyObject::is_extensible() const { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("isExtensible"); @@ -168,7 +168,7 @@ bool ProxyObject::is_extensible() const if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.is_extensible(); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's isExtensible trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "isExtensible"); return {}; } MarkedValueList arguments(interpreter().heap()); @@ -178,7 +178,7 @@ bool ProxyObject::is_extensible() const return false; if (trap_result != m_target.is_extensible()) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's isExtensible trap violates invariant: return value must match the target's extensibility"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyIsExtensibleReturn); return false; } return trap_result; @@ -187,7 +187,7 @@ bool ProxyObject::is_extensible() const bool ProxyObject::prevent_extensions() { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("preventExtensions"); @@ -196,7 +196,7 @@ bool ProxyObject::prevent_extensions() if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.prevent_extensions(); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's preventExtensions trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "preventExtensions"); return {}; } MarkedValueList arguments(interpreter().heap()); @@ -206,7 +206,7 @@ bool ProxyObject::prevent_extensions() return false; if (trap_result && m_target.is_extensible()) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's preventExtensions trap violates invariant: cannot return true if the target object is extensible"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyPreventExtensionsReturn); return false; } return trap_result; @@ -215,7 +215,7 @@ bool ProxyObject::prevent_extensions() Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyName name) const { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("getOwnPropertyDescriptor"); @@ -224,7 +224,7 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyNa if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.get_own_property_descriptor(name); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's getOwnPropertyDescriptor trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor"); return {}; } MarkedValueList arguments(interpreter().heap()); @@ -234,7 +234,7 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyNa if (interpreter().exception()) return {}; if (!trap_result.is_object() && !trap_result.is_undefined()) { - interpreter().throw_exception<TypeError>("Proxy handler's getOwnPropertyDescriptor trap violates invariant: must return an object or undefined"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorReturn); return {}; } auto target_desc = m_target.get_own_property_descriptor(name); @@ -244,12 +244,12 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyNa if (!target_desc.has_value()) return {}; if (!target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception<TypeError>("Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot return undefined for a property on the target which is a non-configurable property"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorNonConfigurable); return {}; } if (!m_target.is_extensible()) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report a property as being undefined if it exists as an own property of the target and the target is non-extensible"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorUndefReturn); return {}; } return {}; @@ -259,11 +259,11 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyNa return {}; if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), result_desc, target_desc)) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorInvalidDescriptor); return {}; } if (!result_desc.attributes.is_configurable() && (!target_desc.has_value() || target_desc.value().attributes.is_configurable())) { - interpreter().throw_exception<TypeError>("Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report target's property as non-configurable if the property does not exist, or if it is configurable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorInvalidNonConfig); return {}; } return result_desc; @@ -272,7 +272,7 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyNa bool ProxyObject::define_property(const FlyString& property_name, const Object& descriptor, bool throw_exceptions) { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("defineProperty"); @@ -281,7 +281,7 @@ bool ProxyObject::define_property(const FlyString& property_name, const Object& if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.define_property(property_name, descriptor, throw_exceptions); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's defineProperty trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "defineProperty"); return false; } MarkedValueList arguments(interpreter().heap()); @@ -302,21 +302,21 @@ bool ProxyObject::define_property(const FlyString& property_name, const Object& if (!target_desc.has_value()) { if (!m_target.is_extensible()) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's defineProperty trap violates invariant: a property cannot be reported as being defined if the property does not exist on the target and the target is non-extensible"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropNonExtensible); return false; } if (setting_config_false) { - interpreter().throw_exception<TypeError>("Proxy handler's defineProperty trap violates invariant: a property cannot be defined as non-configurable if it does not already exist on the target object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropNonConfigurableNonExisting); return false; } } else { if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), PropertyDescriptor::from_dictionary(interpreter(), descriptor), target_desc)) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's defineProperty trap violates invariant: the new descriptor is not compatible with the existing descriptor of the property on the target"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropIncompatibleDescriptor); return false; } if (setting_config_false && target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception<TypeError>("Proxy handler's defineProperty trap violates invariant: a property cannot be defined as non-configurable if it already exists on the target object as a configurable property"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropExistingConfigurable); return false; } } @@ -326,7 +326,7 @@ bool ProxyObject::define_property(const FlyString& property_name, const Object& bool ProxyObject::has_property(PropertyName name) const { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("has"); @@ -335,7 +335,7 @@ bool ProxyObject::has_property(PropertyName name) const if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.has_property(name); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's has trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "has"); return false; } MarkedValueList arguments(interpreter().heap()); @@ -350,12 +350,12 @@ bool ProxyObject::has_property(PropertyName name) const return false; if (target_desc.has_value()) { if (!target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception<TypeError>("Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exists on the target as a non-configurable property"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyHasExistingNonConfigurable); return false; } if (!m_target.is_extensible()) { if (!interpreter().exception()) - interpreter().throw_exception<TypeError>("Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exist on the target and the target is non-extensible"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyHasExistingNonExtensible); return false; } } @@ -366,7 +366,7 @@ bool ProxyObject::has_property(PropertyName name) const Value ProxyObject::get(PropertyName name) const { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("get"); @@ -375,7 +375,7 @@ Value ProxyObject::get(PropertyName name) const if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.get(name); if (!trap.is_function()) - return interpreter().throw_exception<TypeError>("Proxy handler's get trap wasn't undefined, null, or callable"); + return interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "get"); MarkedValueList arguments(interpreter().heap()); arguments.values().append(Value(&m_target)); arguments.values().append(js_string(interpreter(), name.to_string())); @@ -388,9 +388,9 @@ Value ProxyObject::get(PropertyName name) const if (interpreter().exception()) return {}; if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), trap_result, target_desc.value().value)) - return interpreter().throw_exception<TypeError>("Proxy handler's get trap violates invariant: the returned value must match the value on the target if the property exists on the target as a non-writable, non-configurable own data property"); + return interpreter().throw_exception<TypeError>(ErrorType::ProxyGetImmutableDataProperty); if (target_desc.value().is_accessor_descriptor() && target_desc.value().getter == nullptr && !trap_result.is_undefined()) - return interpreter().throw_exception<TypeError>("Proxy handler's get trap violates invariant: the returned value must be undefined if the property exists on the target as a non-configurable accessor property with an undefined get attribute"); + return interpreter().throw_exception<TypeError>(ErrorType::ProxyGetNonConfigurableAccessor); } return trap_result; } @@ -398,7 +398,7 @@ Value ProxyObject::get(PropertyName name) const bool ProxyObject::put(PropertyName name, Value value) { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("set"); @@ -407,7 +407,7 @@ bool ProxyObject::put(PropertyName name, Value value) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.put(name, value); if (!trap.is_function()) { - interpreter().throw_exception<TypeError>("Proxy handler's set trap wasn't undefined, null, or callable"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "set"); return false; } MarkedValueList arguments(interpreter().heap()); @@ -423,11 +423,11 @@ bool ProxyObject::put(PropertyName name, Value value) return false; if (target_desc.has_value() && !target_desc.value().attributes.is_configurable()) { if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), value, target_desc.value().value)) { - interpreter().throw_exception<TypeError>("Proxy handler's set trap violates invariant: cannot return true for a property on the target which is a non-configurable, non-writable own data property"); + interpreter().throw_exception<TypeError>(ErrorType::ProxySetImmutableDataProperty); return false; } if (target_desc.value().is_accessor_descriptor() && !target_desc.value().setter) { - interpreter().throw_exception<TypeError>("Proxy handler's set trap violates invariant: cannot return true for a property on the target which is a non-configurable own accessor property with an undefined set attribute"); + interpreter().throw_exception<TypeError>(ErrorType::ProxySetNonConfigurableAccessor); } } return true; @@ -436,7 +436,7 @@ bool ProxyObject::put(PropertyName name, Value value) Value ProxyObject::delete_property(PropertyName name) { if (m_is_revoked) { - interpreter().throw_exception<TypeError>("An operation was performed on a revoked Proxy object"); + interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("deleteProperty"); @@ -445,7 +445,7 @@ Value ProxyObject::delete_property(PropertyName name) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.delete_property(name); if (!trap.is_function()) - return interpreter().throw_exception<TypeError>("Proxy handler's delete trap wasn't undefined, null, or callable"); + return interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "deleteProperty"); MarkedValueList arguments(interpreter().heap()); arguments.values().append(Value(&m_target)); arguments.values().append(js_string(interpreter(), name.to_string())); @@ -460,7 +460,7 @@ Value ProxyObject::delete_property(PropertyName name) if (!target_desc.has_value()) return Value(true); if (!target_desc.value().attributes.is_configurable()) - return interpreter().throw_exception<TypeError>("Proxy handler's delete trap violates invariant: cannot report a non-configurable own property of the target as deleted"); + return interpreter().throw_exception<TypeError>(ErrorType::ProxyDeleteNonConfigurable); return Value(true); } diff --git a/Libraries/LibJS/Runtime/Reference.cpp b/Libraries/LibJS/Runtime/Reference.cpp index 19b832e7d8..29825de29e 100644 --- a/Libraries/LibJS/Runtime/Reference.cpp +++ b/Libraries/LibJS/Runtime/Reference.cpp @@ -51,7 +51,7 @@ void Reference::put(Interpreter& interpreter, Value value) } if (!base().is_object() && interpreter.in_strict_mode()) { - interpreter.throw_exception<TypeError>(String::format("Can't assign property %s to primitive value", m_name.to_string().characters())); + interpreter.throw_exception<TypeError>(ErrorType::ReferencePrimitiveAssignment, m_name.to_string().characters()); return; } @@ -66,11 +66,11 @@ void Reference::throw_reference_error(Interpreter& interpreter) { auto property_name = m_name.to_string(); String message; - if (property_name.is_empty()) - message = "Unresolvable reference"; - else - message = String::format("'%s' not known", property_name.characters()); - interpreter.throw_exception<ReferenceError>(message); + if (property_name.is_empty()) { + interpreter.throw_exception<ReferenceError>(ErrorType::ReferenceUnresolvable); + } else { + interpreter.throw_exception<ReferenceError>(ErrorType::UnknownIdentifier, property_name.characters()); + } } Value Reference::get(Interpreter& interpreter) diff --git a/Libraries/LibJS/Runtime/ReflectObject.cpp b/Libraries/LibJS/Runtime/ReflectObject.cpp index 917c00c436..9617209d5d 100644 --- a/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -38,7 +38,7 @@ static Object* get_target_object_from(Interpreter& interpreter, const String& na { auto target = interpreter.argument(0); if (!target.is_object()) { - interpreter.throw_exception<TypeError>(String::format("First argument of Reflect.%s() must be an object", name.characters())); + interpreter.throw_exception<TypeError>(ErrorType::ReflectArgumentMustBeAnObject, name.characters()); return nullptr; } return static_cast<Object*>(&target.as_object()); @@ -48,7 +48,7 @@ static Function* get_target_function_from(Interpreter& interpreter, const String { auto target = interpreter.argument(0); if (!target.is_function()) { - interpreter.throw_exception<TypeError>(String::format("First argument of Reflect.%s() must be a function", name.characters())); + interpreter.throw_exception<TypeError>(ErrorType::ReflectArgumentMustBeAFunction, name.characters()); return nullptr; } return &target.as_function(); @@ -57,7 +57,7 @@ static Function* get_target_function_from(Interpreter& interpreter, const String static void prepare_arguments_list(Interpreter& interpreter, Value value, MarkedValueList* arguments) { if (!value.is_object()) { - interpreter.throw_exception<TypeError>("Arguments list must be an object"); + interpreter.throw_exception<TypeError>(ErrorType::ReflectBadArgumentsList); return; } auto& arguments_list = value.as_object(); @@ -125,7 +125,7 @@ Value ReflectObject::construct(Interpreter& interpreter) auto new_target_value = interpreter.argument(2); if (!new_target_value.is_function() || (new_target_value.as_object().is_native_function() && !static_cast<NativeFunction&>(new_target_value.as_object()).has_constructor())) { - interpreter.throw_exception<TypeError>("Optional third argument of Reflect.construct() must be a constructor"); + interpreter.throw_exception<TypeError>(ErrorType::ReflectBadNewTarget); return {}; } new_target = &new_target_value.as_function(); @@ -139,7 +139,7 @@ Value ReflectObject::define_property(Interpreter& interpreter) if (!target) return {}; if (!interpreter.argument(2).is_object()) - return interpreter.throw_exception<TypeError>("Descriptor argument is not an object"); + return interpreter.throw_exception<TypeError>(ErrorType::ReflectBadDescriptorArgument); auto property_key = interpreter.argument(1).to_string(interpreter); if (interpreter.exception()) return {}; @@ -257,7 +257,7 @@ Value ReflectObject::set_prototype_of(Interpreter& interpreter) return {}; auto prototype_value = interpreter.argument(1); if (!prototype_value.is_object() && !prototype_value.is_null()) { - interpreter.throw_exception<TypeError>("Prototype must be an object or null"); + interpreter.throw_exception<TypeError>(ErrorType::ObjectPrototypeWrongType); return {}; } Object* prototype = nullptr; diff --git a/Libraries/LibJS/Runtime/ScriptFunction.cpp b/Libraries/LibJS/Runtime/ScriptFunction.cpp index 1849faf386..d54c3fa395 100644 --- a/Libraries/LibJS/Runtime/ScriptFunction.cpp +++ b/Libraries/LibJS/Runtime/ScriptFunction.cpp @@ -41,7 +41,7 @@ static ScriptFunction* script_function_from(Interpreter& interpreter) if (!this_object) return nullptr; if (!this_object->is_function()) { - interpreter.throw_exception<TypeError>("Not a function"); + interpreter.throw_exception<TypeError>(ErrorType::NotAFunctionNoParam); return nullptr; } return static_cast<ScriptFunction*>(this_object); @@ -126,7 +126,7 @@ Value ScriptFunction::call(Interpreter& interpreter) Value ScriptFunction::construct(Interpreter& interpreter) { if (m_is_arrow_function) - return interpreter.throw_exception<TypeError>(String::format("%s is not a constructor", m_name.characters())); + return interpreter.throw_exception<TypeError>(ErrorType::NotACtor, m_name.characters()); return call(interpreter); } diff --git a/Libraries/LibJS/Runtime/StringConstructor.cpp b/Libraries/LibJS/Runtime/StringConstructor.cpp index f9a5d34631..c42731b58f 100644 --- a/Libraries/LibJS/Runtime/StringConstructor.cpp +++ b/Libraries/LibJS/Runtime/StringConstructor.cpp @@ -82,7 +82,7 @@ Value StringConstructor::raw(Interpreter& interpreter) if (interpreter.exception()) return {}; if (raw.is_empty() || raw.is_undefined() || raw.is_null()) { - interpreter.throw_exception<TypeError>(String::format("Cannot convert property 'raw' to object from %s", raw.is_null() ? "null" : "undefined")); + interpreter.throw_exception<TypeError>(ErrorType::StringRawCannotConvert, raw.is_null() ? "null" : "undefined"); return {}; } if (!raw.is_array()) diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp index cf97e00c3d..c6da030d79 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -45,7 +45,7 @@ static StringObject* string_object_from(Interpreter& interpreter) if (!this_object) return nullptr; if (!this_object->is_string_object()) { - interpreter.throw_exception<TypeError>("Not a String object"); + interpreter.throw_exception<TypeError>(ErrorType::NotA, "String"); return nullptr; } return static_cast<StringObject*>(this_object); @@ -115,9 +115,9 @@ Value StringPrototype::repeat(Interpreter& interpreter) if (interpreter.exception()) return {}; if (count_value.as_double() < 0) - return interpreter.throw_exception<RangeError>("repeat count must be a positive number"); + return interpreter.throw_exception<RangeError>(ErrorType::StringRepeatCountMustBe, "positive"); if (count_value.is_infinity()) - return interpreter.throw_exception<RangeError>("repeat count must be a finite number"); + return interpreter.throw_exception<RangeError>(ErrorType::StringRepeatCountMustBe, "finite"); auto count = count_value.to_size_t(interpreter); if (interpreter.exception()) return {}; diff --git a/Libraries/LibJS/Runtime/SymbolConstructor.cpp b/Libraries/LibJS/Runtime/SymbolConstructor.cpp index 485d90a3ec..a9174f4f28 100644 --- a/Libraries/LibJS/Runtime/SymbolConstructor.cpp +++ b/Libraries/LibJS/Runtime/SymbolConstructor.cpp @@ -71,7 +71,7 @@ Value SymbolConstructor::call(Interpreter& interpreter) Value SymbolConstructor::construct(Interpreter& interpreter) { - interpreter.throw_exception<TypeError>("Symbol is not a constructor"); + interpreter.throw_exception<TypeError>(ErrorType::NotACtor, "Symbol"); return {}; } @@ -91,7 +91,7 @@ Value SymbolConstructor::key_for(Interpreter& interpreter) { auto argument = interpreter.argument(0); if (!argument.is_symbol()) { - interpreter.throw_exception<TypeError>(String::format("%s is not a symbol", argument.to_string_without_side_effects().characters())); + interpreter.throw_exception<TypeError>(ErrorType::NotASymbol, argument.to_string_without_side_effects().characters()); return {}; } diff --git a/Libraries/LibJS/Runtime/SymbolPrototype.cpp b/Libraries/LibJS/Runtime/SymbolPrototype.cpp index 641f365e77..43b959c300 100644 --- a/Libraries/LibJS/Runtime/SymbolPrototype.cpp +++ b/Libraries/LibJS/Runtime/SymbolPrototype.cpp @@ -58,7 +58,7 @@ static SymbolObject* this_symbol_from_interpreter(Interpreter& interpreter) if (!this_object) return nullptr; if (!this_object->is_symbol_object()) { - interpreter.throw_exception<TypeError>("object must be of type Symbol"); + interpreter.throw_exception<TypeError>(ErrorType::NotA, "Symbol"); return nullptr; } return static_cast<SymbolObject*>(this_object); diff --git a/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp b/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp index 5761020781..15ba4295e2 100644 --- a/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp +++ b/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp @@ -59,7 +59,7 @@ Value Uint8ClampedArray::length_getter(Interpreter& interpreter) if (!this_object) return {}; if (StringView(this_object->class_name()) != "Uint8ClampedArray") - return interpreter.throw_exception<TypeError>("Not a Uint8ClampedArray"); + return interpreter.throw_exception<TypeError>(ErrorType::NotA, "Uint8ClampedArray"); return Value(static_cast<const Uint8ClampedArray*>(this_object)->length()); } diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index 13ff1ab920..561bc7d2ca 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -154,7 +154,7 @@ String Value::to_string(Interpreter& interpreter) const case Type::String: return m_value.as_string->string(); case Type::Symbol: - interpreter.throw_exception<TypeError>("Can't convert symbol to string"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "symbol", "string"); return {}; case Type::BigInt: return m_value.as_bigint->big_integer().to_base10(); @@ -206,7 +206,7 @@ Object* Value::to_object(Interpreter& interpreter) const switch (m_type) { case Type::Undefined: case Type::Null: - interpreter.throw_exception<TypeError>("ToObject on null or undefined."); + interpreter.throw_exception<TypeError>(ErrorType::ToObjectNullOrUndef); return nullptr; case Type::Boolean: return BooleanObject::create(interpreter.global_object(), m_value.as_bool); @@ -262,10 +262,10 @@ Value Value::to_number(Interpreter& interpreter) const return Value(parsed_double); } case Type::Symbol: - interpreter.throw_exception<TypeError>("Can't convert symbol to number"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "symbol", "number"); return {}; case Type::BigInt: - interpreter.throw_exception<TypeError>("Can't convert BigInt to number"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "BigInt", "number"); return {}; case Type::Object: { auto primitive = m_value.as_object->to_primitive(PreferredType::Number); @@ -285,10 +285,10 @@ BigInt* Value::to_bigint(Interpreter& interpreter) const return nullptr; switch (primitive.type()) { case Type::Undefined: - interpreter.throw_exception<TypeError>("Can't convert undefined to BigInt"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "undefined", "BigInt"); return nullptr; case Type::Null: - interpreter.throw_exception<TypeError>("Can't convert null to BigInt"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "null", "BigInt"); return nullptr; case Type::Boolean: { auto value = primitive.as_bool() ? 1 : 0; @@ -297,18 +297,18 @@ BigInt* Value::to_bigint(Interpreter& interpreter) const case Type::BigInt: return &primitive.as_bigint(); case Type::Number: - interpreter.throw_exception<TypeError>("Can't convert number to BigInt"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "number", "BigInt"); return {}; case Type::String: { auto& string = primitive.as_string().string(); if (!is_valid_bigint_value(string)) { - interpreter.throw_exception<SyntaxError>(String::format("Invalid value for BigInt: %s", string.characters())); + interpreter.throw_exception<SyntaxError>(ErrorType::BigIntInvalidValue, string.characters()); return {}; } return js_bigint(interpreter, Crypto::SignedBigInteger::from_base10(string.trim_whitespace())); } case Type::Symbol: - interpreter.throw_exception<TypeError>("Can't convert symbol to BigInt"); + interpreter.throw_exception<TypeError>(ErrorType::Convert, "symbol", "BigInt"); return {}; default: ASSERT_NOT_REACHED(); @@ -404,7 +404,7 @@ Value bitwise_and(Interpreter& interpreter, Value lhs, Value rhs) return Value((i32)lhs_numeric.as_double() & (i32)rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use bitwise AND operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "bitwise AND"); return {}; } @@ -427,7 +427,7 @@ Value bitwise_or(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use bitwise OR operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "bitwise OR"); return {}; } @@ -443,7 +443,7 @@ Value bitwise_xor(Interpreter& interpreter, Value lhs, Value rhs) return Value((i32)lhs_numeric.as_double() ^ (i32)rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use bitwise XOR operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "bitwise XOR"); return {}; } @@ -499,7 +499,7 @@ Value left_shift(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) TODO(); - interpreter.throw_exception<TypeError>("Can't use left-shift operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "left-shift"); return {}; } @@ -520,7 +520,7 @@ Value right_shift(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) TODO(); - interpreter.throw_exception<TypeError>("Can't use right-shift operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "right-shift"); return {}; } @@ -539,7 +539,7 @@ Value unsigned_right_shift(Interpreter& interpreter, Value lhs, Value rhs) return lhs_numeric; return Value((unsigned)lhs_numeric.as_double() >> (i32)rhs_numeric.as_double()); } - interpreter.throw_exception<TypeError>("Can't use unsigned right-shift operator with BigInt"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperator, "unsigned right-shift"); return {}; } @@ -575,7 +575,7 @@ Value add(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() + rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().plus(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use addition operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "addition"); return {}; } @@ -591,7 +591,7 @@ Value sub(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() - rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use subtraction operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "subtraction"); return {}; } @@ -607,7 +607,7 @@ Value mul(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() * rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use multiplication operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "multiplication"); return {}; } @@ -623,7 +623,7 @@ Value div(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() / rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient); - interpreter.throw_exception<TypeError>("Can't use division operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "division"); return {}; } @@ -645,7 +645,7 @@ Value mod(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder); - interpreter.throw_exception<TypeError>("Can't use modulo operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "modulo"); return {}; } @@ -661,14 +661,14 @@ Value exp(Interpreter& interpreter, Value lhs, Value rhs) return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double())); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception<TypeError>("Can't use exponentiation operator with BigInt and other type"); + interpreter.throw_exception<TypeError>(ErrorType::BigIntBadOperatorOtherType, "exponentiation"); return {}; } Value in(Interpreter& interpreter, Value lhs, Value rhs) { if (!rhs.is_object()) - return interpreter.throw_exception<TypeError>("'in' operator must be used on object"); + return interpreter.throw_exception<TypeError>(ErrorType::InOperatorWithObject); auto lhs_string = lhs.to_string(interpreter); if (interpreter.exception()) return {}; diff --git a/Libraries/LibJS/Tests/BigInt.js b/Libraries/LibJS/Tests/BigInt.js index e24f34de90..6d0cdebc52 100644 --- a/Libraries/LibJS/Tests/BigInt.js +++ b/Libraries/LibJS/Tests/BigInt.js @@ -33,8 +33,8 @@ try { }, { error: TypeError, message: typeof value === "symbol" - ? "Can't convert symbol to BigInt" - : `Can't convert ${value} to BigInt` + ? "Cannot convert symbol to BigInt" + : `Cannot convert ${value} to BigInt` }); }); diff --git a/Libraries/LibJS/Tests/Boolean.prototype.toString.js b/Libraries/LibJS/Tests/Boolean.prototype.toString.js index 03a7367900..a2130b9622 100644 --- a/Libraries/LibJS/Tests/Boolean.prototype.toString.js +++ b/Libraries/LibJS/Tests/Boolean.prototype.toString.js @@ -12,7 +12,7 @@ try { Boolean.prototype.toString.call("foo"); }, { error: TypeError, - message: "Not a Boolean" + message: "Not a Boolean object" }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Boolean.prototype.valueOf.js b/Libraries/LibJS/Tests/Boolean.prototype.valueOf.js index 7c93eb2f3b..85021d3543 100644 --- a/Libraries/LibJS/Tests/Boolean.prototype.valueOf.js +++ b/Libraries/LibJS/Tests/Boolean.prototype.valueOf.js @@ -12,7 +12,7 @@ try { Boolean.prototype.valueOf.call("foo"); }, { error: TypeError, - message: "Not a Boolean" + message: "Not a Boolean object" }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Object.defineProperty.js b/Libraries/LibJS/Tests/Object.defineProperty.js index db12bb38bb..2fce7a9835 100644 --- a/Libraries/LibJS/Tests/Object.defineProperty.js +++ b/Libraries/LibJS/Tests/Object.defineProperty.js @@ -104,7 +104,7 @@ try { }); }, { error: TypeError, - message: "Accessor property descriptors cannot specify a value or writable key", + message: "Accessor property descriptor cannot specify a value or writable key", }); assertThrowsError(() => { @@ -114,7 +114,7 @@ try { }); }, { error: TypeError, - message: "Accessor property descriptors cannot specify a value or writable key", + message: "Accessor property descriptor cannot specify a value or writable key", }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Object.entries.js b/Libraries/LibJS/Tests/Object.entries.js index d99b24113e..d8786c52b6 100644 --- a/Libraries/LibJS/Tests/Object.entries.js +++ b/Libraries/LibJS/Tests/Object.entries.js @@ -13,14 +13,14 @@ try { Object.entries(null); }, { error: TypeError, - message: "ToObject on null or undefined.", + message: "ToObject on null or undefined", }); assertThrowsError(() => { Object.entries(undefined); }, { error: TypeError, - message: "ToObject on null or undefined.", + message: "ToObject on null or undefined", }); let entries = Object.entries({ foo: 1, bar: 2, baz: 3 }); diff --git a/Libraries/LibJS/Tests/Object.keys.js b/Libraries/LibJS/Tests/Object.keys.js index 3e0ccebc83..14e5597e53 100644 --- a/Libraries/LibJS/Tests/Object.keys.js +++ b/Libraries/LibJS/Tests/Object.keys.js @@ -13,14 +13,14 @@ try { Object.keys(null); }, { error: TypeError, - message: "ToObject on null or undefined.", + message: "ToObject on null or undefined", }); assertThrowsError(() => { Object.keys(undefined); }, { error: TypeError, - message: "ToObject on null or undefined.", + message: "ToObject on null or undefined", }); let keys = Object.keys({ foo: 1, bar: 2, baz: 3 }); diff --git a/Libraries/LibJS/Tests/Object.preventExtensions.js b/Libraries/LibJS/Tests/Object.preventExtensions.js index f8deb7f181..c22cc22a2e 100644 --- a/Libraries/LibJS/Tests/Object.preventExtensions.js +++ b/Libraries/LibJS/Tests/Object.preventExtensions.js @@ -27,7 +27,7 @@ try { Object.defineProperty(o, "baz", { value: "baz" }); }, { error: TypeError, - message: "Unable to define property on non-extensible object", + message: "Cannot define property baz on non-extensible object", }); assert(o.baz === undefined); diff --git a/Libraries/LibJS/Tests/Object.setPrototypeOf.js b/Libraries/LibJS/Tests/Object.setPrototypeOf.js index 78871cd455..dca2118545 100644 --- a/Libraries/LibJS/Tests/Object.setPrototypeOf.js +++ b/Libraries/LibJS/Tests/Object.setPrototypeOf.js @@ -10,12 +10,12 @@ try { message: "Object.setPrototypeOf requires at least two arguments", }); -// assertThrowsError(() => { -// Object.setPrototypeOf({}, "foo"); -// }, { -// error: TypeError, -// message: "Prototype must be null or object" -// }); + assertThrowsError(() => { + Object.setPrototypeOf({}, "foo"); + }, { + error: TypeError, + message: "Prototype must be an object or null" + }); o = {}; p = {}; @@ -26,7 +26,7 @@ try { Object.setPrototypeOf(o, {}); }, { error: TypeError, - message: "Object's setPrototypeOf method returned false" + message: "Object's [[SetPrototypeOf]] method returned false" }); assert(Object.setPrototypeOf(o, p) === o); diff --git a/Libraries/LibJS/Tests/Object.values.js b/Libraries/LibJS/Tests/Object.values.js index 35fb5a34aa..5a360eb70c 100644 --- a/Libraries/LibJS/Tests/Object.values.js +++ b/Libraries/LibJS/Tests/Object.values.js @@ -13,14 +13,14 @@ try { Object.values(null); }, { error: TypeError, - message: "ToObject on null or undefined.", + message: "ToObject on null or undefined", }); assertThrowsError(() => { Object.values(undefined); }, { error: TypeError, - message: "ToObject on null or undefined.", + message: "ToObject on null or undefined", }); let values = Object.values({ foo: 1, bar: 2, baz: 3 }); diff --git a/Libraries/LibJS/Tests/Proxy.handler-defineProperty.js b/Libraries/LibJS/Tests/Proxy.handler-defineProperty.js index 3ea9eceac6..f40accc28a 100644 --- a/Libraries/LibJS/Tests/Proxy.handler-defineProperty.js +++ b/Libraries/LibJS/Tests/Proxy.handler-defineProperty.js @@ -62,7 +62,7 @@ try { Object.defineProperty(p, "foo", {}); }, { error: TypeError, - message: "Proxy handler's defineProperty method returned false", + message: "Object's [[DefineProperty]] method returned false", }); o = {}; diff --git a/Libraries/LibJS/Tests/Proxy.handler-deleteProperty.js b/Libraries/LibJS/Tests/Proxy.handler-deleteProperty.js index 6dcba190e0..45cd4ea910 100644 --- a/Libraries/LibJS/Tests/Proxy.handler-deleteProperty.js +++ b/Libraries/LibJS/Tests/Proxy.handler-deleteProperty.js @@ -47,7 +47,7 @@ try { delete p.foo; }, { error: TypeError, - message: "Proxy handler's delete trap violates invariant: cannot report a non-configurable own property of the target as deleted", + message: "Proxy handler's deleteProperty trap violates invariant: cannot report a non-configurable own property of the target as deleted", }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Proxy.handler-has.js b/Libraries/LibJS/Tests/Proxy.handler-has.js index 849c0b6727..0881dbcb09 100644 --- a/Libraries/LibJS/Tests/Proxy.handler-has.js +++ b/Libraries/LibJS/Tests/Proxy.handler-has.js @@ -53,7 +53,7 @@ try { "bar" in p; }, { error: TypeError, - message: "Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exist on the target and the target is non-extensible", + message: "Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exists on the target and the target is non-extensible", }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Proxy.handler-preventExtensions.js b/Libraries/LibJS/Tests/Proxy.handler-preventExtensions.js index bbc1afa75a..f8e9a62c6a 100644 --- a/Libraries/LibJS/Tests/Proxy.handler-preventExtensions.js +++ b/Libraries/LibJS/Tests/Proxy.handler-preventExtensions.js @@ -30,7 +30,7 @@ try { Object.preventExtensions(p); }, { error: TypeError, - message: "Proxy preventExtensions handler returned false", + message: "Object's [[PreventExtensions]] method returned false", }); o = {}; diff --git a/Libraries/LibJS/Tests/Proxy.handler-setPrototypeOf.js b/Libraries/LibJS/Tests/Proxy.handler-setPrototypeOf.js index 8bad7fe37c..14598b750b 100644 --- a/Libraries/LibJS/Tests/Proxy.handler-setPrototypeOf.js +++ b/Libraries/LibJS/Tests/Proxy.handler-setPrototypeOf.js @@ -57,7 +57,7 @@ try { Object.setPrototypeOf(p, {}); }, { error: TypeError, - message: "Object's setPrototypeOf method returned false" + message: "Object's [[SetPrototypeOf]] method returned false", }); assert(Object.getPrototypeOf(p) === childProto); diff --git a/Libraries/LibJS/Tests/Proxy.js b/Libraries/LibJS/Tests/Proxy.js index e38165828c..8d6dd57afd 100644 --- a/Libraries/LibJS/Tests/Proxy.js +++ b/Libraries/LibJS/Tests/Proxy.js @@ -7,14 +7,14 @@ try { new Proxy(); }, { error: TypeError, - message: "Proxy requires at least two arguments", + message: "Proxy constructor requires at least two arguments", }); assertThrowsError(() => { Proxy(); }, { error: TypeError, - message: "Proxy must be called with the \"new\" operator", + message: "Proxy must be called with the 'new' operator", }); assertThrowsError(() => { diff --git a/Libraries/LibJS/Tests/Symbol.for.js b/Libraries/LibJS/Tests/Symbol.for.js index 9423f215d2..11b586ffcb 100644 --- a/Libraries/LibJS/Tests/Symbol.for.js +++ b/Libraries/LibJS/Tests/Symbol.for.js @@ -21,7 +21,7 @@ try { Symbol.for(Symbol()); }, { error: TypeError, - message: "Can't convert symbol to string", + message: "Cannot convert symbol to string", }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Symbol.js b/Libraries/LibJS/Tests/Symbol.js index 47dd9f5228..a982391921 100644 --- a/Libraries/LibJS/Tests/Symbol.js +++ b/Libraries/LibJS/Tests/Symbol.js @@ -17,7 +17,7 @@ try { Symbol(Symbol('foo')); }, { error: TypeError, - message: "Can't convert symbol to string" + message: "Cannot convert symbol to string" }) console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Symbol.prototype.toString.js b/Libraries/LibJS/Tests/Symbol.prototype.toString.js index 02abeb2ba1..d4c620d8d7 100644 --- a/Libraries/LibJS/Tests/Symbol.prototype.toString.js +++ b/Libraries/LibJS/Tests/Symbol.prototype.toString.js @@ -11,14 +11,14 @@ try { s1 + ""; }, { error: TypeError, - message: "Can't convert symbol to string", + message: "Cannot convert symbol to string", }); assertThrowsError(() => { s1 + 1; }, { error: TypeError, - message: "Can't convert symbol to number", + message: "Cannot convert symbol to number", }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/Symbol.prototype.valueOf.js b/Libraries/LibJS/Tests/Symbol.prototype.valueOf.js index 33c171c5b0..0af3600ad2 100644 --- a/Libraries/LibJS/Tests/Symbol.prototype.valueOf.js +++ b/Libraries/LibJS/Tests/Symbol.prototype.valueOf.js @@ -13,7 +13,7 @@ try { Symbol.prototype.valueOf.call("foo"); }, { error: TypeError, - message: "object must be of type Symbol" + message: "Not a Symbol object", }); console.log("PASS"); diff --git a/Libraries/LibJS/Tests/bigint-basic.js b/Libraries/LibJS/Tests/bigint-basic.js index 896ebae3c0..15ba0245cf 100644 --- a/Libraries/LibJS/Tests/bigint-basic.js +++ b/Libraries/LibJS/Tests/bigint-basic.js @@ -11,7 +11,7 @@ try { +bigint; }, { error: TypeError, - message: "Can't convert BigInt to number" + message: "Cannot convert BigInt to number" }); assert(12n + 34n === 46n); diff --git a/Libraries/LibJS/Tests/bigint-number-mix-errors.js b/Libraries/LibJS/Tests/bigint-number-mix-errors.js index 382201b54b..1fc2b40093 100644 --- a/Libraries/LibJS/Tests/bigint-number-mix-errors.js +++ b/Libraries/LibJS/Tests/bigint-number-mix-errors.js @@ -6,73 +6,73 @@ try { 1n + value; }, { error: TypeError, - message: "Can't use addition operator with BigInt and other type" + message: "Cannot use addition operator with BigInt and other type" }); assertThrowsError(() => { 1n - value; }, { error: TypeError, - message: "Can't use subtraction operator with BigInt and other type" + message: "Cannot use subtraction operator with BigInt and other type" }); assertThrowsError(() => { 1n * value; }, { error: TypeError, - message: "Can't use multiplication operator with BigInt and other type" + message: "Cannot use multiplication operator with BigInt and other type" }); assertThrowsError(() => { 1n / value; }, { error: TypeError, - message: "Can't use division operator with BigInt and other type" + message: "Cannot use division operator with BigInt and other type" }); assertThrowsError(() => { 1n % value; }, { error: TypeError, - message: "Can't use modulo operator with BigInt and other type" + message: "Cannot use modulo operator with BigInt and other type" }); assertThrowsError(() => { 1n ** value; }, { error: TypeError, - message: "Can't use exponentiation operator with BigInt and other type" + message: "Cannot use exponentiation operator with BigInt and other type" }); assertThrowsError(() => { 1n | value; }, { error: TypeError, - message: "Can't use bitwise OR operator with BigInt and other type" + message: "Cannot use bitwise OR operator with BigInt and other type" }); assertThrowsError(() => { 1n & value; }, { error: TypeError, - message: "Can't use bitwise AND operator with BigInt and other type" + message: "Cannot use bitwise AND operator with BigInt and other type" }); assertThrowsError(() => { 1n ^ value; }, { error: TypeError, - message: "Can't use bitwise XOR operator with BigInt and other type" + message: "Cannot use bitwise XOR operator with BigInt and other type" }); assertThrowsError(() => { 1n << value; }, { error: TypeError, - message: "Can't use left-shift operator with BigInt and other type" + message: "Cannot use left-shift operator with BigInt and other type" }); assertThrowsError(() => { 1n >> value; }, { error: TypeError, - message: "Can't use right-shift operator with BigInt and other type" + message: "Cannot use right-shift operator with BigInt and other type" }); assertThrowsError(() => { 1n >>> value; }, { error: TypeError, - message: "Can't use unsigned right-shift operator with BigInt" + message: "Cannot use unsigned right-shift operator with BigInt" }); }); diff --git a/Libraries/LibJS/Tests/for-head-errors.js b/Libraries/LibJS/Tests/for-head-errors.js index 20ed79c07e..195869887b 100644 --- a/Libraries/LibJS/Tests/for-head-errors.js +++ b/Libraries/LibJS/Tests/for-head-errors.js @@ -7,7 +7,7 @@ try { } }, { error: ReferenceError, - message: "'foo' not known" + message: "'foo' is not defined" }); assertThrowsError(() => { @@ -16,7 +16,7 @@ try { } }, { error: ReferenceError, - message: "'foo' not known" + message: "'foo' is not defined" }); var loopCount = 0; @@ -26,7 +26,7 @@ try { } }, { error: ReferenceError, - message: "'foo' not known" + message: "'foo' is not defined" }); assert(loopCount === 1); diff --git a/Libraries/LibJS/Tests/in-operator-basic.js b/Libraries/LibJS/Tests/in-operator-basic.js index 0cc523e756..f6c90a823a 100644 --- a/Libraries/LibJS/Tests/in-operator-basic.js +++ b/Libraries/LibJS/Tests/in-operator-basic.js @@ -6,7 +6,7 @@ try { "prop" in value; }, { error: TypeError, - message: "'in' operator must be used on object" + message: "'in' operator must be used on an object" }); }); diff --git a/Libraries/LibJS/Tests/strict-mode-errors.js b/Libraries/LibJS/Tests/strict-mode-errors.js index 7695957f0d..430596ca9c 100644 --- a/Libraries/LibJS/Tests/strict-mode-errors.js +++ b/Libraries/LibJS/Tests/strict-mode-errors.js @@ -8,7 +8,7 @@ try { primitive.foo = "bar"; }, { error: TypeError, - message: "Can't assign property foo to primitive value" + message: "Cannot assign property foo to primitive value" }); }); diff --git a/Libraries/LibJS/Tests/tagged-template-literals.js b/Libraries/LibJS/Tests/tagged-template-literals.js index 1c7498e1bd..614c7f413a 100644 --- a/Libraries/LibJS/Tests/tagged-template-literals.js +++ b/Libraries/LibJS/Tests/tagged-template-literals.js @@ -5,7 +5,7 @@ try { foo`bar${baz}`; }, { error: ReferenceError, - message: "'foo' not known" + message: "'foo' is not defined" }); assertThrowsError(() => { @@ -13,7 +13,7 @@ try { foo`bar${baz}`; }, { error: ReferenceError, - message: "'baz' not known" + message: "'baz' is not defined" }); assertThrowsError(() => { diff --git a/Libraries/LibJS/Tests/template-literals.js b/Libraries/LibJS/Tests/template-literals.js index 71734cb0d2..d3f07e86b5 100644 --- a/Libraries/LibJS/Tests/template-literals.js +++ b/Libraries/LibJS/Tests/template-literals.js @@ -36,7 +36,7 @@ try { `${b}`; }, { error: ReferenceError, - message: "'b' not known" + message: "'b' is not defined", }) console.log("PASS"); diff --git a/Libraries/LibJS/Tests/update-expressions-basic.js b/Libraries/LibJS/Tests/update-expressions-basic.js index 17e887ed46..a097d52e50 100644 --- a/Libraries/LibJS/Tests/update-expressions-basic.js +++ b/Libraries/LibJS/Tests/update-expressions-basic.js @@ -5,7 +5,7 @@ try { ++x; }, { error: ReferenceError, - message: "'x' not known" + message: "'x' is not defined", }); var n = 0; diff --git a/Libraries/LibJS/Tests/variable-declaration.js b/Libraries/LibJS/Tests/variable-declaration.js index 258b8dbd1a..6adafc7459 100644 --- a/Libraries/LibJS/Tests/variable-declaration.js +++ b/Libraries/LibJS/Tests/variable-declaration.js @@ -7,7 +7,7 @@ try { constantValue = 2; }, { error: TypeError, - message: "Assignment to constant variable" + message: "Invalid assignment to const variable" }); assert(constantValue === 1); diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp index 4312aed643..b112afc222 100644 --- a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp +++ b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp @@ -137,12 +137,12 @@ JS::Value CanvasRenderingContext2DWrapper::draw_image(JS::Interpreter& interpret if (!impl) return {}; if (interpreter.argument_count() < 3) - return interpreter.throw_exception<JS::TypeError>("drawImage() needs three arguments"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::DrawImageArgumentCount); auto* image_argument = interpreter.argument(0).to_object(interpreter); if (!image_argument) return {}; if (StringView(image_argument->class_name()) != "HTMLImageElementWrapper") - return interpreter.throw_exception<JS::TypeError>(String::format("Image is not an HTMLImageElement, it's an %s", image_argument->class_name())); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::ImageIsAn, image_argument->class_name()); auto x = interpreter.argument(1).to_double(interpreter); if (interpreter.exception()) @@ -288,10 +288,10 @@ JS::Value CanvasRenderingContext2DWrapper::fill(JS::Interpreter& interpreter) if (winding_name == "evenodd") { winding = Gfx::Painter::WindingRule::EvenOdd; } else if (winding_name != "nonzero") { - return interpreter.throw_exception<JS::TypeError>("fill winding rule must be either 'nonzero' or 'evenodd'"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::FillBadWindingRule); } } else { - return interpreter.throw_exception<JS::TypeError>("fill called with non-string"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::FillNonString); } } else { // FIXME: Path2D object @@ -378,7 +378,7 @@ JS::Value CanvasRenderingContext2DWrapper::put_image_data(JS::Interpreter& inter return {}; if (StringView(image_data_object->class_name()) != "ImageDataWrapper") { - return interpreter.throw_exception<JS::TypeError>("putImageData called with non-ImageData"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::PutImageDataBadCall); } auto& image_data = static_cast<ImageDataWrapper*>(image_data_object)->impl(); diff --git a/Libraries/LibWeb/Bindings/DocumentWrapper.cpp b/Libraries/LibWeb/Bindings/DocumentWrapper.cpp index 4fd473a5ad..06954130d6 100644 --- a/Libraries/LibWeb/Bindings/DocumentWrapper.cpp +++ b/Libraries/LibWeb/Bindings/DocumentWrapper.cpp @@ -66,7 +66,7 @@ static Document* document_from(JS::Interpreter& interpreter) if (!this_object) return {}; if (StringView("DocumentWrapper") != this_object->class_name()) { - interpreter.throw_exception<JS::TypeError>("That's not a DocumentWrapper, bro."); + interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, "DocumentWrapper"); return {}; } return &static_cast<DocumentWrapper*>(this_object)->node(); @@ -78,7 +78,7 @@ JS::Value DocumentWrapper::get_element_by_id(JS::Interpreter& interpreter) if (!document) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("getElementById() needs one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountOne, "getElementById"); auto id = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) return {}; @@ -94,7 +94,7 @@ JS::Value DocumentWrapper::query_selector(JS::Interpreter& interpreter) if (!document) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("querySelector() needs one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountOne, "querySelector"); auto selector = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) return {}; @@ -111,7 +111,7 @@ JS::Value DocumentWrapper::query_selector_all(JS::Interpreter& interpreter) if (!document) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("querySelectorAll() needs one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountOne, "querySelectorAll"); auto selector = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) return {}; diff --git a/Libraries/LibWeb/Bindings/ElementWrapper.cpp b/Libraries/LibWeb/Bindings/ElementWrapper.cpp index 8ef89e7fa7..a17c43b51b 100644 --- a/Libraries/LibWeb/Bindings/ElementWrapper.cpp +++ b/Libraries/LibWeb/Bindings/ElementWrapper.cpp @@ -79,7 +79,7 @@ JS::Value ElementWrapper::get_attribute(JS::Interpreter& interpreter) return {}; if (interpreter.argument_count() < 1) - return interpreter.throw_exception<JS::TypeError>("getAttribute() needs one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountOne, "getAttribute"); auto attribute_name = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) @@ -99,7 +99,7 @@ JS::Value ElementWrapper::set_attribute(JS::Interpreter& interpreter) return {}; if (interpreter.argument_count() < 2) - return interpreter.throw_exception<JS::TypeError>("setAttribute() needs two arguments"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountMany, "setAttribute", "two"); auto attribute_name = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) diff --git a/Libraries/LibWeb/Bindings/EventTargetWrapper.cpp b/Libraries/LibWeb/Bindings/EventTargetWrapper.cpp index b37a96d226..e53d6f89aa 100644 --- a/Libraries/LibWeb/Bindings/EventTargetWrapper.cpp +++ b/Libraries/LibWeb/Bindings/EventTargetWrapper.cpp @@ -55,7 +55,7 @@ JS::Value EventTargetWrapper::add_event_listener(JS::Interpreter& interpreter) if (!this_object) return {}; if (interpreter.argument_count() < 2) - return interpreter.throw_exception<JS::TypeError>("addEventListener() needs two arguments"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountMany, "addEventListener", "two"); auto event_name = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) return {}; diff --git a/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp b/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp index 6378e7318f..8c52fcae39 100644 --- a/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp +++ b/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp @@ -61,7 +61,7 @@ static ImageData* impl_from(JS::Interpreter& interpreter) return nullptr; } if (StringView("ImageDataWrapper") != this_object->class_name()) { - interpreter.throw_exception<JS::TypeError>("That's not an ImageDataWrapper, bro."); + interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotAn, "ImageDataWrapper"); return nullptr; } return &static_cast<ImageDataWrapper*>(this_object)->impl(); diff --git a/Libraries/LibWeb/Bindings/WindowObject.cpp b/Libraries/LibWeb/Bindings/WindowObject.cpp index 0234e5e97a..244e631306 100644 --- a/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -88,7 +88,7 @@ static Window* impl_from(JS::Interpreter& interpreter) return nullptr; } if (StringView("WindowObject") != this_object->class_name()) { - interpreter.throw_exception<JS::TypeError>("That's not a WindowObject, bro."); + interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, "WindowObject"); return nullptr; } return &static_cast<WindowObject*>(this_object)->impl(); @@ -129,12 +129,12 @@ JS::Value WindowObject::set_interval(JS::Interpreter& interpreter) if (!impl) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("setInterval() needs at least one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "setInterval"); auto* callback_object = interpreter.argument(0).to_object(interpreter); if (!callback_object) return {}; if (!callback_object->is_function()) - return interpreter.throw_exception<JS::TypeError>("Not a function"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); i32 interval = 0; if (interpreter.argument_count() >= 2) { @@ -155,12 +155,12 @@ JS::Value WindowObject::set_timeout(JS::Interpreter& interpreter) if (!impl) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("setTimeout() needs at least one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "setTimeout"); auto* callback_object = interpreter.argument(0).to_object(interpreter); if (!callback_object) return {}; if (!callback_object->is_function()) - return interpreter.throw_exception<JS::TypeError>("Not a function"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); i32 interval = 0; if (interpreter.argument_count() >= 2) { @@ -181,12 +181,12 @@ JS::Value WindowObject::request_animation_frame(JS::Interpreter& interpreter) if (!impl) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("requestAnimationFrame() needs one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); auto* callback_object = interpreter.argument(0).to_object(interpreter); if (!callback_object) return {}; if (!callback_object->is_function()) - return interpreter.throw_exception<JS::TypeError>("Not a function"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); return JS::Value(impl->request_animation_frame(*static_cast<JS::Function*>(callback_object))); } @@ -196,7 +196,7 @@ JS::Value WindowObject::cancel_animation_frame(JS::Interpreter& interpreter) if (!impl) return {}; if (!interpreter.argument_count()) - return interpreter.throw_exception<JS::TypeError>("cancelAnimationFrame() needs one argument"); + return interpreter.throw_exception<JS::TypeError>(JS::ErrorType::BadArgCountOne, "cancelAnimationFrame"); auto id = interpreter.argument(0).to_i32(interpreter); if (interpreter.exception()) return {}; diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp index f668f5b114..e03baa8304 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp @@ -60,7 +60,7 @@ static XMLHttpRequest* impl_from(JS::Interpreter& interpreter) if (!this_object) return nullptr; if (StringView("XMLHttpRequestWrapper") != this_object->class_name()) { - interpreter.throw_exception<JS::TypeError>("This is not an XMLHttpRequest object"); + interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, "XMLHttpRequest"); return nullptr; } return &static_cast<XMLHttpRequestWrapper*>(this_object)->impl(); |