Bug 1120512 - Test all property descriptors in js::TestIntegrityLevel. r=jorendorff
☠☠ backed out by 7cf998040d6b ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Fri, 23 Jan 2015 19:21:35 +0900
changeset 225278 17c4307d167881651c678004593fe444edcb401e
parent 225277 20f9a56f69288341c240d70d6938881b86dd1f23
child 225279 86662d2c6d41d8ac9575be270440bde448cd7560
push id54519
push userarai_a@mac.com
push dateFri, 23 Jan 2015 10:23:35 +0000
treeherdermozilla-inbound@4b6c10b02156 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1120512
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1120512 - Test all property descriptors in js::TestIntegrityLevel. r=jorendorff
js/src/jit-test/tests/proxy/testTestIntegrityLevel.js
js/src/jsobj.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/proxy/testTestIntegrityLevel.js
@@ -0,0 +1,16 @@
+// isSealed/isFrozen should call getOwnPropertyDescriptor for all properties.
+
+var log = [];
+var target = Object.preventExtensions({a: 1, b: 2, c: 3});
+var p = new Proxy(target, {
+    getOwnPropertyDescriptor(t, id) {
+        log.push(id);
+        return Object.getOwnPropertyDescriptor(t, id);
+    }
+});
+assertEq(Object.isSealed(p), false);
+assertEq(log.sort().join(''), 'abc');
+
+log.length = 0;
+assertEq(Object.isFrozen(p), false);
+assertEq(log.sort().join(''), 'abc');
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1139,40 +1139,48 @@ js::TestIntegrityLevel(JSContext *cx, Ha
         return true;
     }
 
     // Steps 7-8.
     AutoIdVector props(cx);
     if (!GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY | JSITER_SYMBOLS, &props))
         return false;
 
-    // Steps 9-11. The spec does not permit stopping as soon as we find out the
-    // answer is false, so we are cheating a little here (bug 1120512).
+    // Steps 9-10.
+    bool configurable = false;
+    bool writable = false;
+
+    // Steps 11.
     RootedId id(cx);
     for (size_t i = 0, len = props.length(); i < len; i++) {
         id = props[i];
 
-        unsigned attrs;
-        if (!GetPropertyAttributes(cx, obj, id, &attrs))
+        // Steps 11.a-b.
+        Rooted<PropertyDescriptor> desc(cx);
+        if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
             return false;
 
-        // If the property is configurable, this object is neither sealed nor
-        // frozen. If the property is a writable data property, this object is
-        // not frozen.
-        if (!(attrs & JSPROP_PERMANENT) ||
-            (level == IntegrityLevel::Frozen &&
-             !(attrs & (JSPROP_READONLY | JSPROP_GETTER | JSPROP_SETTER))))
-        {
-            *result = false;
-            return true;
-        }
+        // Step 11.c.
+        if (!desc.object())
+            continue;
+
+        // Step 11.c.i.
+        if (!desc.isPermanent())
+            configurable = true;
+
+        // Step 11.c.ii.
+        if (desc.isDataDescriptor() && desc.isWritable())
+            writable = true;
     }
 
-    // All properties checked out. This object is sealed/frozen.
-    *result = true;
+    // Steps 12-14.
+    if (level == IntegrityLevel::Frozen && writable)
+        *result = false;
+    else
+        *result = !configurable;
     return true;
 }
 
 
 /* * */
 
 /*
  * Get the GC kind to use for scripted 'new' on the given class.