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

Inconsistency in %ArrayIteratorPrototype%.next for TypedArrays #713

Closed
littledan opened this Issue Oct 18, 2016 · 20 comments

Comments

Projects
None yet
7 participants
@littledan
Member

littledan commented Oct 18, 2016

In %ArrayIteratorPrototype%.next, step 8.a., if the Array being iterated over is a TypedArray, the length used is the TypedArray's [[ArrayLength]]. However, if the TypedArray's ArrayBuffer is detached, then the length accessor would've returned zero (see spec). For consistency, should we do the same here?

One fix would be to make step 8.a check for a detached ArrayBuffer and use 0 for the length in that case. I'd like this one, as it leaves in the special allowance to make TypedArrays a bit more implementation-friendly by using the underlying length. Another possibility would be to always use the length accessor.

Thanks to @caitp and @bmeurer for raising this issue to me and discussing possible fixes.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 24, 2016

Contributor

fwiw: the behaviour that was in v8 before the CL in which Benedikt found this is basically what people would end up with if they polyfilled %ArrayIteratorPrototype%.next, and I believe some discussion in the jslang channel on irc.mozilla.org suggested that SpiderMonkey behaves the same way, so maybe there's some weight behind fixing this inconsistency.

Contributor

caitp commented Oct 24, 2016

fwiw: the behaviour that was in v8 before the CL in which Benedikt found this is basically what people would end up with if they polyfilled %ArrayIteratorPrototype%.next, and I believe some discussion in the jslang channel on irc.mozilla.org suggested that SpiderMonkey behaves the same way, so maybe there's some weight behind fixing this inconsistency.

@bmeurer

This comment has been minimized.

Show comment
Hide comment
@bmeurer

bmeurer Oct 24, 2016

I agree with @caitp, it makes sense to match the polyfill(able) behavior. So +1 for a spec fix.

bmeurer commented Oct 24, 2016

I agree with @caitp, it makes sense to match the polyfill(able) behavior. So +1 for a spec fix.

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Oct 24, 2016

Member

In general, the iterative methods of %TypedArrayPrototype% are specified to throw when applied to a typed array instances whose buffer is detached. This throw occurs, because of the detached check in IntegerIndexedElementGet and IntegerIndexedElementSet combined with that fact that the iterative methods directly access [[ArrayLength]] rather than self invoking their length method.

%ArrayIteratorPrototype%.next, as current specified, is consistent with the behavior of the iterative methods. Changing the specification as suggest above would create a new inconsistency.

Member

allenwb commented Oct 24, 2016

In general, the iterative methods of %TypedArrayPrototype% are specified to throw when applied to a typed array instances whose buffer is detached. This throw occurs, because of the detached check in IntegerIndexedElementGet and IntegerIndexedElementSet combined with that fact that the iterative methods directly access [[ArrayLength]] rather than self invoking their length method.

%ArrayIteratorPrototype%.next, as current specified, is consistent with the behavior of the iterative methods. Changing the specification as suggest above would create a new inconsistency.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 24, 2016

Contributor

I think that soec-side inconsistency is less weird for users than the current one

Contributor

caitp commented Oct 24, 2016

I think that soec-side inconsistency is less weird for users than the current one

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 24, 2016

Contributor

s/soec/spec (mobile github, sorry!)

Contributor

caitp commented Oct 24, 2016

s/soec/spec (mobile github, sorry!)

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Oct 24, 2016

Member

Also, there was a reason why we explicitly make the %ArrayPrototype% methods use [[ArrayLength]] rather than self invoking length. I wish I could remember the exact reasoning, maybe it's somewhere in the meeting notes. But, I think it was a legacy compat issue and/or concerns about fact that length property can be redefined.

Member

allenwb commented Oct 24, 2016

Also, there was a reason why we explicitly make the %ArrayPrototype% methods use [[ArrayLength]] rather than self invoking length. I wish I could remember the exact reasoning, maybe it's somewhere in the meeting notes. But, I think it was a legacy compat issue and/or concerns about fact that length property can be redefined.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 24, 2016

Contributor

it's not clear why "length" is configurable, but you have a point. I'm still in favor of treating length as 0 in the detached case, though.

Contributor

caitp commented Oct 24, 2016

it's not clear why "length" is configurable, but you have a point. I'm still in favor of treating length as 0 in the detached case, though.

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Oct 24, 2016

Member

length is configurable because (unlike regular arrays) it is just an accessor property on %TypedArrayPrototype%. Even if it was non-configurable, it could still be over-ridden at the instance level.

More generally, this bug and the meeting note it references is probably relevant to this thread.

Member

allenwb commented Oct 24, 2016

length is configurable because (unlike regular arrays) it is just an accessor property on %TypedArrayPrototype%. Even if it was non-configurable, it could still be over-ridden at the instance level.

More generally, this bug and the meeting note it references is probably relevant to this thread.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 24, 2016

Contributor

I'm not arguing with any of that, but I am saying it's unexpected for

var array = new Uint8Array([1, 2, 3]);
DetachArrayBuffer(array.buffer);
[...A.p.keys.call(array)] // [0, 1, 2]
array.length // 0
[...A.p.entries.call(array)] // TypeError

This is just weird, IMO

// edited for clarity

Contributor

caitp commented Oct 24, 2016

I'm not arguing with any of that, but I am saying it's unexpected for

var array = new Uint8Array([1, 2, 3]);
DetachArrayBuffer(array.buffer);
[...A.p.keys.call(array)] // [0, 1, 2]
array.length // 0
[...A.p.entries.call(array)] // TypeError

This is just weird, IMO

