diff options
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Value.cpp | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 468760ca27..57184267d6 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -1090,15 +1090,34 @@ ThrowCompletionOr<size_t> Value::to_length(VM& vm) const // 7.1.22 ToIndex ( argument ), https://tc39.es/ecma262/#sec-toindex ThrowCompletionOr<size_t> Value::to_index(VM& vm) const { - if (is_undefined()) + // 1. If value is undefined, then + if (is_undefined()) { + // a. Return 0. return 0; - auto integer_index = TRY(to_integer_or_infinity(vm)); - if (integer_index < 0) + } + + // 2. Else, + // a. Let integer be ? ToIntegerOrInfinity(value). + auto integer = TRY(to_integer_or_infinity(vm)); + + // OPTIMIZATION: If the value is negative, ToLength normalizes it to 0, and we fail the SameValue comparison below. + // Bail out early instead. + if (integer < 0) return vm.throw_completion<RangeError>(ErrorType::InvalidIndex); - auto index = MUST(Value(integer_index).to_length(vm)); - if (integer_index != index) + + // b. Let clamped be ! ToLength(𝔽(integer)). + auto clamped = MUST(Value(integer).to_length(vm)); + + // c. If SameValue(𝔽(integer), clamped) is false, throw a RangeError exception. + if (integer != clamped) return vm.throw_completion<RangeError>(ErrorType::InvalidIndex); - return index; + + // d. Assert: 0 ≤ integer ≤ 2^53 - 1. + VERIFY(0 <= integer && integer <= MAX_ARRAY_LIKE_INDEX); + + // e. Return integer. + // NOTE: We return the clamped value here, which already has the right type. + return clamped; } // 7.1.5 ToIntegerOrInfinity ( argument ), https://tc39.es/ecma262/#sec-tointegerorinfinity |