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

如何记录所有函数调用?EDGE浏览器崩溃排查技术求助

Tracking All Function Calls (Including Direct Invocations) for Edge Crash Debugging

Got it, let's tackle this problem—your current setup only catches .call()/.apply() calls, but you need to log every function invocation (like someFunction()) to pinpoint what's triggering that Edge crash. Here are three practical, actionable strategies to make this work:

1. Wrap All Functions via Function.prototype (Most Comprehensive)

Since every function in JS is an instance of Function, we can modify its prototype to automatically wrap every function (existing and new) with logging logic. This will catch direct calls, .call(), .apply(), and even arrow functions (with caveats for anonymous ones).

Here's the code:

// Flag to avoid infinite wrapping loops
const WRAPPED_FLAG = '__isFunctionWrapped__';

// Core wrapper function to log calls and execute the original function
function wrapFunction(fn, functionName = 'anonymous') {
  // Skip native browser functions to avoid breaking Edge's internal behavior
  if (fn.toString().includes('[native code]')) return fn;
  // Skip already wrapped functions
  if (fn[WRAPPED_FLAG]) return fn;

  const wrapped = function(...args) {
    // Log critical details: function name, arguments, caller context, and stack trace
    console.log(`[Function Invocation] ${functionName}`, {
      args: args,
      callerContext: this,
      stack: new Error().stack
    });

    try {
      // Execute the original function with the correct context and args
      return fn.apply(this, args);
    } catch (err) {
      // Log errors too—crashes often happen after uncaught exceptions
      console.error(`[Function Error] ${functionName}`, err);
      throw err; // Don't swallow errors; keep the original behavior
    }
  };

  wrapped[WRAPPED_FLAG] = true;
  return wrapped;
}

// Rewrite the Function constructor to wrap new functions automatically
const originalFunctionConstructor = Function;
Function = function(...args) {
  const newFn = originalFunctionConstructor.apply(this, args);
  // Try to extract a name (works for function declarations/named expressions)
  const fnName = args.length > 0 ? args[args.length - 1].match(/function\s+([^\s(]+)/)?.[1] : 'anonymous';
  return wrapFunction(newFn, fnName);
};
Function.prototype = originalFunctionConstructor.prototype;
Function.prototype.constructor = Function;

// Wrap all existing functions on the global object (window)
function wrapExistingGlobalFunctions(obj, parentNamespace = '') {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      const prop = obj[key];
      const fullName = parentNamespace ? `${parentNamespace}.${key}` : key;

      if (typeof prop === 'function') {
        obj[key] = wrapFunction(prop, fullName);
      } else if (typeof prop === 'object' && prop !== null && !(prop instanceof HTMLElement)) {
        // Recursively wrap functions in nested objects (skip DOM elements to avoid Edge bugs)
        wrapExistingGlobalFunctions(prop, fullName);
      }
    }
  }
}

// Initialize wrapping for all global functions
wrapExistingGlobalFunctions(window);

Key Notes:

  • We skip native functions (marked with [native code]) to avoid interfering with Edge's internal APIs, which could cause more crashes.
  • The stack trace in the log will help you trace exactly where each function was called from—critical for narrowing down the crash trigger.
  • Anonymous functions will show up as anonymous, but their stack trace will still point you to their definition.

2. Use the Browser Debugger API (Low-Level, No Code Modifications)

Edge supports the Chrome DevTools Debugger API, which lets you intercept every function call at the browser level. This is more reliable for edge cases but requires enabling debugging mode.

if (window.debugger) {
  // Enable the debugger
  debugger;
  const debugInstance = window.debugger;

  // Listen for function call events
  debugInstance.onDebuggerEvent = (event) => {
    if (event.type === 'functionCall') {
      const fnName = event.function.name || 'anonymous';
      console.log(`[Debugger Call] ${fnName}`, {
        args: event.arguments,
        stack: event.stackTrace
      });
    }
  };

  // Enable all function call intercepts
  debugInstance.enable();
}

Key Notes:

  • This will catch every single function invocation, including those from third-party scripts and browser internals.
  • Performance overhead is higher than the prototype wrapping method, so only use this for targeted debugging sessions.
  • Some Edge security settings might block this API—make sure you're running in a non-production, debug-friendly environment.

3. Proxy Wrappers (For Targeted Object Functions)

If you don't need to log every global function, you can use a Proxy to wrap specific objects or modules. This is less intrusive but requires targeting specific parts of your codebase.

const wrappedModule = new Proxy(yourModule, {
  get(target, prop) {
    const value = target[prop];
    if (typeof value === 'function' && !value[WRAPPED_FLAG]) {
      return wrapFunction(value, `yourModule.${prop}`);
    }
    return value;
  }
});

Key Notes:

  • Great for focusing on a specific part of your codebase that you suspect is causing the crash.
  • Won't catch functions outside the proxied object, so it's not a universal solution.

Critical Debugging Tips for Edge:

  • Limit Logging: If your project is large, logging every function call will flood the console. Add filters (e.g., only log functions from your app's namespace) to keep output manageable.
  • Save Logs: Edge's console can export logs to a file. Make sure to save the logs right before the crash—you can use console.save() (a DevTools feature) or write logs to a localStorage buffer.
  • Test in Isolation: Try reproducing the crash in a minimal Edge window (no extensions) to rule out interference from add-ons.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:25:45