使用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
相关产品推荐
相关产品推荐

