Maximum Call Stack Size in JavaScript Engines

This article examines the maximum call stack size across major JavaScript engines, explaining how stack limits work, how they vary across environments like Chrome (V8), Firefox (SpiderMonkey), and Safari (JavaScriptCore), and the primary factors that determine when a “RangeError: Maximum call stack size exceeded” occurs.

ECMAScript Specification and Call Stack Limits

The ECMAScript specification does not define a fixed maximum call stack size. Instead, stack limits are an implementation detail determined by individual JavaScript engines, host operating systems, and available memory.

When a function is called, the engine allocates a stack frame containing arguments, local variables, and return addresses. If recursion or nested function calls exceed the allocated stack memory buffer, the engine terminates execution and throws a RangeError.

Typical Limits Across Major Engines

Stack size limits are generally measured either in bytes of memory allocated to the stack or in the total number of nested function call frames.

Factors Influencing Stack Size

The maximum number of recursive calls is not a constant value. It depends on several key variables:

  1. Stack Frame Complexity: Functions with many local variables, arguments, or large scopes consume more memory per frame, reducing the total number of calls before reaching the stack limit.
  2. Environment and Architecture: 64-bit architectures require larger pointers than 32-bit systems, increasing the size of each stack frame and lowering the total frame count.
  3. Tail Call Optimization (TCO): Although specified in ES6, only JavaScriptCore (Safari) consistently implements Proper Tail Calls (PTC). In engines with TCO support, recursive calls in the tail position reuse the current stack frame, theoretically allowing infinite recursive depth.

Measuring Call Stack Size

The exact limit of an environment can be tested using a simple recursive counter:

let depth = 0;

function measureStack() {
  depth++;
  measureStack();
}

try {
  measureStack();
} catch (error) {
  console.log(`Maximum stack depth: ${depth}`);
  console.error(error.message);
}

How to Prevent Stack Overflow Errors

When dealing with deep recursion, use the following strategies to prevent exceeding the call stack limit: