GateIn JS improvements for 3.5

Version 32

    This spec aims to define JS improvements in GateIn for 3.5 that are required for reaching a milestone in term of JS dev in GateIn. It does not specify a very precise feature but rather a set of changes to perform. The goal is to improve the programming model and make it consistent in the JS side.

     

    JavaScript module improvements

     

    Current JavaScript modules can contain script or native script, at the moment a module can be declared as a set of JavaScript files that use an implicit shared variable named _module. We want to change this model to use JavaScript idioms, i.e to declare a module as a serie of JavaScript files that contains a function with the dependencies as arguments.

     

    The JS up to GateIn 3.4

     

    The JavaScript files:

     

    $(".foo").click(function() { ... });
    _ module.foo = "foo_value";
    

     

    $(".bar").click(function() { ... });
    _module.bar = "bar_value";
    

     

    The XML declaration:

     

    <module>
       <name>mymodule</name>
       <script>
          <path>/script1.js</path>
       </script>
       <script>
          <path>/script2.js</path>
       </script>
       <depends>
          <module>jquery</module>
          <as>$</as>
       </depends>
    </module>
    

     

    The generated Requires.JS module:

     

    define("SHARED/mymodule", ["SHARED/jquery"], function($) {
    
       var _module = {};
    
       //
       function() {
          $(".foo").click(function() { ... });
          _module.foo = "foo_value"; 
       }();
    
    
       //
       function() {
    
          $(".bar").click(function() { ... });
          _module.bar = "bar_value";
       }();
    
       // 
       return _module;
    });
    
    

     

    The returned value by mymodule would be : { "foo":"foo_value", "bar":"bar_value" }

    The 3.5 changes

     

    We declare a single JS function function per module

     

    The JavaScript file:

     

    (function($) {
       $(".foo").click(function() { ... });
       $(".bar").click(function() { ... });
       return {"foo":"foo_value","bar":"bar_value"};
    })($)
    

     

     

    The XML declaration:

     

    <module>
       <name>mymodule</name>
       <script>
          <path>/script.js</path>
       </script>
       <depends>
          <module>jquery</module>
          <as>$</as>
       </depends>
    </module>
    

     

    The overall generated Requirejs by GateIn from the JS files and the XML declaration would be:

     

    define("SHARED/mymodule", ["SHARED/jquery"], function($) {
       // Content is imported from the scripts1.js and inserted
       return (function() { return (function($) { // ... })($);
    });
    

     

    Note about the return type and the merge. A function will be invoked with the return value (initially {}) as this . So a function can use this accessors to mutate it. However if the function returns a non null or non undefined value then this return value replaces the module value.

     

    A few notes about this scheme:

     

    • Function do no need to match XML dependencies order
    • Function can use parameter subset
    • Parameters must be aliased in dependencies with <as> tag
    • All functions must share the same parameter name
    • More natural construct: that's how jQuery defines itself in jquery.js : (function( window, undefined ) { ... })( window );
    • Would work with jquery.js out of the box
    • Would work with jquery plugins out of the box

     

    Native Requirejs support

     

    We do support it with the same syntax and with proposal 2 by redefining locally the define function (yes read it twice), for instance with the native module

     

    define("foo", ["jQuery"], function($) { ... });
    

     

    Declared by

     

    <module>
       <name>mynativemodule</name>
       <script>
          <path>/nativemodule.js</path>
       </script>
       <depends>
          <module>jquery</module>
          <as>jQuery</as>
       </depends>
    </module>
    

     

    • "foo" is ignored as what matters is the XML declaration
    • ["jQuery"] is matched against the XML alias
    • the function is invoked

     

    The construct will be the same than proposal 2, in addition it redefines the define function a bit like:

     

    define("SHARED/mynativemodule", ["SHARED/jquery"], function(jQuery) {
    
       //
       var define = function(name, dependencies, callback) {
         // Invoke callback using the dependencies array and the declared arguments
         // the goal is to make the dependencies match the declared argument and
         // invoke the callback with the correct dependencies
       };
    
       // Here we use the define redefined above
       // "foo" is ignored
       return define("foo", ["jQuery"], function($) { ... });
    });
    

     

    Using plugins

     

    Requirejs plugins are supported using the resource XML tag:

     

     

    <module>
      ...
      <depends>
        <module>text</module>
        <resource>a/b/c.txt</resource>
      </depends>
    </module>
    

     

    It is equivalent to declaring a dependency on text!a/b/c.txt .

    Adapters

     

    Sometimes the included script does not match the function declaration format or requirejs format expected by GateIn and is requirejs integration. Some code is required for adapting the script to the format. To provide this bit of flexibility it is possible to declare an adapter that will wrap the script.

     

    In this example we show how to adapt jQuery because the original jQuery file does not return anything as Requirejs would expect.

     

     

    <module>
      <name>mymodule</name>
      <script>
        <adapter>
          (function() {
            <include>/jquery.js</include>
            return jQuery.noConflict(true);
          })();
        </adapter>
      </script>
    </module>
    

     

    The <adapter> XML contains mixed content with many <include> tags :

     

    <xs:complexType name="adapter" mixed="true">
      <xs:sequence>
        <xs:element name="include" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
    

     

    The script type becomes:

     

    <xs:complexType name="script">
      <xs:sequence>
        <xs:choice>
          <xs:element name="path" type="xs:string" minOccurs="1" maxOccurs="1"/>
          <xs:element name="adapter" type="adapter" minOccurs="1" maxOccurs="1"/>
        </xs:choice>
        <xs:element name="resource-bundle" type="xs:string" minOccurs="0" maxOccurs="1"/>
      </xs:sequence>
    </xs:complexType>
    

    Various XML changes

    • Rename 1.2.1 XSD to 1.3
    • Remove the <name> nested in <script>
    • Remove legacy <native-script>

     

    GateIn jQuery plugin

     

    todo