Skip to content
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: Guard IntegerIndexedElementSet with receiver check #1556

Merged
merged 1 commit into from
Aug 10, 2022

Conversation

shvaikalesh
Copy link
Member

@shvaikalesh shvaikalesh commented May 28, 2019

Closes #1339.
Closes #1541.

Recap

In ES6, both [[Get]] and [[Set]] TypedArray methods had the receiver checks, which were removed in #347 due to consistency with [[HasProperty]]. Removing receiver check from [[Set]] turned out to be web-incompatible (SM bug), breaking the 🚀 NASA's WorldWind web app and SDK.

I've just checked the links in Firefox 63 (release binaries): the web app and SDK examples still don't work. While there are no other sites that are broken, we can't just fix the WorldWind: it's an educational material that is also distributed offline and viewed via file:/// protocol.

The breakage was caused by TypedArray instances being in [[Prototype]] chain (presumably, for default values) of various objects like Matrix or Vector instances.

Proposed change

This PR attempts to specify the most desired behavior while providing the minimum required for web-compatibility: OrdinarySet is performed for canonical numeric strings that are valid indices only.

Implementation status

  • V8 follows the proposed spec except that it performs value coercion even for invalid indices.
  • SM follows the proposed spec for valid indices, but creates property on receiver for invalid indices, without traversing prototype chain further.
  • JSC doesn't currently invoke [[Set]] overrides during prototype chain traversal, and gets Reflect.set wrong for non-ordinary [[Set]]. This bug will fix non-index [[Set]], including canonical numeric strings that are invalid indices. Indexed [[Set]] will be adjusted in a follow-up, as it's quite different and unaware of receiver.

@ljharb ljharb added normative change Affects behavior required to correctly evaluate some ECMAScript source text spec bug web reality labels May 28, 2019
@ljharb ljharb changed the title Editorial: Guard TypedArray methods from non-exotic receivers Normative: Guard TypedArray methods from non-exotic receivers May 28, 2019
ljharb
ljharb previously approved these changes May 28, 2019
@ljharb ljharb requested review from zenparsing and a team May 28, 2019 19:35
@shvaikalesh
Copy link
Member Author

shvaikalesh commented May 28, 2019

It feels more idiomatic to invoke IntegerIndexedElement{Get,Set} on Receiver rather than using SameValue, though I am yet to come up with more practical example.

EDIT: Type checking Receiver is weird and won't be useful. Instead, we should align with other [[Set]] overrides like of mapped arguments or legacy platform objects: perform a simple reference check.

@ljharb
Copy link
Member

ljharb commented May 28, 2019

With this code:

let o = new Int8Array(1)
Object.setPrototypeOf(Array.prototype, o);
const a = [];  //a inherits indirectly from o
a[0] = 4;  //according to current spec. this will set o[0] to 4.
print(a[0], o[0]);

let target = [0]
let receiver = [0]
Reflect.set(target, 0, 1, receiver)
print(target, receiver)

let typedTarget = new Int8Array(1)
let typedReceiver = new Int8Array(1)
Reflect.set(typedTarget, 0, 1, typedReceiver)
print(typedTarget, typedReceiver)

i get these results:

#### Chakra
4 0
0 1
0 1

#### JavaScriptCore
4 0
0 1
1 0

#### SpiderMonkey
4 0
0 1
0 1

#### V8
4 0
0 1
0 1

#### V8 --harmony
4 0
0 1
0 1

so there's actually a variance in the latter case - only JSC returns 1, 0 where the others return 0, 1. This may need consensus after all.

@ljharb ljharb added the needs consensus This needs committee consensus before it can be eligible to be merged. label May 28, 2019
@gsathya gsathya added the needs test262 tests The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262 label May 29, 2019
@shvaikalesh shvaikalesh changed the title Normative: Guard TypedArray methods from non-exotic receivers Normative: Guard IntegerIndexedElementSet with receiver check Feb 25, 2021
@evilpie
Copy link
Contributor

evilpie commented Feb 25, 2021

I am probably misreading the change, but doesn't the return in Step 2.b.ii mean we never set anything in this case?

@akamsmrhill

This comment has been minimized.

@ljharb ljharb added has consensus This has committee consensus. and removed needs consensus This needs committee consensus before it can be eligible to be merged. labels Feb 25, 2021
@rkirsling
Copy link
Member

Same question as @evilpie: Based on @ljharb's third test case, it seems like we set either O or Receiver, no?

@shvaikalesh
Copy link
Member Author

shvaikalesh commented Feb 26, 2021

Oops, my mistake: while always returning w/o setting anything would be a desired change, it is not web-compatible. Fixed to fall back to OrdinarySet instead.

