diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-11-29 20:03:44 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-11-29 20:22:28 +0100 |
commit | eac2add08377eb4ba8e43e7e6a8f385480ebd73b (patch) | |
tree | 0f9a074b8b4ebcb73b0487b4f2cce70ae9330857 /tests/custom | |
parent | 3497da1448f9b1d602e23c10977db0ce0188c959 (diff) |
compiler: fix bytecode for logical assignments of properties
The compiler emitted incorrect bytecode for logical assignment operations
on property expressions. The generated instructions left the stack in an
unclean state when the assignment condition was not fulfilled, causing a
stack layout mismatch between compiler and vm, leading to undefined
variable accesses and other non-deterministic behavior.
Solve this issue by rewriting the bytecode generation to yield an
instruction sequence that does not leave garbage on the stack.
The implementation is not optimal yet, as an expression in the form
`obj.prop ||= val` will load `obj.prop` twice. This is acceptable for
now as the load operation has no side effect, but should be solved in
a better way by introducing new instructions that allow for swapping
stack slots, allowing the vm to operate on a copy of the loaded value.
Also rewrite the corresponding test case to trigger a runtime error
on code versions before this fix.
Fixes: fdc9b6a ("compiler: fix `??=`, `||=` and `&&=` logical assignment semantics")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'tests/custom')
-rw-r--r-- | tests/custom/00_syntax/25_and_or_assignment | 78 |
1 files changed, 66 insertions, 12 deletions
diff --git a/tests/custom/00_syntax/25_and_or_assignment b/tests/custom/00_syntax/25_and_or_assignment index d6a9415..114b39a 100644 --- a/tests/custom/00_syntax/25_and_or_assignment +++ b/tests/custom/00_syntax/25_and_or_assignment @@ -10,6 +10,9 @@ expression result if the lhs is truish. [ null, false, + "is truish", + null, + false, "is truish" ] -- End -- @@ -20,11 +23,23 @@ expression result if the lhs is truish. y = false; z = true; - x &&= "is truish"; - y &&= "is truish"; - z &&= "is truish"; + o = { + a: null, + b: false, + c: true + }; + + res = []; + + push(res, x &&= "is truish"); + push(res, y &&= "is truish"); + push(res, z &&= "is truish"); + + push(res, o.a &&= "is truish"); + push(res, o.b &&= "is truish"); + push(res, o.c &&= "is truish"); - printf("%.J\n", [ x, y, z ]); + printf("%.J\n", res); %} -- End -- @@ -36,6 +51,9 @@ expression result if the lhs is falsy. [ "is falsy", "is falsy", + true, + "is falsy", + "is falsy", true ] -- End -- @@ -46,11 +64,23 @@ expression result if the lhs is falsy. y = false; z = true; - x ||= "is falsy"; - y ||= "is falsy"; - z ||= "is falsy"; + o = { + a: null, + b: false, + c: true + }; + + res = []; + + push(res, x ||= "is falsy"); + push(res, y ||= "is falsy"); + push(res, z ||= "is falsy"); + + push(res, o.a ||= "is falsy"); + push(res, o.b ||= "is falsy"); + push(res, o.c ||= "is falsy"); - printf("%.J\n", [ x, y, z ]); + printf("%.J\n", res); %} -- End -- @@ -60,6 +90,15 @@ assignment condition is false. -- Expect stdout -- [ + false, + false, + true, + false, + false, + true, + 0, + 0, + 0, 0, 0, 0 @@ -71,15 +110,30 @@ assignment condition is false. a = 0; b = 0; c = 0; + d = 0; + e = 0; + f = 0; + + o = { + a: false, + b: false, + c: true + }; x = false; y = false; z = true; - x ??= a++; - y &&= b++; - z ||= c++; + res = []; + + push(res, x ??= a++); + push(res, y &&= b++); + push(res, z ||= c++); + + push(res, o.a ??= d++); + push(res, o.b &&= e++); + push(res, o.c ||= f++); - printf("%.J\n", [ a, b, c ]); + printf("%.J\n", [ ...res, a, b, c, d, e, f ]); %} -- End -- |