/* 
 | 
    MIT License http://www.opensource.org/licenses/mit-license.php 
 | 
    Author Tobias Koppers @sokra 
 | 
*/ 
 | 
"use strict"; 
 | 
  
 | 
const Generator = require("../Generator"); 
 | 
const Template = require("../Template"); 
 | 
const { RawSource } = require("webpack-sources"); 
 | 
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); 
 | 
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); 
 | 
  
 | 
/** @typedef {import("../NormalModule")} NormalModule */ 
 | 
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ 
 | 
/** @typedef {import("webpack-sources").Source} Source */ 
 | 
/** @typedef {import("../Dependency").DependencyTemplate} DependencyTemplate */ 
 | 
  
 | 
class WebAssemblyJavascriptGenerator extends Generator { 
 | 
    /** 
 | 
     * @param {NormalModule} module module for which the code should be generated 
 | 
     * @param {Map<Function, DependencyTemplate>} dependencyTemplates mapping from dependencies to templates 
 | 
     * @param {RuntimeTemplate} runtimeTemplate the runtime template 
 | 
     * @param {string} type which kind of code should be generated 
 | 
     * @returns {Source} generated code 
 | 
     */ 
 | 
    generate(module, dependencyTemplates, runtimeTemplate, type) { 
 | 
        const initIdentifer = Array.isArray(module.usedExports) 
 | 
            ? Template.numberToIdentifer(module.usedExports.length) 
 | 
            : "__webpack_init__"; 
 | 
  
 | 
        let needExportsCopy = false; 
 | 
        const importedModules = new Map(); 
 | 
        const initParams = []; 
 | 
        let index = 0; 
 | 
        for (const dep of module.dependencies) { 
 | 
            const depAsAny = /** @type {any} */ (dep); 
 | 
            if (dep.module) { 
 | 
                let importData = importedModules.get(dep.module); 
 | 
                if (importData === undefined) { 
 | 
                    importedModules.set( 
 | 
                        dep.module, 
 | 
                        (importData = { 
 | 
                            importVar: `m${index}`, 
 | 
                            index, 
 | 
                            request: 
 | 
                                "userRequest" in depAsAny ? depAsAny.userRequest : undefined, 
 | 
                            names: new Set(), 
 | 
                            reexports: [] 
 | 
                        }) 
 | 
                    ); 
 | 
                    index++; 
 | 
                } 
 | 
                if (dep instanceof WebAssemblyImportDependency) { 
 | 
                    importData.names.add(dep.name); 
 | 
                    if (dep.description.type === "GlobalType") { 
 | 
                        const exportName = dep.name; 
 | 
                        const usedName = dep.module && dep.module.isUsed(exportName); 
 | 
  
 | 
                        if (dep.module) { 
 | 
                            if (usedName) { 
 | 
                                initParams.push( 
 | 
                                    runtimeTemplate.exportFromImport({ 
 | 
                                        module: dep.module, 
 | 
                                        request: dep.request, 
 | 
                                        importVar: importData.importVar, 
 | 
                                        originModule: module, 
 | 
                                        exportName: dep.name, 
 | 
                                        asiSafe: true, 
 | 
                                        isCall: false, 
 | 
                                        callContext: null 
 | 
                                    }) 
 | 
                                ); 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
                if (dep instanceof WebAssemblyExportImportedDependency) { 
 | 
                    importData.names.add(dep.name); 
 | 
                    const usedName = module.isUsed(dep.exportName); 
 | 
                    if (usedName) { 
 | 
                        const exportProp = `${module.exportsArgument}[${JSON.stringify( 
 | 
                            usedName 
 | 
                        )}]`; 
 | 
                        const defineStatement = Template.asString([ 
 | 
                            `${exportProp} = ${runtimeTemplate.exportFromImport({ 
 | 
                                module: dep.module, 
 | 
                                request: dep.request, 
 | 
                                importVar: importData.importVar, 
 | 
                                originModule: module, 
 | 
                                exportName: dep.name, 
 | 
                                asiSafe: true, 
 | 
                                isCall: false, 
 | 
                                callContext: null 
 | 
                            })};`, 
 | 
                            `if(WebAssembly.Global) ${exportProp} = ` + 
 | 
                                `new WebAssembly.Global({ value: ${JSON.stringify( 
 | 
                                    dep.valueType 
 | 
                                )} }, ${exportProp});` 
 | 
                        ]); 
 | 
                        importData.reexports.push(defineStatement); 
 | 
                        needExportsCopy = true; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
        const importsCode = Template.asString( 
 | 
            Array.from( 
 | 
                importedModules, 
 | 
                ([module, { importVar, request, reexports }]) => { 
 | 
                    const importStatement = runtimeTemplate.importStatement({ 
 | 
                        module, 
 | 
                        request, 
 | 
                        importVar, 
 | 
                        originModule: module 
 | 
                    }); 
 | 
                    return importStatement + reexports.join("\n"); 
 | 
                } 
 | 
            ) 
 | 
        ); 
 | 
  
 | 
        // create source 
 | 
        const source = new RawSource( 
 | 
            [ 
 | 
                '"use strict";', 
 | 
                "// Instantiate WebAssembly module", 
 | 
                "var wasmExports = __webpack_require__.w[module.i];", 
 | 
  
 | 
                !Array.isArray(module.usedExports) 
 | 
                    ? `__webpack_require__.r(${module.exportsArgument});` 
 | 
                    : "", 
 | 
  
 | 
                // this must be before import for circular dependencies 
 | 
                "// export exports from WebAssembly module", 
 | 
                Array.isArray(module.usedExports) && !needExportsCopy 
 | 
                    ? `${module.moduleArgument}.exports = wasmExports;` 
 | 
                    : "for(var name in wasmExports) " + 
 | 
                      `if(name != ${JSON.stringify(initIdentifer)}) ` + 
 | 
                      `${module.exportsArgument}[name] = wasmExports[name];`, 
 | 
                "// exec imports from WebAssembly module (for esm order)", 
 | 
                importsCode, 
 | 
                "", 
 | 
                "// exec wasm module", 
 | 
                `wasmExports[${JSON.stringify(initIdentifer)}](${initParams.join( 
 | 
                    ", " 
 | 
                )})` 
 | 
            ].join("\n") 
 | 
        ); 
 | 
        return source; 
 | 
    } 
 | 
} 
 | 
  
 | 
module.exports = WebAssemblyJavascriptGenerator; 
 |