-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Normative: Array.prototype.sort
: comparefn must be fn or undefined
#785
Conversation
This requires implementations throw a `TypeError` when the compare function is neither undefined nor a function, which is currently vaguely implied but not explicitly required. This reflects web reality in that every engine except v8 already throws in this case.
spec.html
Outdated
@@ -30780,6 +30780,7 @@ | |||
<emu-alg> | |||
1. Let _obj_ be ? ToObject(*this* value). | |||
1. Let _len_ be ? ToLength(? Get(_obj_, `"length"`)). | |||
1. If _comparefn_ is not *undefined* and IsCallable(_comparefn_) is *false*, throw a *TypeError* exception. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be step 1 instead of step 3, since the other steps aren’t needed in case we throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or have you tested the order in which existing implementations (except for V8) execute these steps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems SpiderMonkey and ChakraCore check comparefn
first. Other engines check ToObject(this)
first.
$ eshost -e 'Array.prototype.sort.call(null, null)'
#### JavaScriptCore
TypeError: Array.prototype.sort requires that |this| not be null
#### ChakraCore
TypeError: Array.prototype.sort: argument is not a JavaScript object
#### SpiderMonkey
TypeError: invalid Array.prototype.sort argument
#### V8
TypeError: Array.prototype.sort called on null or undefined
#### V8 Harmony
TypeError: Array.prototype.sort called on null or undefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since in Firefox, Array.prototype.sort.call(null)
throws "TypeError: can't convert null to object" but Array.prototype.sort.call(null, true)
throws "TypeError: invalid Array.prototype.sort argument", this matches web reality. Changing now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aha, thanks for the full comparison :-) I think since more engines agree on your change, that it's still the correct way to go. Updated!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For v8, it’s quite normal that it throws on ToObject(this)
, since it doesn’t throw on comparefn
at all. (Still, I also prefer JSC behaviour over SpiderMonkey/Chakra one. ... nevermind)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ambivalent over whether the ToObject check or the IsCallable check comes first, but I think both should happen before the ToLength check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub was hiding this part here. I'm also glad this is placed before the get length operation. +1 for this change.
Did you mean eshost ? |
@ariya thanks, fixed |
I'm on board with this but let's wait to hear from our v8 friends. |
This seems reasonable to me, though this seems like a fairly low-leverage tightening of |
@ajklein baby steps! |
Btw, I just checked in SpiderMonkey and we allow |
Turns out we optimize for arrays with length <= 1 so we never try to call the sort function in that case. We will still fail for [1, 2].sort({}). So this change is probably still fine from our side. |
I think most engines probably choose not to call the sorting function for < 2 elements; I'll look into that in a separate PR :-) |
Firefox seems to accept a-priori non-callable objects (but not primitives) as sort function but throws when attempting to use them. Safari TP has also an interesting behaviour:
(I vote for Edge semantics.) |
…ined This requires implementations throw a `TypeError` when the compare function is neither undefined nor a function, which is currently vaguely implied but not explicitly required.
…a non-undefined non-function Per tc39/ecma262#785
I updated to add a commit making the same change in TypedArray.prototype.sort. test262 tests are here |
Thank you @ljharb! I will pull this now that tests are pending on test262. |
…a non-undefined non-function (#1059) Per tc39/ecma262#785
This patch ensures a `TypeError` is thrown when the argument passed to `Array.prototype.sort` or `%TypedArray%.prototype.sort` is neither a function nor `undefined`. Every other major JavaScript engine already threw in this case. Making V8’s behavior match increases interoperability. tc39/ecma262#785 BUG=v8:6542 Cq-Include-Trybots: master.tryserver.v8:v8_linux_noi18n_rel_ng Change-Id: I412a59810abdd118217c8d8361389ec6c2f640bd Reviewed-on: https://chromium-review.googlesource.com/668356 Commit-Queue: Mathias Bynens <mathias@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#48028}
This requires implementations throw a
TypeError
when the compare function is neither undefined nor a function, which is currently vaguely implied but not explicitly required.This reflects web reality in that every engine except v8 already throws in this case. (Safari does not, but Safari TP and webkit latest do)
eshost output of
[1, 2].sort(true)
:This will likely need "web reality" and "needs consensus" labels.