diff --git a/src/ast/nodes/AssignmentExpression.ts b/src/ast/nodes/AssignmentExpression.ts index 98a539d3db5..9daabe0bd36 100644 --- a/src/ast/nodes/AssignmentExpression.ts +++ b/src/ast/nodes/AssignmentExpression.ts @@ -1,5 +1,5 @@ import MagicString from 'magic-string'; -import { RenderOptions } from '../../utils/renderHelpers'; +import { findFirstOccurrenceOutsideComment, RenderOptions } from '../../utils/renderHelpers'; import { getSystemExportStatement } from '../../utils/systemJsRendering'; import { HasEffectsContext } from '../ExecutionContext'; import { EMPTY_PATH, ObjectPath, UNKNOWN_PATH } from '../utils/PathTracker'; @@ -51,9 +51,19 @@ export default class AssignmentExpression extends NodeBase { this.right.render(code, options); if (options.format === 'system') { if (this.left.variable && this.left.variable.exportName) { - code.prependLeft( - code.original.indexOf('=', this.left.end) + 1, - ` exports('${this.left.variable.exportName}',` + const operatorPos = findFirstOccurrenceOutsideComment( + code.original, + this.operator, + this.left.end + ); + const operation = + this.operator.length > 1 + ? ` ${this.left.variable.exportName} ${this.operator.slice(0, -1)}` + : ''; + code.overwrite( + operatorPos, + operatorPos + this.operator.length, + `= exports('${this.left.variable.exportName}',${operation}` ); code.appendLeft(this.right.end, `)`); } else if ('addExportedVariables' in this.left) { diff --git a/src/utils/renderHelpers.ts b/src/utils/renderHelpers.ts index 92b9fdfc82f..3e4610ca9b6 100644 --- a/src/utils/renderHelpers.ts +++ b/src/utils/renderHelpers.ts @@ -30,7 +30,7 @@ export function findFirstOccurrenceOutsideComment(code: string, searchString: st searchPos = code.indexOf(searchString, start); while (true) { start = code.indexOf('/', start); - if (start === -1 || start > searchPos) return searchPos; + if (start === -1 || start >= searchPos) return searchPos; charCodeAfterSlash = code.charCodeAt(++start); ++start; @@ -116,13 +116,13 @@ export function getCommaSeparatedNodesWithBoundaries( code: MagicString, start: number, end: number -): ({ +): { contentEnd: number; end: number; node: N; separator: number | null; start: number; -})[] { +}[] { const splitUpNodes = []; let node, nextNode, nextNodeStart, contentEnd, char; let separator = start - 1; diff --git a/test/form/samples/export-live-bindings/_expected/system.js b/test/form/samples/export-live-bindings/_expected/system.js index 8d0ae5eca0e..9ed7fb7d347 100644 --- a/test/form/samples/export-live-bindings/_expected/system.js +++ b/test/form/samples/export-live-bindings/_expected/system.js @@ -10,7 +10,7 @@ System.register('iife', [], function (exports) { }); function update () { - foo += exports('foo', 10); + foo = exports('foo', foo + 10); } let foo = exports('foo', 10); diff --git a/test/form/samples/updating-assignments/_config.js b/test/form/samples/updating-assignments/_config.js new file mode 100644 index 00000000000..b6633185ee0 --- /dev/null +++ b/test/form/samples/updating-assignments/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'Correctly handles assignment operators on exports', + options: { output: { name: 'bundle' } } +}; diff --git a/test/form/samples/updating-assignments/_expected/amd.js b/test/form/samples/updating-assignments/_expected/amd.js new file mode 100644 index 00000000000..addd8e09cdf --- /dev/null +++ b/test/form/samples/updating-assignments/_expected/amd.js @@ -0,0 +1,20 @@ +define(['exports'], function (exports) { 'use strict'; + + exports.x = 1; + exports.x = 2; + exports.x += 1; + exports.x -= 1; + exports.x *= 2; + exports.x /= 2; + exports.x %= 2; + exports.x **= 2; + exports.x <<= 1; + exports.x >>= 1; + exports.x >>>= 1; + exports.x &= 3; + exports.x ^= 2; + exports.x |= 2; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/samples/updating-assignments/_expected/cjs.js b/test/form/samples/updating-assignments/_expected/cjs.js new file mode 100644 index 00000000000..3824b02062a --- /dev/null +++ b/test/form/samples/updating-assignments/_expected/cjs.js @@ -0,0 +1,18 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +exports.x = 1; +exports.x = 2; +exports.x += 1; +exports.x -= 1; +exports.x *= 2; +exports.x /= 2; +exports.x %= 2; +exports.x **= 2; +exports.x <<= 1; +exports.x >>= 1; +exports.x >>>= 1; +exports.x &= 3; +exports.x ^= 2; +exports.x |= 2; diff --git a/test/form/samples/updating-assignments/_expected/es.js b/test/form/samples/updating-assignments/_expected/es.js new file mode 100644 index 00000000000..79bccd4fc74 --- /dev/null +++ b/test/form/samples/updating-assignments/_expected/es.js @@ -0,0 +1,16 @@ +let x = 1; +x = 2; +x += 1; +x -= 1; +x *= 2; +x /= 2; +x %= 2; +x **= 2; +x <<= 1; +x >>= 1; +x >>>= 1; +x &= 3; +x ^= 2; +x |= 2; + +export { x }; diff --git a/test/form/samples/updating-assignments/_expected/iife.js b/test/form/samples/updating-assignments/_expected/iife.js new file mode 100644 index 00000000000..381fa322c49 --- /dev/null +++ b/test/form/samples/updating-assignments/_expected/iife.js @@ -0,0 +1,21 @@ +var bundle = (function (exports) { + 'use strict'; + + exports.x = 1; + exports.x = 2; + exports.x += 1; + exports.x -= 1; + exports.x *= 2; + exports.x /= 2; + exports.x %= 2; + exports.x **= 2; + exports.x <<= 1; + exports.x >>= 1; + exports.x >>>= 1; + exports.x &= 3; + exports.x ^= 2; + exports.x |= 2; + + return exports; + +}({})); diff --git a/test/form/samples/updating-assignments/_expected/system.js b/test/form/samples/updating-assignments/_expected/system.js new file mode 100644 index 00000000000..78a7127d368 --- /dev/null +++ b/test/form/samples/updating-assignments/_expected/system.js @@ -0,0 +1,23 @@ +System.register('bundle', [], function (exports) { + 'use strict'; + return { + execute: function () { + + let x = exports('x', 1); + x = exports('x', 2); + x = exports('x', x + 1); + x = exports('x', x - 1); + x = exports('x', x * 2); + x = exports('x', x / 2); + x = exports('x', x % 2); + x = exports('x', x ** 2); + x = exports('x', x << 1); + x = exports('x', x >> 1); + x = exports('x', x >>> 1); + x = exports('x', x & 3); + x = exports('x', x ^ 2); + x = exports('x', x | 2); + + } + }; +}); diff --git a/test/form/samples/updating-assignments/_expected/umd.js b/test/form/samples/updating-assignments/_expected/umd.js new file mode 100644 index 00000000000..7500d5fd59f --- /dev/null +++ b/test/form/samples/updating-assignments/_expected/umd.js @@ -0,0 +1,24 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.bundle = {})); +}(this, (function (exports) { 'use strict'; + + exports.x = 1; + exports.x = 2; + exports.x += 1; + exports.x -= 1; + exports.x *= 2; + exports.x /= 2; + exports.x %= 2; + exports.x **= 2; + exports.x <<= 1; + exports.x >>= 1; + exports.x >>>= 1; + exports.x &= 3; + exports.x ^= 2; + exports.x |= 2; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/samples/updating-assignments/main.js b/test/form/samples/updating-assignments/main.js new file mode 100644 index 00000000000..fe7d0c7cde5 --- /dev/null +++ b/test/form/samples/updating-assignments/main.js @@ -0,0 +1,14 @@ +export let x = 1; +x = 2; +x += 1; +x -= 1; +x *= 2; +x /= 2; +x %= 2; +x **= 2; +x <<= 1; +x >>= 1; +x >>>= 1; +x &= 3; +x ^= 2; +x |= 2;