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

Chrome Manifest V3扩展出现Maximum call stack size exceeded问题求助

Chrome Manifest V3扩展请求追踪栈溢出问题解决

问题场景

开发基于Manifest V3的Chrome学习类扩展,需要追踪站点所有包含https://example子串的请求完整URL,但打开页面时控制台触发Maximum call stack size exceeded错误,同时附带报错信息console.error Unknown server error, msg=Maximum call stack size exceeded, requested_url=/webapi/spa/modules/error404。

原实现代码:

function middlewareRequest(url, options) {
    if (url && url.includes && url.includes("https://example")) {
        console.log("URL:", url);
    }

    if (window.XMLHttpRequest) {
        var xhr = new window.XMLHttpRequest();
        xhr.open(options.method || "GET", url, true);

        xhr.send(options.body || null);

        return xhr;
    } else {
        return window.fetch(url, options).then(function (response) {
            return response;
        });
    }
}

window.XMLHttpRequest.prototype.open = function () {
    return middlewareRequest.apply(this, arguments);
};
window.fetch = function () {
    return middlewareRequest.apply(this, arguments);
};

错误根源:无限递归

你重写了XMLHttpRequest.prototype.open和window.fetch,但在middlewareRequest内部又创建新的XMLHttpRequest并调用其open方法,或者直接调用window.fetch——而这两个方法已经被替换为middlewareRequest,导致每次调用都会触发新的middlewareRequest调用,形成无限递归,最终引发栈溢出。

此外,原代码逻辑错误:直接在中间件中发起新请求,而非追踪页面原本的请求,这会干扰页面正常逻辑。

修复方案:保存原生方法并拦截放行

先保存原生的请求方法,在拦截逻辑中调用原生方法而非重写后的版本,避免递归;同时仅做URL追踪,不替代页面发起请求。

修复后的代码:

// 提前保存原生请求方法,避免被重写后无法调用
const originalXhrOpen = window.XMLHttpRequest.prototype.open;
const originalFetch = window.fetch;

// 单独的URL追踪逻辑
function trackTargetUrl(url, options) {
    if (url && url.includes && url.includes("https://example")) {
        console.log("追踪到目标URL:", url);
    }
}

// 重写XMLHttpRequest的open方法
window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
    // 先追踪URL
    trackTargetUrl(url, { method });
    // 调用原生open方法,保留所有参数
    return originalXhrOpen.apply(this, arguments);
};

// 重写fetch方法
window.fetch = function(url, options) {
    // 先追踪URL
    trackTargetUrl(url, options);
    // 调用原生fetch方法
    return originalFetch.apply(this, arguments);
};

关键说明

  • 必须先保存原生方法:在重写全局方法前,把原生的open和fetch存起来,后续在拦截逻辑中调用这个保存的版本,才不会触发递归。
  • 不要替代页面请求:原代码中直接创建XHR发送请求的逻辑是错误的,正确的拦截是在页面发起请求时先记录URL,再放行到原生方法,保证页面原有请求流程不受影响。
  • 保留所有参数:XMLHttpRequest的open方法有多个可选参数,要完整传递给原生方法,避免破坏页面的请求配置。

内容的提问来源于stack exchange,提问作者Даниил Ельчуков

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:50:00