Revision: 5360
Author:   [email protected]
Date:     Wed Apr 17 14:21:05 2013
Log:      Fix test-of-repair for FREEZING_BREAKS_PROTOTYPES from r5359.
https://codereview.appspot.com/8632047

test_FREEZING_BREAKS_PROTOTYPES correctly tested for the problem, but
did it in a frame other than the repaired one, so it failed to confirm
the repair was successful. Unfortunately, there is no way to do this
accurately at repairES5 time since the problem is only exhibited once
Object.prototype is frozen. Instead,

* The test applies the repair to the throwaway frame before testing, if
  and only if the repair has already been applied to this frame, thus
  satisfying the test-and-repair logic.
* startSES, as a special case, executes the test after Object.prototype
  is frozen, and the test then actually tests the SES frame, thus
  ensuring that our repair worked.

The whole thing is a horrible kludge and we should rip it out as soon
as we no longer need to support repairing this problem.

[email protected], [email protected]

http://code.google.com/p/google-caja/source/detail?r=5360

Modified:
 /trunk/src/com/google/caja/ses/repairES5.js
 /trunk/src/com/google/caja/ses/startSES.js

=======================================
--- /trunk/src/com/google/caja/ses/repairES5.js Wed Apr 17 11:49:04 2013
+++ /trunk/src/com/google/caja/ses/repairES5.js Wed Apr 17 14:21:05 2013
@@ -650,22 +650,39 @@
   function test_FREEZING_BREAKS_PROTOTYPES() {
// This problem is sufficiently problematic that testing for it breaks the // frame under some circumstances, so we create another frame to test in. - var otherObject = inTestFrame(function(window) { return window.Object; });
-    if (!otherObject) { return false; }
+ // (However, if we've already frozen Object.prototype, we can test in this
+    // frame without side effects.)
+    var testObject;
+    if (Object.isFrozen(Object.prototype)) {
+      testObject = Object;
+    } else {
+      testObject = inTestFrame(function(window) { return window.Object; });
+      if (!testObject) { return false; }  // not in a web browser

-    var a = new otherObject();
-    otherObject.freeze(otherObject.prototype);
-    var b = otherObject.create(a);  // will fail to set [[Prototype]] to a
+ // Apply the repair which should fix the problem to the testing frame. + // TODO(kpreid): Design a better architecture to handle cases like this
+      // than one-off state flags.
+      if (repair_FREEZING_BREAKS_PROTOTYPES_wasApplied) {
+        // optional argument not supplied by normal repair process
+        repair_FREEZING_BREAKS_PROTOTYPES(testObject);
+      }
+    }
+
+    var a = new testObject();
+    testObject.freeze(testObject.prototype);
+    var b = testObject.create(a);  // will fail to set [[Prototype]] to a
     var proto = Object.getPrototypeOf(b);
     if (proto === a) {
       return false;
-    } else if (proto === otherObject.prototype) {
+    } else if (proto === testObject.prototype) {
       return true;
     } else {
return 'Prototype of created object is neither specified prototype nor ' +
           'Object.prototype';
     }
   }
+  // exported so we can test post-freeze
+ ses.kludge_test_FREEZING_BREAKS_PROTOTYPES = test_FREEZING_BREAKS_PROTOTYPES;

   /**
    * Detects https://bugs.webkit.org/show_bug.cgi?id=64250
@@ -2903,12 +2920,15 @@
   // error message is matched elsewhere (for tighter bounds on catch)
   var NO_CREATE_NULL =
       'Repaired Object.create can not support Object.create(null)';
-  function repair_FREEZING_BREAKS_PROTOTYPES() {
-    var baseObject = Object;
-    var baseDefProp = Object.defineProperties;
+  // flag used for the test-of-repair which cannot operate normally.
+  var repair_FREEZING_BREAKS_PROTOTYPES_wasApplied = false;
+  // optional argument is used for the test-of-repair
+  function repair_FREEZING_BREAKS_PROTOTYPES(opt_Object) {
+    var baseObject = opt_Object || Object;
+    var baseDefProp = baseObject.defineProperties;

     // Object.create fails to override [[Prototype]]; reimplement it.
-    Object.defineProperty(Object, 'create', {
+    baseObject.defineProperty(baseObject, 'create', {
       configurable: true,  // attributes per ES5.1 section 15
       writable: true,
       value: function repairedObjectCreate(O, Properties) {
@@ -2945,14 +2965,14 @@
     // Error.prototype.toString fails to use the .name and .message.
// This is being repaired not because it is a critical issue but because // it is more direct than disabling the tests of error taming which fail.
-    Object.defineProperty(Error.prototype, 'toString', {
+    baseObject.defineProperty(Error.prototype, 'toString', {
       configurable: true,  // attributes per ES5.1 section 15
       writable: true,
       value: function repairedErrorToString() {
         // "1. Let O be the this value."
         var O = this;
         // "2. If Type(O) is not Object, throw a TypeError exception."
-        if (O !== Object(O)) {
+        if (O !== baseObject(O)) {
throw new TypeError('Error.prototype.toString: this not an object');
         }
// "3. Let name be the result of calling the [[Get]] internal method of
@@ -2979,6 +2999,10 @@
         return name + ': ' + msg;
       }
     });
+
+    if (baseObject === Object) {
+      repair_FREEZING_BREAKS_PROTOTYPES_wasApplied = true;
+    }
   }

   ////////////////////// Kludge Records /////////////////////
=======================================
--- /trunk/src/com/google/caja/ses/startSES.js  Wed Apr 17 11:49:04 2013
+++ /trunk/src/com/google/caja/ses/startSES.js  Wed Apr 17 14:21:05 2013
@@ -1468,6 +1468,23 @@
     var group = propertyReports[status];
     ses.logger.reportDiagnosis(group.severity, status, group.list);
   });
+
+ // This repair cannot be fully tested until after Object.prototype is frozen.
+  // TODO(kpreid): Less one-off kludge for this one problem -- or, once the
+  // problem is obsolete, delete all this code.
+  // (We cannot reuse any infrastructure from repairES5 because it is not
+  // exported.)
+  var result;
+  try {
+    result = ses.kludge_test_FREEZING_BREAKS_PROTOTYPES();
+  } catch (e) { result = e; }
+  if (result !== false) {
+    ses.logger.error(
+        'FREEZING_BREAKS_PROTOTYPES repair not actually successful (' +
+        result + ')');
+    ses.updateMaxSeverity(
+        ses.es5ProblemReports.FREEZING_BREAKS_PROTOTYPES.preSeverity);
+  }

   ses.logger.reportMax();

--

--- 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