W3C home > Mailing lists > Public > www-voice@w3.org > January to March 2014

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

From: Jim Barnett <1jhbarnett@gmail.com>
Date: Tue, 25 Mar 2014 09:26:18 -0400
Message-ID: <533183FA.3070504@gmail.com>
To: www-voice@w3.org
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: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

Jim Barnett
Received on Tuesday, 25 March 2014 13:26:50 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 23:04:01 UTC