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

fix(deconflictChunk): Deconflict multiple index imports for ES format using nested export star statements #3435

Merged
11 changes: 10 additions & 1 deletion src/utils/deconflictChunk.ts
Expand Up @@ -51,9 +51,18 @@ export function deconflictChunk(
function deconflictImportsEsm(
usedNames: Set<string>,
imports: Set<Variable>,
_dependencies: Set<ExternalModule | Chunk>,
dependencies: Set<ExternalModule | Chunk>,
interop: boolean
) {
for (const chunkOrExternalModule of dependencies) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this logic from deconflictImportsOther and only applied with the index variable name to account for export * from './inner' statements. However, I don't know what other implications this has! 🤔

Copy link
Member

Choose a reason for hiding this comment

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

I'll have a look, thanks already for your work!

Copy link
Member

Choose a reason for hiding this comment

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

Your proposed fix will only work for your example as the variable is only called "index" because your file is called "index". A general fix would be to run this for ALL dependencies, however this will cause a lot of test regressions (as you may have noticed) due to a lot of unnecessary renames. The core of the problem is that reexporting a namespace is rendered (in es.ts) as importing the namespace as some variable and then exporting this variable, and this variable is not considered for deconflicting. A "nice" fix would be much more involved, but maybe this extends the scope of the bug fix. A simple hot "blanket" fix with only few regressions would be to unconditionally deconflict the chunk variable names for all dependencies, but only do it if we are preserving modules. Maybe you could do that and add a comment what is fixed here and that this solution is not yet ideal (so that it is not forgotten)?

Copy link
Member

Choose a reason for hiding this comment

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

The reason it is only necessary for preserveModules is that these kinds of reexports will not occur for other formats. Basically this line is responsible:

rollup/src/Chunk.ts

Lines 386 to 388 in 3ef6f07

if (this.graph.preserveModules && variable instanceof NamespaceVariable) {
return '*';
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Awesome, I will do that and can update the specs to see what that impacts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What I did was only apply this logic for es and preserveModules: true which lessens the impact so it doesn't impact current SystemJS behavior. Am I right in assuming this shouldn't really take effect for SystemJS? Otherwise it was affecting a lot more tests (56 vs. <10).

// only deconflict index aliased variables for ESM/System
if (chunkOrExternalModule.variableName === 'index') {
chunkOrExternalModule.variableName = getSafeName(
chunkOrExternalModule.variableName,
usedNames
);
}
}
for (const variable of imports) {
const module = variable.module;
const name = variable.name;
Expand Down
@@ -0,0 +1,7 @@
module.exports = {
description: 'confirm exports are deconflicted when exporting nested index aliases',
options: {
input: 'main.js',
preserveModules: true
}
};
@@ -0,0 +1,10 @@
define(['exports', './module-a/v1/index', './module-b/v1/index'], function (exports, index, index$1) { 'use strict';



exports.ModuleA_V1 = index;
exports.ModuleB_V1 = index$1;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,9 @@
define(['exports'], function (exports) { 'use strict';

const TEST_MODULE_A = 'A';

exports.TEST_MODULE_A = TEST_MODULE_A;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,9 @@
define(['exports'], function (exports) { 'use strict';

const TEST_MODULE_B = 'A';

exports.TEST_MODULE_B = TEST_MODULE_B;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,11 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var index = require('./module-a/v1/index.js');
var index$1 = require('./module-b/v1/index.js');



exports.ModuleA_V1 = index;
exports.ModuleB_V1 = index$1;
@@ -0,0 +1,7 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const TEST_MODULE_A = 'A';

exports.TEST_MODULE_A = TEST_MODULE_A;
@@ -0,0 +1,7 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const TEST_MODULE_B = 'A';

exports.TEST_MODULE_B = TEST_MODULE_B;
@@ -0,0 +1,4 @@
import * as index from './module-a/v1/index.js';
export { index as ModuleA_V1 };
import * as index$1 from './module-b/v1/index.js';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the main goal of this PR, to deconflict the index imports.

export { index$1 as ModuleB_V1 };
@@ -0,0 +1,3 @@
const TEST_MODULE_A = 'A';

export { TEST_MODULE_A };
@@ -0,0 +1,3 @@
const TEST_MODULE_B = 'A';

export { TEST_MODULE_B };
@@ -0,0 +1,15 @@
System.register(['./module-a/v1/index.js', './module-b/v1/index.js'], function (exports) {
'use strict';
return {
setters: [function (module) {
exports('ModuleA_V1', module);
}, function (module) {
exports('ModuleB_V1', module);
}],
execute: function () {



}
};
});
@@ -0,0 +1,10 @@
System.register([], function (exports) {
'use strict';
return {
execute: function () {

const TEST_MODULE_A = exports('TEST_MODULE_A', 'A');

}
};
});
@@ -0,0 +1,10 @@
System.register([], function (exports) {
'use strict';
return {
execute: function () {

const TEST_MODULE_B = exports('TEST_MODULE_B', 'A');

}
};
});
@@ -0,0 +1,2 @@
export * from './module-a/index'
export * from './module-b/index'
@@ -0,0 +1,3 @@
import * as ModuleA_V1 from './v1/index'

export { ModuleA_V1 }
@@ -0,0 +1 @@
export const TEST_MODULE_A = 'A'
@@ -0,0 +1,3 @@
import * as ModuleB_V1 from './v1/index'

export { ModuleB_V1 }
@@ -0,0 +1 @@
export const TEST_MODULE_B = 'A'