Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort module export names #13788

Merged
merged 4 commits into from Sep 26, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.
const chunkSize = 100;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chunk behaviour has existed since 95e08b6#diff-f9b022d801ca0bab9bbb7057b9ac49aac0d8c2ab53f41f97e7e15bdd10f26069R272. I don't know if it is a workaround of browser quirks or it is for aesthetic reasons.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's to avoid a too deeply nested AST

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref - #14272

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