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 HarmonyEvaluatedImportSpecifierDependency #15660

Merged
merged 3 commits into from Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
36 changes: 34 additions & 2 deletions lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js
Expand Up @@ -61,14 +61,46 @@ HarmonyEvaluatedImportSpecifierDependency.Template = class HarmonyEvaluatedImpor
const dep = /** @type {HarmonyEvaluatedImportSpecifierDependency} */ (
dependency
);
const { moduleGraph, runtime } = templateContext;
const { module, moduleGraph, runtime } = templateContext;
const connection = moduleGraph.getConnection(dep);
// Skip rendering depending when dependency is conditional
if (connection && !connection.isTargetActive(runtime)) return;

const exportsInfo = moduleGraph.getExportsInfo(connection.module);
const ids = dep.getIds(moduleGraph);
const value = exportsInfo.isExportProvided(ids);

let value;

const exportsType = connection.module.getExportsType(
moduleGraph,
module.buildMeta.strictHarmonyModule
);
switch (exportsType) {
case "default-with-named": {
if (ids[0] === "default") {
value =
ids.length === 1 || exportsInfo.isExportProvided(ids.slice(1));
} else {
value = exportsInfo.isExportProvided(ids);
}
break;
}
case "namespace": {
if (ids[0] === "__esModule") {
value = ids.length === 1 || undefined;
} else {
value = exportsInfo.isExportProvided(ids);
}
break;
}
case "dynamic": {
if (ids[0] !== "default") {
value = exportsInfo.isExportProvided(ids);
}
break;
}
// default-only could lead to runtime error, when default value is primitive
}

if (typeof value === "boolean") {
source.replace(dep.range[0], dep.range[1] - 1, `${value}`);
Expand Down
1 change: 1 addition & 0 deletions test/cases/parsing/harmony-deep-exports/cjs2.js
@@ -0,0 +1 @@
module.exports = require("./cjs3");
3 changes: 3 additions & 0 deletions test/cases/parsing/harmony-deep-exports/cjs3.js
@@ -0,0 +1,3 @@
exports.a = 1;
exports.b = 2;
exports.cjs3DefaultProvidedInfo = __webpack_exports_info__.default.provideInfo;
2 changes: 2 additions & 0 deletions test/cases/parsing/harmony-deep-exports/esm1.js
@@ -0,0 +1,2 @@
export default 2;
export const esmDefaultProvidedInfo = __webpack_exports_info__.default.provideInfo;
13 changes: 13 additions & 0 deletions test/cases/parsing/harmony-deep-exports/index.js
@@ -1,6 +1,19 @@
import * as C from "./reexport-namespace";
import { counter } from "./reexport-namespace";
import * as C2 from "./reexport-namespace-again";
import cj2, { cjs3DefaultProvidedInfo } from "./cjs2";
import esm1, { esmDefaultProvidedInfo } from "./esm1";

it("default providedInfo should be correct for cjs", () => {
expect(cj2.a).toBe(1);
expect(cjs3DefaultProvidedInfo).toBe(false);
expect(__webpack_exports_info__.cj2.default.provideInfo).toBe(false);
});

it("default providedInfo and usedInfo should be correct for esm", () => {
expect(esm1).toBe(2);
expect(esmDefaultProvidedInfo).toBe(true);
});

it("should allow to reexport namespaces 1", () => {
(0, counter.reset)();
Expand Down
2 changes: 2 additions & 0 deletions test/cases/parsing/harmony-export-import-specifier/cjs1.js
@@ -0,0 +1,2 @@
exports.a = 2;
exports.b = 3;
1 change: 1 addition & 0 deletions test/cases/parsing/harmony-export-import-specifier/cjs2.js
@@ -0,0 +1 @@
module.exports = require("./cjs1");
14 changes: 14 additions & 0 deletions test/cases/parsing/harmony-export-import-specifier/index.js
Expand Up @@ -7,11 +7,15 @@ import { usedE1, usedE2 } from "./e.js";
import { h } from "./h.js";
import * as m from "./m";
import {object as obj} from "./m";
import cjs from "./cjs2";
import * as o from "./o";
import * as p from "./p";
import * as q from "./q";
import * as so from "./side-effect-free/o";
import * as sm from "./side-effect-free/m";
import json1 from "./some.json";
import json2 from "./some1.json";
import weirdCjs from "./weird-cjs";

it("namespace export as from commonjs should override named export", function () {
expect(x).toBe(1);
Expand Down Expand Up @@ -48,6 +52,16 @@ it("should handle 'm in n' case", () => {
expect(obj.aaa).toBe(true);
expect("not_here" in m.object).toBe(false);
expect("not_here" in obj).toBe(false);
expect("__esModule" in q).toBe(true);
expect(() => "value" in q.__esModule).toThrow();
expect(() => "not_here" in json1).toThrow();
expect("not_here" in json2).toBe(false);
expect("a" in json2).toBe(true);
expect("a" in cjs).toBe(true);
expect("not_here" in cjs).toBe(false);
expect("not_here" in weirdCjs).toBe(false);
expect("a" in weirdCjs).toBe(true);
expect(() => "a" in weirdCjs.a).toThrow();
expect("aaa" in o).toBe(true);
expect("aaa" in p).toBe(false);
expect("ccc" in m).toBe(false);
Expand Down
@@ -0,0 +1 @@
true
3 changes: 3 additions & 0 deletions test/cases/parsing/harmony-export-import-specifier/some1.json
@@ -0,0 +1,3 @@
{
"a": 1
}
@@ -0,0 +1,7 @@
exports.__esModule = false;

function dynamic(exports) {
exports.a = 1;
}

dynamic(exports);