@shvaikalesh shvaikalesh marked this pull request as ready for review March 1, 2021 15:51
@ljharb ljharb force-pushed the master branch 3 times, most recently from 3d0c24c to 7a79833 Compare June 29, 2021 02:21
@ljharb ljharb added the editor call to be discussed in the next editor call label Sep 8, 2021
spec.html Outdated
1. If ! SameValue(_O_, _Receiver_) is *true*, then
1. Perform ? IntegerIndexedElementSet(_O_, _numericIndex_, _V_).
1. Return *true*.
1. If ! IsValidIntegerIndex(_O_, _numericIndex_) is *false*, return *true*.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if you have an integer index which is in bounds for O, but O and Receiver are different values, you'll now fall through to OrdinarySet. Is that intended?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I don't remember what the behavior we got consensus for was, but this PR currently doesn't have interop wrt in-bounds/OOB accesses.

In-bounds falls through to OrdinarySet in SM and V8. OOB falls through to OrdinarySet in SM only. JSC currently always sets the value on the target instead of the receiver.

// test-iieo-receiver-mismatch.js
let target = new Int8Array(1);
let receiver = [0];

// In-bounds
Reflect.set(target, 0, 1, receiver);
print('after in-bounds set:', target, receiver);

// OOB
Reflect.set(target, 2, 1, receiver);
print('after OOB set:', target, receiver);
$ eshost ./test-iieo-receiver-mismatch.js
#### ch
after in-bounds set: 0 1
after OOB set: 0 1,,1

#### jsc
after in-bounds set: 1 0
after OOB set: 1 0

#### sm
after in-bounds set: 0 1
after OOB set: 0 1,,1

#### v8
after in-bounds set: 0 1
after OOB set: 0 1

#### xs
after in-bounds set: 1 0
after OOB set: 1 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, it looks like both chakra and SM had the same behavior. Whats the usecase? This only impacts reflect api iiuc, so tooling?

@ljharb ljharb removed the editor call to be discussed in the next editor call label Sep 15, 2021
@ljharb ljharb added the editor call to be discussed in the next editor call label Apr 14, 2022
@syg
Copy link
Contributor

syg commented Apr 20, 2022

I'll try to jog my memory for what the consensus was. Failing that we might need to relitigate this, unfortunately.

@bakkot bakkot removed the editor call to be discussed in the next editor call label Apr 27, 2022
@ljharb ljharb dismissed their stale review April 27, 2022 22:10

removing pending reconfirming what consensus is

@shvaikalesh
Copy link
Member Author

shvaikalesh commented Jun 5, 2022

@syg The consensus for TypedArray's [[Set]] was to invoke OrdinarySet if receiver is altered, for all indices, including OOB (please see EDIT 2): https://docs.google.com/presentation/d/1Cg7XDFmq2_Aa7h1ZNdgrmT_UCIm0w02P9Z7Krht46Kw/edit#slide=id.g75ac69d4fb_0_131.

EDIT: found meeting notes for that meeting: https://github.com/tc39/notes/blob/167155eeb708d84e1758d99c88b15670f9b81f75/meetings/2019-12/december-3.md#normative-typedarray-on-prototypes-web-reality.

EDIT 2: actually, the presentation that got consensus doesn't seem to include semantics for OOB indices. As for non-canonical keys, this PR and the presentation agree to invoke OrdinarySet for those.

That matches SpiderMonkey behaviour, while this PR matches V8's. Neither proposals have interop, but both are web-compatible, so in this PR I'm suggesting to match TypedArray's [[Get]] behaviour to suppress further prototype lookup (and not invoke getters upper in prototype chain) for invalid indices.

So formally this PR must receive committee's approval.

@codehag Not only the Reflect.set, but also code like ({ __proto__: new Int32Array(10) })[0] = 1. I can't come up with a use case here, so the goal here is to spec something idiomatic while ensuring NASA's WorldWind web app, which cares only about in-bounds indices, won't break 😄.

@bakkot bakkot added the editor call to be discussed in the next editor call label Jul 27, 2022
@bakkot bakkot added ready to merge Editors believe this PR needs no further reviews, and is ready to land. and removed editor call to be discussed in the next editor call labels Aug 10, 2022
ljharb pushed a commit to shvaikalesh/ecma262 that referenced this pull request Aug 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has consensus This has committee consensus. needs test262 tests The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262 normative change Affects behavior required to correctly evaluate some ECMAScript source text ready to merge Editors believe this PR needs no further reviews, and is ready to land. spec bug web reality
Projects
None yet
10 participants