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

On 25-03-14 14:26, Jim Barnett wrote:
> 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.

Sound good to me.

Maybe it would be helpful to be a little bit more explicit by saying:

   [...] and, in the case where the history pseudo-state was the target of its 
parent <initial> transition, [...]

to make sure this isn't (incorrectly) confused with the case when the history 
was the target of an initial of one of its parent ancestor(s).

Your sentence already is correct of course because of the "and, " in front, so 
either way, I think its fine syntactically.

Ate

>
> 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
> Genesys

Received on Tuesday, 25 March 2014 21:44:54 UTC