Reviewers: metaweta,

Description:
Right now, caja.js does
  load taming frame
  when taming frame ready
    load guest frame
    when guest frame ready
      run gadget

This is unnecessarily serial.  Since we always need at least one guest
frame, we can start loading one before the taming frame is ready.

This change wraps guest frame creation in a frameMaker object that
can preload a frame and supply it to a later call to frameMaker.make().

Please review this at http://codereview.appspot.com/5486057/

Affected files:
  M     src/com/google/caja/plugin/caja.js
  M     src/com/google/caja/plugin/es53-frame-group.js
  M     src/com/google/caja/plugin/ses-frame-group.js


Index: src/com/google/caja/plugin/caja.js
===================================================================
--- src/com/google/caja/plugin/caja.js  (revision 4679)
+++ src/com/google/caja/plugin/caja.js  (working copy)
@@ -257,18 +257,21 @@
   //----------------

   function initES53(config, frameGroupReady) {
-    // TODO(felix8a): start loading a guest-frame here too
     // TODO(felix8a): with api change, can start cajoler early too
-    loadCajaFrame(config, 'es53-taming-frame', function (frameWin) {
-      var fg = frameWin.ES53FrameGroup(cajaInt, config, frameWin, window);
+    var guestMaker = makeFrameMaker(config, 'es53-guest-frame');
+    loadCajaFrame(config, 'es53-taming-frame', function (tamingWin) {
+      var fg = tamingWin.ES53FrameGroup(
+          cajaInt, config, tamingWin, window, guestMaker);
       frameGroupReady(fg);
     });
   }

   function trySES(config, frameGroupReady) {
-    loadCajaFrame(config, 'ses-taming-frame', function (frameWin) {
-      if (canSES(frameWin.ses, config.forceES5Mode)) {
-        var fg = frameWin.SESFrameGroup(cajaInt, config, frameWin, window);
+    var guestMaker = makeFrameMaker(config, 'ses-guest-frame');
+    loadCajaFrame(config, 'ses-taming-frame', function (tamingWin) {
+      if (canSES(tamingWin.ses, config.forceES5Mode)) {
+        var fg = tamingWin.SESFrameGroup(
+            cajaInt, config, tamingWin, window, guestMaker);
         frameGroupReady(fg);
       } else {
         config.log('Unable to use SES.  Switching to ES53.');
@@ -291,6 +294,51 @@

   //----------------

+  /**
+   * Returns an object that wraps loadCajaFrame() with preload support.
+   * Calling frameMaker.prefetch() will start creation of a new frame now,
+   * and make it available to a later call to frameMaker.make().
+   */
+  function makeFrameMaker(config, filename) {
+    var IDLE = 'IDLE', LOADING = 'LOADING', WAITING = 'WAITING';
+    var preState = IDLE, preWin, preReady;
+    var self = {
+      preload: function () {
+        if (preState === IDLE) {
+          preState = LOADING;
+          preWin = null;
+          loadCajaFrame(config, filename, function (win) {
+            preWin = win;
+            consumeIfReady();
+          });
+        }
+      },
+      make: function (onReady) {
+        if (preState === LOADING) {
+          preState = WAITING;
+          preReady = onReady;
+          consumeIfReady();
+        } else {
+          loadCajaFrame(config, filename, onReady);
+        }
+      }
+    };
+    self.preload();
+    return self;
+
+    function consumeIfReady() {
+      if (preState === WAITING && preWin) {
+        var win = preWin, ready = preReady;
+        preState = IDLE;
+        preWin = null;
+        preReady = null;
+        ready(win);
+      }
+    }
+  }
+
+  //----------------
+
   function loadCajaFrame(config, filename, frameReady) {
     var frameWin = createFrame(filename);
     var url = joinUrl(
@@ -392,8 +440,6 @@

   //----------------

-  // TODO(felix8a): move getId etc into taming frame?
-
   /**
    * Enforces {@code typeof specimen === typename}, in which case
    * specimen is returned.
Index: src/com/google/caja/plugin/es53-frame-group.js
===================================================================
--- src/com/google/caja/plugin/es53-frame-group.js      (revision 4679)
+++ src/com/google/caja/plugin/es53-frame-group.js      (working copy)
@@ -25,7 +25,7 @@
  * @requires window
  */

-function ES53FrameGroup(cajaInt, config, tamingWin, feralWin) {
+function ES53FrameGroup(cajaInt, config, tamingWin, feralWin, guestMaker) {
   if (tamingWin !== window) {
     throw new Error('wrong frame');
   }
@@ -60,7 +60,7 @@

   function makeES5Frame(div, uriPolicy, es5ready, opt_idClass) {
     var divs = cajaInt.prepareContainerDiv(div, feralWin, opt_idClass);
-    cajaInt.loadCajaFrame(config, 'es53-guest-frame', function (guestWin) {
+    guestMaker.make(function (guestWin) {
       var domicile = makeDomicile(divs, uriPolicy, guestWin);
       var gman = GuestManager(divs, domicile, guestWin, es53run);
       gman._loader = guestWin.loadModuleMaker(
Index: src/com/google/caja/plugin/ses-frame-group.js
===================================================================
--- src/com/google/caja/plugin/ses-frame-group.js       (revision 4679)
+++ src/com/google/caja/plugin/ses-frame-group.js       (working copy)
@@ -21,7 +21,7 @@
  * @requires window
  */

-function SESFrameGroup(cajaInt, config, tamingWin, feralWin) {
+function SESFrameGroup(cajaInt, config, tamingWin, feralWin, guestMaker) {
   if (tamingWin !== window) {
     throw new Error('wrong frame');
   }
@@ -54,7 +54,7 @@

   function makeES5Frame(div, uriPolicy, es5ready, opt_idClass) {
     var divs = cajaInt.prepareContainerDiv(div, feralWin, opt_idClass);
-    cajaInt.loadCajaFrame(config, 'ses-guest-frame', function (guestWin) {
+    guestMaker.make(function (guestWin) {
       var domicile = makeDomicile(divs, uriPolicy, guestWin);
       var gman = GuestManager(divs, domicile, guestWin, sesRun);
       es5ready(gman);


Reply via email to