diff options
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Map.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/PrimitiveString.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/PrimitiveString.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Reference.cpp | 15 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Value.h | 22 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ValueTraits.h | 35 |
7 files changed, 77 insertions, 24 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 3472e5b28a..666ce7e2f9 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -18,6 +18,7 @@ #include <LibJS/Runtime/Environment.h> #include <LibJS/Runtime/EnvironmentCoordinate.h> #include <LibJS/Runtime/Value.h> +#include <LibJS/Runtime/ValueTraits.h> namespace JS::Bytecode::Op { diff --git a/Userland/Libraries/LibJS/Runtime/Map.h b/Userland/Libraries/LibJS/Runtime/Map.h index 476aa7bee7..3cce53cfab 100644 --- a/Userland/Libraries/LibJS/Runtime/Map.h +++ b/Userland/Libraries/LibJS/Runtime/Map.h @@ -12,6 +12,7 @@ #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/Value.h> +#include <LibJS/Runtime/ValueTraits.h> namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/PrimitiveString.cpp b/Userland/Libraries/LibJS/Runtime/PrimitiveString.cpp index 063c518f4a..b2d328677c 100644 --- a/Userland/Libraries/LibJS/Runtime/PrimitiveString.cpp +++ b/Userland/Libraries/LibJS/Runtime/PrimitiveString.cpp @@ -4,9 +4,13 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include "LibJS/Runtime/Value.h" #include <AK/CharacterTypes.h> #include <AK/Utf16View.h> +#include <LibJS/Runtime/AbstractOperations.h> +#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/PrimitiveString.h> +#include <LibJS/Runtime/PropertyKey.h> #include <LibJS/Runtime/VM.h> namespace JS { @@ -51,6 +55,26 @@ Utf16View PrimitiveString::utf16_string_view() const return utf16_string().view(); } +Optional<Value> PrimitiveString::get(GlobalObject& global_object, PropertyKey const& property_key) const +{ + if (property_key.is_symbol()) + return {}; + if (property_key.is_string()) { + if (property_key.as_string() == global_object.vm().names.length.as_string()) { + auto length = utf16_string().length_in_code_units(); + return Value(static_cast<double>(length)); + } + } + auto index = canonical_numeric_index_string(property_key); + if (!index.has_value()) + return {}; + auto str = utf16_string_view(); + auto length = str.length_in_code_units(); + if (length <= *index) + return {}; + return js_string(vm(), str.substring_view(*index, 1)); +} + PrimitiveString* js_string(Heap& heap, Utf16View const& view) { return js_string(heap, Utf16String(view)); diff --git a/Userland/Libraries/LibJS/Runtime/PrimitiveString.h b/Userland/Libraries/LibJS/Runtime/PrimitiveString.h index dd15cb4d49..e293c259be 100644 --- a/Userland/Libraries/LibJS/Runtime/PrimitiveString.h +++ b/Userland/Libraries/LibJS/Runtime/PrimitiveString.h @@ -7,7 +7,9 @@ #pragma once #include <AK/String.h> +#include <LibJS/Forward.h> #include <LibJS/Heap/Cell.h> +#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Utf16String.h> namespace JS { @@ -28,6 +30,7 @@ public: Utf16View utf16_string_view() const; bool has_utf16_string() const { return m_has_utf16_string; } + Optional<Value> get(GlobalObject&, PropertyKey const&) const; private: virtual const char* class_name() const override { return "PrimitiveString"; } diff --git a/Userland/Libraries/LibJS/Runtime/Reference.cpp b/Userland/Libraries/LibJS/Runtime/Reference.cpp index 8986511909..f9a25872ca 100644 --- a/Userland/Libraries/LibJS/Runtime/Reference.cpp +++ b/Userland/Libraries/LibJS/Runtime/Reference.cpp @@ -63,15 +63,26 @@ ThrowCompletionOr<Value> Reference::get_value(GlobalObject& global_object) const return throw_reference_error(global_object); if (is_property_reference()) { - auto* base_obj = TRY(m_base_value.to_object(global_object)); - if (is_private_reference()) { // FIXME: We need to be able to specify the receiver for this // if we want to use it in error messages in future // as things currently stand this does the "wrong thing" but // the error is unobservable + auto base_obj = TRY(m_base_value.to_object(global_object)); return base_obj->private_get(m_private_name); } + Object* base_obj = nullptr; + if (m_base_value.is_string()) { + auto string_value = m_base_value.as_string().get(global_object, m_name); + if (string_value.has_value()) + return *string_value; + base_obj = global_object.string_prototype(); + } else if (m_base_value.is_number()) + base_obj = global_object.number_prototype(); + else if (m_base_value.is_boolean()) + base_obj = global_object.boolean_prototype(); + else + base_obj = TRY(m_base_value.to_object(global_object)); return base_obj->internal_get(m_name, m_base_value); } diff --git a/Userland/Libraries/LibJS/Runtime/Value.h b/Userland/Libraries/LibJS/Runtime/Value.h index 6a001cf9b0..fca480e91e 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.h +++ b/Userland/Libraries/LibJS/Runtime/Value.h @@ -18,7 +18,6 @@ #include <AK/Types.h> #include <LibJS/Forward.h> #include <LibJS/Runtime/BigInt.h> -#include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/Utf16String.h> #include <math.h> @@ -435,27 +434,6 @@ ThrowCompletionOr<TriState> is_less_than(GlobalObject&, bool left_first, Value l inline bool Value::operator==(Value const& value) const { return same_value(*this, value); } -struct ValueTraits : public Traits<Value> { - static unsigned hash(Value value) - { - VERIFY(!value.is_empty()); - if (value.is_string()) - return value.as_string().string().hash(); - - if (value.is_bigint()) - return value.as_bigint().big_integer().hash(); - - if (value.is_negative_zero()) - value = Value(0); - - return u64_hash(value.encoded()); // FIXME: Is this the best way to hash pointers, doubles & ints? - } - static bool equals(const Value a, const Value b) - { - return same_value_zero(a, b); - } -}; - } namespace AK { diff --git a/Userland/Libraries/LibJS/Runtime/ValueTraits.h b/Userland/Libraries/LibJS/Runtime/ValueTraits.h new file mode 100644 index 0000000000..14e2dfd23c --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/ValueTraits.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Runtime/PrimitiveString.h> +#include <LibJS/Runtime/Value.h> + +namespace JS { +struct ValueTraits : public Traits<Value> { + static unsigned hash(Value value) + { + VERIFY(!value.is_empty()); + if (value.is_string()) + return value.as_string().string().hash(); + + if (value.is_bigint()) + return value.as_bigint().big_integer().hash(); + + if (value.is_negative_zero()) + value = Value(0); + + return u64_hash(value.encoded()); // FIXME: Is this the best way to hash pointers, doubles & ints? + } + static bool equals(const Value a, const Value b) + { + return same_value_zero(a, b); + } +}; + +} |