Skip to content

Commit

Permalink
[JSC] Reinstate String#at
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=219124

Reviewed by Yusuke Suzuki.

JSTests:

* stress/at-method.js: Re-add tests.
* test262/config.yaml: Re-enable feature.
* test262/expectations.yaml:
"at/prop-desc.js" failures are due to a typo; will be fixed in tc39/test262#2908.

Source/JavaScriptCore:

At this week's TC39 meeting, consensus was achieved on renaming item() *and* keeping it for strings too.
Accordingly, this patch reinstates String.prototype.at behind the existing useAtMethod runtime option.

* builtins/StringPrototype.js:
(at):
* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):


Canonical link: https://commits.webkit.org/231748@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@270005 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
rkirsling committed Nov 19, 2020
1 parent dab8e3b commit 9ce3e44
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 2 deletions.
12 changes: 12 additions & 0 deletions JSTests/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
2020-11-18 Ross Kirsling <ross.kirsling@sony.com>

[JSC] Reinstate String#at
https://bugs.webkit.org/show_bug.cgi?id=219124

Reviewed by Yusuke Suzuki.

* stress/at-method.js: Re-add tests.
* test262/config.yaml: Re-enable feature.
* test262/expectations.yaml:
"at/prop-desc.js" failures are due to a typo; will be fixed in https://github.com/tc39/test262/pull/2908.

2020-11-17 Yusuke Suzuki <ysuzuki@apple.com>

[JSC] Improve Wasm binary test coverage
Expand Down
18 changes: 18 additions & 0 deletions JSTests/stress/at-method.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,21 @@ for (const TA of [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Ar
shouldBe(ta.at(null), ta[0]);
shouldBe(ta.at({ valueOf: () => -1 }), ta[ta.length - 1]);
}

shouldBe(String.prototype.at.length, 1);
shouldThrowTypeError(() => String.prototype.at.call(undefined));
shouldThrowTypeError(() => String.prototype.at.call(null));

const string = 'abc';
// intentionally go one too far to ensure that we get undefined instead of wrapping
for (let i = 0; i <= string.length; i++) {
shouldBe(string.at(i), string[i]);
shouldBe(string.at(-i - 1), string[string.length - i - 1]);
}
shouldBe(string.at(), string[0]);
shouldBe(string.at(null), string[0]);
shouldBe(string.at({ valueOf: () => -1 }), string[string.length - 1]);

const emojiPseudoString = { toString: () => '😅' };
shouldBe(String.prototype.at.call(emojiPseudoString, 0), '\u{d83d}');
shouldBe(String.prototype.at.call(emojiPseudoString, -1), '\u{de05}');
3 changes: 1 addition & 2 deletions JSTests/test262/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ flags:
Atomics: useSharedArrayBuffer
Array.prototype.at: useAtMethod
TypedArray.prototype.at: useAtMethod
String.prototype.at: useAtMethod
skip:
features:
- Atomics.waitAsync
Expand All @@ -27,8 +28,6 @@ skip:
- regexp-match-indices
- top-level-await
- Intl.ListFormat

- String.prototype.at
paths:
- test/built-ins/DataView/prototype/getBigInt64
- test/built-ins/DataView/prototype/getBigUint64
Expand Down
3 changes: 3 additions & 0 deletions JSTests/test262/expectations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,9 @@ test/built-ins/RegExp/prototype/exec/u-lastindex-adv.js:
test/built-ins/RegExp/quantifier-integer-limit.js:
default: 'SyntaxError: Invalid regular expression: number too large in {} quantifier'
strict mode: 'SyntaxError: Invalid regular expression: number too large in {} quantifier'
test/built-ins/String/prototype/at/prop-desc.js:
default: 'Test262Error: descriptor should be writable'
strict mode: 'Test262Error: descriptor should be writable'
test/built-ins/TypedArray/prototype/at/prop-desc.js:
default: 'Test262Error: descriptor should be writable'
strict mode: 'Test262Error: descriptor should be writable'
Expand Down
15 changes: 15 additions & 0 deletions Source/JavaScriptCore/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
2020-11-18 Ross Kirsling <ross.kirsling@sony.com>

[JSC] Reinstate String#at
https://bugs.webkit.org/show_bug.cgi?id=219124

Reviewed by Yusuke Suzuki.

At this week's TC39 meeting, consensus was achieved on renaming item() *and* keeping it for strings too.
Accordingly, this patch reinstates String.prototype.at behind the existing useAtMethod runtime option.

* builtins/StringPrototype.js:
(at):
* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):

2020-11-17 Yusuke Suzuki <ysuzuki@apple.com>

[JSC] Improve Wasm binary test coverage
Expand Down
19 changes: 19 additions & 0 deletions Source/JavaScriptCore/builtins/StringPrototype.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,25 @@ function concat(arg /* ... */)
return @tailCallForwardArguments(@stringConcatSlowPath, this);
}

// FIXME: This is extremely similar to charAt, so we should optimize it accordingly.
// https://bugs.webkit.org/show_bug.cgi?id=217139
function at(index)
{
"use strict";

if (@isUndefinedOrNull(this))
@throwTypeError("String.prototype.at requires that |this| not be null or undefined");

var string = @toString(this);
var length = string.length;

var k = @toInteger(index);
if (k < 0)
k += length;

return (k >= 0 && k < length) ? string[k] : @undefined;
}

@globalPrivate
function createHTML(func, string, tag, attribute, value)
{
Expand Down
3 changes: 3 additions & 0 deletions Source/JavaScriptCore/runtime/StringPrototype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ void StringPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject, JSStr
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("normalize", stringProtoFuncNormalize, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().charCodeAtPrivateName(), stringProtoFuncCharCodeAt, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, CharCodeAtIntrinsic);

if (Options::useAtMethod())
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().atPublicName(), stringPrototypeAtCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));

JSFunction* trimStartFunction = JSFunction::create(vm, globalObject, 0, "trimStart"_s, stringProtoFuncTrimStart, NoIntrinsic);
JSFunction* trimEndFunction = JSFunction::create(vm, globalObject, 0, "trimEnd"_s, stringProtoFuncTrimEnd, NoIntrinsic);
putDirectWithoutTransition(vm, Identifier::fromString(vm, "trimStart"), trimStartFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
Expand Down

0 comments on commit 9ce3e44

Please sign in to comment.