WXL
2025-12-27 05e6b08007a86b5b10c680babc9c3bcc3a1a201b
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
/*
    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 {object} ImportPhaseUtils
 * @property {(phase: ImportPhaseType) => boolean} isDefer true if phase is defer
 * @property {(phase: ImportPhaseType) => boolean} isSource true if phase is source
 */
 
/** @type {ImportPhaseUtils} */
const ImportPhaseUtils = {
    isDefer(phase) {
        return phase === ImportPhase.Defer;
    },
    isSource(phase) {
        return phase === ImportPhase.Source;
    }
};
 
/**
 * @typedef {() => Record<string, EXPECTED_ANY> | null} GetCommentOptions
 */
 
/**
 * @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
 */
 
/**
 * @param {boolean=} enableImportPhase enable import phase detection
 * @returns {GetImportPhase} evaluates the import phase for ast node
 */
function createGetImportPhase(enableImportPhase) {
    return (parser, node, getCommentOptions) => {
        if (!enableImportPhase) return ImportPhase.Evaluation;
 
        // We now only support `defer import`
        const phaseBySyntax =
            "phase" in node && node.phase === "defer"
                ? ImportPhase.Defer
                : 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 || !options.webpackDefer) return phaseBySyntax;
 
        const { webpackDefer } = options;
        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
                )
            );
        }
 
        return phaseBySyntax;
    };
}
 
module.exports = {
    ImportPhase,
    ImportPhaseUtils,
    createGetImportPhase
};