Skip to content
Browse files

Changed: externals shadow globals and root scope locals.

  • Loading branch information...
1 parent cf7d465 commit 6a3093f45f1a12a15562d11732c2186d022f9a51 @mauricemach mauricemach committed
Showing with 100 additions and 39 deletions.
  1. +1 −1 CHANGELOG.md
  2. +25 −23 docs/zappa.html
  3. +21 −15 src/zappa.coffee
  4. +53 −0 tests/externals.coffee
View
2 CHANGELOG.md
@@ -1,6 +1,6 @@
**v0.2.0beta2** (xxxx-xx-xx):
- - Changed: external vars (`zappa {foo} ->`) overwrite all others.
+ - Changed: externals (`zappa {foo} ->`) are available at all scopes, shadow globals and root scope locals.
- Fixed: inline templates with multiple apps.
View
48 docs/zappa.html
@@ -55,16 +55,16 @@
<span class="k">return</span> <span class="nx">views</span><span class="p">[</span><span class="nx">p</span><span class="p">]</span> <span class="k">if</span> <span class="nx">views</span><span class="p">[</span><span class="nx">p</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Try appid/foo in memory.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">p = </span><span class="nx">p</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">p</span><span class="p">),</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">views</span><span class="p">[</span><span class="nx">p</span><span class="p">]</span> <span class="k">if</span> <span class="nx">views</span><span class="p">[</span><span class="nx">p</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Try /path/to/foo.bar in filesystem (normal express behaviour).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">p = </span><span class="nx">@path</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">id</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">p</span><span class="p">,</span> <span class="s1">&#39;utf8&#39;</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Takes in a function and builds express/socket.io apps based on the rules contained in it.
-The optional data object allows passing variables from the outside to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">zappa.app = </span><span class="o">-&gt;</span>
+The optional externals object allows passing variables from the outside to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">zappa.app = </span><span class="o">-&gt;</span>
<span class="nv">id = </span><span class="nx">uuid</span><span class="p">()</span>
- <span class="nv">data = </span><span class="kc">null</span>
+ <span class="nv">externals = </span><span class="kc">null</span>
<span class="nv">root_function = </span><span class="kc">null</span>
<span class="k">for</span> <span class="nx">a</span> <span class="k">in</span> <span class="nx">arguments</span>
<span class="k">switch</span> <span class="k">typeof</span> <span class="nx">a</span>
<span class="k">when</span> <span class="s1">&#39;function&#39;</span> <span class="k">then</span> <span class="nv">root_function = </span><span class="nx">a</span>
- <span class="k">when</span> <span class="s1">&#39;object&#39;</span> <span class="k">then</span> <span class="nv">data = </span><span class="nx">a</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Names of local variables that we have to know beforehand, to use with <code>rewrite_function</code>.
+ <span class="k">when</span> <span class="s1">&#39;object&#39;</span> <span class="k">then</span> <span class="nv">externals = </span><span class="nx">a</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Names of local variables that we have to know beforehand, to use with <code>rewrite_function</code>.
Helpers and defs will be known after we execute the user-provided <code>root_function</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">names =</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>The last four (<code>require</code>, <code>module</code>, <code>__filename</code> and <code>__dirname</code>) are not actually real globals,
but locals to each module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">globals: </span><span class="p">[</span><span class="s1">&#39;global&#39;</span><span class="p">,</span> <span class="s1">&#39;process&#39;</span><span class="p">,</span> <span class="s1">&#39;console&#39;</span><span class="p">,</span> <span class="s1">&#39;setTimeout&#39;</span><span class="p">,</span> <span class="s1">&#39;clearTimeout&#39;</span><span class="p">,</span> <span class="s1">&#39;setInterval&#39;</span><span class="p">,</span> <span class="s1">&#39;clearInterval&#39;</span><span class="p">,</span>
<span class="s1">&#39;require&#39;</span><span class="p">,</span> <span class="s1">&#39;module&#39;</span><span class="p">,</span> <span class="s1">&#39;__filename&#39;</span><span class="p">,</span> <span class="s1">&#39;__dirname&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>TODO: route?, error</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root: </span><span class="p">[</span><span class="s1">&#39;zappa&#39;</span><span class="p">,</span> <span class="s1">&#39;express&#39;</span><span class="p">,</span> <span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="s1">&#39;io&#39;</span><span class="p">,</span> <span class="s1">&#39;requiring&#39;</span><span class="p">,</span> <span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="s1">&#39;post&#39;</span><span class="p">,</span> <span class="s1">&#39;put&#39;</span><span class="p">,</span> <span class="s1">&#39;del&#39;</span><span class="p">,</span> <span class="s1">&#39;at&#39;</span><span class="p">,</span>
@@ -72,7 +72,7 @@
<span class="s1">&#39;stylus&#39;</span><span class="p">,</span> <span class="s1">&#39;enable&#39;</span><span class="p">,</span> <span class="s1">&#39;disable&#39;</span><span class="p">,</span> <span class="s1">&#39;settings&#39;</span><span class="p">,</span> <span class="s1">&#39;postrender&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>TODO: session, cookies, app data, clients list</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">http: </span><span class="p">[</span><span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="s1">&#39;settings&#39;</span><span class="p">,</span> <span class="s1">&#39;response&#39;</span><span class="p">,</span> <span class="s1">&#39;request&#39;</span><span class="p">,</span> <span class="s1">&#39;next&#39;</span><span class="p">,</span> <span class="s1">&#39;params&#39;</span><span class="p">,</span> <span class="s1">&#39;send&#39;</span><span class="p">,</span> <span class="s1">&#39;render&#39;</span><span class="p">,</span> <span class="s1">&#39;redirect&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>TODO: app data, clients list, join</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ws: </span><span class="p">[</span><span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="s1">&#39;io&#39;</span><span class="p">,</span> <span class="s1">&#39;settings&#39;</span><span class="p">,</span> <span class="s1">&#39;socket&#39;</span><span class="p">,</span> <span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="s1">&#39;params&#39;</span><span class="p">,</span> <span class="s1">&#39;client&#39;</span><span class="p">,</span> <span class="s1">&#39;emit&#39;</span><span class="p">,</span> <span class="s1">&#39;broadcast&#39;</span><span class="p">]</span>
<span class="nv">postrender: </span><span class="p">[</span><span class="s1">&#39;window&#39;</span><span class="p">,</span> <span class="s1">&#39;$&#39;</span><span class="p">]</span>
- <span class="nv">externals: </span><span class="p">(</span><span class="nx">k</span> <span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">data</span><span class="p">)</span>
+ <span class="nv">externals: </span><span class="p">(</span><span class="nx">k</span> <span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">externals</span><span class="p">)</span>
<span class="nv">helpers: </span><span class="p">[]</span>
<span class="nv">defs: </span><span class="p">[]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>Storage for user-provided stuff.
Views are kept at the module level.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">routes = </span><span class="p">[]</span>
@@ -197,12 +197,12 @@
<span class="nv">js = </span><span class="s2">&quot;;zappa.run(#{v});&quot;</span>
<span class="nx">routes</span><span class="p">.</span><span class="nx">push</span> <span class="nv">verb: </span><span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="nv">path: </span><span class="nx">k</span><span class="p">,</span> <span class="nv">handler: </span><span class="nx">js</span><span class="p">,</span> <span class="nv">contentType: </span><span class="s1">&#39;js&#39;</span>
- <span class="nv">rewritten_shared = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;root + globals + externals&#39;</span><span class="p">)</span>
+ <span class="nv">rewritten_shared = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + root + externals&#39;</span><span class="p">)</span>
<span class="nx">rewritten_shared</span><span class="p">(</span><span class="nx">root_context</span><span class="p">,</span> <span class="nx">root_locals</span><span class="p">)</span>
<span class="nv">root_locals.include = </span><span class="nf">(name) -&gt;</span>
<span class="nv">sub = </span><span class="nx">root_locals</span><span class="p">.</span><span class="nx">require</span> <span class="nx">name</span>
- <span class="nv">rewritten_sub = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">sub</span><span class="p">.</span><span class="nx">include</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;root + globals + externals&#39;</span><span class="p">)</span>
+ <span class="nv">rewritten_sub = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">sub</span><span class="p">.</span><span class="nx">include</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + root + externals&#39;</span><span class="p">)</span>
<span class="nv">include_locals = </span><span class="p">{}</span>
<span class="nx">include_locals</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">root_locals</span>
@@ -212,15 +212,15 @@
from the required module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">include_locals.module = </span><span class="nx">include_module</span>
<span class="nv">include_locals.__filename = </span><span class="nx">include_module</span><span class="p">.</span><span class="nx">filename</span>
<span class="nv">include_locals.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">include_module</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>TODO: Find out how to pass the correct <code>require</code> (the module's, not zappa's) to the include.
-include_locals.require = ???</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">rewritten_sub</span><span class="p">(</span><span class="nx">root_context</span><span class="p">,</span> <span class="nx">include_locals</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Variables passed through the object parameter.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">root_locals</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">data</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>Executes the (rewriten) end-user function and learns how the app should be structured.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewritten_root = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">root_function</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;root + globals + externals&#39;</span><span class="p">)</span>
+include_locals.require = ???</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">rewritten_sub</span><span class="p">(</span><span class="nx">root_context</span><span class="p">,</span> <span class="nx">include_locals</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Variables passed through the object parameter.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">root_locals</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">externals</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>Executes the (rewriten) end-user function and learns how the app should be structured.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewritten_root = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">root_function</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + root + externals&#39;</span><span class="p">)</span>
<span class="nx">rewritten_root</span><span class="p">(</span><span class="nx">root_context</span><span class="p">,</span> <span class="nx">root_locals</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>Implements the application according to the specification.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">helpers</span>
- <span class="nx">helpers</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;http + helpers + defs + globals&#39;</span><span class="p">)</span>
+ <span class="nx">helpers</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + http + externals + helpers + defs&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">ws_handlers</span>
- <span class="nx">ws_handlers</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;ws + helpers + defs + globals&#39;</span><span class="p">)</span>
+ <span class="nx">ws_handlers</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + ws + externals + helpers + defs&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">postrenders</span>
- <span class="nx">postrenders</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;postrender + helpers + defs + globals&#39;</span><span class="p">)</span>
+ <span class="nx">postrenders</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + postrender + externals + helpers + defs&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;serve zappa&#39;</span><span class="p">]</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">get</span> <span class="s1">&#39;/zappa/zappa.js&#39;</span><span class="p">,</span> <span class="nf">(req, res) -&gt;</span>
@@ -260,11 +260,12 @@
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span> <span class="nx">r</span><span class="p">.</span><span class="nx">handler</span>
<span class="k">else</span>
<span class="nv">rewritten_handler = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">handler</span><span class="p">,</span>
- <span class="nx">select</span><span class="p">(</span><span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;http + helpers + defs + globals&#39;</span><span class="p">))</span>
+ <span class="nx">select</span><span class="p">(</span><span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + http + externals + helpers + defs&#39;</span><span class="p">))</span>
<span class="nv">context = </span><span class="kc">null</span>
<span class="nv">locals = </span><span class="p">{</span><span class="nx">app</span><span class="p">,</span> <span class="nv">settings: </span><span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">}</span>
</pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>TODO: fix pseudo-globals here too.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">locals</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="nx">g</span><span class="p">)</span> <span class="k">for</span> <span class="nx">g</span> <span class="k">in</span> <span class="nx">names</span><span class="p">.</span><span class="nx">globals</span>
+ </pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>TODO: externals are also shadowing certain immutable request scope vars. Should it?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">locals</span><span class="p">[</span><span class="nx">e</span><span class="p">]</span> <span class="o">=</span> <span class="nx">externals</span><span class="p">[</span><span class="nx">e</span><span class="p">]</span> <span class="k">for</span> <span class="nx">e</span> <span class="k">in</span> <span class="nx">names</span><span class="p">.</span><span class="nx">externals</span>
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">def</span> <span class="k">of</span> <span class="nx">defs</span>
<span class="nx">locals</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">def</span>
@@ -287,14 +288,14 @@
<span class="nv">locals.send = </span><span class="o">-&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">arguments</span>
<span class="nv">locals.redirect = </span><span class="o">-&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">redirect</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">arguments</span>
- <span class="nv">locals.render = </span><span class="nf">(args...) -&gt;</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>Adds the app id to the view name so that the monkeypatched
+ <span class="nv">locals.render = </span><span class="nf">(args...) -&gt;</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>Adds the app id to the view name so that the monkeypatched
express.View.exists and express.View.contents can lookup
this app's inline templates.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nx">id</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span> <span class="o">+</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
- </pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>Make sure the second arg is an object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">?=</span> <span class="p">{}</span>
+ </pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>Make sure the second arg is an object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">?=</span> <span class="p">{}</span>
<span class="nx">args</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">{}</span> <span class="k">if</span> <span class="k">typeof</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;function&#39;</span>
- </pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>Send request input vars to template as <code>params</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">params</span> <span class="o">?=</span> <span class="nx">locals</span><span class="p">.</span><span class="nx">params</span>
+ </pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>Send request input vars to template as <code>params</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">params</span> <span class="o">?=</span> <span class="nx">locals</span><span class="p">.</span><span class="nx">params</span>
- <span class="k">if</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">postrender</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>Apply postrender before sending response.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">res</span><span class="p">.</span><span class="nx">render</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nf">(err, str) -&gt;</span>
+ <span class="k">if</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">postrender</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>Apply postrender before sending response.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">res</span><span class="p">.</span><span class="nx">render</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nf">(err, str) -&gt;</span>
<span class="nx">jsdom</span><span class="p">.</span><span class="nx">env</span> <span class="nv">html: </span><span class="nx">str</span><span class="p">,</span> <span class="nv">src: </span><span class="p">[</span><span class="nx">jquery</span><span class="p">],</span> <span class="nv">done: </span><span class="nf">(err, window) -&gt;</span>
<span class="nv">locals.window = </span><span class="nb">window</span>
<span class="nx">locals</span><span class="p">.</span><span class="nv">$ = </span><span class="nb">window</span><span class="p">.</span><span class="nx">$</span>
@@ -303,13 +304,13 @@
<span class="nv">doctype = </span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">doctype</span> <span class="o">or</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;\n&quot;</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span> <span class="nx">doctype</span> <span class="o">+</span> <span class="nb">window</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">outerHTML</span>
- <span class="k">else</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>Just forward params to express.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">args</span>
+ <span class="k">else</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">&#182;</a> </div> <p>Just forward params to express.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">args</span>
<span class="nv">result = </span><span class="nx">rewritten_handler</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span> <span class="nx">locals</span><span class="p">)</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">contentType</span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">contentType</span><span class="p">)</span> <span class="k">if</span> <span class="nx">r</span><span class="p">.</span><span class="nx">contentType</span><span class="o">?</span>
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">result</span> <span class="o">is</span> <span class="s1">&#39;string&#39;</span> <span class="k">then</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span> <span class="nx">result</span>
- <span class="k">else</span> <span class="k">return</span> <span class="nx">result</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">&#182;</a> </div> <p>Implements the websockets server with socket.io.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">io</span><span class="p">.</span><span class="nx">sockets</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;connection&#39;</span><span class="p">,</span> <span class="nf">(socket) -&gt;</span>
+ <span class="k">else</span> <span class="k">return</span> <span class="nx">result</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>Implements the websockets server with socket.io.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">io</span><span class="p">.</span><span class="nx">sockets</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;connection&#39;</span><span class="p">,</span> <span class="nf">(socket) -&gt;</span>
<span class="nv">context = </span><span class="p">{}</span>
<span class="nv">locals =</span>
<span class="nv">app: </span><span class="nx">app</span>
@@ -319,7 +320,8 @@
<span class="nv">id: </span><span class="nx">socket</span><span class="p">.</span><span class="nx">id</span>
<span class="nv">client: </span><span class="p">{}</span>
<span class="nv">emit: </span><span class="o">-&gt;</span> <span class="nx">socket</span><span class="p">.</span><span class="nx">emit</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">socket</span><span class="p">,</span> <span class="nx">arguments</span>
- <span class="nv">broadcast: </span><span class="o">-&gt;</span> <span class="nx">socket</span><span class="p">.</span><span class="nx">broadcast</span><span class="p">.</span><span class="nx">emit</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">socket</span><span class="p">.</span><span class="nx">broadcast</span><span class="p">,</span> <span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>TODO: fix pseudo-globals here too.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">locals</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="nx">g</span><span class="p">)</span> <span class="k">for</span> <span class="nx">g</span> <span class="k">in</span> <span class="nx">names</span><span class="p">.</span><span class="nx">globals</span>
+ <span class="nv">broadcast: </span><span class="o">-&gt;</span> <span class="nx">socket</span><span class="p">.</span><span class="nx">broadcast</span><span class="p">.</span><span class="nx">emit</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">socket</span><span class="p">.</span><span class="nx">broadcast</span><span class="p">,</span> <span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>TODO: fix pseudo-globals here too.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">locals</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="nx">g</span><span class="p">)</span> <span class="k">for</span> <span class="nx">g</span> <span class="k">in</span> <span class="nx">names</span><span class="p">.</span><span class="nx">globals</span>
+ </pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>TODO: externals are also shadowing certain immutable socket scope vars. Should it?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">locals</span><span class="p">[</span><span class="nx">e</span><span class="p">]</span> <span class="o">=</span> <span class="nx">externals</span><span class="p">[</span><span class="nx">e</span><span class="p">]</span> <span class="k">for</span> <span class="nx">e</span> <span class="k">in</span> <span class="nx">names</span><span class="p">.</span><span class="nx">externals</span>
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">def</span> <span class="k">of</span> <span class="nx">defs</span>
<span class="nx">locals</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">def</span>
@@ -343,7 +345,7 @@
<span class="nv">locals.params = </span><span class="nx">context</span>
<span class="nx">h</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span> <span class="nx">locals</span><span class="p">)</span>
- <span class="p">{</span><span class="nx">id</span><span class="p">,</span> <span class="nx">app</span><span class="p">,</span> <span class="nx">io</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>Takes a function and runs it as a zappa app. Optionally accepts a number for port,
+ <span class="p">{</span><span class="nx">id</span><span class="p">,</span> <span class="nx">app</span><span class="p">,</span> <span class="nx">io</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>Takes a function and runs it as a zappa app. Optionally accepts a number for port,
and/or a string for hostname (any order).
Returns an object where <code>app</code> is the express server and <code>io</code> is the socket.io handle.
Ex.:
@@ -353,16 +355,16 @@
<span class="nv">host = </span><span class="kc">null</span>
<span class="nv">port = </span><span class="mi">3000</span>
<span class="nv">root_function = </span><span class="kc">null</span>
- <span class="nv">data = </span><span class="kc">null</span>
+ <span class="nv">externals = </span><span class="kc">null</span>
<span class="k">for</span> <span class="nx">a</span> <span class="k">in</span> <span class="nx">arguments</span>
<span class="k">switch</span> <span class="k">typeof</span> <span class="nx">a</span>
<span class="k">when</span> <span class="s1">&#39;string&#39;</span> <span class="k">then</span> <span class="nv">host = </span><span class="nx">a</span>
<span class="k">when</span> <span class="s1">&#39;number&#39;</span> <span class="k">then</span> <span class="nv">port = </span><span class="nx">a</span>
<span class="k">when</span> <span class="s1">&#39;function&#39;</span> <span class="k">then</span> <span class="nv">root_function = </span><span class="nx">a</span>
- <span class="k">when</span> <span class="s1">&#39;object&#39;</span> <span class="k">then</span> <span class="nv">data = </span><span class="nx">a</span>
+ <span class="k">when</span> <span class="s1">&#39;object&#39;</span> <span class="k">then</span> <span class="nv">externals = </span><span class="nx">a</span>
- <span class="nv">zapp = </span><span class="nx">zappa</span><span class="p">.</span><span class="nx">app</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">root_function</span><span class="p">)</span>
+ <span class="nv">zapp = </span><span class="nx">zappa</span><span class="p">.</span><span class="nx">app</span><span class="p">(</span><span class="nx">externals</span><span class="p">,</span> <span class="nx">root_function</span><span class="p">)</span>
<span class="nv">app = </span><span class="nx">zapp</span><span class="p">.</span><span class="nx">app</span>
<span class="k">if</span> <span class="nx">host</span> <span class="k">then</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span> <span class="nx">port</span><span class="p">,</span> <span class="nx">host</span>
@@ -373,7 +375,7 @@
<span class="nx">log</span> <span class="s2">&quot;Zappa #{zappa.version} orchestrating the show&quot;</span>
- <span class="nx">zapp</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>Creates a zappa view adapter for templating engine <code>engine</code>. This adapter
+ <span class="nx">zapp</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">&#182;</a> </div> <p>Creates a zappa view adapter for templating engine <code>engine</code>. This adapter
can be used with <code>app.register</code> and creates params "shortcuts".</p>
<p>Zappa, by default, automatically sends all request params to templates,
View
36 src/zappa.coffee
@@ -96,17 +96,17 @@ express.View.prototype.__defineGetter__ 'contents', ->
fs.readFileSync p, 'utf8'
# Takes in a function and builds express/socket.io apps based on the rules contained in it.
-# The optional data object allows passing variables from the outside to the root scope.
+# The optional externals object allows passing variables from the outside to the root scope.
zappa.app = ->
id = uuid()
- data = null
+ externals = null
root_function = null
for a in arguments
switch typeof a
when 'function' then root_function = a
- when 'object' then data = a
+ when 'object' then externals = a
# Names of local variables that we have to know beforehand, to use with `rewrite_function`.
# Helpers and defs will be known after we execute the user-provided `root_function`.
@@ -128,7 +128,7 @@ zappa.app = ->
ws: ['app', 'io', 'settings', 'socket', 'id', 'params', 'client', 'emit', 'broadcast']
postrender: ['window', '$']
- externals: (k for k, v of data)
+ externals: (k for k, v of externals)
helpers: []
defs: []
@@ -267,12 +267,12 @@ zappa.app = ->
js = ";zappa.run(#{v});"
routes.push verb: 'get', path: k, handler: js, contentType: 'js'
- rewritten_shared = rewrite_function(v, select names, 'root + globals + externals')
+ rewritten_shared = rewrite_function(v, select names, 'globals + root + externals')
rewritten_shared(root_context, root_locals)
root_locals.include = (name) ->
sub = root_locals.require name
- rewritten_sub = rewrite_function(sub.include, select names, 'root + globals + externals')
+ rewritten_sub = rewrite_function(sub.include, select names, 'globals + root + externals')
include_locals = {}
include_locals[k] = v for k, v of root_locals
@@ -290,22 +290,22 @@ zappa.app = ->
rewritten_sub(root_context, include_locals)
# Variables passed through the object parameter.
- root_locals[k] = v for k, v of data
+ root_locals[k] = v for k, v of externals
# Executes the (rewriten) end-user function and learns how the app should be structured.
- rewritten_root = rewrite_function(root_function, select names, 'root + globals + externals')
+ rewritten_root = rewrite_function(root_function, select names, 'globals + root + externals')
rewritten_root(root_context, root_locals)
# Implements the application according to the specification.
for k, v of helpers
- helpers[k] = rewrite_function(v, select names, 'http + helpers + defs + globals')
+ helpers[k] = rewrite_function(v, select names, 'globals + http + externals + helpers + defs')
for k, v of ws_handlers
- ws_handlers[k] = rewrite_function(v, select names, 'ws + helpers + defs + globals')
+ ws_handlers[k] = rewrite_function(v, select names, 'globals + ws + externals + helpers + defs')
for k, v of postrenders
- postrenders[k] = rewrite_function(v, select names, 'postrender + helpers + defs + globals')
+ postrenders[k] = rewrite_function(v, select names, 'globals + postrender + externals + helpers + defs')
if app.settings['serve zappa']
app.get '/zappa/zappa.js', (req, res) ->
@@ -348,13 +348,16 @@ zappa.app = ->
res.send r.handler
else
rewritten_handler = rewrite_function(r.handler,
- select(names, 'http + helpers + defs + globals'))
+ select(names, 'globals + http + externals + helpers + defs'))
context = null
locals = {app, settings: app.settings}
# TODO: fix pseudo-globals here too.
locals[g] = eval(g) for g in names.globals
+
+ # TODO: externals are also shadowing certain immutable request scope vars. Should it?
+ locals[e] = externals[e] for e in names.externals
for name, def of defs
locals[name] = def
@@ -426,6 +429,9 @@ zappa.app = ->
# TODO: fix pseudo-globals here too.
locals[g] = eval(g) for g in names.globals
+
+ # TODO: externals are also shadowing certain immutable socket scope vars. Should it?
+ locals[e] = externals[e] for e in names.externals
for name, def of defs
locals[name] = def
@@ -462,16 +468,16 @@ zappa.run = ->
host = null
port = 3000
root_function = null
- data = null
+ externals = null
for a in arguments
switch typeof a
when 'string' then host = a
when 'number' then port = a
when 'function' then root_function = a
- when 'object' then data = a
+ when 'object' then externals = a
- zapp = zappa.app(data, root_function)
+ zapp = zappa.app(externals, root_function)
app = zapp.app
if host then app.listen port, host
View
53 tests/externals.coffee
@@ -0,0 +1,53 @@
+zappa = require('./support/tester') require('../src/zappa')
+assert = require 'assert'
+
+module.exports =
+ 'Externals: available at the root scope': ->
+ t = zappa {assert, foo: 'bar'}, ->
+ assert.eql foo, 'bar'
+
+ 'Externals: available at the request scope': ->
+ t = zappa {foo: 'bar'}, ->
+ get '/': -> foo
+
+ t.get '/', 'bar'
+
+ 'Externals: shadowed by defs': ->
+ t = zappa {foo: 'bar'}, ->
+ def foo: 'zag'
+ get '/': -> foo
+
+ t.get '/', 'zag'
+
+ 'Externals: shadowed by helpers': ->
+ t = zappa {foo: 'bar'}, ->
+ helper foo: -> 'pong'
+ get '/': -> foo()
+
+ t.get '/', 'pong'
+
+ 'Externals: shadow globals': ->
+ t = zappa {__filename: 'shadowglobals.coffee'}, ->
+ get '/': -> __filename
+
+ t.get '/', 'shadowglobals.coffee'
+
+ 'Externals: shadow root scope variables': ->
+ t = zappa {assert, get: 'got'}, ->
+ assert.eql get, 'got'
+
+ 'Externals: primitives are passed by value': ->
+ foo = 'bar'
+ t = zappa {foo}, ->
+ get '/': -> foo
+ foo += '!'
+
+ t.get '/', 'bar'
+
+ 'Externals: objects are passed by reference': ->
+ foo = {zig: 'zag'}
+ t = zappa {foo}, ->
+ get '/': -> foo.zig
+ foo.zig += '!'
+
+ t.get '/', 'zag!'

0 comments on commit 6a3093f

Please sign in to comment.
Something went wrong with that request. Please try again.