WXL
4 天以前 2cc85c64f1c64a2dbaeae276a3e2ca8420de76b7
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Haijie Xie @hai-x
*/
 
"use strict";
 
const memoize = require("../util/memoize");
 
const getCommentCompilationWarning = memoize(() =>
    require("../CommentCompilationWarning")
);
 
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../javascript/JavascriptParser").ExportAllDeclaration} ExportAllDeclaration */
/** @typedef {import("../javascript/JavascriptParser").ExportNamedDeclaration} ExportNamedDeclaration */
/** @typedef {import("../javascript/JavascriptParser").ImportDeclaration} ImportDeclaration */
/** @typedef {import("../javascript/JavascriptParser").ImportExpression} ImportExpression */
 
/** @typedef {typeof ImportPhase.Evaluation | typeof ImportPhase.Defer | typeof ImportPhase.Source}  ImportPhaseType */
 
const ImportPhase = Object.freeze({
    Evaluation: 0b00,
    Defer: 0b01,
    Source: 0b10
});
 
/** @typedef {"defer" | "source" | "evaluation"} ImportPhaseName */
 
/**
 * Defines the import phase utils type used by this module.
 * @typedef {object} ImportPhaseUtils
 * @property {(phase: ImportPhaseType | undefined) => boolean} isEvaluation true if phase is evaluation
 * @property {(phase: ImportPhaseType | undefined) => boolean} isDefer true if phase is defer
 * @property {(phase: ImportPhaseType | undefined) => boolean} isSource true if phase is source
 * @property {(phase: ImportPhaseType) => ImportPhaseName} stringify return stringified name of phase
 */
 
/** @type {ImportPhaseUtils} */
const ImportPhaseUtils = {
    isEvaluation(phase) {
        return phase === ImportPhase.Evaluation;
    },
    isDefer(phase) {
        return phase === ImportPhase.Defer;
    },
    isSource(phase) {
        return phase === ImportPhase.Source;
    },
    stringify(phase) {
        switch (phase) {
            case ImportPhase.Defer:
                return "defer";
            case ImportPhase.Source:
                return "source";
            default:
                return "evaluation";
        }
    }
};
 
/**
 * Defines the get comment options type used by this module.
 * @typedef {() => Record<string, EXPECTED_ANY> | null} GetCommentOptions
 */
 
/**
 * Defines the get import phase callback.
 * @callback GetImportPhase
 * @param {JavascriptParser} parser parser
 * @param {ExportNamedDeclaration | ExportAllDeclaration | ImportDeclaration | ImportExpression} node node
 * @param {GetCommentOptions=} getCommentOptions optional function that returns the comment options object.
 * @returns {ImportPhaseType} import phase
 */
 
/**
 * Creates an import phase resolver.
 * @param {boolean=} enableDeferPhase enable defer phase detection
 * @param {boolean=} enableSourcePhase enable source phase detection
 * @returns {GetImportPhase} evaluates the import phase for ast node
 */
function createGetImportPhase(enableDeferPhase, enableSourcePhase) {
    return (parser, node, getCommentOptions) => {
        if (!enableDeferPhase && !enableSourcePhase) return ImportPhase.Evaluation;
 
        // We now only support `defer import` and `source import` syntax
        const phaseBySyntax =
            "phase" in node
                ? node.phase === "defer" && enableDeferPhase
                    ? ImportPhase.Defer
                    : node.phase === "source" && enableSourcePhase
                        ? ImportPhase.Source
                        : ImportPhase.Evaluation
                : ImportPhase.Evaluation;
 
        if (!node.range) {
            return phaseBySyntax;
        }
 
        getCommentOptions =
            getCommentOptions ||
            (() => {
                if (!node.range) return null;
                const { options, errors } = parser.parseCommentOptions(node.range);
                if (errors) {
                    for (const e of errors) {
                        const { comment } = e;
                        if (!comment.loc) continue;
 
                        const CommentCompilationWarning = getCommentCompilationWarning();
                        parser.state.module.addWarning(
                            new CommentCompilationWarning(
                                `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
                                comment.loc
                            )
                        );
                    }
                }
                return options;
            });
 
        const options = getCommentOptions();
 
        if (!options) {
            return phaseBySyntax;
        }
 
        if (!options.webpackDefer && !options.webpackSource) {
            return phaseBySyntax;
        }
 
        const { webpackDefer, webpackSource } = options;
 
        if (enableDeferPhase && typeof options.webpackDefer !== "undefined") {
            if (typeof webpackDefer === "boolean") {
                return webpackDefer ? ImportPhase.Defer : phaseBySyntax;
            } else if (node.loc) {
                const CommentCompilationWarning = getCommentCompilationWarning();
 
                parser.state.module.addWarning(
                    new CommentCompilationWarning(
                        "webpackDefer magic comment expected a boolean value.",
                        node.loc
                    )
                );
            }
        }
 
        if (enableSourcePhase && typeof options.webpackSource !== "undefined") {
            if (typeof webpackSource === "boolean") {
                return webpackSource ? ImportPhase.Source : phaseBySyntax;
            } else if (node.loc) {
                const CommentCompilationWarning = getCommentCompilationWarning();
 
                parser.state.module.addWarning(
                    new CommentCompilationWarning(
                        "webpackSource magic comment expected a boolean value.",
                        node.loc
                    )
                );
            }
        }
 
        return phaseBySyntax;
    };
}
 
module.exports = {
    ImportPhase,
    ImportPhaseUtils,
    createGetImportPhase
};