Skip to content

Commit

Permalink
Sort module export names (#13788)
Browse files Browse the repository at this point in the history
* fix: sort export init statements by name

* update test fixtures

* refactor: reduce memory footprint

* review comments
  • Loading branch information
JLHwung committed Sep 26, 2021
1 parent 6818b22 commit 14572e1
Show file tree
Hide file tree
Showing 74 changed files with 220 additions and 171 deletions.
97 changes: 69 additions & 28 deletions packages/babel-helper-module-transforms/src/index.ts
Expand Up @@ -241,7 +241,7 @@ export function buildNamespaceInitStatements(
const ReexportTemplate = {
constant: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`,
constantComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`,
spec: template`
spec: template.statement`
Object.defineProperty(EXPORTS, "EXPORT_NAME", {
enumerable: true,
get: function() {
Expand Down Expand Up @@ -412,43 +412,92 @@ function buildExportInitializationStatements(
constantReexports: boolean = false,
noIncompleteNsImportDetection = false,
) {
const initStatements = [];
const initStatements: Array<[string, t.Statement | null]> = [];

const exportNames = [];
for (const [localName, data] of metadata.local) {
if (data.kind === "import") {
// No-open since these are explicitly set with the "reexports" block.
} else if (data.kind === "hoisted") {
initStatements.push(
initStatements.push([
// data.names is always of length 1 because a hoisted export
// name must be id of a function declaration
data.names[0],
buildInitStatement(metadata, data.names, identifier(localName)),
);
} else {
exportNames.push(...data.names);
]);
} else if (!noIncompleteNsImportDetection) {
for (const exportName of data.names) {
initStatements.push([exportName, null]);
}
}
}

for (const data of metadata.source.values()) {
if (!constantReexports) {
initStatements.push(...buildReexportsFromMeta(metadata, data, false));
const reexportsStatements = buildReexportsFromMeta(metadata, data, false);
const reexports = [...data.reexports.keys()];
for (let i = 0; i < reexportsStatements.length; i++) {
initStatements.push([reexports[i], reexportsStatements[i]]);
}
}
for (const exportName of data.reexportNamespace) {
exportNames.push(exportName);
if (!noIncompleteNsImportDetection) {
for (const exportName of data.reexportNamespace) {
initStatements.push([exportName, null]);
}
}
}

if (!noIncompleteNsImportDetection) {
initStatements.push(
...chunk(exportNames, 100).map(members => {
return buildInitStatement(
metadata,
members,
programPath.scope.buildUndefinedNode(),
// https://tc39.es/ecma262/#sec-module-namespace-exotic-objects
// The [Exports] list is ordered as if an Array of those String values
// had been sorted using %Array.prototype.sort% using undefined as comparefn
initStatements.sort((a, b) => (a[0] > b[0] ? 1 : -1));

const results = [];
if (noIncompleteNsImportDetection) {
for (const [, initStatement] of initStatements) {
results.push(initStatement);
}
} else {
// We generate init statements (`exports.a = exports.b = ... = void 0`)
// for every 100 exported names to avoid deeply-nested AST structures.
const chunkSize = 100;
for (
let i = 0, uninitializedExportNames = [];
i < initStatements.length;
i += chunkSize
) {
for (let j = 0; j < chunkSize && i + j < initStatements.length; j++) {
const [exportName, initStatement] = initStatements[i + j];
if (initStatement !== null) {
if (uninitializedExportNames.length > 0) {
results.push(
buildInitStatement(
metadata,
uninitializedExportNames,
programPath.scope.buildUndefinedNode(),
),
);
// reset after uninitializedExportNames has been transformed
// to init statements
uninitializedExportNames = [];
}
results.push(initStatement);
} else {
uninitializedExportNames.push(exportName);
}
}
if (uninitializedExportNames.length > 0) {
results.push(
buildInitStatement(
metadata,
uninitializedExportNames,
programPath.scope.buildUndefinedNode(),
),
);
}),
);
}
}
}

return initStatements;
return results;
}

/**
Expand Down Expand Up @@ -477,11 +526,3 @@ function buildInitStatement(metadata: ModuleMetadata, exportNames, initExpr) {
}, initExpr),
);
}

function chunk(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
Expand Up @@ -4,16 +4,16 @@ define(["exports", "foo"], function (_exports, _foo) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
Object.defineProperty(_exports, "foo", {
Object.defineProperty(_exports, "bar", {
enumerable: true,
get: function () {
return _foo.foo;
return _foo.bar;
}
});
Object.defineProperty(_exports, "bar", {
Object.defineProperty(_exports, "foo", {
enumerable: true,
get: function () {
return _foo.bar;
return _foo.foo;
}
});
});
Expand Up @@ -4,16 +4,16 @@ define(["exports", "foo"], function (_exports, _foo) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
Object.defineProperty(_exports, "default", {
Object.defineProperty(_exports, "bar", {
enumerable: true,
get: function () {
return _foo.foo;
return _foo.bar;
}
});
Object.defineProperty(_exports, "bar", {
Object.defineProperty(_exports, "default", {
enumerable: true,
get: function () {
return _foo.bar;
return _foo.foo;
}
});
});
Expand Up @@ -4,7 +4,7 @@ define(["exports"], function (_exports) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.foo = void 0;
_exports.foo = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports.foo = foo;
Expand Down
Expand Up @@ -4,7 +4,7 @@ define(["exports"], function (_exports) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.default = void 0;
_exports.default = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports.default = foo;
Expand Down
Expand Up @@ -4,8 +4,9 @@ define(["exports"], function (_exports) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.foo7 = _exports.foo6 = _exports.foo5 = _exports.foo4 = _exports.foo3 = _exports.foo2 = _exports.foo = _exports.bar = void 0;
_exports.foo8 = foo8;
_exports.foo9 = _exports.foo7 = _exports.foo6 = _exports.foo5 = _exports.foo4 = _exports.foo3 = _exports.bar = _exports.foo2 = _exports.foo = void 0;
_exports.foo9 = void 0;
var foo = 1;
_exports.foo = foo;
var foo2 = 1,
Expand Down
Expand Up @@ -4,8 +4,8 @@ define(["exports", "./evens"], function (_exports, _evens) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.nextOdd = nextOdd;
_exports.isOdd = void 0;
_exports.nextOdd = nextOdd;

function nextOdd(n) {
return (0, _evens.isEven)(n) ? n + 1 : n + 2;
Expand Down
Expand Up @@ -4,7 +4,7 @@ define(["exports", "foo", "foo-bar", "./directory/foo-bar"], function (_exports,
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.default = _exports.test2 = _exports.test = void 0;
_exports.test2 = _exports.test = _exports.default = void 0;
foo2 = babelHelpers.interopRequireWildcard(foo2);
var test;
_exports.test = test;
Expand Down
Expand Up @@ -4,7 +4,7 @@ define(["exports"], function (_exports) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.f = _exports.e = _exports.c = _exports.a = _exports.test = void 0;
_exports.test = _exports.f = _exports.e = _exports.c = _exports.a = void 0;
var test = 2;
_exports.test = test;
_exports.test = test = 5;
Expand Down
Expand Up @@ -4,7 +4,7 @@ define(["exports", "foo"], function (_exports, _foo) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.default = void 0;
_exports.default = _exports.bar = void 0;
_exports.default = _foo.foo;
_exports.bar = _foo.bar;
});
Expand Up @@ -4,7 +4,7 @@ define(["exports", "foo"], function (_exports, _foo) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.foo = void 0;
_exports.foo = _exports.bar = void 0;
_exports.foo = _foo.foo;
_exports.bar = _foo.bar;
});
Expand Up @@ -2,7 +2,7 @@ define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.bar = _exports.defaultExports = void 0;
_exports.defaultExports = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports.defaultExports = foo;
Expand Down
Expand Up @@ -2,7 +2,7 @@ define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.bar = _exports["default exports"] = void 0;
_exports["default exports"] = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports["default exports"] = foo;
Expand Down
Expand Up @@ -4,7 +4,7 @@ define(["exports"], function (_exports) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.defaultExports = void 0;
_exports.defaultExports = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports.defaultExports = foo;
Expand Down
Expand Up @@ -4,7 +4,7 @@ define(["exports"], function (_exports) {
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports["default exports"] = void 0;
_exports["default exports"] = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports["default exports"] = foo;
Expand Down
Expand Up @@ -2,7 +2,7 @@ define(["exports", "foo"], function (_exports, _foo) {
"use strict";

_exports.__esModule = true;
_exports.bar = _exports.foo = void 0;
_exports.foo = _exports.bar = void 0;
_exports.foo = _foo.foo;
_exports.bar = _foo.bar;
});
Expand Up @@ -2,7 +2,7 @@ define(["exports", "foo"], function (_exports, _foo) {
"use strict";

_exports.__esModule = true;
_exports.bar = _exports.default = void 0;
_exports.default = _exports.bar = void 0;
_exports.default = _foo.foo;
_exports.bar = _foo.bar;
});
Expand Up @@ -2,7 +2,7 @@ define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.bar = _exports.foo = void 0;
_exports.foo = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports.foo = foo;
Expand Down
Expand Up @@ -2,7 +2,7 @@ define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.bar = _exports.default = void 0;
_exports.default = _exports.bar = void 0;
var foo, bar;
_exports.bar = bar;
_exports.default = foo;
Expand Down
Expand Up @@ -2,8 +2,9 @@ define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.foo7 = _exports.foo6 = _exports.foo5 = _exports.foo4 = _exports.foo3 = _exports.foo2 = _exports.foo = _exports.bar = void 0;
_exports.foo8 = foo8;
_exports.foo9 = _exports.foo7 = _exports.foo6 = _exports.foo5 = _exports.foo4 = _exports.foo3 = _exports.bar = _exports.foo2 = _exports.foo = void 0;
_exports.foo9 = void 0;
var foo = 1;
_exports.foo = foo;
var foo2 = 1,
Expand Down
Expand Up @@ -2,8 +2,8 @@ define(["exports", "./evens"], function (_exports, _evens) {
"use strict";

_exports.__esModule = true;
_exports.nextOdd = nextOdd;
_exports.isOdd = void 0;
_exports.nextOdd = nextOdd;

function nextOdd(n) {
return (0, _evens.isEven)(n) ? n + 1 : n + 2;
Expand Down
Expand Up @@ -2,7 +2,7 @@ define(["exports", "foo", "foo-bar", "./directory/foo-bar"], function (_exports,
"use strict";

_exports.__esModule = true;
_exports.default = _exports.test2 = _exports.test = void 0;
_exports.test2 = _exports.test = _exports.default = void 0;
foo2 = babelHelpers.interopRequireWildcard(foo2);
var test;
_exports.test = test;
Expand Down
Expand Up @@ -2,7 +2,7 @@ define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.f = _exports.e = _exports.c = _exports.a = _exports.test = void 0;
_exports.test = _exports.f = _exports.e = _exports.c = _exports.a = void 0;
var test = 2;
_exports.test = test;
_exports.test = test = 5;
Expand Down
Expand Up @@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.bar = exports.default = void 0;
exports.default = exports.bar = void 0;

var _foo = require("foo");

Expand Down
Expand Up @@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.bar = exports.foo = void 0;
exports.foo = exports.bar = void 0;

var _foo = require("foo");

Expand Down
@@ -1,7 +1,7 @@
"use strict";

exports.__esModule = true;
exports.bar = exports.foo = void 0;
exports.foo = exports.bar = void 0;

var _foo = require("foo");

Expand Down
@@ -1,7 +1,7 @@
"use strict";

exports.__esModule = true;
exports.bar = exports.default = void 0;
exports.default = exports.bar = void 0;

var _foo = require("foo");

Expand Down

0 comments on commit 14572e1

Please sign in to comment.