保誠-保戶業務員媒合平台
Tomas
2022-05-19 957a1f10a06fdbb76f1a0ba94fe44126c613fee3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/
"use strict";
 
/** @typedef {import("./Module")} Module */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
 
/** @typedef {false | true | string[]} UsedExports */
 
const addToSet = (a, b) => {
    for (const item of b) {
        if (!a.includes(item)) a.push(item);
    }
    return a;
};
 
const isSubset = (biggerSet, subset) => {
    if (biggerSet === true) return true;
    if (subset === true) return false;
    return subset.every(item => biggerSet.indexOf(item) >= 0);
};
 
class FlagDependencyUsagePlugin {
    apply(compiler) {
        compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {
            compilation.hooks.optimizeDependencies.tap(
                "FlagDependencyUsagePlugin",
                modules => {
                    const processModule = (module, usedExports) => {
                        module.used = true;
                        if (module.usedExports === true) return;
                        if (usedExports === true) {
                            module.usedExports = true;
                        } else if (Array.isArray(usedExports)) {
                            const old = module.usedExports ? module.usedExports.length : -1;
                            module.usedExports = addToSet(
                                module.usedExports || [],
                                usedExports
                            );
                            if (module.usedExports.length === old) {
                                return;
                            }
                        } else if (Array.isArray(module.usedExports)) {
                            return;
                        } else {
                            module.usedExports = false;
                        }
 
                        // for a module without side effects we stop tracking usage here when no export is used
                        // This module won't be evaluated in this case
                        if (module.factoryMeta.sideEffectFree) {
                            if (module.usedExports === false) return;
                            if (
                                Array.isArray(module.usedExports) &&
                                module.usedExports.length === 0
                            )
                                return;
                        }
 
                        queue.push([module, module, module.usedExports]);
                    };
 
                    const processDependenciesBlock = (module, depBlock, usedExports) => {
                        for (const dep of depBlock.dependencies) {
                            processDependency(module, dep);
                        }
                        for (const variable of depBlock.variables) {
                            for (const dep of variable.dependencies) {
                                processDependency(module, dep);
                            }
                        }
                        for (const block of depBlock.blocks) {
                            queue.push([module, block, usedExports]);
                        }
                    };
 
                    const processDependency = (module, dep) => {
                        const reference = compilation.getDependencyReference(module, dep);
                        if (!reference) return;
                        const referenceModule = reference.module;
                        const importedNames = reference.importedNames;
                        const oldUsed = referenceModule.used;
                        const oldUsedExports = referenceModule.usedExports;
                        if (
                            !oldUsed ||
                            (importedNames &&
                                (!oldUsedExports || !isSubset(oldUsedExports, importedNames)))
                        ) {
                            processModule(referenceModule, importedNames);
                        }
                    };
 
                    for (const module of modules) {
                        if (!module.used) module.used = false;
                    }
 
                    /** @type {[Module, DependenciesBlock, UsedExports][]} */
                    const queue = [];
                    for (const preparedEntrypoint of compilation._preparedEntrypoints) {
                        if (preparedEntrypoint.module) {
                            processModule(preparedEntrypoint.module, true);
                        }
                    }
 
                    while (queue.length) {
                        const queueItem = queue.pop();
                        processDependenciesBlock(queueItem[0], queueItem[1], queueItem[2]);
                    }
                }
            );
        });
    }
}
module.exports = FlagDependencyUsagePlugin;