r9656 - in helma-ng/trunk: apps/demo apps/demo/skins modules/helma/webapp

[email protected] Wed, 22 Apr 2009 15:10:07 +0200 (CEST)
Newsgroups gmane.comp.java.helma.cvs
Message-ID <20090422131007.B2B0A3D0D6@mia>
Author: hannes
Date: 2009-04-22 15:10:07 +0200 (Wed, 22 Apr 2009)
New Revision: 9656

Modified:
   helma-ng/trunk/apps/demo/actions.js
   helma-ng/trunk/apps/demo/skins/continuation.html
   helma-ng/trunk/modules/helma/webapp/continuation.js
Log:
Rewrite continuation support once again. Starting to look usable.

Details at http://dev.helma.org/trac/helma/changeset/9656

Modified: helma-ng/trunk/apps/demo/actions.js
===================================================================
--- helma-ng/trunk/apps/demo/actions.js	2009-04-22 13:10:04 UTC (rev 9655)
+++ helma-ng/trunk/apps/demo/actions.js	2009-04-22 13:10:07 UTC (rev 9656)
@@ -46,49 +46,41 @@
 
     // local data - this is the data that is shared between continuations of this function
     var data = {};
+    var session = new ContinuationSession("welcome", "ask_name", "ask_food", "ask_animal", "result");
+    req = session.start(req);
 
-    req = ContinuationMark(req, "welcome");
-
     // render intro page
-    req = ContinuationRequest(req, "ask_name", SkinnedResponse('skins/continuation.html', {
-        skin: "welcome",
+    req = session.step(1).render(req, SkinnedResponse('skins/continuation.html', {
+        session: session,
         title: "Continuations Demo",
-        data: data,
-        forward: ContinuationUrl("ask_name")
+        data: data
     }));
     
-    req = ContinuationRequest(req, "ask_food", SkinnedResponse('skins/continuation.html', {
-        skin: "ask_name",
+    req = session.step(2).render(req, SkinnedResponse('skins/continuation.html', {
+        session: session,
         title: "Question 1",
-        data: data,
-        back: ContinuationUrl("welcome"),
-        forward: ContinuationUrl("ask_food")
+        data: data
     }));
     data.name = req.params.name || data.name;
 
-    req = ContinuationRequest(req, "ask_animal", SkinnedResponse('skins/continuation.html', {
-        skin: "ask_food",
+    req = session.step(3).render(req, SkinnedResponse('skins/continuation.html', {
+        session: session,
         title: "Question 2",
-        data: data,
-        back: ContinuationUrl("ask_name"),
-        forward: ContinuationUrl("ask_animal")
+        data: data
     }));
     data.food = req.params.food || data.food;
 
-    req = ContinuationRequest(req, "result", SkinnedResponse('skins/continuation.html', {
-        skin: "ask_animal",
+    req = session.step(4).render(req, SkinnedResponse('skins/continuation.html', {
+        session: session,
         title: "Question 3",
-        data: data,
-        back: ContinuationUrl("ask_food"),
-        forward: ContinuationUrl("result")
+        data: data
     }));
     data.animal = req.params.animal || data.animal;
 
-    return SkinnedResponse('skins/continuation.html', {
-        skin: "result",
+    session.step(5).render(req, SkinnedResponse('skins/continuation.html', {
+        session: session,
         title: "Thank you!",
-        data: data,
-        back: ContinuationUrl("ask_animal")
-    });
+        data: data
+    }));
 
 }
\ No newline at end of file

Modified: helma-ng/trunk/apps/demo/skins/continuation.html
===================================================================
--- helma-ng/trunk/apps/demo/skins/continuation.html	2009-04-22 13:10:04 UTC (rev 9655)
+++ helma-ng/trunk/apps/demo/skins/continuation.html	2009-04-22 13:10:07 UTC (rev 9656)
@@ -1,7 +1,7 @@
 <% extends 'base.html' %>
 
 <% subskin 'content' -------------------------------------------------------------------- %>
-<% render <% skin %> %>
+<% render <% session.page %> %>
 
 <% subskin 'welcome' %>
 
@@ -10,7 +10,7 @@
     <p>This is a little game to show off continuations support in Helma NG.
     All you'll have to do is answer a few easy questions.</p>
 
-    <p><a href="<% forward %>">start</a></p>
+    <p><a href="<% session.forward %>">start</a></p>
 
     <p>What's special about this demo is that all pages are generated by
     one JavaScript function which is run only once, but resumed and suspended
@@ -22,34 +22,34 @@
 
 <% subskin 'ask_name' %>
 
-    What is your name? <form method="post" action="<% forward %>">
+    What is your name? <form method="post" action="<% session.forward %>">
     <input name="name" value="<% data.name %>">
     <input type="submit">
     </form>
 
-    <p><a href="<% back %>">back</a> <a href="<% forward %>">forward</a></p>
+    <p><a href="<% session.back %>">back</a> <a href="<% session.forward %>">forward</a></p>
 
     <% render 'list' %>
 
 <% subskin 'ask_food' %>
 
-    What is your favorite food? <form method="post" action="<% forward %>">
+    What is your favorite food? <form method="post" action="<% session.forward %>">
     <input name="food" value="<% data.food %>">
     <input type="submit">
     </form>
 
-    <p><a href="<% back %>">back</a> <a href="<% forward %>">forward</a></p>
+    <p><a href="<% session.back %>">back</a> <a href="<% session.forward %>">forward</a></p>
 
     <% render 'list' %>
 
 <% subskin 'ask_animal' %>
 
-    What is your favorite animal? <form method="post" action="<% forward %>">
+    What is your favorite animal? <form method="post" action="<% session.forward %>">
     <input name="animal" value="<% data.animal %>">
     <input type="submit">
     </form>
 
-    <p><a href="<% back %>">back</a> <a href="<% forward %>">forward</a></p>
+    <p><a href="<% session.back %>">back</a> <a href="<% session.forward %>">forward</a></p>
 
     <% render 'list' %>
 
@@ -59,7 +59,7 @@
     you love to eat <b><% data.food %></b> and your favorite animal
     is <b><% data.animal %></b>.
 
-    <p><a href="<% back %>">back</a></p>
+    <p><a href="<% session.back %>">back</a></p>
 
     <% render 'list' %>
 

Modified: helma-ng/trunk/modules/helma/webapp/continuation.js
===================================================================
--- helma-ng/trunk/modules/helma/webapp/continuation.js	2009-04-22 13:10:04 UTC (rev 9655)
+++ helma-ng/trunk/modules/helma/webapp/continuation.js	2009-04-22 13:10:07 UTC (rev 9656)
@@ -2,70 +2,94 @@
  * Continuation support for Helma NG
  */
 
-include('helma/webapp/response');
+export('ContinuationSession', 'handleRequest');
+
 var system = require('helma/system');
+var log = require('helma/logging').getLogger(__name__);
 
-export('handleRequest', "ContinuationMark", "ContinuationRequest", "ContinuationUrl", "ContinuationId");
+var __shared__ = true;
 
-var log = require('helma/logging').getLogger(__name__);
+function ContinuationSession() {
+    var pages = [];
+    var ids = [];
+    var currentstep = 0;
+    for (var i = 0; i < arguments.length; i++) {
+        pages.push(arguments[i]);
+    }
+    var length = pages.length;
 
-var ids = {};
+    this.start = function(req) {
+        if (!req.params.helma_continuation) {
+            // set query param so helma knows to switch rhino optimization level to -1
+            throw { redirect: getContinuationUrl(0) };
+        }
+        if (system.getOptimizationLevel() > -1) {
+            system.setOptimizationLevel(-1);
+            throw { retry: true };
+        }
+        currentstep = 0;
+        ids[0] = id = req.params.helma_continuation;
+        var continuation = createContinuation();
+        if (continuation instanceof Continuation) {
+            log.debug("Recording continuation start: " + id);
+            setCallback(req, id, continuation);
+            return req;
+        } else {
+            return continuation;
+        }
+    };
 
-function ContinuationUrl(name) {
-    return "?helma_continuation=" + ContinuationId(name);
-}
+    this.step = function(step) {
+        currentstep = step - 1;
+        return this;
+    };
 
-function ContinuationId(name) {
-    if (!name)
-        return generateId();
-    if (!(name in ids))
-        ids[name] = generateId();
-    return ids[name];
-}
+    this.render = function(req, res) {
+        // capture continuation and store it in callback container
+        var id = getContinuationId(currentstep + 1);
+        var continuation = createContinuation();
+        if (continuation instanceof Continuation) {
+            if (!getCallback(req, id))
+                setCallback(req, id, continuation);
+            // Exit current js context by calling empty continuation with return value
+            new org.mozilla.javascript.NativeContinuation()(res);
+        } else {
+            return continuation;
+        }        
+    };
 
-/**
- * Stop current execution and register continuation for later resumption.
- * @param id the continuation id. If not given a new id is generated.
- */
-function ContinuationRequest(req, name, res) {
-    // capture continuation and store it in callback container
-    var id = ContinuationId(name);
-    var continuation = createContinuation();
-    if (continuation instanceof Continuation) {
-        log.debug("Registering continuation for id: " + id);
-        setCallback(req, id, continuation);
-        // Exit current js context by calling empty continuation with return value
-        new org.mozilla.javascript.NativeContinuation()(res);
-    } else {
-        return continuation;
+    this.page = function() {
+        return pages[currentstep];
+    };
+
+    this.back = function() {
+        return currentstep > 0 ? getContinuationUrl(currentstep - 1) : null;
+    };
+
+    this.forward = function() {
+        return currentstep < length ? getContinuationUrl(currentstep + 1) : null;
+    };
+
+    function getContinuationUrl(step) {
+        return "?helma_continuation=" + getContinuationId(step);
     }
-}
 
-function ContinuationMark(req, name) {
-    if (!req.params.helma_continuation) {
-        // set query param so helma knows to switch rhino optimization level to -1
-        throw { redirect: ContinuationUrl() };
+    function getContinuationId(step) {
+        if (ids[step] == null) {
+            ids[step] = generateId();
+        }
+        return ids[step];
     }
-    if (system.getOptimizationLevel() > -1) {
-        system.setOptimizationLevel(-1);
-        throw { retry: true };
+
+    function createContinuation() {
+        return new Continuation();
     }
-    var id = req.params.helma_continuation;
-    ids[name] = id;
-    var continuation = createContinuation();
-    if (continuation instanceof Continuation) {
-        log.debug("Recording continuation start: " + id);
-        setCallback(req, id, continuation);
-        return req;
-    } else {
-        return continuation;
+
+    function generateId() {
+        return Math.ceil(Math.random() * Math.pow(2, 32)).toString(36);
     }
 }
 
-function createContinuation() {
-    return new Continuation();
-}
-
 /**
  * Continuation middleware function
  * @param req the request
@@ -85,16 +109,13 @@
     return req.process();
 }
 
-function generateId() {
-    return Math.ceil(Math.random() * Math.pow(2, 32)).toString(36);
-}
-
 var setCallback = function(req, id, func) {
     if (!req.session.data.continuation) {
         req.session.data.continuation = {};
     }
     log.debug("Registered continuation: " + id);
     req.session.data.continuation[id] = func;
+    // fauxsessions[id] = func;
 };
 
 var getCallback = function(req, id) {
@@ -102,4 +123,8 @@
         return null;
     }
     return req.session.data.continuation[id];
+    // return fauxsessions[id];
 };
+
+// awful hack to make this work on google app engine
+// var fauxsessions = {}