jbeard4 / SCION

SCXML/Statecharts in JavaScript, moved to gitlab: https://gitlab.com/scion-scxml/scion
https://scion.scxml.io
Apache License 2.0
149 stars 29 forks source link

Support dynamic script injection of script/@src #320

Closed jbeard4 closed 7 years ago

jbeard4 commented 9 years ago

We would transform:

<scxml>
  <script src="foo.js"/>
  <script src="bar.js"/>
  <state id="A"/>
</scxml>

To:

<scxml initial="$generate-before-scripts-loaded">
  <parallel id="$generate-before-scripts-loaded">
    <onentry>
      <fetch id="foo" url="foo.js"/>
      <fetch id="bar" url="bar.js"/>
    </onentry>
    <state id="$generated-loading-script-foo.js">
      <state id="$generated-before-script-script-foo.js-loaded">
        <transition target="$generated-after-script-script-foo.js-loaded" event="fetch.response.success.foo"/>
      </state>
      <state id="$generated-after-script-script-foo.js-loaded">
        <onentry>
          <!-- eval downloaded script -->
          <script> eval(_event.data); </script>
        </onentry>
      </state>
    </state>
    <state id="$generated-loading-script-bar.js">
      <state id="$generated-before-script-script-bar.js-loaded">
        <transition target="$generated-after-script-script-bar.js-loaded" event="fetch.response.success.bar"/>
      </state>
      <state id="$generated-after-script-script-bar.js-loaded">
        <onentry>
          <!-- eval downloaded script -->
          <script> eval(_event.data); </script>
        </onentry>
      </state>
    </state>

    <transition 
        event="fetch.response.success.*"
        target="$generated-after-script-tags-loaded-successfully" 
        cond="In('$generated-after-script-script-foo.js-loaded') &amp;&amp; 
                In('$generated-after-script-script-bar.js-loaded') "/>
    <transition 
        event="fetch.response.failure"
        target="$generated-after-script-tags-loaded-failed" />
  </parallel>

  <state id="$generated-after-script-tags-loaded-successfully">
    <onentry>
      <!-- TODO: init the datamodel -->
    </onentry>
    <transition event="scion.internal.start" target="A"/>
  </state>

  <state id="$generated-after-script-tags-loaded-successfully">
    <transition event="scion.internal.start" target="A"/>
  </state>

  <state id="$generated-after-script-tags-loaded-failed"></state>

  <state id="A"/>
</scxml>

<fetch> would be parameterizable on the scripting context.

eval could potentially be replaced with something safer such as the nodejs vm module.

jbeard4 commented 9 years ago

Although eval(_event.data); would fail to evaluate the downloaded code in module scope.

jbeard4 commented 7 years ago

Fixed in 3.0.0