You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Microsoft ClearScript封装xkpasswd时遇'main is not defined'错误求助

用ClearScript封装xkpasswd时获取main函数失败的解决办法

背景

我要给xkpasswd的JS库做.NET封装,用Microsoft ClearScript实现。已经解决了第一个问题:执行generate.js时的require is not defined错误,通过设置执行文档为CommonJS模块类别,移除原代码里的Node.js fs、path模块解决。但现在调用时,获取main函数提示main is not defined,尝试获取module.exports也提示module is not defined。

修改后的generate.js代码(关键部分)

// 移除了fs、path模块的引用
var defaultWordList = require('./xkpasswd-words.json');

// 辅助函数h的定义...(省略原有辅助函数代码)

// 简化readCustomWordList,去掉外部文件读取功能
h.readCustomWordList = function readCustomWordList(input) {
    var rtn = [];
    if (!input) return rtn;
    
    var data = Array.isArray(input) ? input : input.split(',').map(word => word.trim());
    
    data.forEach(word => {
        var trimmed = word.trim();
        if (trimmed.length) rtn.push(trimmed);
    });
    return rtn;
};

module.exports = function main(opts) {
    var o = h.processOpts(opts || {});
    var pattern = o.pattern.split('');
    var uppercase = (typeof o.transform === 'string' && o.transform.toLowerCase() === 'uppercase');
    var password = [];

    var wordList = defaultWordList;
    var customWordList = h.readCustomWordList(o.wordList);

    if (Array.isArray(customWordList) && customWordList.length) {
        wordList = customWordList;
    }

    pattern.forEach(function generatePasswordSegment(type) {
        var value;
        if (type === 'd') value = h.random(0, 9);
        if (type === 's') value = o.separator;
        if (type === 'w' || type === 'W') {
            value = h.getRandomWord(wordList);
            if (typeof o.transform === 'string' && o.transform.toLowerCase() === 'alternate') {
                uppercase = !uppercase;
            }
            if (uppercase || type === 'W') {
                value = value.toUpperCase();
            } else {
                value = value.toLowerCase();
            }
        }
        password.push(value);
    });
    return password.join('');
};

当前.NET调用代码

Using engine As New V8ScriptEngine("xkpasswd_engine", V8ScriptEngineFlags.None)
    engine.ExecuteDocument("\generate.js", ModuleCategory.CommonJS)

    Dim mainFunction As ScriptObject =
        DirectCast(engine.Evaluate("main"), ScriptObject)

    Dim opts As Object = New With {
        .complexity = 3,
        .separators = "#.-=+_",
        .pattern = "wswswsdd",
        .transform = "lowercase",
        .wordList = Nothing
    }

    Dim password As String =
        CStr(mainFunction.Invoke(asConstructor:=False, opts))

    Console.WriteLine("Generated password: " & password)
End Using

问题原因

ClearScript执行CommonJS模块时,模块内部的module、exports以及定义的main函数都属于模块私有作用域,不会自动暴露到全局,所以直接用engine.Evaluate("main")找不到对应的变量。

修复方案

方案1:修改JS代码,把main函数暴露到全局

在module.exports = function main(opts) {...}后面添加一行,将main挂载到全局对象:

global.main = main;

修改后,原.NET代码里的engine.Evaluate("main")就能正常获取到函数。

方案2:用ClearScript的Require方法加载模块(推荐)

不需要修改JS代码,直接在.NET里用Require方法加载模块,获取其导出对象:

Using engine As New V8ScriptEngine("xkpasswd_engine", V8ScriptEngineFlags.None)
    ' 用Require加载模块,返回的就是module.exports对应的函数
    Dim mainFunction As ScriptObject = DirectCast(engine.Require("\generate.js"), ScriptObject)

    Dim opts As Object = New With {
        .complexity = 3,
        .separators = "#.-=+_",
        .pattern = "wswswsdd",
        .transform = "lowercase",
        .wordList = Nothing
    }

    Dim password As String = CStr(mainFunction.Invoke(asConstructor:=False, opts))

    Console.WriteLine("Generated password: " & password)
End Using

这个方案符合CommonJS模块加载规范,不需要改动原JS代码结构。

内容的提问来源于stack exchange,提问作者ElektroStudios

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:24:56