RESOLVED FIXED210317
The rhs in `ReadModifyResolveNode` should be evaluated before throwing an exception if the lhs is read-only
https://bugs.webkit.org/show_bug.cgi?id=210317
Summary The rhs in `ReadModifyResolveNode` should be evaluated before throwing an exc...
Devin Rousso
Reported 2020-04-09 20:22:47 PDT
``` (function() { let count = 0; const x = 42; try { x += (() => ++count)(); } catch { } if (count !== 1) throw new Error(`expected 1 but got ${count}`); })(); ``` See NOTE 2 on <https://tc39.es/proposal-logical-assignment/#sec-assignment-operators-runtime-semantics-evaluation>.
Attachments
Patch (7.59 KB, patch)
2020-04-09 20:26 PDT, Devin Rousso
no flags
Patch (7.74 KB, patch)
2020-04-10 10:23 PDT, Devin Rousso
no flags
Patch (7.41 KB, patch)
2020-04-10 14:16 PDT, Devin Rousso
no flags
Devin Rousso
Comment 1 2020-04-09 20:26:25 PDT
Joseph Pecoraro
Comment 2 2020-04-09 21:12:13 PDT
Comment on attachment 396038 [details] Patch Does this cause a test262 test to change, or maybe not one we have imported?
Ross Kirsling
Comment 3 2020-04-09 21:34:12 PDT
Comment on attachment 396038 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=396038&action=review > JSTests/stress/const-read-modify-assignment-eval-rhs-before-exception.js:24 > + try { > + testConstReadModifyAssignmentRHSEvalBeforeException += (() => ++count)(); > + } catch { } I'm a bit worried about the fact that this test doesn't fail before your patch. I spent a good while playing and I'm honestly not sure how to hit the `!var.local() && var.isReadOnly()` path in ReadModifyResolveNode (or AssignResolveNode). (Tried top-level const, non-configurable non-writable global var, freezing the global object and then trying to set a global var in strict mode...these all lack `var.local()`, but none satisfy `var.isReadOnly()`.)
Ross Kirsling
Comment 4 2020-04-10 01:12:09 PDT
Alright, so here is a test that hits the non-local read-only path, fails before your patch, and succeeds with it: (function () { let count = 0; const x = 42; function captureX() { return x; } try { x -= (() => count++)(); } catch { if (count === 1) return; } throw new Error('failed!'); })(); I...actually don't understand why. I just adapted it from here: https://github.com/WebKit/webkit/blob/master/JSTests/stress/const-semantics.js#L125-L129
Devin Rousso
Comment 5 2020-04-10 10:17:23 PDT
(In reply to Ross Kirsling from comment #4) > Alright, so here is a test that hits the non-local read-only path, fails before your patch, and succeeds with it: > > (function () { > let count = 0; > > const x = 42; > function captureX() { return x; } > > try { > x -= (() => count++)(); > } catch { > if (count === 1) > return; > } > throw new Error('failed!'); > })(); > > > I...actually don't understand why. I just adapted it from here: https://github.com/WebKit/webkit/blob/master/JSTests/stress/const-semantics.js#L125-L129 (o.0) funky stuff :P Thanks for the help! :)
Devin Rousso
Comment 6 2020-04-10 10:23:15 PDT
Ross Kirsling
Comment 7 2020-04-10 10:45:53 PDT
Comment on attachment 396098 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=396098&action=review r=me > JSTests/stress/const-read-modify-assignment-eval-rhs-before-exception.js:27 > +Object.defineProperty(globalThis, "testConstReadModifyAssignmentRHSEvalBeforeException", { Hmm, if you don't remove this test you should probably at least change the property name, since it's a `!var.local() && !var.isReadOnly()` red herring.
Devin Rousso
Comment 8 2020-04-10 14:15:15 PDT
Comment on attachment 396098 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=396098&action=review >> JSTests/stress/const-read-modify-assignment-eval-rhs-before-exception.js:27 >> +Object.defineProperty(globalThis, "testConstReadModifyAssignmentRHSEvalBeforeException", { > > Hmm, if you don't remove this test you should probably at least change the property name, since it's a `!var.local() && !var.isReadOnly()` red herring. I'll just remove it :)
Devin Rousso
Comment 9 2020-04-10 14:16:15 PDT
EWS
Comment 10 2020-04-10 14:50:15 PDT
Committed r259905: <https://trac.webkit.org/changeset/259905> All reviewed patches have been landed. Closing bug and clearing flags on attachment 396121 [details].
Radar WebKit Bug Importer
Comment 11 2020-04-10 14:51:17 PDT
Saam Barati
Comment 12 2020-04-13 01:03:43 PDT
(In reply to Ross Kirsling from comment #4) > Alright, so here is a test that hits the non-local read-only path, fails > before your patch, and succeeds with it: > > (function () { > let count = 0; > > const x = 42; > function captureX() { return x; } > > try { > x -= (() => count++)(); > } catch { > if (count === 1) > return; > } > throw new Error('failed!'); > })(); > > > I...actually don't understand why. I just adapted it from here: > https://github.com/WebKit/webkit/blob/master/JSTests/stress/const-semantics. > js#L125-L129 This makes sense. !!.local() means it wasn’t captured. So it lives in a bytecode local for this function that’s being compiled. If .local() is false, it’s captured
Ross Kirsling
Comment 13 2020-04-13 12:42:13 PDT
(In reply to Saam Barati from comment #12) > This makes sense. !!.local() means it wasn’t captured. So it lives in a > bytecode local for this function that’s being compiled. If .local() is > false, it’s captured Ahh, that's clear then, thanks! My brain was stuck on thinking about "local vs. global"...
Note You need to log in before you can comment on or make changes to this bug.