EXAMPLE 03 • inlining.ts

Multi-Level Function Inlining & Virtual Call Stacks

Expand a single physical V8 stack frame into 4 authored call frames with per-frame scopes, call sites, and Debug Evaluate.

Multi-Level Inlined Ranges (processCustomerOrder -> calculateCartTotal -> computeTierDiscount -> clampPercentage)Call-Site Positions (callSite: { sourceIndex, line, column })isStackFrame: true (OriginalScope) vs isStackFrame: false (Inlined GeneratedRange)Inlined Argument & Parameter Expression Bindings (value -> y * 4, min -> 5, max -> 25)
OPEN CHROME DEVTOOLS (F12) FIRST, THEN TRIGGER:
Ready. Click "Run & Pause in Debugger" with DevTools open.

How This Example Works

Modern bundlers and compilers aggressively inline small helper functions. Here, processCustomerOrder calls calculateCartTotal, which calls computeTierDiscount, which calls clampPercentage. In bundle.js, all three helpers are completely inlined into processCustomerOrder(n, s, y).

By nesting three GeneratedRange entries with isStackFrame: false and callSite coordinates inside processCustomerOrder's range, Chrome DevTools synthesizes the full 4-frame Call Stack. Clicking any inlined frame in the Call Stack pane switches the editor to that caller's call site and updates the Scope view, Autocomplete suggestions, and Console Debug Evaluate to that frame's lexical variables!

What to Try & Verify in DevTools

Call Stack

Try:Click "Run & Pause in Debugger" to pause at debugger; on line 5 of inlining.ts (clampPercentage).

  • 4 Virtual Frames from 1 Physical Frame: Even though only processCustomerOrder exists in bundle.js, the Call Stack pane shows clampPercentage (line 5) → computeTierDiscount (line 11) → calculateCartTotal (line 20) → processCustomerOrder (line 30).
Scope View

Try:Click each frame in the Call Stack pane (clampPercentage, computeTierDiscount, calculateCartTotal, processCustomerOrder) and watch the editor and Scope pane.

  • clampPercentage Frame: Shows value: 32, min: 5, max: 25, clamped: 25.
  • computeTierDiscount Frame: Highlights the call site on line 11 (clampPercentage(rawPercent, 5, 25)) and switches Scope variables to baseAmount: 240, loyaltyYears: 8, rawPercent: 32, effectivePercent: 25.
  • calculateCartTotal Frame: Highlights line 20 and shows subtotal: 240, loyaltyYears: 8, couponFixed: 15. discountAmount and finalTotal are <unavailable> (not computed yet).
  • processCustomerOrder Frame: Highlights line 30 and shows customerName: "Grace Hopper", subtotal: 240, loyaltyYears: 8. payable is <unavailable>. The generated-only parameter pause must not show up.
Autocomplete

Try:Select computeTierDiscount in the Call Stack and type rawP or eff in the Console; then switch to calculateCartTotal and type coup.

  • Per-Frame Suggestions: Autocomplete dynamically updates to suggest the lexical variables of whichever virtual inlined frame is currently selected.
Conditional Breakpoints

Try:Right-click line 12 (return baseAmount * (effectivePercent / 100); inside computeTierDiscount), set conditional breakpoint rawPercent > effectivePercent, resume (F8), and click "Run & Pause in Debugger" again.

  • Inlined Condition Evaluation: DevTools evaluates (y * 4) > pct (32 > 25 → true) and pauses directly inside the inlined computeTierDiscount frame.
Debug Evaluate

Try:Select different frames in the Call Stack and run the corresponding expressions below in the Console.

  • Frame-Relative Resolution: Identical variable names (like subtotal) or frame-specific parameters (rawPercent, couponFixed) resolve against the selected virtual frame's GeneratedRange.
Other things to try
  • Click Log Inlined Error Stack and check the Console stack trace lists all 4 authored functions.
  • Select an inlined frame (e.g. computeTierDiscount) and use Restart frame, or step with F10/Shift+F11.
  • Right-click the Call Stack › Copy stack trace.

Not sure if it's a DevTools bug? Tab 4. Decoded Scopes shows what the source map actually encodes.

Try in the Console While Paused

While paused, select a frame and evaluate these in the Console (Esc opens the drawer) using the authored names:

{ value, min, max, clamped }
Expected Result: { value: 32, min: 5, max: 25, clamped: 25 } (when clampPercentage frame is selected)
Evaluates the inlined arguments (y * 4, 5, 25) and local variable (pct) of clampPercentage.
rawPercent - effectivePercent
Expected Result: 7 (when computeTierDiscount frame is selected)
In the caller frame computeTierDiscount, rawPercent (32) minus effectivePercent (25) equals 7.
subtotal - couponFixed
Expected Result: 225 (when calculateCartTotal frame is selected)
In calculateCartTotal, subtotal (240) and constant-inlined parameter couponFixed (15) evaluate to 225.