From cd12b2aa577bd977ec19214e7099c02dadd5d765 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 6 Jun 2021 16:10:23 +0100 Subject: [PATCH] LibJS: Implement the RequireObjectCoercible abstract operation Throws an exception if the given value is nullish, returns it otherwise. We can now gradually replace such manual checks with this function where applicable. This also has the advantage that the somewhat useless "ToObject on null or undefined" will be replaced with "null cannot be converted to an object" or "undefined cannot be converted to an object". :^) --- Userland/Libraries/LibJS/Runtime/ErrorTypes.h | 3 ++- Userland/Libraries/LibJS/Runtime/Value.cpp | 12 ++++++++++++ Userland/Libraries/LibJS/Runtime/Value.h | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index c23e43a6123..db659226262 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -44,6 +44,7 @@ M(JsonCircular, "Cannot stringify circular object") \ M(JsonMalformed, "Malformed JSON string") \ M(NegativeExponent, "Exponent must be positive") \ + M(NonExtensibleDefine, "Cannot define property {} on non-extensible object") \ M(NotA, "Not a {} object") \ M(NotAConstructor, "{} is not a constructor") \ M(NotAFunction, "{} is not a function") \ @@ -52,7 +53,7 @@ M(NotAnObject, "{} is not an object") \ M(NotASymbol, "{} is not a symbol") \ M(NotIterable, "{} is not iterable") \ - M(NonExtensibleDefine, "Cannot define property {} on non-extensible object") \ + M(NotObjectCoercible, "{} cannot be converted to an object") \ M(NumberIncompatibleThis, "Number.prototype.{}() called with incompatible this target") \ M(ObjectDefinePropertyReturnedFalse, "Object's [[DefineProperty]] method returned false") \ M(ObjectFreezeFailed, "Could not freeze object") \ diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 1801f752459..69e8c3272cf 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -1390,4 +1390,16 @@ Object* species_constructor(GlobalObject& global_object, const Object& object, O vm.throw_exception(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects()); return nullptr; } + +// 7.2.1 RequireObjectCoercible, https://tc39.es/ecma262/#sec-requireobjectcoercible +Value require_object_coercible(GlobalObject& global_object, Value value) +{ + auto& vm = global_object.vm(); + if (value.is_nullish()) { + vm.throw_exception(global_object, ErrorType::NotObjectCoercible, value.to_string_without_side_effects()); + return {}; + } + return value; +} + } diff --git a/Userland/Libraries/LibJS/Runtime/Value.h b/Userland/Libraries/LibJS/Runtime/Value.h index 37cbf2cfccb..40122ee9a66 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.h +++ b/Userland/Libraries/LibJS/Runtime/Value.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021, Andreas Kling + * Copyright (c) 2020-2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -366,6 +367,7 @@ TriState abstract_relation(GlobalObject&, bool left_first, Value lhs, Value rhs) Function* get_method(GlobalObject& global_object, Value, const PropertyName&); size_t length_of_array_like(GlobalObject&, const Object&); Object* species_constructor(GlobalObject&, const Object&, Object& default_constructor); +Value require_object_coercible(GlobalObject&, Value); }