mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
AK+Everywhere: Do not implicitly copy variables in TRY macros
For example, consider cases where we want to propagate errors only in specific instances: auto result = read_data(); // something like ErrorOr<ByteBuffer> if (result.is_error() && result.error().code() != EINTR) continue; auto bytes = TRY(result); The TRY invocation will currently copy the byte buffer when the expression (in this case, just a local variable) is stored into _temporary_result. This patch binds the expression to a reference to prevent such copies. In less trival invocations (such as TRY(some_function()), this will incur only temporary lifetime extensions, i.e. no functional change.
This commit is contained in:
parent
4a916cd379
commit
604d5f5bca
Notes:
sideshowbarker
2024-07-18 05:01:22 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/604d5f5bca Pull-request: https://github.com/SerenityOS/serenity/pull/17399 Reviewed-by: https://github.com/linusg
11 changed files with 15 additions and 15 deletions
4
AK/Try.h
4
AK/Try.h
|
@ -25,7 +25,7 @@
|
|||
({ \
|
||||
/* Ignore -Wshadow to allow nesting the macro. */ \
|
||||
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
|
||||
auto _temporary_result = (expression)); \
|
||||
auto&& _temporary_result = (expression)); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
|
@ -37,7 +37,7 @@
|
|||
({ \
|
||||
/* Ignore -Wshadow to allow nesting the macro. */ \
|
||||
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
|
||||
auto _temporary_result = (expression)); \
|
||||
auto&& _temporary_result = (expression)); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
VERIFY(!_temporary_result.is_error()); \
|
||||
|
|
|
@ -188,7 +188,7 @@ private:
|
|||
// This is a special variant of TRY() that also updates the socket's SO_ERROR field on error.
|
||||
#define SOCKET_TRY(expression) \
|
||||
({ \
|
||||
auto result = (expression); \
|
||||
auto&& result = (expression); \
|
||||
if (result.is_error()) \
|
||||
return set_so_error(result.release_error()); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(result.release_value())>, \
|
||||
|
|
|
@ -233,7 +233,7 @@ struct CLDR {
|
|||
// with locales such as "en-GB-oed" that are canonically invalid locale IDs.
|
||||
#define TRY_OR_DISCARD(expression) \
|
||||
({ \
|
||||
auto _temporary_result = (expression); \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) \
|
||||
return; \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
|
|
|
@ -68,7 +68,7 @@ struct LoaderError {
|
|||
// Convenience TRY-like macro to convert an Error to a LoaderError
|
||||
#define LOADER_TRY(expression) \
|
||||
({ \
|
||||
auto _temporary_result = (expression); \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) \
|
||||
return LoaderError(_temporary_result.release_error()); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace JS {
|
|||
({ \
|
||||
/* Ignore -Wshadow to allow nesting the macro. */ \
|
||||
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
|
||||
auto _temporary_result = (expression)); \
|
||||
auto&& _temporary_result = (expression)); \
|
||||
if (_temporary_result.is_error()) { \
|
||||
VERIFY(_temporary_result.error().code() == ENOMEM); \
|
||||
return vm.throw_completion<JS::InternalError>(JS::ErrorType::OutOfMemory); \
|
||||
|
@ -35,7 +35,7 @@ namespace JS {
|
|||
({ \
|
||||
/* Ignore -Wshadow to allow nesting the macro. */ \
|
||||
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
|
||||
auto _temporary_result = (expression)); \
|
||||
auto&& _temporary_result = (expression)); \
|
||||
if (_temporary_result.is_error()) { \
|
||||
auto _completion = _temporary_result.release_error(); \
|
||||
\
|
||||
|
|
|
@ -43,7 +43,7 @@ private:
|
|||
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
|
||||
#define __TRY_OR_REJECT(vm, capability, expression, CALL_CHECK) \
|
||||
({ \
|
||||
auto _temporary_try_or_reject_result = (expression); \
|
||||
auto&& _temporary_try_or_reject_result = (expression); \
|
||||
/* 1. If value is an abrupt completion, then */ \
|
||||
if (_temporary_try_or_reject_result.is_error()) { \
|
||||
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
|
||||
|
@ -69,7 +69,7 @@ private:
|
|||
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
|
||||
#define TRY_OR_REJECT_WITH_VALUE(vm, capability, expression) \
|
||||
({ \
|
||||
auto _temporary_try_or_reject_result = (expression); \
|
||||
auto&& _temporary_try_or_reject_result = (expression); \
|
||||
/* 1. If value is an abrupt completion, then */ \
|
||||
if (_temporary_try_or_reject_result.is_error()) { \
|
||||
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
|
||||
|
|
|
@ -79,7 +79,7 @@ private:
|
|||
|
||||
#define DECODER_TRY(category, expression) \
|
||||
({ \
|
||||
auto _result = ((expression)); \
|
||||
auto&& _result = ((expression)); \
|
||||
if (_result.is_error()) [[unlikely]] { \
|
||||
auto _error_string = _result.release_error().string_literal(); \
|
||||
return DecoderError::from_source_location( \
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Video {
|
|||
|
||||
#define TRY_OR_FATAL_ERROR(expression) \
|
||||
({ \
|
||||
auto _fatal_expression = (expression); \
|
||||
auto&& _fatal_expression = (expression); \
|
||||
if (_fatal_expression.is_error()) { \
|
||||
dispatch_fatal_error(_fatal_expression.release_error()); \
|
||||
return; \
|
||||
|
@ -156,7 +156,7 @@ bool PlaybackManager::decode_and_queue_one_sample()
|
|||
|
||||
#define TRY_OR_ENQUEUE_ERROR(expression) \
|
||||
({ \
|
||||
auto _temporary_result = ((expression)); \
|
||||
auto&& _temporary_result = ((expression)); \
|
||||
if (_temporary_result.is_error()) { \
|
||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Enqueued decoder error: {}", _temporary_result.error().string_literal()); \
|
||||
m_frame_queue->enqueue(FrameQueueItem::error_marker(_temporary_result.release_error())); \
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Web::Fetch::Fetching {
|
|||
|
||||
#define TRY_OR_IGNORE(expression) \
|
||||
({ \
|
||||
auto _temporary_result = (expression); \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) \
|
||||
return; \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Web::WebDriver {
|
|||
|
||||
#define TRY_OR_JS_ERROR(expression) \
|
||||
({ \
|
||||
auto _temporary_result = (expression); \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
return ExecuteScriptResultType::JavaScriptError; \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#define TRY_PARSE(expression) \
|
||||
({ \
|
||||
auto _temporary_result = ((expression)); \
|
||||
auto&& _temporary_result = ((expression)); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] { \
|
||||
outln("Encountered a parsing error: {}", _temporary_result.error().string_literal()); \
|
||||
return Error::from_string_literal("Failed to parse :("); \
|
||||
|
|
Loading…
Reference in a new issue