Bug 736742 - Fix decompiler precedence for destructuring assignment with comma-expression (r=jorendorff)
authorLuke Wagner <luke@mozilla.com>
Tue, 27 Mar 2012 14:48:10 -0700
changeset 93848 d15eb9db765a7a6cb6177fcbc01fbe5e7ab3d201
parent 93847 4166e7ce816c0235aeb06c55b72b4abe030dcd94
child 93849 e44e3729a05203aa3c7116f3d642711dc3ad665d
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs736742
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 736742 - Fix decompiler precedence for destructuring assignment with comma-expression (r=jorendorff)
js/src/jit-test/tests/basic/testLet.js
js/src/jsopcode.cpp
--- a/js/src/jit-test/tests/basic/testLet.js
+++ b/js/src/jit-test/tests/basic/testLet.js
@@ -68,16 +68,18 @@ test('return let (x = x) x;');
 test('return let (x = eval("x")) x;');
 test('return let (x = (let (x = x + 1) x) + 1) x;', 1, 3);
 test('return let (x = (let (x = eval("x") + 1) eval("x")) + 1) eval("x");', 1, 3);
 test('return let (x = x + 1, y = x) y;');
 test('return let (x = x + 1, [] = x, [[, , ]] = x, y = x) y;');
 test('return let ([{a: x}] = x, [, {b: y}] = x) let (x = x + 1, y = y + 2) x + y;', [{a:"p"},{b:"p"}], "p1p2");
 test('return let ([] = []) x;');
 test('return let ([] = [x]) x;');
+test('return let ([a] = (1, [x])) a;');
+test('return let ([a] = (1, x, 1, x)) a;', ['ponies']);
 test('return let ([x] = [x]) x;');
 test('return let ([[a, [b, c]]] = [[x, []]]) a;');
 test('return let ([x, y] = [x, x + 1]) x + y;', 1, 3);
 test('return let ([x, y, z] = [x, x + 1, x + 2]) x + y + z;', 1, 6);
 test('return let ([[x]] = [[x]]) x;');
 test('return let ([x, y] = [x, x + 1]) x;');
 test('return let ([x, [y, z]] = [x, x + 1]) x;');
 test('return let ([{x: [x]}, {y1: y, z1: z}] = [x, x + 1]) x;',{x:['ponies']});
@@ -124,16 +126,18 @@ test('let (x = x) {return x;}');
 test('let (x = eval("x")) {return x;}');
 test('let (x = (let (x = x + 1) x) + 1) {return x;}', 1, 3);
 test('let (x = (let (x = eval("x") + 1) eval("x")) + 1) {return eval("x");}', 1, 3);
 test('let (x = x + 1, y = x) {return y;}');
 test('let (x = x + 1, [] = x, [[, , ]] = x, y = x) {return y;}');
 test('let ([{a: x}] = x, [, {b: y}] = x) {let (x = x + 1, y = y + 2) {return x + y;}}', [{a:"p"},{b:"p"}], "p1p2");
 test('let ([] = []) {return x;}');
 test('let ([] = [x]) {return x;}');
+test('let ([a] = (1, [x])) {return a;}');
+test('let ([a] = (1, x, 1, x)) {return a;}', ['ponies']);
 test('let ([x] = [x]) {return x;}');
 test('let ([[a, [b, c]]] = [[x, []]]) {return a;}');
 test('let ([x, y] = [x, x + 1]) {return x + y;}', 1, 3);
 test('let ([x, y, z] = [x, x + 1, x + 2]) {return x + y + z;}', 1, 6);
 test('let ([[x]] = [[x]]) {return x;}');
 test('let ([x, y] = [x, x + 1]) {return x;}');
 test('let ([x, [y, z]] = [x, x + 1]) {return x;}');
 test('let ([{x: [x]}, {y1: y, z1: z}] = [x, x + 1]) {return x;}',{x:['ponies']});
@@ -169,16 +173,18 @@ test('var x = eval("x");return x;');
 test('var x = (let (x = x + 1) x) + 1;return x;', 1, 3);
 test('var x = (let (x = eval("x") + 1) eval("x")) + 1;return eval("x");', 1, 3);
 test('var X = x + 1, y = x;return y;');
 test('var X = x + 1, [] = X, [[, , ]] = X, y = x;return y;');
 test('var [{a: X}] = x, [, {b: y}] = x;var X = X + 1, y = y + 2;return X + y;', [{a:"p"},{b:"p"}], "p1p2");
 test('var [x] = [x];return x;');
 test('var [[a, [b, c]]] = [[x, []]];return a;');
 test('var [y] = [x];return y;');
