Add 'webpackExports' & make only referenced exports available in import()

This commit is contained in:
Pushkar DK 2020-05-28 00:04:55 +05:30
parent f8021aba1f
commit 31e3369a73
28 changed files with 335 additions and 74 deletions

View File

@ -43,7 +43,10 @@ module.exports = {
"jsdoc/require-returns-type": "error",
"jsdoc/require-returns": "error",
// Disallow @ts-ignore directive. Use @ts-expect-error instead
"no-warning-comments": ["error", { terms: ["@ts-ignore"], location: "start" }]
"no-warning-comments": [
"error",
{ terms: ["@ts-ignore"], location: "start" }
]
},
settings: {
jsdoc: {

View File

@ -77,6 +77,7 @@ const {
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
@ -355,7 +356,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
/** @type {SyncHook<[Dependency, EntryOptions, Module]>} */
succeedEntry: new SyncHook(["entry", "options", "module"]),
/** @type {SyncWaterfallHook<[string[][], Dependency]>} */
/** @type {SyncWaterfallHook<[(string[] | ReferencedExport)[], Dependency]>} */
dependencyReferencedExports: new SyncWaterfallHook([
"referencedExports",
"dependency"
@ -2178,7 +2179,7 @@ Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*
/**
* @param {Dependency} dependency the dependency
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getDependencyReferencedExports(dependency) {
const referencedExports = dependency.getReferencedExports(this.moduleGraph);

View File

@ -52,6 +52,14 @@
* @property {Module[]=} dependencies module on which the result depends on
*/
/**
* @typedef {Object} ReferencedExportItem
* @property {string} name name of the referenced export
* @property {boolean=} canMangle when true, referenced export can be mangled
*/
/** @typedef {ReferencedExportItem[]} ReferencedExport */
class Dependency {
constructor() {
// TODO check if this can be moved into ModuleDependency
@ -93,7 +101,7 @@ class Dependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return Dependency.EXPORTS_OBJECT_REFERENCED;

View File

@ -13,6 +13,7 @@ const Queue = require("./util/Queue");
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleGraph").ExportsInfo} ExportsInfo */
@ -39,9 +40,8 @@ class FlagDependencyUsagePlugin {
const exportInfoToModuleMap = new Map();
/**
* @typedef {string[]} StringArray
* @param {Module} module module to process
* @param {StringArray[]} usedExports list of used exports
* @param {(string[] | ReferencedExport)[]} usedExports list of used exports
* @returns {void}
*/
const processModule = (module, usedExports) => {
@ -55,10 +55,17 @@ class FlagDependencyUsagePlugin {
} else {
let currentExportsInfo = exportsInfo;
for (let i = 0; i < usedExport.length; i++) {
const exportName = usedExport[i];
const exportInfo = currentExportsInfo.getExportInfo(
exportName
);
const exportItem = usedExport[i];
let exportInfo;
if (typeof exportItem === "object") {
exportInfo = currentExportsInfo.getExportInfo(
exportItem.name
);
if (exportItem.canMangle === false)
exportInfo.canMangleUse = false;
} else {
exportInfo = currentExportsInfo.getExportInfo(exportItem);
}
const lastOne = i === usedExport.length - 1;
if (!lastOne) {
const nestedInfo = exportInfo.getNestedExportsInfo();

View File

@ -10,6 +10,7 @@ const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
@ -30,7 +31,7 @@ class CommonJsFullRequireDependency extends ModuleDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
if (this.call) {

View File

@ -14,6 +14,7 @@ const NullDependency = require("./NullDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
@ -39,7 +40,7 @@ class CommonJsSelfReferenceDependency extends NullDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return [this.names];

View File

@ -19,6 +19,7 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
@ -395,7 +396,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
const mode = this.getMode(moduleGraph, false);

View File

@ -16,6 +16,7 @@ const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
@ -38,7 +39,7 @@ class HarmonyImportDependency extends ModuleDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return Dependency.NO_EXPORTS_REFERENCED;

View File

@ -14,6 +14,7 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../WebpackError")} WebpackError */
@ -99,7 +100,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
let ids = this.getIds(moduleGraph);

View File

@ -5,22 +5,37 @@
"use strict";
const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../dependencies/ImportDependenciesBlock")} ImportDependenciesBlock */
class ImportDependency extends ModuleDependency {
constructor(request) {
constructor(request, referencedExports) {
super(request);
this.referencedExports = referencedExports;
}
get type() {
return "import()";
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return this.referencedExports
? this.referencedExports
: Dependency.EXPORTS_OBJECT_REFERENCED;
}
}
makeSerializable(ImportDependency, "webpack/lib/dependencies/ImportDependency");

View File

@ -5,23 +5,37 @@
"use strict";
const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
class ImportEagerDependency extends ModuleDependency {
constructor(request, range) {
constructor(request, range, referencedExports) {
super(request);
this.referencedExports = referencedExports;
this.range = range;
}
get type() {
return "import() eager";
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return this.referencedExports
? this.referencedExports
: Dependency.EXPORTS_OBJECT_REFERENCED;
}
}
makeSerializable(

View File

@ -31,6 +31,7 @@ class ImportParserPlugin {
let mode = "lazy";
let include = null;
let exclude = null;
let exports = null;
/** @type {RawChunkGroupOptions} */
const groupOptions = {};
@ -149,6 +150,43 @@ class ImportParserPlugin {
exclude = new RegExp(importOptions.webpackExclude);
}
}
if (importOptions.webpackExports !== undefined) {
if (
!(
typeof importOptions.webpackExports === "string" ||
(Array.isArray(importOptions.webpackExports) &&
importOptions.webpackExports.every(
item => typeof item === "string"
))
)
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackExports\` expected a string or an array of strings, but received: ${importOptions.webpackExports}.`,
expr.loc
)
);
} else {
// Convert export names to be of type Object[] with name and other properties:
if (typeof importOptions.webpackExports === "string") {
exports = [
[
{
name: importOptions.webpackExports,
canMangle: false
}
]
];
} else {
exports = importOptions.webpackExports.map(exp => [
{
name: exp,
canMangle: false
}
]);
}
}
}
}
if (param.isString()) {
@ -162,10 +200,18 @@ class ImportParserPlugin {
}
if (mode === "eager") {
const dep = new ImportEagerDependency(param.string, expr.range);
const dep = new ImportEagerDependency(
param.string,
expr.range,
exports
);
parser.state.current.addDependency(dep);
} else if (mode === "weak") {
const dep = new ImportWeakDependency(param.string, expr.range);
const dep = new ImportWeakDependency(
param.string,
expr.range,
exports
);
parser.state.current.addDependency(dep);
} else {
const depBlock = new ImportDependenciesBlock(
@ -177,7 +223,7 @@ class ImportParserPlugin {
param.string,
expr.range
);
const dep = new ImportDependency(param.string);
const dep = new ImportDependency(param.string, exports);
dep.loc = expr.loc;
depBlock.addDependency(dep);
parser.state.current.addBlock(depBlock);

View File

@ -5,17 +5,20 @@
"use strict";
const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
class ImportWeakDependency extends ModuleDependency {
constructor(request, range) {
constructor(request, range, referencedExports) {
super(request);
this.referencedExports = referencedExports;
this.range = range;
this.weak = true;
}
@ -23,6 +26,17 @@ class ImportWeakDependency extends ModuleDependency {
get type() {
return "import() weak";
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return this.referencedExports
? this.referencedExports
: Dependency.EXPORTS_OBJECT_REFERENCED;
}
}
makeSerializable(

View File

@ -14,6 +14,7 @@ const NullDependency = require("./NullDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
@ -47,7 +48,7 @@ class ModuleDecoratorDependency extends NullDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return this.allowExportsAccess

View File

@ -12,6 +12,7 @@ const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
@ -25,7 +26,7 @@ class RequireIncludeDependency extends ModuleDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
// This doesn't use any export

View File

@ -10,6 +10,7 @@ const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId");
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
class RequireResolveDependency extends ModuleDependency {
@ -26,7 +27,7 @@ class RequireResolveDependency extends ModuleDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
// This doesn't use any export

View File

@ -8,6 +8,7 @@
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
class WebAssemblyExportImportedDependency extends ModuleDependency {
@ -24,7 +25,7 @@ class WebAssemblyExportImportedDependency extends ModuleDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return [[this.name]];

View File

@ -10,6 +10,7 @@ const UnsupportedWebAssemblyFeatureError = require("../wasm/UnsupportedWebAssemb
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("@webassemblyjs/ast").ModuleImportDescription} ModuleImportDescription */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../WebpackError")} WebpackError */
@ -33,7 +34,7 @@ class WebAssemblyImportDependency extends ModuleDependency {
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @returns {string[][]} referenced exports
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph) {
return [[this.name]];

View File

@ -47,6 +47,7 @@ class WasmFinalizeExportsPlugin {
for (const names of referencedExports) {
if (names.length === 0) continue;
const name = names[0];
if (typeof name === "object") continue;
// 3. and uses a func with an incompatible JS signature
if (
Object.prototype.hasOwnProperty.call(

View File

@ -0,0 +1,5 @@
export const a = "a";
export const b = "b";
export default "default";

View File

@ -0,0 +1,5 @@
export const a = "a";
export const b = "b";
export default "default";

View File

@ -0,0 +1,5 @@
export const a = "a";
export const b = "b";
export default "default";

View File

@ -0,0 +1,5 @@
export const a = "a";
export const b = "b";
export default "default";

View File

@ -0,0 +1,5 @@
export const a = "a";
export const longnameforexport = "longnameforexport";
export default "default";

View File

@ -0,0 +1,5 @@
export const a = "a";
export const b = "b";
export default "default";

View File

@ -0,0 +1,5 @@
export const a = "a";
export const b = "b";
export default "default";

View File

@ -1,48 +1,56 @@
it("should be able to use eager mode", function() {
it("should be able to use eager mode", function () {
function load(name) {
return import(/* webpackMode: "eager" */ "./dir1/" + name);
}
return testChunkLoading(load, true, true);
});
it("should be able to use lazy-once mode", function() {
it("should be able to use lazy-once mode", function () {
function load(name) {
return import(/* webpackMode: "lazy-once" */ "./dir2/" + name);
}
return testChunkLoading(load, false, true);
});
it("should be able to use lazy-once mode with name", function() {
it("should be able to use lazy-once mode with name", function () {
function load(name) {
return import(/* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */ "./dir3/" + name);
return import(
/* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */ "./dir3/" +
name
);
}
return testChunkLoading(load, false, true);
});
it("should be able to use lazy mode", function() {
it("should be able to use lazy mode", function () {
function load(name) {
return import(/* webpackMode: "lazy" */ "./dir4/" + name);
}
return testChunkLoading(load, false, false);
});
it("should be able to use lazy mode with name", function() {
it("should be able to use lazy mode with name", function () {
function load(name) {
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy" */ "./dir5/" + name);
return import(
/* webpackMode: "lazy", webpackChunkName: "name-lazy" */ "./dir5/" + name
);
}
return testChunkLoading(load, false, false);
});
it("should be able to use lazy mode with name and placeholder", function() {
it("should be able to use lazy mode with name and placeholder", function () {
function load(name) {
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */ "./dir6/" + name);
return import(
/* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */ "./dir6/" +
name
);
}
return testChunkLoading(load, false, false);
});
it("should be able to combine chunks by name", function() {
it("should be able to combine chunks by name", function () {
function load(name) {
switch(name) {
switch (name) {
case "a":
return import(/* webpackMode: "eager" */ "./dir7/a");
case "b":
@ -58,19 +66,19 @@ it("should be able to combine chunks by name", function() {
return testChunkLoading(load, false, true);
});
it("should be able to use weak mode", function() {
it("should be able to use weak mode", function () {
function load(name) {
return import(/* webpackMode: "weak" */ "./dir8/" + name);
}
require("./dir8/a") // chunks served manually by the user
require("./dir8/b")
require("./dir8/c")
require("./dir8/a"); // chunks served manually by the user
require("./dir8/b");
require("./dir8/c");
return testChunkLoading(load, true, true);
});
it("should be able to use weak mode (without context)", function() {
it("should be able to use weak mode (without context)", function () {
function load(name) {
switch(name) {
switch (name) {
case "a":
return import(/* webpackMode: "weak" */ "./dir9/a");
case "b":
@ -81,54 +89,136 @@ it("should be able to use weak mode (without context)", function() {
throw new Error("Unexcepted test data");
}
}
require("./dir9/a") // chunks served manually by the user
require("./dir9/b")
require("./dir9/c")
require("./dir9/a"); // chunks served manually by the user
require("./dir9/b");
require("./dir9/c");
return testChunkLoading(load, true, true);
});
it("should not find module when mode is weak and chunk not served elsewhere", function() {
it("should not find module when mode is weak and chunk not served elsewhere", function () {
var name = "a";
return import(/* webpackMode: "weak" */ "./dir10/" + name)
.catch(function(e) {
expect(e).toMatchObject({ message: /not available/, code: /MODULE_NOT_FOUND/ });
return import(/* webpackMode: "weak" */ "./dir10/" + name).catch(function (
e
) {
expect(e).toMatchObject({
message: /not available/,
code: /MODULE_NOT_FOUND/
});
});
});
it("should not find module when mode is weak and chunk not served elsewhere (without context)", function() {
return import(/* webpackMode: "weak" */ "./dir11/a")
.catch(function(e) {
expect(e).toMatchObject({ message: /not available/, code: /MODULE_NOT_FOUND/ });
it("should not find module when mode is weak and chunk not served elsewhere (without context)", function () {
return import(/* webpackMode: "weak" */ "./dir11/a").catch(function (e) {
expect(e).toMatchObject({
message: /not available/,
code: /MODULE_NOT_FOUND/
});
});
});
it("should contain only one export from webpackExports from module", function () {
return import(/* webpackExports: "a" */ "./dir12/a").then(module => {
expect(module).toHaveProperty("a");
expect(module).not.toHaveProperty("b");
expect(module).not.toHaveProperty("default");
});
});
it("should contain only webpackExports from module", function () {
return import(/* webpackExports: ["a", "b"] */ "./dir12/b").then(module => {
expect(module).toHaveProperty("a");
expect(module).toHaveProperty("b");
expect(module).not.toHaveProperty("default");
});
});
it("should contain only webpackExports from module in eager mode", function () {
return import(
/*
webpackMode: "eager",
webpackExports: ["a", "b"]
*/ "./dir12/c"
).then(module => {
expect(module).toHaveProperty("a");
expect(module).toHaveProperty("b");
expect(module).not.toHaveProperty("default");
});
});
it("should contain webpackExports from module in weak mode", function () {
require("./dir12/d");
return import(
/*
webpackMode: "weak",
webpackExports: ["a", "b"]
*/ "./dir12/d"
).then(module => {
expect(module).toHaveProperty("a");
expect(module).toHaveProperty("b");
});
});
it("should not mangle webpackExports from module", function () {
return import(/* webpackExports: "longnameforexport" */ "./dir12/e").then(
module => {
expect(module).toHaveProperty("longnameforexport");
}
);
});
it("should not mangle default webpackExports from module", function () {
return import(/* webpackExports: "default" */ "./dir12/f").then(module => {
expect(module).toHaveProperty("default");
});
});
it("should contain only default from webpackExports from module", function () {
return import(/* webpackExports: "default" */ "./dir12/g").then(module => {
expect(module).not.toHaveProperty("a");
expect(module).not.toHaveProperty("b");
expect(module).toHaveProperty("default");
});
});
function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested) {
var sync = false;
var syncInitial = true;
var p = Promise.all([load("a"), load("b")]).then(function() {
var p = Promise.all([load("a"), load("b")]).then(function () {
expect(syncInitial).toBe(expectedSyncInitial);
sync = true;
var p = Promise.all([
load("a").then(function(a) {
expect(a).toEqual(nsObj({
default: "a"
}));
load("a").then(function (a) {
expect(a).toEqual(
nsObj({
default: "a"
})
);
expect(sync).toBe(true);
}),
load("c").then(function(c) {
expect(c).toEqual(nsObj({
default: "c"
}));
load("c").then(function (c) {
expect(c).toEqual(
nsObj({
default: "c"
})
);
expect(sync).toBe(expectedSyncRequested);
})
]);
Promise.resolve().then(function(){}).then(function(){}).then(function(){}).then(function(){
sync = false;
});
Promise.resolve()
.then(function () {})
.then(function () {})
.then(function () {})
.then(function () {
sync = false;
});
return p;
});
Promise.resolve().then(function(){}).then(function(){}).then(function(){}).then(function(){
syncInitial = false;
});
Promise.resolve()
.then(function () {})
.then(function () {})
.then(function () {})
.then(function () {
syncInitial = false;
});
return p;
}

23
types.d.ts vendored
View File

@ -887,7 +887,9 @@ declare class Compilation {
],
void
>;
dependencyReferencedExports: SyncWaterfallHook<[string[][], Dependency]>;
dependencyReferencedExports: SyncWaterfallHook<
[(string[] | ReferencedExportItem[])[], Dependency]
>;
finishModules: AsyncSeriesHook<[Iterable<Module>]>;
finishRebuildingModule: AsyncSeriesHook<[Module]>;
unseal: SyncHook<[], void>;
@ -1137,7 +1139,9 @@ declare class Compilation {
*/
addChunk(name?: string): Chunk;
assignDepth(module: Module): void;
getDependencyReferencedExports(dependency: Dependency): string[][];
getDependencyReferencedExports(
dependency: Dependency
): (string[] | ReferencedExportItem[])[];
removeReasonsOfDependencyBlock(
module: Module,
block: DependenciesBlockLike
@ -1683,7 +1687,9 @@ declare class Dependency {
/**
* Returns list of exports referenced by this dependency
*/
getReferencedExports(moduleGraph: ModuleGraph): string[][];
getReferencedExports(
moduleGraph: ModuleGraph
): (string[] | ReferencedExportItem[])[];
getCondition(moduleGraph: ModuleGraph): () => boolean;
/**
@ -5417,6 +5423,17 @@ type RecursiveArrayOrRecord =
| RuntimeValue
| { [index: string]: RecursiveArrayOrRecord }
| RecursiveArrayOrRecord[];
declare interface ReferencedExportItem {
/**
* name of the referenced export
*/
name: string;
/**
* when true, referenced export can be mangled
*/
canMangle?: boolean;
}
type Remotes = (string | RemotesObject)[] | RemotesObject;
/**