Agent skill

inheritance-debugging

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/inheritance-debugging

SKILL.md

Skill: inheritance-debugging

Scope

Debug constructor inheritance issues where subclass properties are accessed before initialization.

Does:

  • Diagnose "undefined is not iterable" and NaN calculation errors
  • Fix super() initialization order problems
  • Add fallback defaults in render methods
  • Verify fixes with incremental testing

Does Not:

  • Cover general JavaScript debugging
  • Handle non-inheritance related bugs

Context

In jsgui3 controls, a common pattern is:

  1. Base class constructor calls compose() or render()
  2. Subclass constructor calls super(spec) then sets its own properties
  3. Problem: Base class render runs BEFORE subclass properties exist

This manifests as:

  • undefined is not iterable when destructuring this._property
  • NaN calculations using undefined numeric properties
  • Missing SVG attributes (x, width, height)
  • Silent failures with empty renders

Procedure

1. Identify the Pattern

Look for this constructor structure:

javascript
class Child extends Parent {
    constructor(spec) {
        super(spec);  // ← Parent calls render() here
        
        this._my_property = spec.value || 'default';  // ← Too late!
    }
}

2. Run Isolated Tests

Create a debug script to test with abstract: true:

javascript
const control = new MyControl({
    context,
    abstract: true,  // Skips compose/render
    ...options
});

console.log('Properties:', control._my_property);

If it works with abstract: true but fails without, this confirms the timing issue.

3. Add Fallback Defaults in Methods

In every method that uses subclass properties, add defaults:

javascript
// Before (breaks during super())
render() {
    const [min, max] = this._range;  // undefined error
    const gap = this._gap;  // NaN
}

// After (safe)
render() {
    const range = this._range || [-10, 10];  // Fallback
    const [min, max] = range;
    const gap = this._gap !== undefined ? this._gap : 0.1;
}

4. Add Re-render After Properties Set

In the subclass constructor, re-render after setting properties:

javascript
constructor(spec) {
    super(spec);  // Renders with defaults
    
    this._my_property = spec.value || 'default';
    
    // Re-render now that properties are set
    if (!spec.abstract && !spec.el && this._svg) {
        this.render_chart();
    }
}

5. Verify with Browser Subagent

Use browser testing to visually confirm the fix:

1. Start demo server
2. Navigate to demo page
3. Inspect rendered elements for correct attributes
4. Check console for errors
5. Screenshot for documentation

6. Run Unit Tests

Ensure all tests pass after the fix:

bash
npx mocha test/controls/<control>.test.js --reporter min

Real Example: Bar_Chart Fix

Problem: Bar rects had y and height but missing x and width.

Root Cause: super(spec) called compose_chart()render_chart()render_bars(), which used this._bar_gap before it was set.

Fix: Added fallback in render_bars():

javascript
const bar_gap = this._bar_gap !== undefined ? this._bar_gap : 0.1;
const group_gap = this._group_gap !== undefined ? this._group_gap : 0.2;

Result: 35 chart tests passing, bars render correctly.

Validation Checklist

  • Identified properties accessed before initialization
  • Added fallback defaults to all affected methods
  • Added re-render call after subclass properties set
  • Debug script with abstract: true works
  • Debug script without abstract: true works
  • Unit tests pass
  • Browser visual verification passed

References

Didn't find tool you were looking for?

Be as detailed as possible for better results