This API looks really useful for other purposes as well- RPC request  
batching with multipart HTTP responses would be really cool.  Looking  
forward to playing with it.

It would be really useful if there was an API that wrapped these  
common entry point incantations.  I've been pretty neglectful of  
wrapping some non-GWT entry points with the exception handling  
pattern, then cursed myself later when I wished I had caught an  
unhandled exception.

Something like this would be great, though it would require some  
additional compiler magic to elide the anonymous Callback:

   static void dispatchEvent(final Event evt, final Element elem,  
final EventListener listener) {
     GWT.doEntryPoint(new Callback() {
       public void do() {
         // If this element has capture...
         if (elem == sCaptureElem) {
           // ... and it's losing capture, clear sCaptureElem.
           if (eventGetType(evt) == Event.ONLOSECAPTURE) {
             sCaptureElem = null;
           }
         }

         // snipped
       }
     });
   }

Cheers,
Matt.

On 2-Sep-09, at 2:30 PM, Bruce Johnson wrote:

> As is our team custom, I'd like unanimous signoff (or FHMP) from the  
> GWT team on this new API, as well as any and all feedback from the  
> larger community.
>
> === Proposal ===
> Add a new API called BatchedCommand that enqueues callbacks that  
> should be called "later", much like a DeferredCommand, but  
> definitely prior to the next dispatch of the native event loop.
>
> === Key use case: Style injection ===
> Injecting CSS styles programmatically (e.g. StyleInjector) causes  
> the browser to do a lot of work (e.g. selector matching,  
> assimilating the new CSS with the existing CSS) and this work  
> happens synchronously during the "inject" call. Therefore, a  
> sequence of such injections across independent calls in GWT code  
> tends to induce a huge amount of overhead in the browser (that is,  
> because the browser does so much recalculation for each call). It is  
> much faster to concatenate each small chunk of CSS across calls to  
> "inject" into one large CSS chunk so that the overhead need only  
> occur once when all the CSS text has been concatenated (vs. doing  
> the work once per "inject" call site). Measurements have show 8-10x  
> difference in speed between the two approaches on Chrome and other  
> browsers. (I'm not being especially precise in the timings because  
> the savings is large enough that there's simply no question that  
> it's beneficial).
>
> The above describes exactly the sort of thing that DeferredCommands  
> are perfect for, except for one thing: DeferredCommands are  
> guaranteed to run *after* the JavaScript causing them to be enqueued  
> has finished and the native event loop has executed at least once.  
> In the case of programmatically injected styles, we definitely do  
> not want this behavior, because it would mean that DOM structures  
> created could be rendered (because the event loop might dispatch  
> paint handlers) before their associated CSS has been injected. The  
> net results would be the user seeing ugly unstyled DOM structures  
> for at least a short amount of time, which is unacceptable.
>
> Thus, we need a BatchedCommand that is guaranteed to execute  
> callbacks *before* the JavaScript call stack in which they are  
> enqueued has fully unwound. A prototype version of StyleInjector has  
> been created that uses the new technique, and it works nicely.
>
> === The Actual API ===
> It is small enough that I can include the code directly:
>
> package com.google.gwt.core.client;
>
> /**
>  * A <code>BatchedCommand</code> is a command that will be executed  
> by the GWT
>  * libraries before the JavaScript stack unwinds (before the browser's
>  * native event queue is pumped whenever feasible).
>  */
> public abstract class BatchedCommand {
>
>   /**
>    * Enqueues a BatchedCommand to be executed before the JavaScript  
> stack
>    * unwinds (typically before the browser's native event queue is  
> pumped).
>    *
>    * @param cmd the command to be fired. Must not be <code>null</ 
> code>.
>    */
>   public static void add(BatchedCommand cmd);
>
>   /**
>    * Causes the <code>BatchedCommand</code> to execute its  
> encapsulated
>    * behavior.
>    */
>   public abstract void execute();
> }
>
> As you can see above, it is in the "core.client" package. It is  
> necessary to put it here (vs. alongside or integrated with  
> DeferredCommand) because we have to guard every known entrypoint  
> into Java code, which includes things like runAsync callbacks, which  
> are themselves in core. In other words, putting BatchedCommand in  
> gwt-user would have meant that core code would have to depend on gwt- 
> user, which would be a bad idea.
>
> The last note is that the API pattern differs from DeferredCommand/ 
> Command and IncrementalCommand in that it doesn't have a separate  
> callback interface. BatchedComand#add() doesn't take a "Command"  
> callback; it takes a BatchCommand which has overridden the execute()  
> method. This isn't a vitally important design divergence from  
> DeferredCommand/Command, but it seemed kinda nice to have one less  
> type.
>
> Okay, that's my story. Thoughts?
>
> -- Bruce
>
> P.S. Bob V has already signed off on this; we pair-programmed the  
> prototype code for it.
>
>
> >


--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to