mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:47:35 +00:00
LibJS: Implement normative change in String.prototype.substr
And add spec comments while we're in the neighborhood.
This commit is contained in:
parent
60a6bae53d
commit
446a10a1ac
2 changed files with 35 additions and 3 deletions
|
@ -568,26 +568,40 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
|
||||||
// B.2.2.1 String.prototype.substr ( start, length ), https://tc39.es/ecma262/#sec-string.prototype.substr
|
// B.2.2.1 String.prototype.substr ( start, length ), https://tc39.es/ecma262/#sec-string.prototype.substr
|
||||||
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
|
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
|
||||||
{
|
{
|
||||||
|
// 1. Let O be ? RequireObjectCoercible(this value).
|
||||||
|
// 2. Let S be ? ToString(O).
|
||||||
auto string = TRY(utf16_string_from(vm));
|
auto string = TRY(utf16_string_from(vm));
|
||||||
|
|
||||||
|
// 3. Let size be the length of S.
|
||||||
auto size = string.length_in_code_units();
|
auto size = string.length_in_code_units();
|
||||||
|
|
||||||
|
// 4. Let intStart be ? ToIntegerOrInfinity(start).
|
||||||
auto int_start = TRY(vm.argument(0).to_integer_or_infinity(vm));
|
auto int_start = TRY(vm.argument(0).to_integer_or_infinity(vm));
|
||||||
|
|
||||||
|
// 5. If intStart is -∞, set intStart to 0.
|
||||||
if (Value(int_start).is_negative_infinity())
|
if (Value(int_start).is_negative_infinity())
|
||||||
int_start = 0;
|
int_start = 0;
|
||||||
|
// 6. Else if intStart < 0, set intStart to max(size + intStart, 0).
|
||||||
else if (int_start < 0)
|
else if (int_start < 0)
|
||||||
int_start = max(size + int_start, 0);
|
int_start = max(size + int_start, 0);
|
||||||
|
// 7. Else, set intStart to min(intStart, size).
|
||||||
|
else
|
||||||
|
int_start = min(int_start, size);
|
||||||
|
|
||||||
|
// 8. If length is undefined, let intLength be size; otherwise let intLength be ? ToIntegerOrInfinity(length).
|
||||||
auto length = vm.argument(1);
|
auto length = vm.argument(1);
|
||||||
|
|
||||||
auto int_length = length.is_undefined() ? size : TRY(length.to_integer_or_infinity(vm));
|
auto int_length = length.is_undefined() ? size : TRY(length.to_integer_or_infinity(vm));
|
||||||
if (Value(int_start).is_positive_infinity() || (int_length <= 0) || Value(int_length).is_positive_infinity())
|
|
||||||
return js_string(vm, String::empty());
|
|
||||||
|
|
||||||
|
// 9. Set intLength to the result of clamping intLength between 0 and size.
|
||||||
|
int_length = clamp(int_length, 0, size);
|
||||||
|
|
||||||
|
// 10. Let intEnd be min(intStart + intLength, size).
|
||||||
auto int_end = min((i32)(int_start + int_length), size);
|
auto int_end = min((i32)(int_start + int_length), size);
|
||||||
|
|
||||||
if (int_start >= int_end)
|
if (int_start >= int_end)
|
||||||
return js_string(vm, String::empty());
|
return js_string(vm, String::empty());
|
||||||
|
|
||||||
|
// 11. Return the substring of S from intStart to intEnd.
|
||||||
return js_string(vm, string.substring_view(int_start, int_end - int_start));
|
return js_string(vm, string.substring_view(int_start, int_end - int_start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,24 @@ test("basic functionality", () => {
|
||||||
expect("hello friends".substr(-3, -5)).toBe("");
|
expect("hello friends".substr(-3, -5)).toBe("");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Non numeric values", () => {
|
||||||
|
expect("a".substr(0, Infinity)).toBe("a");
|
||||||
|
expect("a".substr(0, -Infinity)).toBe("");
|
||||||
|
expect("abc".substr(0, Infinity)).toBe("abc");
|
||||||
|
expect("abc".substr(0, -Infinity)).toBe("");
|
||||||
|
expect("abc".substr(Infinity, Infinity)).toBe("");
|
||||||
|
expect("abc".substr(Infinity)).toBe("");
|
||||||
|
expect("abc".substr(-Infinity)).toBe("abc");
|
||||||
|
expect("abc".substr(-Infinity, 1)).toBe("a");
|
||||||
|
expect("abc".substr(-Infinity, Infinity)).toBe("abc");
|
||||||
|
|
||||||
|
expect("abc".substr(NaN)).toBe("abc");
|
||||||
|
expect("abc".substr(NaN, NaN)).toBe("");
|
||||||
|
expect("abc".substr(0, NaN)).toBe("");
|
||||||
|
expect("abc".substr(NaN, Infinity)).toBe("abc");
|
||||||
|
expect("abc".substr(NaN, -Infinity)).toBe("");
|
||||||
|
});
|
||||||
|
|
||||||
test("UTF-16", () => {
|
test("UTF-16", () => {
|
||||||
var s = "😀";
|
var s = "😀";
|
||||||
expect(s).toHaveLength(2);
|
expect(s).toHaveLength(2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue