Bug 1076588 - Object.freeze() should return its argument with no conversion when the argument is a primitive value. r=till, r=Yoric
authorziyunfei <446240525@qq.com>
Fri, 03 Oct 2014 02:42:00 -0400
changeset 208710 1b532d05bccf46194922ec52acf91e78bcdd0a04
parent 208709 939cf8134947cc9d5061ec022ce9f9985bdbd160
child 208711 91ffa2ab03aa45d35668db72612e32049d8b241b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerstill, Yoric
bugs1076588
milestone35.0a1
Bug 1076588 - Object.freeze() should return its argument with no conversion when the argument is a primitive value. r=till, r=Yoric
js/src/builtin/Object.cpp
js/src/tests/ecma_6/Object/freeze.js
toolkit/components/crashmonitor/CrashMonitor.jsm
toolkit/components/crashmonitor/test/unit/test_invalid_file.js
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -1046,26 +1046,29 @@ obj_preventExtensions(JSContext *cx, uns
         return true;
 
     // Steps 2-5.
     RootedObject obj(cx, &args.get(0).toObject());
 
     return JSObject::preventExtensions(cx, obj);
 }
 
+// ES6 draft rev27 (2014/08/24) 19.1.2.5 Object.freeze(O)
 static bool
 obj_freeze(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    RootedObject obj(cx);
-    if (!GetFirstArgumentAsObject(cx, args, "Object.freeze", &obj))
-        return false;
+    args.rval().set(args.get(0));
 
-    args.rval().setObject(*obj);
+    // Step 1.
+    if (!args.get(0).isObject())
+        return true;
 
+    // Steps 2-5.
+    RootedObject obj(cx, &args.get(0).toObject());
     return JSObject::freeze(cx, obj);
 }
 
 // ES6 draft rev27 (2014/08/24) 19.1.2.12 Object.isFrozen(O)
 static bool
 obj_isFrozen(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/freeze.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1076588;
+var summary = "Object.freeze() should return its argument with no conversion when the argument is a primitive value";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.freeze(), undefined);
+assertEq(Object.freeze(undefined), undefined);
+assertEq(Object.freeze(null), null);
+assertEq(Object.freeze(1), 1);
+assertEq(Object.freeze("foo"), "foo");
+assertEq(Object.freeze(true), true);
+if (typeof Symbol === "function") {
+    assertEq(Object.freeze(Symbol.for("foo")), Symbol.for("foo"));
+}
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
--- a/toolkit/components/crashmonitor/CrashMonitor.jsm
+++ b/toolkit/components/crashmonitor/CrashMonitor.jsm
@@ -113,16 +113,22 @@ let CrashMonitorInternal = {
       let notifications;
       try {
         notifications = JSON.parse(data);
       } catch (ex) {
         Cu.reportError("Error while parsing crash monitor data: " + ex);
         return null;
       }
 
+      // If `notifications` isn't an object, then the monitor data isn't valid.
+      if (Object(notifications) !== notifications) {
+        Cu.reportError("Error while parsing crash monitor data: invalid monitor data");
+        return null;
+      }
+
       return Object.freeze(notifications);
     });
 
     return this.previousCheckpoints;
   }
 };
 
 this.CrashMonitor = {
--- a/toolkit/components/crashmonitor/test/unit/test_invalid_file.js
+++ b/toolkit/components/crashmonitor/test/unit/test_invalid_file.js
@@ -7,24 +7,16 @@
  * Test with sessionCheckpoints.json containing invalid data
  */
 add_task(function test_invalid_file() {
   // Write bogus data to checkpoint file
   let data = "1234";
   yield OS.File.writeAtomic(sessionCheckpointsPath, data,
                             {tmpPath: sessionCheckpointsPath + ".tmp"});
 
-  // An invalid file will cause |init| to throw an exception
-  try {
-    let status = yield CrashMonitor.init();
-    do_check_true(false);
-  } catch (ex) {
-    do_check_true(true);
-  }
+  // An invalid file will cause |init| to return null
+  let status = yield CrashMonitor.init();
+  do_check_true(status === null ? true : false);
 
-  // and |previousCheckpoints| will be rejected
-  try {
-    let checkpoints = yield CrashMonitor.previousCheckpoints;
-    do_check_true(false);
-  } catch (ex) {
-    do_check_true(true);
-  }
+  // and |previousCheckpoints| will be null
+  let checkpoints = yield CrashMonitor.previousCheckpoints;
+  do_check_true(checkpoints === null ? true : false);
 });