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.