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

Jim Barnett <[email protected]>
Newsgroups gmane.comp.web.voice
Message-ID <[email protected]>
I agree that a using a table is cleaner than hacking an attribute into 
state.  It is probably also cleaner to pass it as an extra argument, 
though we do use a number of globals in the algorithm already.  As long 
as the extra argument is used in only a  few places and _none_ of the 
other entry/exit logic changes, it's a safe change.

For the prose in the spec, I am thinking of adding something like the 
following in 3.10.2, right after the penultimate sentence (which is "If 
it has not, the SCXML processor /MUST/ behave as if the transition had 
taken the default stored state configuration for that history state as 
its target"):

The Process MUST execute any executable content in the transition after 
the history pseudo-state's parent state's onentry handlers, and, in the 
case where the history pseudo-state was the target of an <initial> 
transition, after any executable content in the <initial> transition.

Let's wait a couple of days to see if there are any other comments. Then 
I will update the editor's draft and send around a link to it so that 
people can have a look.  There won't be a new public draft until we go 
through the publication procedure, which will take a couple of weeks.

- Jim


On 3/25/2014 2:42 AM, Ate Douma wrote:
> 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:[email protected]]
>> Sent: Monday, March 24, 2014 4:20 PM
>> To: [email protected]
>> 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
>>
>>
>
>

-- 
Jim Barnett
Genesys
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.