+test('var [a] = (1, [x]);return a;');
+test('var [a] = (1, x, 1, x);return a;', ['ponies']);
 test('var [x, y] = [x, x + 1];return x + y;', 1, 3);
 test('var [x, y, z] = [x, x + 1, x + 2];return x + y + z;', 1, 6);
 test('var [[x]] = [[x]];return x;');
 test('var [x, y] = [x, x + 1];return x;');
 test('var [x, [y, z]] = [x, x + 1];return x;');
 test('var [{x: [x]}, {y1: y, z1: z}] = [x, x + 1];return x;',{x:['ponies']});
 test('var [] = [[]] = {};return x;');
 test('if (x) {var y = x;return x;}');
@@ -208,16 +214,18 @@ test('if (x) {let x = eval("x");return "
 test('if (x) {let y = (let (x = x + 1) x) + 1;return y;}', 1, 3);
 test('if (x) {let y = (let (x = eval("x") + 1) eval("x")) + 1;return eval("y");}', 1, 3);
 test('if (x) {let X = x + 1, y = x;return y;}');
 test('if (x) {let X = x + 1, [] = X, [[, , ]] = X, y = x;return y;}');
 test('if (x) {let [{a: X}] = x, [, {b: Y}] = x;var XX = X + 1, YY = Y + 2;return XX + YY;}', [{a:"p"},{b:"p"}], "p1p2");
 test('if (x) {let [[a, [b, c]]] = [[x, []]];return a;}');
 test('if (x) {let [X] = [x];return X;}');
 test('if (x) {let [y] = [x];return y;}');
+test('if (x) {let [a] = (1, [x]);return a;}');
+test('if (x) {let [a] = (1, x, 1, x);return a;}', ['ponies']);
 test('if (x) {let [X, y] = [x, x + 1];return X + y;}', 1, 3);
 test('if (x) {let [X, y, z] = [x, x + 1, x + 2];return X + y + z;}', 1, 6);
 test('if (x) {let [[X]] = [[x]];return X;}');
 test('if (x) {let [X, y] = [x, x + 1];return X;}');
 test('if (x) {let [X, [y, z]] = [x, x + 1];return X;}');
 test('if (x) {let [{x: [X]}, {y1: y, z1: z}] = [x, x + 1];return X;}',{x:['ponies']});
 test('if (x) {let y = x;try {let x = 1;throw 2;} catch (e) {return y;}}');
 test('if (x) {let [] = [[]] = {};return x;}');
@@ -274,16 +282,18 @@ test('var sum = 0;for (var X = eval("x")
 test('try {for (let x = eval("throw x");;) {}} catch (e) {return e;}');
 test('try {for (let x = x + "s"; eval("throw x");) {}} catch (e) {return e;}', 'ponie');
 test('for (let y = x;;) {let x;return y;}');
 test('for (let y = x;;) {let y;return x;}');
 test('for (let y;;) {let y;return x;}');
 test('for (let a = x;;) {let c = x, d = x;return c;}');
 test('for (let [a, b] = x;;) {let c = x, d = x;return c;}');
 test('for (let [] = [[]] = {};;) {return x;}');
+test('for (let [a] = (1, [x]);;) {return a;}');
+test('for (let [a] = (1, x, 1, x);;) {return a;}', ['ponies']);
 isError('for (let x = 1, x = 2;;) {}');
 isError('for (let [x, y] = a, {a:x} = b;;) {}');
 isError('for (let [x, y, x] = a;;) {}');
 isError('for (let [x, [y, [x]]] = a;;) {}');
 
 // for(in)
 test('for (let i in x) {return x;}');
 test('for (let i in x) {let y;return x;}');
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -4090,18 +4090,23 @@ Decompile(SprintStack *ss, jsbytecode *p
 #if JS_HAS_DESTRUCTURING
                 sn = js_GetSrcNote(jp->script, pc);
                 if (sn) {
                     if (SN_TYPE(sn) == SRC_DESTRUCT) {
                         pc = DecompileDestructuring(ss, pc, endpc);
                         if (!pc)
                             return NULL;
 
-                        lval = POP_STR();  /* Pop the decompiler result. */
-                        rval = POP_STR();  /* Pop the initializer expression. */
+                        /* Left-hand side never needs parens. */
+                        JS_ASSERT(js_CodeSpec[JSOP_POP].prec <= 3);
+                        lval = PopStr(ss, JSOP_POP);
+
+                        /* Make sure comma-expression on rhs gets parens. */
+                        JS_ASSERT(js_CodeSpec[JSOP_SETNAME].prec > js_CodeSpec[JSOP_POP].prec);
+                        rval = PopStr(ss, JSOP_SETNAME);
 
                         if (strcmp(rval, forelem_cookie) == 0) {
                             todo = Sprint(&ss->sprinter, ss_format,
                                           VarPrefix(sn), lval);
 
                             /* Skip POP so the SRC_FOR_IN code can pop for itself. */
                             if (*pc == JSOP_POP)
                                 len = JSOP_POP_LENGTH;