EXAMPLE 02 • register-reuse.ts

Register Reuse & Sub-Range Variable Bindings

Track variable liveness and register coalescing when a single minified variable 'r' is overwritten across multiple stages.

SubRangeBinding[] Contiguous IntervalsRegister Coalescing / Reuse (r -> calibratedMv, temperatureCelsius, statusBadge)Temporal Variable Liveness (unavailable before init & after overwrite)Reverse Algebraic Reconstruction across Sub-Ranges
OPEN CHROME DEVTOOLS (F12) FIRST, THEN TRIGGER:
Ready. Click "Run & Pause in Debugger" with DevTools open.

How This Example Works

Optimizing compilers and minifiers perform register allocation / variable coalescing: if three authored variables (calibratedMv, temperatureCelsius, and statusBadge) have non-overlapping lifetimes, the compiler reuses a single JavaScript variable let r for all three!

Without sub-range bindings, mapping all three names to r would cause every variable to show the wrong value (e.g. statusBadge showing 1250 at Step 1). Using SubRangeBinding[], each variable specifies exact [from, to) positions in generated code where it is unavailable, bound directly to "r", or algebraically reconstructed (`r * 10 + 500`).

What to Try & Verify in DevTools

Scope View

Try:Click "Run & Pause in Debugger" to stop at debugger; // Step 1 in register-reuse.ts (where let r = 1250).

  • Active Binding: calibratedMv displays 1250 (bound directly to r).
  • Pre-Initialization Liveness: temperatureCelsius and statusBadge both display <unavailable> instead of leaking r's current value.
Scope View

Try:Press F8 (Resume) once to advance to debugger; // Step 2 (where r is overwritten with 75).

  • Reassigned Register: temperatureCelsius becomes live with value 75 (now bound to r).
  • Reverse Algebraic Binding: calibratedMv stays 1250 because its active sub-range [step2Pos, step3Pos) switches its binding expression to "r * 10 + 500".
  • Still Uninitialized: statusBadge remains <unavailable>.
Inline Hints & Popover

Try:Press F8 (Resume) once more to reach debugger; // Step 3 (where r is overwritten with the badge string).

  • New Register Owner: statusBadge becomes "[CORE-TEMP-04] 75.0°C (WARN)" (bound to r).
  • Clobbered Register: calibratedMv transitions to <unavailable> because r now holds a string.
  • Fallback Expression: temperatureCelsius (75) stays live via (e.rawMillivolts + e.calibrationOffset - 500) / 10.
Conditional Breakpoints

Try:Type cal, temp, or statusB in the Console to check autocomplete, or set a conditional breakpoint on line 18 (const statusBadge = ...) with condition temperatureCelsius >= 70 && calibratedMv === 1250.

  • Autocomplete: All three coalesced variables appear in Console and breakpoint autocomplete.
  • Sub-Range Condition Evaluation: At line 18, DevTools simultaneously resolves temperatureCelsius (r) and calibratedMv (r * 10 + 500) to pause execution.
Debug Evaluate

Try:Run the expressions below in the Console at Steps 1, 2, and 3.

  • PC-Sensitive Rewriting: DevTools picks the exact SubRangeBinding interval matching the current paused line:column in bundle.js.
Other things to try
  • Step with F10 instead of resuming, and watch when each variable switches between a value and <unavailable>.
  • Add calibratedMv, temperatureCelsius and statusBadge as Watch expressions before running.
  • Set a breakpoint on each const line (instead of using debugger;) and check the Scope view.

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:

calibratedMv
Expected Result: 1250 (at Step 1 & Step 2) | ReferenceError / unavailable (at Step 3)
Resolves to r at Step 1, r * 10 + 500 at Step 2, and is marked unavailable at Step 3.
temperatureCelsius * 1.8 + 32
Expected Result: 167 (at Step 2 & Step 3)
Converts Celsius (75) to Fahrenheit (167°F) using r at Step 2 and (e.rawMillivolts + e.calibrationOffset - 500) / 10 at Step 3.
statusBadge
Expected Result: "[CORE-TEMP-04] 75.0°C (WARN)" (at Step 3)
Resolves to r only after execution reaches step3Pos.