Reviewers: ihab.awad,

Description:
In Chrome 28.0.1480.0 canary (among other versions),
Object.freeze(Object.prototype) causes __proto__ to lose its magic and,
more critically, Object.create(X) to produce objects whose [[Prototype]]
is Object.prototype rather than X. Repair this by reimplementing
Object.create from scratch.

The repair cannot support Object.create(null), but that's OK because
ES5/3 does not support it either.

Note that there is further fatal-to-Caja misbehavior in the same Chrome
versions, with apparently the same root cause, if the "Enable
Experimental JavaScript" flag is on (symptom: {}.constructor === Symbol
(itself an experimental feature), rather than Object), and this repair
does not deal with that.

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

Affected files:
  M     src/com/google/caja/ses/repairES5.js


Index: src/com/google/caja/ses/repairES5.js
===================================================================
--- src/com/google/caja/ses/repairES5.js        (revision 5357)
+++ src/com/google/caja/ses/repairES5.js        (working copy)
@@ -2877,6 +2877,42 @@
     });
   }

+  function repair_OBJECT_CREATE() {
+    var baseObject = Object;
+    var baseDefProp = Object.defineProperties;
+    Object.defineProperty(Object, 'create', {
+      configurable: true,  // attributes per ES5.1 section 15
+      writable: true,
+      value: function repairedObjectCreate(O, Properties) {
+ // "1. If Type(O) is not Object or Null throw a TypeError exception."
+        if (typeof O !== 'object') {
+ throw new TypeError('Object.create: prototype must be an object');
+        }
+        if (O === null) {
+ // Not ES5 conformant, but hopefully adequate for Caja as ES5/3 also
+          // does not support Object.create(null).
+          throw new TypeError(
+            'Repaired Object.create cannot implement Object.create(null)');
+        }
+        // "2. Let obj be the result of creating a new object as if by the
+        // expression new Object() where Object is the standard built-in
+        // constructor with that name"
+        // "3. Set the [[Prototype]] internal property of obj to O."
+ // Cannot redefine [[Prototype]], so we use the .prototype trick instead
+        function temporaryConstructor() {}
+        temporaryConstructor.prototype = O;
+        var obj = new temporaryConstructor();
+ // "4. If the argument Properties is present and not undefined, add own + // properties to obj as if by calling the standard built-in function
+        // Object.defineProperties with arguments obj and Properties."
+        if (Properties !== void 0) {
+          baseDefProp(obj, Properties);
+        }
+        // "5. Return obj."
+        return obj;
+      }
+    });
+  }

   ////////////////////// Kludge Records /////////////////////
   //
@@ -2929,17 +2965,6 @@
       sections: ['15.2.3.4'],
       tests: ['15.2.3.4-0-1']
     },
-    {
-      id: 'FREEZING_BREAKS_CREATE',
-      description: 'Freezing Object.prototype breaks Object.create',
-      test: test_FREEZING_BREAKS_CREATE,
-      repair: void 0,
-      preSeverity: severities.NOT_SUPPORTED,
-      canRepair: false,
-      urls: ['https://code.google.com/p/v8/issues/detail?id=2565'],
-      sections: ['15.2.3.5'],
-      tests: []  // TODO(kpreid): find test242
-    }
   ];

   /**
@@ -3638,7 +3663,18 @@
sections: [], // Not spelled out in spec, according to Brendan Eich (see
                      // es-discuss link)
tests: [] // TODO(kpreid): add to test262 once we have a section to cite
-    }
+    },
+    {
+      id: 'FREEZING_BREAKS_CREATE',
+      description: 'Freezing Object.prototype breaks Object.create',
+      test: test_FREEZING_BREAKS_CREATE,
+      repair: repair_OBJECT_CREATE,
+      preSeverity: severities.UNSAFE_SPEC_VIOLATION,
+      canRepair: true,
+      urls: ['https://code.google.com/p/v8/issues/detail?id=2565'],
+      sections: ['15.2.3.5'],
+      tests: []  // TODO(kpreid): find/add test262
+    },
   ];

   ////////////////////// Testing, Repairing, Reporting ///////////


--

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