diff --git a/src/ast/nodes/VariableDeclaration.ts b/src/ast/nodes/VariableDeclaration.ts index f9c0d902007..8bd75f33223 100644 --- a/src/ast/nodes/VariableDeclaration.ts +++ b/src/ast/nodes/VariableDeclaration.ts @@ -1,5 +1,6 @@ import MagicString from 'magic-string'; import { BLANK } from '../../utils/blank'; +import { isReassignedExportsMember } from '../../utils/reassignedExportsMember'; import { findFirstOccurrenceOutsideComment, findNonWhiteSpace, @@ -19,15 +20,6 @@ import * as NodeType from './NodeType'; import { IncludeChildren, NodeBase } from './shared/Node'; import VariableDeclarator from './VariableDeclarator'; -function isReassignedExportsMember( - variable: Variable, - exportNamesByVariable: Map -): boolean { - return ( - variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned - ); -} - function areAllDeclarationsIncludedAndNotExported( declarations: VariableDeclarator[], exportNamesByVariable: Map @@ -168,15 +160,7 @@ export default class VariableDeclaration extends NodeBase { nextSeparatorString; const systemPatternExports: Variable[] = []; for (const { node, start, separator, contentEnd, end } of separatedNodes) { - if ( - !node.included || - (node.id instanceof Identifier && - isReassignedExportsMember( - (node.id as IdentifierWithVariable).variable, - options.exportNamesByVariable - ) && - node.init === null) - ) { + if (!node.included) { code.remove(start, end); continue; } diff --git a/src/ast/nodes/VariableDeclarator.ts b/src/ast/nodes/VariableDeclarator.ts index 4ffca9274b7..40cd81a57db 100644 --- a/src/ast/nodes/VariableDeclarator.ts +++ b/src/ast/nodes/VariableDeclarator.ts @@ -1,5 +1,6 @@ import MagicString from 'magic-string'; import { BLANK } from '../../utils/blank'; +import { isReassignedExportsMember } from '../../utils/reassignedExportsMember'; import { findFirstOccurrenceOutsideComment, findNonWhiteSpace, @@ -8,6 +9,7 @@ import { import { HasEffectsContext, InclusionContext } from '../ExecutionContext'; import { ObjectPath } from '../utils/PathTracker'; import { UNDEFINED_EXPRESSION } from '../values'; +import Identifier from './Identifier'; import * as NodeType from './NodeType'; import { ExpressionNode, IncludeChildren, NodeBase } from './shared/Node'; import { PatternNode } from './shared/Pattern'; @@ -53,6 +55,12 @@ export default class VariableDeclarator extends NodeBase { options, renderId ? BLANK : { renderedParentType: NodeType.ExpressionStatement } ); + } else if ( + this.id instanceof Identifier && + isReassignedExportsMember(this.id.variable!, options.exportNamesByVariable) + ) { + const _ = options.compact ? '' : ' '; + code.appendLeft(this.end, `${_}=${_}void 0`); } } } diff --git a/src/utils/reassignedExportsMember.ts b/src/utils/reassignedExportsMember.ts new file mode 100644 index 00000000000..c51081a5bc4 --- /dev/null +++ b/src/utils/reassignedExportsMember.ts @@ -0,0 +1,10 @@ +import Variable from '../ast/variables/Variable'; + +export function isReassignedExportsMember( + variable: Variable, + exportNamesByVariable: Map +): boolean { + return ( + variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned + ); +} diff --git a/test/form/samples/assignment-to-exports/_expected/amd.js b/test/form/samples/assignment-to-exports/_expected/amd.js index 105bbafaa28..0dd931f9d2c 100644 --- a/test/form/samples/assignment-to-exports/_expected/amd.js +++ b/test/form/samples/assignment-to-exports/_expected/amd.js @@ -5,6 +5,7 @@ define(['exports'], function (exports) { 'use strict'; // Reassigned uninitialised export exports.bar1 = 1; + exports.bar1 = void 0; // Reassigned initialised export exports.baz1 = 1; @@ -14,7 +15,7 @@ define(['exports'], function (exports) { 'use strict'; var kept1, foo2, kept2; // Reassigned uninitialised export - var kept1, kept2; + var kept1; exports.bar2 = void 0; var kept2; exports.bar2 = 1; // Reassigned initialised export diff --git a/test/form/samples/assignment-to-exports/_expected/cjs.js b/test/form/samples/assignment-to-exports/_expected/cjs.js index ea5ad72b662..2adec04748f 100644 --- a/test/form/samples/assignment-to-exports/_expected/cjs.js +++ b/test/form/samples/assignment-to-exports/_expected/cjs.js @@ -7,6 +7,7 @@ var foo1; // Reassigned uninitialised export exports.bar1 = 1; +exports.bar1 = void 0; // Reassigned initialised export exports.baz1 = 1; @@ -16,7 +17,7 @@ exports.baz1 = 2; var kept1, foo2, kept2; // Reassigned uninitialised export -var kept1, kept2; +var kept1; exports.bar2 = void 0; var kept2; exports.bar2 = 1; // Reassigned initialised export diff --git a/test/form/samples/assignment-to-exports/_expected/es.js b/test/form/samples/assignment-to-exports/_expected/es.js index c62d345cab2..ff2fbc305b8 100644 --- a/test/form/samples/assignment-to-exports/_expected/es.js +++ b/test/form/samples/assignment-to-exports/_expected/es.js @@ -3,7 +3,7 @@ var foo1; // Reassigned uninitialised export bar1 = 1; -var bar1; // this will be removed for non ES6 bundles +var bar1; // Reassigned initialised export var baz1 = 1; diff --git a/test/form/samples/assignment-to-exports/_expected/iife.js b/test/form/samples/assignment-to-exports/_expected/iife.js index 6e80662b252..a26ab26dabe 100644 --- a/test/form/samples/assignment-to-exports/_expected/iife.js +++ b/test/form/samples/assignment-to-exports/_expected/iife.js @@ -6,6 +6,7 @@ var bundle = (function (exports) { // Reassigned uninitialised export exports.bar1 = 1; + exports.bar1 = void 0; // Reassigned initialised export exports.baz1 = 1; @@ -15,7 +16,7 @@ var bundle = (function (exports) { var kept1, foo2, kept2; // Reassigned uninitialised export - var kept1, kept2; + var kept1; exports.bar2 = void 0; var kept2; exports.bar2 = 1; // Reassigned initialised export diff --git a/test/form/samples/assignment-to-exports/_expected/system.js b/test/form/samples/assignment-to-exports/_expected/system.js index f854248e45a..4c730ae6d67 100644 --- a/test/form/samples/assignment-to-exports/_expected/system.js +++ b/test/form/samples/assignment-to-exports/_expected/system.js @@ -15,7 +15,7 @@ System.register('bundle', [], function (exports) { // Reassigned uninitialised export bar1 = exports('bar1', 1); - var bar1; // this will be removed for non ES6 bundles + var bar1; // Reassigned initialised export var baz1 = exports('baz1', 1); diff --git a/test/form/samples/assignment-to-exports/_expected/umd.js b/test/form/samples/assignment-to-exports/_expected/umd.js index 9243760ae9c..3f3358fec23 100644 --- a/test/form/samples/assignment-to-exports/_expected/umd.js +++ b/test/form/samples/assignment-to-exports/_expected/umd.js @@ -9,6 +9,7 @@ // Reassigned uninitialised export exports.bar1 = 1; + exports.bar1 = void 0; // Reassigned initialised export exports.baz1 = 1; @@ -18,7 +19,7 @@ var kept1, foo2, kept2; // Reassigned uninitialised export - var kept1, kept2; + var kept1; exports.bar2 = void 0; var kept2; exports.bar2 = 1; // Reassigned initialised export diff --git a/test/form/samples/assignment-to-exports/main.js b/test/form/samples/assignment-to-exports/main.js index d86f2ee5a1e..63c522cffc2 100644 --- a/test/form/samples/assignment-to-exports/main.js +++ b/test/form/samples/assignment-to-exports/main.js @@ -3,7 +3,7 @@ export var foo1; // Reassigned uninitialised export bar1 = 1; -export var bar1; // this will be removed for non ES6 bundles +export var bar1; // Reassigned initialised export export var baz1 = 1; diff --git a/test/form/samples/render-named-export-declarations/_expected/amd.js b/test/form/samples/render-named-export-declarations/_expected/amd.js index 69e4e761995..cf8c0616726 100644 --- a/test/form/samples/render-named-export-declarations/_expected/amd.js +++ b/test/form/samples/render-named-export-declarations/_expected/amd.js @@ -1,9 +1,9 @@ define(['exports'], function (exports) { 'use strict'; - var aFoo; + var aFoo; exports.aBar = void 0; exports.aBar = 2; - var bBar; + exports.bFoo = void 0; var bBar; exports.bFoo = 2; var cFoo; exports.cBar = 1; diff --git a/test/form/samples/render-named-export-declarations/_expected/cjs.js b/test/form/samples/render-named-export-declarations/_expected/cjs.js index f5fac90e0ce..f21aa19e750 100644 --- a/test/form/samples/render-named-export-declarations/_expected/cjs.js +++ b/test/form/samples/render-named-export-declarations/_expected/cjs.js @@ -2,10 +2,10 @@ Object.defineProperty(exports, '__esModule', { value: true }); -var aFoo; +var aFoo; exports.aBar = void 0; exports.aBar = 2; -var bBar; +exports.bFoo = void 0; var bBar; exports.bFoo = 2; var cFoo; exports.cBar = 1; diff --git a/test/form/samples/render-named-export-declarations/_expected/iife.js b/test/form/samples/render-named-export-declarations/_expected/iife.js index 495366e72c2..bdc716b73cf 100644 --- a/test/form/samples/render-named-export-declarations/_expected/iife.js +++ b/test/form/samples/render-named-export-declarations/_expected/iife.js @@ -1,10 +1,10 @@ var bundle = (function (exports) { 'use strict'; - var aFoo; + var aFoo; exports.aBar = void 0; exports.aBar = 2; - var bBar; + exports.bFoo = void 0; var bBar; exports.bFoo = 2; var cFoo; exports.cBar = 1; diff --git a/test/form/samples/render-named-export-declarations/_expected/umd.js b/test/form/samples/render-named-export-declarations/_expected/umd.js index 1b5c9d55db3..578818ce0c5 100644 --- a/test/form/samples/render-named-export-declarations/_expected/umd.js +++ b/test/form/samples/render-named-export-declarations/_expected/umd.js @@ -4,10 +4,10 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bundle = {})); }(this, (function (exports) { 'use strict'; - var aFoo; + var aFoo; exports.aBar = void 0; exports.aBar = 2; - var bBar; + exports.bFoo = void 0; var bBar; exports.bFoo = 2; var cFoo; exports.cBar = 1; diff --git a/test/function/samples/create-undefined-export-property/_config.js b/test/function/samples/create-undefined-export-property/_config.js new file mode 100644 index 00000000000..7c95c097373 --- /dev/null +++ b/test/function/samples/create-undefined-export-property/_config.js @@ -0,0 +1,16 @@ +const assert = require('assert'); + +module.exports = { + description: 'creates an export as an exports property even if is has no initializer', + exports(exports) { + assert.strictEqual(exports.foo, undefined); + assert.strictEqual(exports.bar, undefined); + assert.strictEqual(exports.baz, undefined); + assert.ok(exports.hasOwnProperty('foo')); + assert.ok(exports.hasOwnProperty('bar')); + assert.ok(exports.hasOwnProperty('baz')); + exports.defineFooBar(); + assert.strictEqual(exports.foo, 'defined'); + assert.strictEqual(exports.bar, 'defined'); + } +}; diff --git a/test/function/samples/create-undefined-export-property/main.js b/test/function/samples/create-undefined-export-property/main.js new file mode 100644 index 00000000000..a8140d19b7f --- /dev/null +++ b/test/function/samples/create-undefined-export-property/main.js @@ -0,0 +1,6 @@ +export let foo; +export let bar, quux = 3, baz; +export function defineFooBar() { + foo = 'defined'; + bar = 'defined'; +} diff --git a/test/function/samples/destructuring-loop/_config.js b/test/function/samples/destructuring-loop/_config.js new file mode 100644 index 00000000000..a7307a7e141 --- /dev/null +++ b/test/function/samples/destructuring-loop/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'handles loops with destructuring declarations' +}; diff --git a/test/function/samples/destructuring-loop/main.js b/test/function/samples/destructuring-loop/main.js new file mode 100644 index 00000000000..15e47102ef3 --- /dev/null +++ b/test/function/samples/destructuring-loop/main.js @@ -0,0 +1,11 @@ +let result; + +for (const [foo] of [['foo']]) { + result = foo; +} +assert.strictEqual(result, 'foo'); + +for (const { bar } of [{ bar: 'bar' }]) { + result = bar; +} +assert.strictEqual(result, 'bar');