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