mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 18:27:35 +00:00
LibJS: Stop propagating small OOM errors from the Error object
This commit is contained in:
parent
df915f8a98
commit
54d1f4e234
17 changed files with 68 additions and 77 deletions
|
@ -347,17 +347,17 @@ ThrowCompletionOr<void> NewRegExp::execute_impl(Bytecode::Interpreter& interpret
|
|||
return {};
|
||||
}
|
||||
|
||||
#define JS_DEFINE_NEW_BUILTIN_ERROR_OP(ErrorName) \
|
||||
ThrowCompletionOr<void> New##ErrorName::execute_impl(Bytecode::Interpreter& interpreter) const \
|
||||
{ \
|
||||
auto& vm = interpreter.vm(); \
|
||||
auto& realm = *vm.current_realm(); \
|
||||
interpreter.accumulator() = MUST_OR_THROW_OOM(ErrorName::create(realm, interpreter.current_executable().get_string(m_error_string))); \
|
||||
return {}; \
|
||||
} \
|
||||
DeprecatedString New##ErrorName::to_deprecated_string_impl(Bytecode::Executable const& executable) const \
|
||||
{ \
|
||||
return DeprecatedString::formatted("New" #ErrorName " {} (\"{}\")", m_error_string, executable.string_table->get(m_error_string)); \
|
||||
#define JS_DEFINE_NEW_BUILTIN_ERROR_OP(ErrorName) \
|
||||
ThrowCompletionOr<void> New##ErrorName::execute_impl(Bytecode::Interpreter& interpreter) const \
|
||||
{ \
|
||||
auto& vm = interpreter.vm(); \
|
||||
auto& realm = *vm.current_realm(); \
|
||||
interpreter.accumulator() = ErrorName::create(realm, interpreter.current_executable().get_string(m_error_string)); \
|
||||
return {}; \
|
||||
} \
|
||||
DeprecatedString New##ErrorName::to_deprecated_string_impl(Bytecode::Executable const& executable) const \
|
||||
{ \
|
||||
return DeprecatedString::formatted("New" #ErrorName " {} (\"{}\")", m_error_string, executable.string_table->get(m_error_string)); \
|
||||
}
|
||||
|
||||
JS_ENUMERATE_NEW_BUILTIN_ERROR_OPS(JS_DEFINE_NEW_BUILTIN_ERROR_OP)
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Runtime/Completion.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/ExecutionContext.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/ThrowableStringBuilder.h>
|
||||
#include <LibJS/SourceRange.h>
|
||||
|
||||
namespace JS {
|
||||
|
@ -44,9 +44,9 @@ NonnullGCPtr<Error> Error::create(Realm& realm, String message)
|
|||
return error;
|
||||
}
|
||||
|
||||
ThrowCompletionOr<NonnullGCPtr<Error>> Error::create(Realm& realm, StringView message)
|
||||
NonnullGCPtr<Error> Error::create(Realm& realm, StringView message)
|
||||
{
|
||||
return create(realm, TRY_OR_THROW_OOM(realm.vm(), String::from_utf8(message)));
|
||||
return create(realm, MUST(String::from_utf8(message)));
|
||||
}
|
||||
|
||||
Error::Error(Object& prototype)
|
||||
|
@ -95,9 +95,9 @@ void Error::populate_stack()
|
|||
}
|
||||
}
|
||||
|
||||
ThrowCompletionOr<String> Error::stack_string(VM& vm) const
|
||||
String Error::stack_string() const
|
||||
{
|
||||
ThrowableStringBuilder stack_string_builder(vm);
|
||||
StringBuilder stack_string_builder;
|
||||
|
||||
// Note: We roughly follow V8's formatting
|
||||
// Note: The error's name and message get prepended by ErrorPrototype::stack
|
||||
|
@ -111,15 +111,15 @@ ThrowCompletionOr<String> Error::stack_string(VM& vm) const
|
|||
if (!source_range.filename().is_empty() || source_range.start.offset != 0 || source_range.end.offset != 0) {
|
||||
|
||||
if (function_name == "<unknown>"sv)
|
||||
MUST_OR_THROW_OOM(stack_string_builder.appendff(" at {}:{}:{}\n", source_range.filename(), source_range.start.line, source_range.start.column));
|
||||
stack_string_builder.appendff(" at {}:{}:{}\n", source_range.filename(), source_range.start.line, source_range.start.column);
|
||||
else
|
||||
MUST_OR_THROW_OOM(stack_string_builder.appendff(" at {} ({}:{}:{})\n", function_name, source_range.filename(), source_range.start.line, source_range.start.column));
|
||||
stack_string_builder.appendff(" at {} ({}:{}:{})\n", function_name, source_range.filename(), source_range.start.line, source_range.start.column);
|
||||
} else {
|
||||
MUST_OR_THROW_OOM(stack_string_builder.appendff(" at {}\n", function_name.is_empty() ? "<unknown>"sv : function_name.view()));
|
||||
stack_string_builder.appendff(" at {}\n", function_name.is_empty() ? "<unknown>"sv : function_name.view());
|
||||
}
|
||||
}
|
||||
|
||||
return stack_string_builder.to_string();
|
||||
return MUST(stack_string_builder.to_string());
|
||||
}
|
||||
|
||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||
|
@ -137,9 +137,9 @@ ThrowCompletionOr<String> Error::stack_string(VM& vm) const
|
|||
return error; \
|
||||
} \
|
||||
\
|
||||
ThrowCompletionOr<NonnullGCPtr<ClassName>> ClassName::create(Realm& realm, StringView message) \
|
||||
NonnullGCPtr<ClassName> ClassName::create(Realm& realm, StringView message) \
|
||||
{ \
|
||||
return create(realm, TRY_OR_THROW_OOM(realm.vm(), String::from_utf8(message))); \
|
||||
return create(realm, MUST(String::from_utf8(message))); \
|
||||
} \
|
||||
\
|
||||
ClassName::ClassName(Object& prototype) \
|
||||
|
|
|
@ -28,11 +28,11 @@ class Error : public Object {
|
|||
public:
|
||||
static NonnullGCPtr<Error> create(Realm&);
|
||||
static NonnullGCPtr<Error> create(Realm&, String message);
|
||||
static ThrowCompletionOr<NonnullGCPtr<Error>> create(Realm&, StringView message);
|
||||
static NonnullGCPtr<Error> create(Realm&, StringView message);
|
||||
|
||||
virtual ~Error() override = default;
|
||||
|
||||
[[nodiscard]] ThrowCompletionOr<String> stack_string(VM&) const;
|
||||
[[nodiscard]] String stack_string() const;
|
||||
|
||||
ThrowCompletionOr<void> install_error_cause(Value options);
|
||||
|
||||
|
@ -49,17 +49,17 @@ private:
|
|||
// NOTE: Making these inherit from Error is not required by the spec but
|
||||
// our way of implementing the [[ErrorData]] internal slot, which is
|
||||
// used in Object.prototype.toString().
|
||||
#define DECLARE_NATIVE_ERROR(ClassName, snake_name, PrototypeName, ConstructorName) \
|
||||
class ClassName final : public Error { \
|
||||
JS_OBJECT(ClassName, Error); \
|
||||
\
|
||||
public: \
|
||||
static NonnullGCPtr<ClassName> create(Realm&); \
|
||||
static NonnullGCPtr<ClassName> create(Realm&, String message); \
|
||||
static ThrowCompletionOr<NonnullGCPtr<ClassName>> create(Realm&, StringView message); \
|
||||
\
|
||||
explicit ClassName(Object& prototype); \
|
||||
virtual ~ClassName() override = default; \
|
||||
#define DECLARE_NATIVE_ERROR(ClassName, snake_name, PrototypeName, ConstructorName) \
|
||||
class ClassName final : public Error { \
|
||||
JS_OBJECT(ClassName, Error); \
|
||||
\
|
||||
public: \
|
||||
static NonnullGCPtr<ClassName> create(Realm&); \
|
||||
static NonnullGCPtr<ClassName> create(Realm&, String message); \
|
||||
static NonnullGCPtr<ClassName> create(Realm&, StringView message); \
|
||||
\
|
||||
explicit ClassName(Object& prototype); \
|
||||
virtual ~ClassName() override = default; \
|
||||
};
|
||||
|
||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||
|
|
|
@ -65,7 +65,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
|
|||
return PrimitiveString::create(vm, move(name));
|
||||
|
||||
// 9. Return the string-concatenation of name, the code unit 0x003A (COLON), the code unit 0x0020 (SPACE), and msg.
|
||||
return PrimitiveString::create(vm, TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", name, message)));
|
||||
return PrimitiveString::create(vm, MUST(String::formatted("{}: {}", name, message)));
|
||||
}
|
||||
|
||||
// B.1.1 get Error.prototype.stack ( ), https://tc39.es/proposal-error-stacks/#sec-get-error.prototype-stack
|
||||
|
@ -96,9 +96,9 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::stack_getter)
|
|||
|
||||
auto header = message.is_empty()
|
||||
? move(name)
|
||||
: TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", name, message));
|
||||
: MUST(String::formatted("{}: {}", name, message));
|
||||
|
||||
return PrimitiveString::create(vm, TRY_OR_THROW_OOM(vm, String::formatted("{}\n{}", header, MUST_OR_THROW_OOM(error.stack_string(vm)))));
|
||||
return PrimitiveString::create(vm, MUST(String::formatted("{}\n{}", header, error.stack_string())));
|
||||
}
|
||||
|
||||
// B.1.2 set Error.prototype.stack ( value ), https://tc39.es/proposal-error-stacks/#sec-set-error.prototype-stack
|
||||
|
|
|
@ -71,7 +71,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
|
|||
// 6. Set resolve.[[AlreadyResolved]] to alreadyResolved.
|
||||
|
||||
// 27.2.1.3.2 Promise Resolve Functions, https://tc39.es/ecma262/#sec-promise-resolve-functions
|
||||
auto resolve_function = PromiseResolvingFunction::create(realm, *this, *already_resolved, [](auto& vm, auto& promise, auto& already_resolved) -> ThrowCompletionOr<Value> {
|
||||
auto resolve_function = PromiseResolvingFunction::create(realm, *this, *already_resolved, [](auto& vm, auto& promise, auto& already_resolved) {
|
||||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Resolve function was called", &promise);
|
||||
|
||||
auto& realm = *vm.current_realm();
|
||||
|
@ -97,7 +97,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
|
|||
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Promise can't be resolved with itself, rejecting with error", &promise);
|
||||
|
||||
// a. Let selfResolutionError be a newly created TypeError object.
|
||||
auto self_resolution_error = MUST_OR_THROW_OOM(TypeError::create(realm, "Cannot resolve promise with itself"sv));
|
||||
auto self_resolution_error = TypeError::create(realm, "Cannot resolve promise with itself"sv);
|
||||
|
||||
// b. Perform RejectPromise(promise, selfResolutionError).
|
||||
promise.reject(self_resolution_error);
|
||||
|
|
|
@ -26,7 +26,7 @@ class PromiseResolvingFunction final : public NativeFunction {
|
|||
JS_OBJECT(PromiseResolvingFunction, NativeFunction);
|
||||
|
||||
public:
|
||||
using FunctionType = Function<ThrowCompletionOr<Value>(VM&, Promise&, AlreadyResolved&)>;
|
||||
using FunctionType = Function<Value(VM&, Promise&, AlreadyResolved&)>;
|
||||
|
||||
static NonnullGCPtr<PromiseResolvingFunction> create(Realm&, Promise&, AlreadyResolved&, FunctionType);
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ VM::VM(OwnPtr<CustomData> custom_data, ErrorMessages error_messages)
|
|||
// If you are here because you want to enable dynamic module importing make sure it won't be a security problem
|
||||
// by checking the default implementation of HostImportModuleDynamically and creating your own hook or calling
|
||||
// vm.enable_default_host_import_module_dynamically_hook().
|
||||
promise->reject(MUST_OR_THROW_OOM(Error::create(realm, ErrorType::DynamicImportNotAllowed.message())));
|
||||
promise->reject(Error::create(realm, ErrorType::DynamicImportNotAllowed.message()));
|
||||
|
||||
promise->perform_then(
|
||||
NativeFunction::create(realm, "", [](auto&) -> ThrowCompletionOr<Value> {
|
||||
|
|
|
@ -178,10 +178,7 @@ public:
|
|||
auto& realm = *current_realm();
|
||||
auto completion = T::create(realm, forward<Args>(args)...);
|
||||
|
||||
if constexpr (IsSame<decltype(completion), ThrowCompletionOr<NonnullGCPtr<T>>>)
|
||||
return JS::throw_completion(MUST_OR_THROW_OOM(completion));
|
||||
else
|
||||
return JS::throw_completion(completion);
|
||||
return JS::throw_completion(completion);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue