Re: History transition executable content - when is it executed?

On 24-03-14 21:40, Jim Barnett wrote:
> I have looked at this and think it's a nasty bug in the spec.  As far as I can see, the algorithm never executes the executable content inside a history state's transition child.  (Somebody please tell me if I'm wrong - it will save us a lot of time.)  Furthermore the text of the specification does not specify when such executable content is to be executed.
>
> If the bug is as serious as I think, the fix will involve changes to the normative language of the specification and we will have to go back to Last Call again.  Furthermore, I don't see a clean way to fix the algorithm because all trace of the fact that we're entering a history state is gone by the point in enterStates where executable content is executed.  I see several possible solutions, and am open to others:
>
> 1.  Forbid executable content in the <transition> inside history.  I know that there's good reason to allow it there, but I mention this because it is the smallest possible change to the specification that restores correctness.  However it weakens the language and leaves us with a transition element that has no motivation.
>
> 2.  Get rid of the transition and add an 'defaultInitial' attribute to the history state.  This is basically the same idea as 1, but it fixes the syntax.  There would be only one trivial change to the algorithm - we would take the default history configuration from the history state's  defaultInitial attribute rather than from the target of its child transition.  But it still weakens the expressiveness of the language.
>
> 3.  Try to fix the algorithm so that it executes the content in the transition.  To avoid breaking anything else, this change should be as small and as isolated as possible.  What I've come up with so far is to kluge a 'extraContent' attribute onto a state.  Then in addDescendantStatesToEnter we would modify the clause that handles the default transition so that it also appends the transition's executable content to the parent state's extraContent attribute (that is, to the parent state of the history state).  Then in enterStates right after we execute a state's onentry content, we would execute its extraContent and then set it to null. This is aesthetically unsatisfying, to say the least, but seems safer than trying to rejuggle a bunch of definitions to handle things cleanly.
>
> Please send me your thoughts on this. All options are ugly, but I think that we have to do something.

I agree this should be properly fixed in the algorithm, but I dislike kludging 
some extra attribute on a state object for the duration and scope of one micro 
step only. If possible I'd keep the SCXML element model definitions independent 
of current execution state and context.

A maybe cleaner way to do is to introduce and use a temporary 
table<State.id,Transition> data structure and use that to keep track and look up 
the History transition to be executed when entering a state.
This table then only is needed and used in the scope of the enterState() procedure:

   procedure enterStates(enabledTransitions):
       statesToEnter = new OrderedSet()
       statesForDefaultEntry = new OrderedSet()
       // initialize the temporary table for targeted History transitions
       defaultHistoryTransitionOnEntry = new HashTable()
       // pass on this table to computeEntrySet
       computeEntrySet(enabledTransitions, statesToEnter, statesForDefaultEntry, 
defaultHistoryTransitionOnEntry)
       for s in statesToEnter.toList().sort(entryOrder):
           configuration.add(s)
           statesToInvoke.add(s)
           if binding == "late" and s.isFirstEntry:
               initializeDataModel(datamodel.s,doc.s)
               s.isFirstEntry = false
           for content in s.onentry:
               executeContent(content)
           if statesForDefaultEntry.isMember(s):
               executeContent(s.initial.transition)
           // if this State is a parent of a targeted History, now execute the 
History transition executable content (if any)
           if defaultHistoryTransitionOnEntry[s.id]
               executeContent(defaultHistoryTransitionOnEntry[s.id]
       ...

This table also will have to be passed on from computeEntrySet(), 
addAncestorStatesToEnter() and addDescendantStatesToEnter() (recursively), and 
the latter then is modified like:

   procedure 
addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry, 
defaultHistoryTransitionOnEntry):
       if isHistoryState(state):
           if historyValue[state.id]:
               // track this targeted History its transition on its parent state 
id for processing in enterStates() after entering its parent
               defaultHistoryTransitionOnEntry[state.parent.id] = state.transition
       ....

Alternatively, the defaultHistoryTransitionOnEntry table can be defined global 
and initialized in procedure interpret() so as not having to modify the 
signatures of any of these procedures, but then you probably also will want to 
clear/reset this table in enterState() and assert its empty afterwards as it 
only is used within its context. You only need to modify the *body* of the 
interpret(), enterStates() and addDescendantsStatesToEnter() procedures then.

I prefer the first solution though as it is more clean and clear, the second 
solution only to be considered to minimize the impact of the change.

Note also I put the History transition handling after its parent 
initial.transition handling explicitly, as the parent.initial might actually be 
the one which targeted the History. Therefore their execution order is significant.

Ate

>
> - Jim
>
> -----Original Message-----
> From: Ate Douma [mailto:ate@douma.nu]
> Sent: Monday, March 24, 2014 4:20 PM
> To: www-voice@w3.org
> Subject: History transition executable content - when is it executed?
>
> While implementing the SCXML Algorithm, I noticed the handling/processing of executable content of a History transition isn't taken care of yet.
> Neither in the Algorithm nor in wording (when) in the specification.
>
> The addDescendantStatesToEnter procedure dereferences History states, so these History states correctly don't end up in the statesToEnter, but then neither will their possible transition executable content be processed.
>
> And as important: when should History transition executable content be processed?
>
> It seems like an obvious choice that it should happen after the History parent state onentry and before any History default targets onentry execution.
>
> Any opinions?
>
> At any rate, I think this needs to be clarified in the specification, and also integrated in the Algorithm.
>
> Kind regards,
> Ate
>
>

Received on Tuesday, 25 March 2014 06:43:14 UTC