xwt
2025-07-04 b76e716ff4656191d73eba398e9eb39ee975e13b
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
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/
 
"use strict";
 
const formatLocation = require("../formatLocation");
const UnsupportedWebAssemblyFeatureError = require("./UnsupportedWebAssemblyFeatureError");
 
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
 
const PLUGIN_NAME = "WasmFinalizeExportsPlugin";
 
class WasmFinalizeExportsPlugin {
    /**
     * Apply the plugin
     * @param {Compiler} compiler the compiler instance
     * @returns {void}
     */
    apply(compiler) {
        compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
            compilation.hooks.finishModules.tap(PLUGIN_NAME, modules => {
                for (const module of modules) {
                    // 1. if a WebAssembly module
                    if (module.type.startsWith("webassembly") === true) {
                        const jsIncompatibleExports =
                            /** @type {BuildMeta} */
                            (module.buildMeta).jsIncompatibleExports;
 
                        if (jsIncompatibleExports === undefined) {
                            continue;
                        }
 
                        for (const connection of compilation.moduleGraph.getIncomingConnections(
                            module
                        )) {
                            // 2. is active and referenced by a non-WebAssembly module
                            if (
                                connection.isTargetActive(undefined) &&
                                /** @type {Module} */
                                (connection.originModule).type.startsWith("webassembly") ===
                                    false
                            ) {
                                const referencedExports =
                                    compilation.getDependencyReferencedExports(
                                        /** @type {Dependency} */ (connection.dependency),
                                        undefined
                                    );
 
                                for (const info of referencedExports) {
                                    const names = Array.isArray(info) ? info : info.name;
                                    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(
                                            jsIncompatibleExports,
                                            name
                                        )
                                    ) {
                                        // 4. error
                                        const error = new UnsupportedWebAssemblyFeatureError(
                                            `Export "${name}" with ${jsIncompatibleExports[name]} can only be used for direct wasm to wasm dependencies\n` +
                                                `It's used from ${
                                                    /** @type {Module} */
                                                    (connection.originModule).readableIdentifier(
                                                        compilation.requestShortener
                                                    )
                                                } at ${formatLocation(
                                                    /** @type {Dependency} */ (connection.dependency).loc
                                                )}.`
                                        );
                                        error.module = module;
                                        compilation.errors.push(error);
                                    }
                                }
                            }
                        }
                    }
                }
            });
        });
    }
}
 
module.exports = WasmFinalizeExportsPlugin;