在Tampermonkey中运行Golang WASM出现编译错误的解决求助
解决Tampermonkey中WebAssembly.instantiateStreaming解码溢出错误
我在Tampermonkey中运行Golang编译的WASM文件,该WASM在普通网页环境下可正常运行。为绕过跨域限制,我用GM_xmlhttpRequest获取WASM并手动构造Response对象,但调用WebAssembly.instantiateStreaming时出现错误:
CompileError: WebAssembly.instantiateStreaming(): length overflow while decoding section length @+13
原脚本代码
// ==UserScript== // @name test // @namespace http://tampermonkey.net/ // @version v1 // @description test // @author test // @match *://*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=google.com // @require https://raw.githubusercontent.com/golang/go/master/misc/wasm/wasm_exec.js // @grant unsafeWindow // @grant GM_xmlhttpRequest // ==/UserScript== async function xFetch(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, onload: function (lol) { const headers = new Headers(); lol.responseHeaders.trim().split(/[\r\n]+/).forEach(line => { const parts = line.split(':'); headers.append(parts.shift().trim(), parts.join(':').trim()); }); const response = new Response(lol.responseText, { status: lol.status, statusText: lol.statusText, headers: headers, }); response.arrayBuffer = () => Promise.resolve(lol.response); resolve(response); }, fetch: true, responseType: 'arraybuffer', onerror: reject, }); }); } (async function () { const go = new Go(); WebAssembly.instantiateStreaming(await xFetch("https://****.glitch.me/wasm" /* its return wasm data with application/wasm content-type */ ), go.importObject).then(async (result) => { await go.run(result.instance); }).catch((err) => { console.error(err); }); })()
问题原因
错误根源是构造Response时,把二进制WASM数据通过responseText转成了UTF-8字符串,这会破坏原始二进制结构。WebAssembly.instantiateStreaming需要未被篡改的二进制流,转码后的字符串再转回ArrayBuffer会导致数据损坏,从而触发解码溢出错误。
修正方案
直接用GM_xmlhttpRequest返回的原始ArrayBuffer创建Blob,再生成Response,不需要处理responseText,也不用手动重写arrayBuffer方法:
async function xFetch(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, onload: function (lol) { const headers = new Headers(); lol.responseHeaders.trim().split(/[\r\n]+/).forEach(line => { const parts = line.split(':'); headers.append(parts.shift().trim(), parts.join(':').trim()); }); // 用原始ArrayBuffer创建Blob,确保二进制数据完整 const blob = new Blob([lol.response], { type: 'application/wasm' }); const response = new Response(blob, { status: lol.status, statusText: lol.statusText, headers: headers, }); resolve(response); }, responseType: 'arraybuffer', onerror: reject, }); }); }
额外注意事项
- 移除了
fetch: true参数,手动构造Response时不需要GM_xmlhttpRequest模拟fetch行为,避免冲突 - 确保服务器返回的WASM文件Content-Type为
application/wasm,如果服务器返回不正确,可以手动在Blob的type参数中指定,保证instantiateStreaming能正确识别数据类型
内容的提问来源于stack exchange,提问作者a a
相关产品推荐
相关产品推荐

