matthewp / robot

🤖 A functional, immutable Finite State Machine library

Home Page:https://thisrobot.life

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[bug] Nested tree machines final state

kybarg opened this issue · comments

When there is a tree of nested state machines, when the very child final state is reached it goes straight to the root machine

Can you share some example code or a link to codesandbox / codepen?

@HipsterBrown output is

childStart
grandChildStart
grandChildDone
rootStart
rootStart

when expected output is

childStart
grandChildStart
grandChildDone
childResult

@matthewp any thoughts?

It appears the invoke function type sends the done event to the interpreted service in general, rather than a specific machine, i.e the root machine vs the child machine, so the root done transition is happening when the grandChild machine has completed and invoked done.

let invokeType = {
  enter(machine, service, event) {
    this.fn.call(service, service.context, event)
      .then(data => service.send({ type: 'done', data }))
      .catch(error => service.send({ type: 'error', error }));
    return machine;
  }
};

My guess is this could be addressed by updating the invokeType to send that done event to a specific machine?

Yes, this does sound like a bug. I can't look at it today but will try to do shortly (if someone else wants to try and do a PR that would be great too).

@matthewp
This seems like a solution, but it breaks test, so not sure...
kybarg@d12adc2#diff-34d800fceb92f13afae91cf2013e361fR93-R106

const machineToThen = machine => function(ctx, ev) {
  return {
    then: resolve => {
      this.child = interpret(machine, s => {
-        this.onChange(this);
+        if (this.child !== s) this.onChange(s);
+        else this.onChange(this);
        if(s.machine.state.value.final) {
          delete this.child;
          resolve(s.context);
        }
      }, ctx, ev);
      return { catch: identity };
    }
  };
};