// edited for clarity

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Oct 24, 2016

Member

@caitp I agree the keys example is weird.

How about throwing in 8.a if buffer is detatched? Then keys and values would behave the same.

Member

allenwb commented Oct 24, 2016

@caitp I agree the keys example is weird.

How about throwing in 8.a if buffer is detatched? Then keys and values would behave the same.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 24, 2016

Contributor

I'd vouch for either of the following:

8. If a has a [[TypedArrayName]] internal slot, then
  a. Perform ? ValidateTypedArray(a).
  b. Let len be a.[[ArrayLength]].
9. Else,
  a. Let len be ? ToLength(? Get(a, "length")).

OR

8. If a has a [[TypedArrayName]] internal slot, then
  a. Let buffer be a.[[ViewedArrayBuffer]]
  b. If IsDetachedBuffer(buffer), let len be 0.
  c. Else, let len be a.[[ArrayLength]].
9. Else,
  a. Let len be ? ToLength(? Get(a, "length")).

The latter is what's been implemented for a long time, but it's possible that this isn't observable anywhere so it probably wouldn't break anything to change it. I'm okay with either one.

Contributor

caitp commented Oct 24, 2016

I'd vouch for either of the following:

8. If a has a [[TypedArrayName]] internal slot, then
  a. Perform ? ValidateTypedArray(a).
  b. Let len be a.[[ArrayLength]].
9. Else,
  a. Let len be ? ToLength(? Get(a, "length")).

OR

8. If a has a [[TypedArrayName]] internal slot, then
  a. Let buffer be a.[[ViewedArrayBuffer]]
  b. If IsDetachedBuffer(buffer), let len be 0.
  c. Else, let len be a.[[ArrayLength]].
9. Else,
  a. Let len be ? ToLength(? Get(a, "length")).

The latter is what's been implemented for a long time, but it's possible that this isn't observable anywhere so it probably wouldn't break anything to change it. I'm okay with either one.

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Oct 25, 2016

Member

Well, I vote for a. ValidateTypedArray does some tests that are redundant in this situation, but I assume that implementations will be smart enough to skip those.

Whether or not this is a safe change: what does Safari and Edge do for this case. If any of them follow the current spec. this won't be a change to web interoperable behavior.

Member

allenwb commented Oct 25, 2016

Well, I vote for a. ValidateTypedArray does some tests that are redundant in this situation, but I assume that implementations will be smart enough to skip those.

Whether or not this is a safe change: what does Safari and Edge do for this case. If any of them follow the current spec. this won't be a change to web interoperable behavior.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 25, 2016

Contributor

Whether or not this is a safe change: what does Safari and Edge do for this case. If any of them follow the current spec. this won't be a change to web interoperable behavior.

I doubt it's a web breaking change whether they follow the current spec or not, it seems incredibly unlikely that anyone is actually reaching this branch of spec text in code on the web today

Contributor

caitp commented Oct 25, 2016

Whether or not this is a safe change: what does Safari and Edge do for this case. If any of them follow the current spec. this won't be a change to web interoperable behavior.

I doubt it's a web breaking change whether they follow the current spec or not, it seems incredibly unlikely that anyone is actually reaching this branch of spec text in code on the web today

@leobalter

This comment has been minimized.

Show comment
Hide comment
@leobalter

leobalter Oct 25, 2016

Member

Well, I vote for a. ValidateTypedArray does some tests that are redundant in this situation, but I assume that implementations will be smart enough to skip those.

I'm +1 to it.

I'm also not against the other option if proven necessary.

Member

leobalter commented Oct 25, 2016

Well, I vote for a. ValidateTypedArray does some tests that are redundant in this situation, but I assume that implementations will be smart enough to skip those.

I'm +1 to it.

I'm also not against the other option if proven necessary.

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Oct 26, 2016

Member

+1 on ValidateTypedArray. I also highly doubt this will break anyone.

Member

bterlson commented Oct 26, 2016

+1 on ValidateTypedArray. I also highly doubt this will break anyone.

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan

littledan Oct 28, 2016

Member

OK, ValidateTypedArray sounds good to me. I wrote a spec change and a test262 test (which fails on current V8). Thoughts?

Member

littledan commented Oct 28, 2016

OK, ValidateTypedArray sounds good to me. I wrote a spec change and a test262 test (which fails on current V8). Thoughts?

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 28, 2016

Contributor

Works for me.

Contributor

caitp commented Oct 28, 2016

Works for me.

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Nov 2, 2016

Member

I've added needs-consensus to #724, but would be good to get a look from @jswalden and @msaboff.

Member

bterlson commented Nov 2, 2016

I've added needs-consensus to #724, but would be good to get a look from @jswalden and @msaboff.

@jswalden

This comment has been minimized.

Show comment
Hide comment
@jswalden

jswalden Nov 2, 2016

Contributor

Throwing for during-iteration detaching seems fine to me. I'd just write out the single step of checking for detachment rather than reuse the ill-fitting ValidateTypedArray (and commented to that effect on the PR), but semantically they're the same.

Contributor

jswalden commented Nov 2, 2016

Throwing for during-iteration detaching seems fine to me. I'd just write out the single step of checking for detachment rather than reuse the ill-fitting ValidateTypedArray (and commented to that effect on the PR), but semantically they're the same.

littledan added a commit to littledan/ecma262 that referenced this issue Nov 2, 2016

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan

littledan Dec 3, 2016

Member

This pull request gained consensus at the November 2016 TC39 meeting.

Member

littledan commented Dec 3, 2016

This pull request gained consensus at the November 2016 TC39 meeting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment