Reviewers: felix8a,

Description:
* Due to our previous detection strategy not catching Firefox 22.0a2,
  always assume host WeakMap is broken on Firefox. Fixes
  <https://code.google.com/p/google-caja/issues/detail?id=1704>.
* DoubleWeakMap avoids using an emulated WeakMap until it meets a
  problematic key.
* Additional comments on what DoubleWeakMap is doing.
* Test framework: boolean asserts receiving a non-boolean argument
  report the comment to help identify the assert.

Please review this at https://codereview.appspot.com/9236043/

Affected files:
  M     src/com/google/caja/ses/WeakMap.js
  M     third_party/js/jsunit/2.2/jsUnitCore.js


Index: src/com/google/caja/ses/WeakMap.js
===================================================================
--- src/com/google/caja/ses/WeakMap.js  (revision 5401)
+++ src/com/google/caja/ses/WeakMap.js  (working copy)
@@ -23,8 +23,8 @@
  * quite conform, run <code>repairES5.js</code> first.
  *
  * @author Mark S. Miller
- * @requires ses, crypto, ArrayBuffer, Uint8Array, document
- * @overrides WeakMap, WeakMapModule
+ * @requires ses, crypto, ArrayBuffer, Uint8Array
+ * @overrides WeakMap, WeakMapModule, navigator
  */

 /**
@@ -103,15 +103,25 @@
   var HostWeakMap = WeakMap;
   if (typeof HostWeakMap === 'function') {
     // There is a WeakMap -- is it good enough?
-    if (typeof document !== 'undefined') {
-      var problematic = document.createEvent('HTMLEvents');
-      var testHostMap = new HostWeakMap();
-      try {
-        testHostMap.set(problematic, 1);  // Firefox 20 will throw here
-        if (testHostMap.get(problematic) === 1) {
-          return;
-        }
-      } catch (e) {}
+    if (typeof navigator !== 'undefined' &&
+        /Firefox/.test(navigator.userAgent)) {
+      // We're now *assuming not*, because as of this writing (2013-05-06)
+ // Firefox's WeakMaps have a miscellany of objects they won't accept, and
+      // we don't want to make an exhaustive list, and testing for just one
+ // will be a problem if that one is fixed alone (as they did for Event).
+
+ // If there is a platform that we *can* reliably test on, here's how to
+      // do it:
+      //  var problematic = ... ;
+      //  var testHostMap = new HostWeakMap();
+      //  try {
+      //    testHostMap.set(problematic, 1);  // Firefox 20 will throw here
+      //    if (testHostMap.get(problematic) === 1) {
+      //      return;
+      //    }
+      //  } catch (e) {}
+
+      // Fall through to installing our WeakMap.
     } else {
       return;
     }
@@ -461,33 +471,44 @@

   if (typeof HostWeakMap === 'function') {
     (function() {
- // If we got here, then the platform has a WeakMap but it refuses to store - // some key types. Therefore, make a map implementation which makes use of
-      // both as possible.
+ // If we got here, then the platform has a WeakMap but we are concerned
+      // that it may refuse to store some key types. Therefore, make a map
+      // implementation which makes use of both as possible.

       function DoubleWeakMap() {
+        // Preferable, truly weak map.
         var hmap = new HostWeakMap();
-        var omap = new OurWeakMap();

+ // Our hidden-property-based pseudo-weak-map. Lazily initialized in the + // 'set' implementation; thus we can avoid performing extra lookups if
+        // we know all entries actually stored are entered in 'hmap'.
+        var omap = undefined;
+
         function dget(key, opt_default) {
- return hmap.has(key) ? hmap.get(key) : omap.get___(key, opt_default);
+          if (omap) {
+            return hmap.has(key) ? hmap.get(key)
+                : omap.get___(key, opt_default);
+          } else {
+            return hmap.get(key, opt_default);
+          }
         }

         function dhas(key) {
-          return hmap.has(key) || omap.has___(key);
+          return hmap.has(key) || (omap ? omap.has___(key) : false);
         }

         function dset(key, value) {
           try {
             hmap.set(key, value);
           } catch (e) {
+            if (!omap) { omap = new OurWeakMap(); }
             omap.set___(key, value);
           }
         }

         function ddelete(key) {
           hmap['delete'](key);
-          omap.delete___(key);
+          if (omap) { omap.delete___(key); }
         }

         return Object.create(OurWeakMap.prototype, {
Index: third_party/js/jsunit/2.2/jsUnitCore.js
===================================================================
--- third_party/js/jsunit/2.2/jsUnitCore.js     (revision 5401)
+++ third_party/js/jsunit/2.2/jsUnitCore.js     (working copy)
@@ -160,7 +160,7 @@
     var booleanValue = nonCommentArg(1, 1, arguments);

     if (typeof(booleanValue) != 'boolean')
-        error('Bad argument to assert(boolean)');
+ error(commentArg(1, arguments) + ': Bad argument to assert(boolean)');

_assert(commentArg(1, arguments), booleanValue === true, 'Call to assert(boolean) with false');
 }
@@ -170,7 +170,7 @@
     var booleanValue = nonCommentArg(1, 1, arguments);

     if (typeof(booleanValue) != 'boolean')
-        error('Bad argument to assertTrue(boolean)');
+ error(commentArg(1, arguments) + ': Bad argument to assertTrue(boolean)');

_assert(commentArg(1, arguments), booleanValue === true, 'Call to assertTrue(boolean) with false');
 }
@@ -180,7 +180,7 @@
     var booleanValue = nonCommentArg(1, 1, arguments);

     if (typeof(booleanValue) != 'boolean')
-        error('Bad argument to assertFalse(boolean)');
+ error(commentArg(1, arguments) + ': Bad argument to assertFalse(boolean)');

_assert(commentArg(1, arguments), booleanValue === false, 'Call to assertFalse(boolean) with true');
 }


--

--- You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to