I just pushed the latest version of machina.js (v0.3.8). I've been working to eliminate some edge case bugs with extended machina.Fsm constructors and it appears we may have squashed the last bug there (until the next one, of course).

This is the perfect segue to mention a feature that not many are aware of. When you extend a machina constructor, if the 'base' FSM contains states and input handlers, you can blend additional input handlers & states onto an instance created by that constructor. The end result is an FSM that contains instance-level states that are a merging of what was on the prototype chain (base, etc.) and what was passed into the constructor upon instantiation. As with any inheritance-related feature - use discretely and with caution, as inheritance is the best kind of paint to paint yourself into a corner with.

"Blended States" Example

Let's say we have a base FSM constructor that looks like this (I'm hiding other top level methods just to focus on the initialState and states members):

var WorldCupPlayer = machina.Fsm.extend({  
  initialState: "ready",
  states: {
    ready: {
      "talk.smack": function() {
        this.emit("smack.talking");
      },
      play: "playing"
    },
    playing: {
      play: function() {
        this.emit("wat", "I'm already playing!");
      }
    },
    done: {
      _onEnter: function() {
        this.collapseAndSleep();
      }
    }
  }
});

Now we have a base FSM that provides some foundational behavior common to all FSMs that apply to a certain scenario. Let's extend this to create a more specific constructor:

var TimHoward = WorldCupPlayer.extend({  
  saves: 15,
  states: {
    playing: {
      "opponent.goal.attempt": "blocking"
    },
    blocking: {
      _onEnter: function() {
        this.saves += 1;
        if (this.saves >= 16) {
          this.emit("record.broken", {
            player: "Tim Howard",
            msg: "Most saves in World Cup Match"
          });
        }
        this.transition("playing");
      }
    }
  }
});

We added a playing and blocking state to our TimHoward FSM (I never thought I'd use those words in a sentence together....). Since this FSM constructor extends our WorldCupPlayer FSM, it will also contain the ready and done states, and its playing state will contain the play handler provided in WorldCupPlayer. Let's extend our base FSM to create another constructor:

var LuisSuarez = WorldCupPlayer.extend({  
  states: {
    playing: {
      "play": function() {
        this.emit("bite.me", {
          player: "Giorgio Chiellini",
          bitten: true
        });
      }
    },
    done: {
      _onEnter: function() {
        this.ejectFromStadium();
      }
    }
  }
});

Our LuisSuarez FSM provides an implementation for a play input handler that overrides the one in WorldCupPlayer, and it also overrides the _onEnter handler of the done state. To prove it actually works, you can view this fiddle.

This screen shot shows the TimHoward instance in Chrome's console, with the prototypes expanded so you can see that the instance level states member (surrounded in blue) is a merging of what's in the TimHoward prototype (surrounded in orange) and the WorldCupPlayer prototype (green). You can also see that the instance level initialState member was set by pulling the "default" value from the prototype chain (from WorldCupPlayer):

Examining machina prototype

Wrapping Up

How's that for a bite-sized chunk example? (Oh, puns, how I love them). Now that v0.3.8 seems to have covered the bases of the inheritance issues I wanted to address, I'm turning my attention to v0.4 and the roadmap beyond.