diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 41b45524159..467b3a4d536 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2509,37 +2509,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** * Emit ES7 exponentiation operator downlevel using Math.pow - * @param node {BinaryExpression} a binary expression node containing exponentiationOperator (**, **=) + * @param node a binary expression node containing exponentiationOperator (**, **=) */ function emitExponentiationOperator(node: BinaryExpression) { let leftHandSideExpression = node.left; if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) { let synthesizedLHS: ElementAccessExpression | PropertyAccessExpression; - - // This is used to decide whether to emit parenthesis around the expresison. - // Parenthesis is required for following cases: - // capture variable while emitting right-hand side operand. - // a[0] **= a[0] **= 2 - // _a = a, _a[0] = Math.pow(_a[0], (_b = a, _b[0] = Math.pow(_b[0], 2))); - // ^ -> required extra parenthesis controlled by shouldEmitParenthesis - // exponentiation compound in variable declaration - // var x = a[0] **= a[0] **= 2 - // var x = (_a = a, _a[0] = Math.pow(_a[0], (_b = a, _b[0] = Math.pow(_b[0], 2)))); - // ^ -> required extra parenthesis controlled by shouldEmitParenthesis - // Otherwise, false - let shouldEmitParenthesis = false; - + let shouldEmitParentheses = false; if (isElementAccessExpression(leftHandSideExpression)) { - shouldEmitParenthesis = node.parent.kind === SyntaxKind.VariableDeclaration || node.parent.kind === SyntaxKind.BinaryExpression; - - if (shouldEmitParenthesis) { - write("("); - } + shouldEmitParentheses = true; + write("("); synthesizedLHS = createSynthesizedNode(SyntaxKind.ElementAccessExpression, /*startsOnNewLine*/ false); - let tempVariable = createAndRecordTempVariable(TempFlags.Auto); - emitAssignment(tempVariable, leftHandSideExpression.expression, /*shouldEmitCommaBeforeAssignment*/ false); - synthesizedLHS.expression = tempVariable + + let identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefinedTempVariablesInPlaces*/ false, /*shouldemitCommaBeforeAssignment*/ false); + synthesizedLHS.expression = identifier; if (leftHandSideExpression.argumentExpression.kind !== SyntaxKind.NumericLiteral && leftHandSideExpression.argumentExpression.kind !== SyntaxKind.StringLiteral) { @@ -2553,16 +2537,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(", "); } else if (isPropertyAccessExpression(leftHandSideExpression)) { - shouldEmitParenthesis = node.parent.kind === SyntaxKind.VariableDeclaration || node.parent.kind === SyntaxKind.BinaryExpression; - - if (shouldEmitParenthesis) { - write("("); - } - + shouldEmitParentheses = true; + write("("); synthesizedLHS = createSynthesizedNode(SyntaxKind.PropertyAccessExpression, /*startsOnNewLine*/ false); - let tempVariable = createAndRecordTempVariable(TempFlags.Auto); - synthesizedLHS.expression = tempVariable - emitAssignment(tempVariable, leftHandSideExpression.expression, /*shouldEmitCommaBeforeAssignment*/ false); + + let identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefinedTempVariablesInPlaces*/ false, /*shouldemitCommaBeforeAssignment*/ false); + synthesizedLHS.expression = identifier; + (synthesizedLHS).dotToken = leftHandSideExpression.dotToken; (synthesizedLHS).name = leftHandSideExpression.name; write(", "); @@ -2575,7 +2556,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(", "); emit(node.right); write(")"); - if (shouldEmitParenthesis) { + if (shouldEmitParentheses) { write(")"); } } @@ -3254,6 +3235,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(";"); } + /** + * Emit an assignment to a given identifier, 'name', with a given expression, 'value'. + * @param name an identifier as a left-hand-side operand of the assignment + * @param value an expression as a right-hand-side operand of the assignment + * @param shouldEmitCommaBeforeAssignment a boolean indicating whether to prefix an assignment with comma + */ function emitAssignment(name: Identifier, value: Expression, shouldEmitCommaBeforeAssignment: boolean) { if (shouldEmitCommaBeforeAssignment) { write(", "); @@ -3285,6 +3272,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } + /** + * Create temporary variable, emit an assignment of the variable the given expression + * @param expression an expression to assign to the newly created temporary variable + * @param canDefineTempVariablesInPlace a boolean indicating whether you can define the temporary variable at an assignment location + * @param shouldEmitCommaBeforeAssignment a boolean indicating whether an assignment should prefix with comma + */ + function emitTempVariableAssignment(expression: Expression, canDefineTempVariablesInPlace: boolean, shouldEmitCommaBeforeAssignment: boolean): Identifier { + let identifier = createTempVariable(TempFlags.Auto); + if (!canDefineTempVariablesInPlace) { + recordTempDeclaration(identifier); + } + emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment); + return identifier; + } + function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, isAssignmentExpressionStatement: boolean, value?: Expression) { let emitCount = 0; @@ -3325,11 +3327,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return expr; } - let identifier = createTempVariable(TempFlags.Auto); - if (!canDefineTempVariablesInPlace) { - recordTempDeclaration(identifier); - } - emitAssignment(identifier, expr, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0); + let identifier = emitTempVariableAssignment(expr, canDefineTempVariablesInPlace, emitCount > 0); emitCount++; return identifier; } diff --git a/tests/baselines/reference/compoundExponentiationAssignmentLHSIsReference.js b/tests/baselines/reference/compoundExponentiationAssignmentLHSIsReference.js index cca4a7b55bf..f41962cf9e1 100644 --- a/tests/baselines/reference/compoundExponentiationAssignmentLHSIsReference.js +++ b/tests/baselines/reference/compoundExponentiationAssignmentLHSIsReference.js @@ -36,8 +36,8 @@ function fn1(x2) { } // property accesses var x3; -_a = x3, _a.a = Math.pow(_a.a, value); -_b = x3, _b['a'] = Math.pow(_b['a'], value); +(_a = x3, _a.a = Math.pow(_a.a, value)); +(_b = x3, _b['a'] = Math.pow(_b['a'], value)); // parentheses, the contained expression is reference (x1) = Math.pow((x1), value); function fn2(x4) { diff --git a/tests/baselines/reference/compoundExponentiationAssignmentLHSIsValue.js b/tests/baselines/reference/compoundExponentiationAssignmentLHSIsValue.js index ed825904d7a..f4e14e54242 100644 --- a/tests/baselines/reference/compoundExponentiationAssignmentLHSIsValue.js +++ b/tests/baselines/reference/compoundExponentiationAssignmentLHSIsValue.js @@ -140,15 +140,15 @@ var Derived = (function (_super) { __extends(Derived, _super); function Derived() { _super.call(this); - _a = _super.prototype, _a. = Math.pow(_a., value); + (_a = _super.prototype, _a. = Math.pow(_a., value)); var _a; } Derived.prototype.foo = function () { - _a = _super.prototype, _a. = Math.pow(_a., value); + (_a = _super.prototype, _a. = Math.pow(_a., value)); var _a; }; Derived.sfoo = function () { - _a = _super, _a. = Math.pow(_a., value); + (_a = _super, _a. = Math.pow(_a., value)); var _a; }; return Derived; diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.js b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.js index fb2a7d5a88d..3b9db4c6998 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.js +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.js @@ -19,14 +19,14 @@ array3[j0++] **= array3[j1++] **= array3[j0++] **= 1; //// [emitCompoundExponentiationAssignmentWithIndexingOnLHS1.js] var array0 = [1, 2, 3]; var i0 = 0; -_a = array0, _i = ++i0, _a[_i] = Math.pow(_a[_i], 2); +(_a = array0, _i = ++i0, _a[_i] = Math.pow(_a[_i], 2)); var array1 = [1, 2, 3]; var i1 = 0; -_b = array1, _c = ++i1, _b[_c] = Math.pow(_b[_c], (_d = array1, _e = ++i1, _d[_e] = Math.pow(_d[_e], 2))); +(_b = array1, _c = ++i1, _b[_c] = Math.pow(_b[_c], (_d = array1, _e = ++i1, _d[_e] = Math.pow(_d[_e], 2)))); var array2 = [1, 2, 3]; var i2 = 0; -_f = array2, _g = ++i2, _f[_g] = Math.pow(_f[_g], Math.pow(array2[++i2], 2)); +(_f = array2, _g = ++i2, _f[_g] = Math.pow(_f[_g], Math.pow(array2[++i2], 2))); var array3 = [2, 2, 3]; var j0 = 0, j1 = 1; -_h = array3, _j = j0++, _h[_j] = Math.pow(_h[_j], (_k = array3, _l = j1++, _k[_l] = Math.pow(_k[_l], (_m = array3, _o = j0++, _m[_o] = Math.pow(_m[_o], 1))))); +(_h = array3, _j = j0++, _h[_j] = Math.pow(_h[_j], (_k = array3, _l = j1++, _k[_l] = Math.pow(_k[_l], (_m = array3, _o = j0++, _m[_o] = Math.pow(_m[_o], 1)))))); var _a, _i, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.js b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.js index e2392e4074b..83e0b2473e8 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.js +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.js @@ -17,10 +17,10 @@ function foo() { globalCounter += 1; return { 0: 2 }; } -_a = foo(), _a[0] = Math.pow(_a[0], foo()[0]); +(_a = foo(), _a[0] = Math.pow(_a[0], foo()[0])); var result_foo1 = (_b = foo(), _b[0] = Math.pow(_b[0], foo()[0])); -_c = foo(), _c[0] = Math.pow(_c[0], (_d = foo(), _d[0] = Math.pow(_d[0], 2))); +(_c = foo(), _c[0] = Math.pow(_c[0], (_d = foo(), _d[0] = Math.pow(_d[0], 2)))); var result_foo2 = (_e = foo(), _e[0] = Math.pow(_e[0], (_f = foo(), _f[0] = Math.pow(_f[0], 2)))); -_g = foo(), _g[0] = Math.pow(_g[0], Math.pow(foo()[0], 2)); +(_g = foo(), _g[0] = Math.pow(_g[0], Math.pow(foo()[0], 2))); var result_foo3 = (_h = foo(), _h[0] = Math.pow(_h[0], Math.pow(foo()[0], 2))); var _a, _b, _c, _d, _e, _f, _g, _h; diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.js b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.js index b4b8a8a1b1f..797ccccc331 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.js +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.js @@ -23,7 +23,7 @@ var object = { this._0 = x; }, }; -_a = object, _a[0] = Math.pow(_a[0], object[0]); -_b = object, _b[0] = Math.pow(_b[0], (_c = object, _c[0] = Math.pow(_c[0], 2))); -_d = object, _d[0] = Math.pow(_d[0], Math.pow(object[0], 2)); +(_a = object, _a[0] = Math.pow(_a[0], object[0])); +(_b = object, _b[0] = Math.pow(_b[0], (_c = object, _c[0] = Math.pow(_c[0], 2)))); +(_d = object, _d[0] = Math.pow(_d[0], Math.pow(object[0], 2))); var _a, _b, _c, _d; diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.js b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.js index 001f970b0d3..f61693f192c 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.js +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.js @@ -23,7 +23,7 @@ function incrementIdx(max) { return idx; } var array1 = [1, 2, 3, 4, 5]; -_a = array1, _i = incrementIdx(array1.length), _a[_i] = Math.pow(_a[_i], 3); -_b = array1, _c = incrementIdx(array1.length), _b[_c] = Math.pow(_b[_c], (_d = array1, _e = incrementIdx(array1.length), _d[_e] = Math.pow(_d[_e], 2))); -_f = array1, _g = incrementIdx(array1.length), _f[_g] = Math.pow(_f[_g], Math.pow(array1[incrementIdx(array1.length)], 2)); +(_a = array1, _i = incrementIdx(array1.length), _a[_i] = Math.pow(_a[_i], 3)); +(_b = array1, _c = incrementIdx(array1.length), _b[_c] = Math.pow(_b[_c], (_d = array1, _e = incrementIdx(array1.length), _d[_e] = Math.pow(_d[_e], 2)))); +(_f = array1, _g = incrementIdx(array1.length), _f[_g] = Math.pow(_f[_g], Math.pow(array1[incrementIdx(array1.length)], 2))); var _a, _i, _b, _c, _d, _e, _f, _g; diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.js b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.js index 5f51b432e20..99204e6362c 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.js +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.js @@ -18,10 +18,10 @@ function foo() { globalCounter += 1; return { prop: 2 }; } -_a = foo(), _a.prop = Math.pow(_a.prop, 2); +(_a = foo(), _a.prop = Math.pow(_a.prop, 2)); var result0 = (_b = foo(), _b.prop = Math.pow(_b.prop, 2)); -_c = foo(), _c.prop = Math.pow(_c.prop, (_d = foo(), _d.prop = Math.pow(_d.prop, 2))); +(_c = foo(), _c.prop = Math.pow(_c.prop, (_d = foo(), _d.prop = Math.pow(_d.prop, 2)))); var result1 = (_e = foo(), _e.prop = Math.pow(_e.prop, (_f = foo(), _f.prop = Math.pow(_f.prop, 2)))); -_g = foo(), _g.prop = Math.pow(_g.prop, Math.pow(foo().prop, 2)); +(_g = foo(), _g.prop = Math.pow(_g.prop, Math.pow(foo().prop, 2))); var result2 = (_h = foo(), _h.prop = Math.pow(_h.prop, Math.pow(foo().prop, 2))); var _a, _b, _c, _d, _e, _f, _g, _h;