mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-25 19:56:30 +00:00
LibJS: Make Value() default-construct the undefined value
The special empty value (that we use for array holes, Optional<Value> when empty and a few other other placeholder/sentinel tasks) still exists, but you now create one via JS::js_special_empty_value() and check for it with Value::is_special_empty_value(). The main idea here is to make it very unlikely to accidentally create an unexpected special empty value.
This commit is contained in:
parent
0d91363742
commit
3cf50539ec
Notes:
github-actions[bot]
2025-04-05 09:21:31 +00:00
Author: https://github.com/awesomekling
Commit: 3cf50539ec
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4232
43 changed files with 165 additions and 122 deletions
|
@ -95,7 +95,7 @@ public:
|
|||
|
||||
[[nodiscard]] u16 tag() const { return m_value.tag; }
|
||||
|
||||
bool is_empty() const { return m_value.tag == EMPTY_TAG; }
|
||||
bool is_special_empty_value() const { return m_value.tag == EMPTY_TAG; }
|
||||
bool is_undefined() const { return m_value.tag == UNDEFINED_TAG; }
|
||||
bool is_null() const { return m_value.tag == NULL_TAG; }
|
||||
bool is_number() const { return is_double() || is_int32(); }
|
||||
|
@ -155,7 +155,7 @@ public:
|
|||
}
|
||||
|
||||
Value()
|
||||
: Value(EMPTY_TAG << GC::TAG_SHIFT, (u64)0)
|
||||
: Value(UNDEFINED_TAG << GC::TAG_SHIFT, (u64)0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -379,12 +379,14 @@ public:
|
|||
|
||||
[[nodiscard]] String to_string_without_side_effects() const;
|
||||
|
||||
#if 0
|
||||
Value value_or(Value fallback) const
|
||||
{
|
||||
if (is_empty())
|
||||
if (is_special_empty_value())
|
||||
return fallback;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
[[nodiscard]] GC::Ref<PrimitiveString> typeof_(VM&) const;
|
||||
|
||||
|
@ -424,6 +426,13 @@ private:
|
|||
ThrowCompletionOr<Value> to_numeric_slow_case(VM&) const;
|
||||
ThrowCompletionOr<Value> to_primitive_slow_case(VM&, PreferredType) const;
|
||||
|
||||
enum class EmptyTag { Empty };
|
||||
|
||||
Value(EmptyTag)
|
||||
: Value(EMPTY_TAG << GC::TAG_SHIFT, (u64)0)
|
||||
{
|
||||
}
|
||||
|
||||
Value(u64 tag, u64 val)
|
||||
{
|
||||
ASSERT(!(tag & val));
|
||||
|
@ -460,6 +469,7 @@ private:
|
|||
|
||||
friend Value js_undefined();
|
||||
friend Value js_null();
|
||||
friend Value js_special_empty_value();
|
||||
friend ThrowCompletionOr<Value> greater_than(VM&, Value lhs, Value rhs);
|
||||
friend ThrowCompletionOr<Value> greater_than_equals(VM&, Value lhs, Value rhs);
|
||||
friend ThrowCompletionOr<Value> less_than(VM&, Value lhs, Value rhs);
|
||||
|
@ -478,6 +488,11 @@ inline Value js_null()
|
|||
return Value(NULL_TAG << GC::TAG_SHIFT, (u64)0);
|
||||
}
|
||||
|
||||
inline Value js_special_empty_value()
|
||||
{
|
||||
return Value(Value::EmptyTag::Empty);
|
||||
}
|
||||
|
||||
inline Value js_nan()
|
||||
{
|
||||
return Value(NAN);
|
||||
|
@ -600,12 +615,12 @@ public:
|
|||
|
||||
void clear()
|
||||
{
|
||||
m_value = {};
|
||||
m_value = JS::js_special_empty_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool has_value() const
|
||||
{
|
||||
return !m_value.is_empty();
|
||||
return !m_value.is_special_empty_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] JS::Value& value() &
|
||||
|
@ -634,7 +649,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
JS::Value m_value;
|
||||
JS::Value m_value { JS::js_special_empty_value() };
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -690,7 +705,7 @@ template<>
|
|||
struct Formatter<JS::Value> : Formatter<StringView> {
|
||||
ErrorOr<void> format(FormatBuilder& builder, JS::Value value)
|
||||
{
|
||||
if (value.is_empty())
|
||||
if (value.is_special_empty_value())
|
||||
return Formatter<StringView>::format(builder, "<empty>"sv);
|
||||
return Formatter<StringView>::format(builder, value.to_string_without_side_effects());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue