8013337: Issues with Date.prototype's get, set functions
authorsundar
Fri, 26 Apr 2013 18:31:42 +0530
changeset 17251 444648345fa6
parent 17250 e102b63819ad
child 17252 9aeb443c4740
8013337: Issues with Date.prototype's get, set functions Reviewed-by: jlaskey, hannesw, lagergren
nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
nashorn/test/script/basic/JDK-8013337.js
nashorn/test/script/basic/JDK-8013337.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java	Fri Apr 26 09:48:41 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java	Fri Apr 26 18:31:42 2013 +0530
@@ -519,7 +519,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object getTimezoneOffset(final Object self) {
         final NativeDate nd = getNativeDate(self);
-        if (nd != null) {
+        if (nd != null && nd.isValidDate()) {
             final long msec = (long) nd.getTime();
             return - nd.getTimeZone().getOffset(msec) / msPerMinute;
         }
@@ -535,8 +535,8 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object setTime(final Object self, final Object time) {
+        final NativeDate nd  = getNativeDate(self);
         final double     num = timeClip(JSType.toNumber(time));
-        final NativeDate nd  = getNativeDate(self);
         nd.setTime(num);
         return num;
     }
@@ -551,9 +551,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static Object setMilliseconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, MILLISECOND, args, true);
-        }
+        setFields(nd, MILLISECOND, args, true);
         return nd.getTime();
     }
 
@@ -567,9 +565,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static Object setUTCMilliseconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, MILLISECOND, args, false);
-        }
+        setFields(nd, MILLISECOND, args, false);
         return nd.getTime();
     }
 
@@ -583,9 +579,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
     public static Object setSeconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, SECOND, args, true);
-        }
+        setFields(nd, SECOND, args, true);
         return nd.getTime();
     }
 
@@ -599,9 +593,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
     public static Object setUTCSeconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, SECOND, args, false);
-        }
+        setFields(nd, SECOND, args, false);
         return nd.getTime();
     }
 
@@ -615,9 +607,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
     public static Object setMinutes(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, MINUTE, args, true);
-        }
+        setFields(nd, MINUTE, args, true);
         return nd.getTime();
     }
 
@@ -631,9 +621,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
     public static Object setUTCMinutes(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, MINUTE, args, false);
-        }
+        setFields(nd, MINUTE, args, false);
         return nd.getTime();
     }
 
@@ -647,9 +635,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
     public static Object setHours(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, HOUR, args, true);
-        }
+        setFields(nd, HOUR, args, true);
         return nd.getTime();
     }
 
@@ -663,9 +649,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
     public static Object setUTCHours(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, HOUR, args, false);
-        }
+        setFields(nd, HOUR, args, false);
         return nd.getTime();
     }
 
@@ -679,9 +663,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static Object setDate(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, DAY, args, true);
-        }
+        setFields(nd, DAY, args, true);
         return nd.getTime();
     }
 
@@ -695,9 +677,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static Object setUTCDate(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, DAY, args, false);
-        }
+        setFields(nd, DAY, args, false);
         return nd.getTime();
     }
 
@@ -711,9 +691,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
     public static Object setMonth(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, MONTH, args, true);
-        }
+        setFields(nd, MONTH, args, true);
         return nd.getTime();
     }
 
@@ -727,9 +705,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
     public static Object setUTCMonth(final Object self, final Object... args) {
         final NativeDate nd = ensureNativeDate(self);
-        if (nd.isValidDate()) {
-            setFields(nd, MONTH, args, false);
-        }
+        setFields(nd, MONTH, args, false);
         return nd.getTime();
     }
 
@@ -747,7 +723,11 @@
             setFields(nd, YEAR, args, true);
         } else {
             final double[] d = convertArgs(args, 0, YEAR, YEAR, 3);
-            nd.setTime(timeClip(utc(makeDate(makeDay(d[0], d[1], d[2]), 0), nd.getTimeZone())));
+            if (d != null) {
+                nd.setTime(timeClip(utc(makeDate(makeDay(d[0], d[1], d[2]), 0), nd.getTimeZone())));
+            } else {
+                nd.setTime(NaN);
+            }
         }
         return nd.getTime();
     }
@@ -782,13 +762,13 @@
     public static Object setYear(final Object self, final Object year) {
         final NativeDate nd = getNativeDate(self);
         if (isNaN(nd.getTime())) {
-            return null;
+            nd.setTime(utc(0, nd.getTimeZone()));
         }
 
         final double yearNum = JSType.toNumber(year);
         if (isNaN(yearNum)) {
             nd.setTime(NaN);
-            return nd;
+            return nd.getTime();
         }
         int yearInt = JSType.toInteger(yearNum);
         if (0 <= yearInt && yearInt <= 99) {
@@ -796,7 +776,7 @@
         }
         setFields(nd, YEAR, new Object[] {yearInt}, true);
 
-        return nd;
+        return nd.getTime();
     }
 
     /**
@@ -1298,6 +1278,10 @@
         final double time = local ? nd.getLocalTime() : nd.getTime();
         final double d[] = convertArgs(args, time, fieldId, start, length);
 
+        if (! nd.isValidDate()) {
+            return;
+        }
+
         double newTime;
         if (d == null) {
             newTime = NaN;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8013337.js	Fri Apr 26 18:31:42 2013 +0530
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8013337: Issues with Date.prototype's get, set functions 
+ *
+ * @test
+ * @option -timezone=Asia/Calcutta
+ * @run
+ */
+
+function check(str) {
+    print(str + " = " + eval(str));
+}
+
+check('new Date(NaN).setFullYear(NaN)');
+check('new Date(0).setYear(70)');
+check('new Date(0).setYear(NaN)');
+check('new Date(NaN).setYear(70)');
+check('new Date(NaN).getTimezoneOffset()');
+
+function checkGetterCalled(func) {
+    var getterCalled = false;
+
+    new Date(NaN)[func]( { valueOf: function() { getterCalled = true } } );
+
+    if (getterCalled) {
+       print("Date.prototype." + func + " calls valueOf on arg");
+    }
+}
+
+checkGetterCalled("setMilliseconds");
+checkGetterCalled("setUTCMilliseconds");
+checkGetterCalled("setSeconds");
+checkGetterCalled("setUTCSeconds");
+checkGetterCalled("setMinutes");
+checkGetterCalled("setUTCMinutes");
+checkGetterCalled("setHours");
+checkGetterCalled("setUTCHours");
+checkGetterCalled("setDate");
+checkGetterCalled("setUTCDate");
+checkGetterCalled("setMonth");
+checkGetterCalled("setUTCMonth");
+
+try {
+    Date.prototype.setTime.call({}, { valueOf: function() { throw "err" } }) 
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        fail("TypeError expected, got " + e);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8013337.js.EXPECTED	Fri Apr 26 18:31:42 2013 +0530
@@ -0,0 +1,17 @@
+new Date(NaN).setFullYear(NaN) = NaN
+new Date(0).setYear(70) = 0
+new Date(0).setYear(NaN) = NaN
+new Date(NaN).setYear(70) = -19800000
+new Date(NaN).getTimezoneOffset() = NaN
+Date.prototype.setMilliseconds calls valueOf on arg
+Date.prototype.setUTCMilliseconds calls valueOf on arg
+Date.prototype.setSeconds calls valueOf on arg
+Date.prototype.setUTCSeconds calls valueOf on arg
+Date.prototype.setMinutes calls valueOf on arg
+Date.prototype.setUTCMinutes calls valueOf on arg
+Date.prototype.setHours calls valueOf on arg
+Date.prototype.setUTCHours calls valueOf on arg
+Date.prototype.setDate calls valueOf on arg
+Date.prototype.setUTCDate calls valueOf on arg
+Date.prototype.setMonth calls valueOf on arg
+Date.prototype.setUTCMonth calls valueOf on arg