[Twisted-web] Livepage, ClientHandle and context

Donovan Preston dp at ulaluma.com
Wed Jun 1 20:25:42 MDT 2005

Thank you very much for your feedback. Please, anyone else on this  
list who is using or attempting to use LivePage, let me know what you  
are doing with it or plan on doing with it. I want to take it from  
long-running experiment to solid, deployable code before the next  
release, and need to know how much API stability/backwards  
compatibility I should provide. I also need to know how people want  
to use LivePage, and if it has any usability shortcomings with this  
new design which I describe below. If there are any, I'd like to fix  
them before the next release.

On Jun 1, 2005, at 4:46 PM, Alexey Shamrin wrote:

> On 5/31/05, Donovan Preston <dp at ulaluma.com> wrote:
>> In this branch, input handlers can also return javascript which will
>> be executed as the response to the input event.
> What do you mean? I don't understand...
> Are you talking about javascript that will be executed without
> round-trip to server?

When a client-side event generates a trip to the server over the  
input conduit, the server-side handler method which is invoked can  
now return javascript stan. This return result is written as the  
response to the HTTP request which dispatched the event to the  
server, and the browser evals it. Previously, the server would  
arrange for the handler method to be called in the next reactor  
iteration and close the input HTTP request, writing nothing to it.  
The handler method would then call methods on the client handle which  
would generate javascript and buffer it or write it directly to the  
output conduit.

So yes, one (output conduit) round trip is eliminated, and it becomes  
easier to support normal AJaX style events (where the browser is the  
only thing initiating requests, and the server does no pushing),  
which I call input only mode.

>> I encourage anyone who is interested in livepage to take a look at
>> this branch to see where it is going. Take a look at the examples to
>> see what has changed, read the code, and experiment with it. Ask
>> questions if you have any. I'll be trying to merge this branch into
>> the mainline (after adding some backwards compatibility) in the next
>> week.
>> I'll also be adding some LivePage docs. I think the API will settle
>> down after this last round of changes.
> 1. nevow_insertNode from liveglue.js (and livepage.insert) is broken.
> And (as far as I can see) it is not used anywhere in Nevow (including
> examples). Remove?

I think I might fix it rather than removing it. I'll also write a  
test for it, since livetest can now reliably test livepage apps.

> 2. I think you should have "nevow_" prefix for all things in  
> liveglue.js.

I agree, except I think I want the new "server" object to keep that  
name. It will be much easier for people to understand and use  
livepage if they know that calling server.handle('foo') in javascript  
invokes the handle_foo method on the server. Are there other things  
in there that aren't prefixed with nevow_?

> 3. What is the purpose of ClientHandle.transient?

ClientHandle.transient and LivePage.locateHandler (whose default  
implementation looks for handle_* methods) are the new, easier to  
understand and use replacements for the handler decorator.  
Previously, there was a problem with handler because it registered  
the callable you gave it in a dictionary which lived for as long as  
the LivePage instance it was associated with. This means if you had a  
really, really long lived LivePage (which LivePage is designed to  
allow) you would leak more and more closures that the client can't  
ever call again (because you replaced the client-side dom that  
referenced those server-side closures with something else)

Now, if you provide a handle_foo method, the client can always call  
server.handle('foo') as many times as it wants. However, it is still  
useful to register closures on the server and give the client the  
capability to call it. To avoid the aforementioned garbage problem,  
transient allows you to do this, but only allows the client to call  
it once, then pops the registration.

This avoids the garbage problem well; if the client closes the  
browser, LivePage guarantees that the ClientHandle will die no more  
than 90 seconds later, taking the transient closure registration  
dictionary with it. If you are, for example, putting an "ok/cancel"  
dialog on the user's screen, you can register a single transient  
which gets called by either the ok or cancel button, ensuring that  
the transient will be popped when the client no longer has the  
capability to call it (because the UI has gone away, by the user  
clicking either ok or cancel)

> 4. Are these two equivalent?
> onsubmit=livepage.server.handle(livepage.js.onSubmit, getValue 
> ('inputline'))
> onsubmit=livepage.server.handle('onSubmit', getValue('inputline'))

No, because the client-side javascript "handle" function takes a  
string. The first would render down to:

server.handle(onSubmit, getValue('inputline'))

The second would render down to:

server.handle('onSubmit', getValue('inputLine'))

The first would barf because the global name onSubmit doesn't exist.

The livepage.js object is like a stan.Tag for javascript; it creates  
literal javascript. For example:

livepage.js.foo -> foo
livepage.js.foo('1') -> foo('1')
livepage.js('any string') -> any string
livepage.js['1'] -> ['1']
livepage.js.foo['1'] -> foo['1']

There are a bunch of other js objects in the module now, such as  
window, document, this, server, set, append, alert, etc. They are  
really convenient for making your python code much shorter.

I have an incredible LivePage app I wrote recently I am calling  
"Pavel". I will be cleaning it up soon and I will create a new open  
source project for it (rather than including it as a nevow example).  
I think it really showcases the power of LivePage and I'm excited to  
show it to people, but for now it is somewhat of a secret :-)

> P.S. At this time I have only read the code and checked new
> examples... I will try to experiment with it soon. But I must say your
> javascript "constructor" looks interesting (livepage.assign,
> livepage.var etc.)

assign and var are two experiments to get around the fact that python  
has no assignment overloading. Here are examples of usage:

var(js.x, 5) -> var x = 5
assign(js.x, 10) -> x = 10

One other thing while I am discussing stan for javascript. This is a  
pain once you start using it, but I don't think there is any way  
around it other than education. You need to terminate your  
statements, since the javascript flatteners have no idea where it is  
appropriate to put newlines in javascript. So if you were sending the  

     livepage.set('name', 'Donovan Preston')])

You would need to terminate each statement, otherwise the javascript  
won't be correct. The above example would render as:

alert('hello')set('name', 'Donovan Preston')

Right now, you need to do:

     livepage.alert('hello'), livepage.eol,
     livepage.set('name', 'Donovan Preston')])

Which will render down to:

set('name', 'Donovan Preston')

It occurs to me that it may be possible for Nevow to just infer that  
a newline is required between each element of a list or a tuple while  
in JavascriptContext. I will have to experiment and see whether this  
causes any inadvertent problems. If not, the requirement to manually  
insert newline characters will go away (horray!)


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-web/attachments/20050601/501e0bb3/attachment.htm

More information about the Twisted-web mailing list