optimize storage format of ExportMode

This commit is contained in:
Tobias Koppers 2020-07-06 21:39:54 +02:00
parent da98e09d13
commit 25a41fa9bb
3 changed files with 70 additions and 63 deletions

View File

@ -33,12 +33,6 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
const idsSymbol = Symbol("HarmonyExportImportedSpecifierDependency.ids");
/** @type {Map<string, string[]>} */
const EMPTY_MAP = new Map();
/** @type {Set<string>} */
const EMPTY_SET = new Set();
/**
* @param {string[][]} referencedExports list of referenced exports, will be added to
* @param {string[]} prefix export prefix
@ -82,6 +76,21 @@ const processExportInfo = (
}
};
class NormalReexportItem {
/**
* @param {string} name export name
* @param {string[]} ids reexported ids from other module
* @param {ExportInfo=} exportInfo export info from other module
* @param {boolean} checked true, if it should be checked at runtime if this export exists
*/
constructor(name, ids, exportInfo, checked) {
this.name = name;
this.ids = ids;
this.exportInfo = exportInfo;
this.checked = checked;
}
}
class ExportMode {
/**
* @param {ExportModeType} type type of the mode
@ -89,18 +98,26 @@ class ExportMode {
constructor(type) {
/** @type {ExportModeType} */
this.type = type;
// for "normal-reexport":
/** @type {NormalReexportItem[] | null} */
this.items = null;
// for "reexport-named-default" | "reexport-fake-namespace-object" | "reexport-namespace-object"
/** @type {string|null} */
this.name = null;
/** @type {Map<string, string[]>} */
this.map = EMPTY_MAP;
/** @type {Map<string, ExportInfo>|undefined|ExportInfo} */
this.partialNamespaceExportInfo = undefined;
/** @type {Set<string>|null} */
/** @type {ExportInfo | null} */
this.partialNamespaceExportInfo = null;
// for "dynamic-reexport":
/** @type {Set<string> | null} */
this.ignored = null;
/** @type {Set<string>|null} */
this.checked = null;
/** @type {string|null} */
// for "missing":
/** @type {string | null} */
this.userRequest = null;
// for "reexport-fake-namespace-object":
/** @type {number} */
this.fakeType = 0;
}
@ -245,10 +262,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
break;
default:
mode = new ExportMode("normal-reexport");
mode.map = new Map([[name, ids]]);
mode.partialNamespaceExportInfo = new Map();
mode.partialNamespaceExportInfo.set(name, exportInfo);
mode.checked = EMPTY_SET;
mode.items = [new NormalReexportItem(name, ids, exportInfo, false)];
break;
}
} else {
@ -305,23 +319,18 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
return mode;
}
/** @type {Map<string, string[]>} */
const map = new Map();
/** @type {Map<string, ExportInfo>} */
const exportsInfoMap = new Map();
for (const exportName of exports) {
map.set(exportName, [exportName]);
exportsInfoMap.set(
exportName,
exportsInfo.getReadOnlyExportInfo(exportName)
);
}
const mode = new ExportMode("normal-reexport");
mode.map = map;
mode.partialNamespaceExportInfo = exportsInfoMap;
mode.checked = checked;
mode.items = Array.from(
exports,
exportName =>
new NormalReexportItem(
exportName,
[exportName],
exportsInfo.getReadOnlyExportInfo(exportName),
checked.has(exportName)
)
);
return mode;
}
@ -452,17 +461,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
return Dependency.EXPORTS_OBJECT_REFERENCED;
case "normal-reexport": {
if (!mode.partialNamespaceExportInfo)
return Array.from(mode.map.values());
const referencedExports = [];
for (const [key, value] of mode.map) {
const exportInfo = /** @type {Map<string, ExportInfo>} */ (mode.partialNamespaceExportInfo).get(
key
);
processExportInfo(referencedExports, value, exportInfo, false);
for (const { ids, exportInfo } of mode.items) {
processExportInfo(referencedExports, ids, exportInfo, false);
}
return referencedExports;
}
@ -523,15 +525,17 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
exports: [],
dependencies: [moduleGraph.getModule(this)]
};
case "normal-reexport":
case "normal-reexport": {
const from = moduleGraph.getModule(this);
return {
exports: Array.from(mode.map.keys()).map(name => ({
name,
from: moduleGraph.getModule(this),
export: mode.map.get(name)
exports: Array.from(mode.items, item => ({
name: item.name,
from,
export: item.ids
})),
dependencies: [moduleGraph.getModule(this)]
dependencies: [from]
};
}
case "reexport-dynamic-default":
case "reexport-undefined":
return {
@ -641,9 +645,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
const mode = this.getMode(chunkGraph.moduleGraph);
hash.update(mode.type);
for (const [k, v] of mode.map) {
hash.update(k);
hash.update(v.join());
if (mode.items) {
for (const item of mode.items) {
hash.update(item.name);
hash.update(item.ids.join());
if (item.checked) hash.update("checked");
}
}
if (mode.ignored) {
hash.update("ignored");
@ -824,16 +831,16 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
break;
case "normal-reexport":
for (const [key, id] of mode.map) {
if (mode.checked.has(key)) {
for (const { name, ids, checked } of mode.items) {
if (checked) {
initFragments.push(
new InitFragment(
"/* harmony reexport (checked) */ " +
this.getConditionalReexportStatement(
module,
key,
name,
importVar,
id,
ids,
runtimeRequirements
),
InitFragment.STAGE_HARMONY_IMPORTS,
@ -845,9 +852,9 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
this.getReexportFragment(
module,
"reexport safe",
module.getUsedName(moduleGraph, key),
module.getUsedName(moduleGraph, name),
importVar,
importedModule.getUsedName(moduleGraph, id),
importedModule.getUsedName(moduleGraph, ids),
runtimeRequirements
)
);

View File

@ -214,15 +214,15 @@ class SideEffectsFlagPlugin {
const targetModule = moduleGraph.getModule(dep);
switch (mode.type) {
case "normal-reexport":
for (const [key, ids] of mode.map) {
for (const { name, ids, checked } of mode.items) {
// TODO Support reexporting namespace object
if (ids.length > 0) {
addStaticReexport(
info,
key,
name,
targetModule,
ids[0],
mode.checked.has(key)
checked
);
}
}

View File

@ -2738,7 +2738,7 @@ Entrypoint main = main.js
`;
exports[`StatsTestCases should print correct stats for side-effects-optimization 1`] = `
"Hash: d7d1b4f45cd90d4abdb64369e7ea517dce8ffb09
"Hash: d7d1b4f45cd90d4abdb6d61ad7aea717eb8e1363
Child
Hash: d7d1b4f45cd90d4abdb6
Time: X ms
@ -2762,7 +2762,7 @@ Child
ModuleConcatenation bailout: Module is not an ECMAScript module
+ 2 hidden modules
Child
Hash: 4369e7ea517dce8ffb09
Hash: d61ad7aea717eb8e1363
Time: X ms
Built at: 1970-04-20 12:42:42
Asset Size
@ -3843,7 +3843,7 @@ chunk default/async-a.js (async-a) 134 bytes <{179}> [rendered]
`;
exports[`StatsTestCases should print correct stats for tree-shaking 1`] = `
"Hash: 0653813b0ee99f2a94bd
"Hash: cd2fbd230872570f58af
Time: X ms
Built at: 1970-04-20 12:42:42
Asset Size