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

如何修复Proxy中toString.caller调用报错:get caller method called on incompatible proxy

问题描述

请参考以下代码:

handler.toString = function() {
    return Reflect.get(original,'toString');
}
handler.apply = scope.exportFunctionWithName(function(target, thisArgs, args){
    try {
        return args.length?
            replacement.call(thisArgs, ...args):
            replacement.call(thisArgs);
    }
    catch (error){
        try {
            return original.apply(thisArgs, args);
        }
        catch (error){
            return target.apply(thisArgs, args);
        }
    }
}, window, "");
const proxy = new window.Proxy(original, handler);

当调用ApiObj.toString()时,运行符合预期。但调用ApiObj.toString.caller时出现报错,错误信息如下:

get caller method called on incompatible proxy

修复方案

这个错误的核心原因是:你直接返回了原始的toString方法,而原生函数的caller属性对执行上下文有严格检查——当该方法在代理对象的上下文被访问时,会因代理与原始函数的上下文不匹配触发兼容性报错。

可以通过代理的get陷阱统一处理属性访问,确保方法的执行上下文与原始对象一致,修复代码如下:

const handler = {
  get(target, prop) {
    const value = Reflect.get(target, prop);
    // 对所有函数类型的属性,绑定原始对象作为执行上下文
    if (typeof value === 'function') {
      return value.bind(target);
    }
    return value;
  },
  apply(target, thisArgs, args) {
    try {
      return args.length ? replacement.call(thisArgs, ...args) : replacement.call(thisArgs);
    } catch (error) {
      try {
        return original.apply(thisArgs, args);
      } catch (error) {
        return target.apply(thisArgs, args);
      }
    }
  }
};

const proxy = new window.Proxy(original, handler);

如果只想针对toString做单独处理,也可以用更精准的写法:

const handler = {
  get(target, prop) {
    if (prop === 'toString') {
      // 返回绑定了原始对象的toString方法,确保上下文一致
      return original.toString.bind(original);
    }
    return Reflect.get(target, prop);
  },
  apply(target, thisArgs, args) {
    try {
      return args.length ? replacement.call(thisArgs, ...args) : replacement.call(thisArgs);
    } catch (error) {
      try {
        return original.apply(thisArgs, args);
      } catch (error) {
        return target.apply(thisArgs, args);
      }
    }
  }
};

const proxy = new window.Proxy(original, handler);
原理说明
  • 直接给handler赋值toString会跳过代理的get陷阱,导致返回的原始方法在代理上下文被访问时,caller属性的内部检查不通过。
  • 通过get陷阱返回绑定了原始对象的方法,能确保方法的执行上下文与原始对象完全一致,从而避免兼容性报错。
  • 通用的函数绑定逻辑可以覆盖所有类似的方法属性,无需单独处理每个函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 21:15:08