Skip to content

Commit fd55587

Browse files
authored
fix: add declaration for unused harmony import specifier (#20286)
1 parent 03440e2 commit fd55587

7 files changed

Lines changed: 94 additions & 3 deletions

File tree

.changeset/sixty-elephants-poke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"webpack": patch
3+
---
4+
5+
Add declaration for unused harmony import specifier.

lib/dependencies/HarmonyImportSpecifierDependency.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"use strict";
77

88
const Dependency = require("../Dependency");
9+
const InitFragment = require("../InitFragment");
910
const Template = require("../Template");
1011
const {
1112
getDependencyUsedByExportsCondition
@@ -336,10 +337,22 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
336337
*/
337338
apply(dependency, source, templateContext) {
338339
const dep = /** @type {HarmonyImportSpecifierDependency} */ (dependency);
339-
const { moduleGraph, runtime } = templateContext;
340+
const { moduleGraph, runtime, initFragments } = templateContext;
340341
const connection = moduleGraph.getConnection(dep);
341-
// Skip rendering depending when dependency is conditional
342-
if (connection && !connection.isTargetActive(runtime)) return;
342+
343+
// Only render declaration for import specifier when the dependency is conditional
344+
if (connection && !connection.isTargetActive(runtime)) {
345+
initFragments.push(
346+
new InitFragment(
347+
`/* unused harmony import specifier */ var ${dep.name};\n`,
348+
InitFragment.STAGE_HARMONY_IMPORTS,
349+
0,
350+
`unused import specifier ${dep.name}`
351+
)
352+
);
353+
354+
return;
355+
}
343356

344357
const ids = dep.getIds(moduleGraph);
345358
const {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function __( v ) {
2+
console.log( v );
3+
}
4+
5+
export default {
6+
__,
7+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import i18n from "./i18n.js";
2+
import { used } from "./wtf.js";
3+
import { parse } from "acorn";
4+
import fs from "fs";
5+
6+
const __ = i18n.__;
7+
8+
function xyz() {
9+
used();
10+
__("abc");
11+
}
12+
xyz();
13+
14+
it("Should keep top-level `__` variable name in the entry module", () => {
15+
const bundle = fs.readFileSync(__filename, "utf-8");
16+
17+
const ast = parse(bundle, {
18+
sourceType: "module",
19+
ecmaVersion: "latest"
20+
});
21+
22+
expect(
23+
ast.body.some(
24+
(node) =>
25+
node.type === "VariableDeclaration" &&
26+
node.declarations.some(
27+
(declaration) =>
28+
declaration.id.type === "Identifier" && declaration.id.name === "__"
29+
)
30+
)
31+
).toBe(true);
32+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"use strict";
2+
3+
const supportsRequireInModule = require("../../../helpers/supportsRequireInModule");
4+
5+
module.exports = () => supportsRequireInModule();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"use strict";
2+
3+
/** @type {import("../../../../").Configuration} */
4+
module.exports = {
5+
mode: "production",
6+
target: "node14",
7+
optimization: {
8+
minimize: false,
9+
mangleExports: false,
10+
concatenateModules: false,
11+
emitOnErrors: true
12+
},
13+
output: {
14+
module: true
15+
},
16+
experiments: {
17+
outputModule: true
18+
},
19+
externals: ["acorn"]
20+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { __ } from './i18n.js';
2+
3+
export function unused() {
4+
return __( "wtf" );
5+
}
6+
7+
export function used() {
8+
return __( "ok" );
9+
}

0 commit comments

Comments
 (0)