Uploaded image for project: 'Fluid Infusion'
  1. Fluid Infusion
  2. FLUID-4930

Correct "ginger world" algorithm so that it behaves correctly in cases of "retrunking" - clarify semantics for full evaluation

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Reopened
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 1.5, 2.0
    • Fix Version/s: 3.0
    • Component/s: IoC System
    • Labels:
      None

      Description

      When writing a test case for FLUID-4918, a pretty simple case came to light where the existing "ginger world" algorithm for FLUID-4330 behaves incorrectly.

          fluid.defaults("fluid.tests.memberTest", {
              gradeNames: ["fluid.littleComponent", "autoInit"],
              members: {
                 expanded: {
                     expander: {
                         func: "{that}.identity",
                         args: "{that}.emptyArray"
                     }  
                 },
                 emptyArray: []
              },
              invokers: {
                  identity: "fluid.identity"
              }  
          });
      

      In the case above, the member "expanded" did not appear in the final component at all! The process for ginger evaluation for options during EXPANSION correctly evaluated the merge block corresponding to "expanded", causing evaluation of the reference to "

      {that}.identity" and hence the FULL evaluation of "{that}

      .emptyArray" which duly appeared in the final component as a result of complete evaluation of that path.

      However, when the MERGE algorithm came to process the path "members", as required by the "initter" for the member strategy:

              shadow.memberStrategy.initter(); 
      

      in fluid.initDependents, it inspected the path "members", discovered that it was present in the options structure and hence concluded that it had already been evaluated! It then returned it as is, without following any further recursion.

      Some things are clear: i) It's clear that in some contents, the "extremely ginger" semantics operated by the ginger world are appropriate, in that it MAY refuse to evaluate any subpaths which are not immediately demanded. However, right now, the situations where these semantics are delivered are extremely patchy - a caller can't be sure how much of an object they will actually get, and what's more we are probably relying on this phenomenon to save us from circularity in at least some cases where we shouldn't depend on it - for example, it is believed that the indirect mutual reference between the Reorderer and LayoutHandler with respect to their DOM binder selectors currently works exactly because of this sort of "opportunistic bug". The real issue/problem is whether we can ever expect to be fully clear about this. It may simply have to be part of a client's grade or other info that explains their expectations on "full evaluation". You would expect that any client which is simply the options system itself or "members" would be happy with the current semantics, which guarantee the maximum freedom from circularity by maximum gingerness - however, a client which is an invoker or expander would most likely only be happy with fully evaluated arguments - unless it could somehow explain to the contrary.

      Clearly the situation right now - where an options structure was in fact NEVER fully evaluated even by the end of the ginger process is an outright bug, but the fix we have issued, a special flag in the expander's options named "evaluateFully" is an insufficient fix. More subtle instances of this problem can continue to recur, even though we can now at least guarantee that all evaluation is complete by the end of the ginger process.

      ii) The system that we implemented whereby the ginger world relies on "self-timing" by storing properties (whether they are "undefined" or no) in the LH target object is inadequate to solve this problem fully. It was hoped that we could get by without any auxiliary storage, but it seems clear that we can't - since otherwise we can't disambiguate the situations where we visited a trunk path partially but need to return to it later to fully evaluate its child paths, and where we have completely evaluated it and don't need to return. This definitely requires flags held in some auxiliary "shadow structure" which is a painful result for efficiency but will at least spare us from returning the current ugly and probably dangerously confusing options structures filled with concrete properties with value "undefined" which appear everywhere where there is a value demand but no value present. This "shadow structure" would also be a place we could store provenance information which could be useful in interpreting merge results, as well as these flags indicating evaluation state. We might then even be able to return to the old semantics for "fluid.merge", in which the change has been an annoying bump in the release process for the "new framework".

      The real challenge is finding where to express the client's "evaluation intent" since there is just not room for it in either the strategy API, or fluid.get, or any of the other "state API" expressions we have in the system. The "shadow structure" may itself be the only place to put this - given it is really associated with the evaluation of a particular PATH during a particular process, and the "shadow structure" is only good for that one process anyway - it is expected to be discarded on completion of a "ginger wave".

        Attachments

        1. aboveExpandExpander.png
          335 kB
          Antranig Basman

          Issue Links

            Activity

              People

              Assignee:
              antranig Antranig Basman
              Reporter:
              antranig Antranig Basman
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated: