1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * JDK-8072426: Can't compare Java objects to strings or numbers
  26  *
  27  * @test
  28  * @run
  29  */
  30 
  31 Assert.assertTrue(java.math.RoundingMode.UP == "UP");
  32 
  33 var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
  34 
  35 // Adds an "isFunction" member to the JSObject that returns the specified value
  36 function addIsFunction(isFunction, obj) {
  37     obj.isFunction = function() {
  38         return isFunction;
  39     };
  40     return obj;
  41 }
  42 
  43 function makeJSObjectConstantFunction(value) {
  44     return new JSObject(addIsFunction(true, {
  45         call: function() {
  46             return value;
  47         }
  48     }));
  49 }
  50 
  51 function makeJSObjectWithMembers(mapping) {
  52     return new JSObject({
  53         getMember: function(name) {
  54             Assert.assertTrue(mapping.hasOwnProperty(name));
  55             return mapping[name];
  56         },
  57         toNumber: function() {
  58             // toNumber no longer invoked
  59             Assert.fail();
  60         }
  61     });
  62 }
  63 
  64 // Test JSObjectLinker toInt32/toLong/toNumber
  65 function testNumericJSObject(kind, value) {
  66     var obj = makeJSObjectWithMembers({
  67             valueOf: makeJSObjectConstantFunction(value)
  68         });
  69 
  70     if (kind === "double") {
  71         // There's no assertEquals(double actual, double expected). There's only
  72         // assertEquals(double actual, double expected, double delta).
  73         Assert["assertEquals(double,double,double)"](value, obj, 0);
  74     } else {
  75         Assert["assertEquals(" + kind + ", " + kind + ")"](value, obj);
  76     }
  77     Assert.assertTrue(value == Number(obj));
  78 }
  79 testNumericJSObject("int", 42);
  80 testNumericJSObject("long", 4294967296);
  81 testNumericJSObject("double", 1.2);
  82 
  83 // Test fallback from toNumber to toString for numeric conversion when toNumber doesn't exist
  84 (function() {
  85     var obj = makeJSObjectWithMembers({
  86         valueOf:  null, // Explicitly no valueOf
  87         toString: makeJSObjectConstantFunction("123")
  88     });
  89     Assert["assertEquals(int,int)"](123, obj);
  90 })();
  91 
  92 // Test fallback from toNumber to toString for numeric conversion when toNumber isn't a callable
  93 (function() {
  94     var obj = makeJSObjectWithMembers({
  95         valueOf:  new JSObject(addIsFunction(false, {})),
  96         toString: makeJSObjectConstantFunction("124")
  97     });
  98     Assert["assertEquals(int,int)"](124, obj);
  99 })();
 100 
 101 // Test fallback from toNumber to toString for numeric conversion when toNumber returns a non-primitive
 102 (function() {
 103     var obj = makeJSObjectWithMembers({
 104         valueOf:  makeJSObjectConstantFunction({}),
 105         toString: makeJSObjectConstantFunction("125")
 106     });
 107     Assert["assertEquals(int,int)"](125, obj);
 108 })();
 109 
 110 // Test TypeError from toNumber to toString when both return a non-primitive
 111 (function() {
 112     var obj = makeJSObjectWithMembers({
 113         valueOf:  makeJSObjectConstantFunction({}),
 114         toString: makeJSObjectConstantFunction({})
 115     });
 116     try {
 117         Number(obj);
 118         Assert.fail(); // must throw
 119     } catch(e) {
 120         Assert.assertTrue(e instanceof TypeError); 
 121     }
 122 })();
 123 
 124 // Test toString for string conversion
 125 (function() {
 126     var obj = makeJSObjectWithMembers({
 127         toString: makeJSObjectConstantFunction("Hello")
 128     });
 129     Assert.assertTrue("Hello" === String(obj));
 130     Assert["assertEquals(String,String)"]("Hello", obj);
 131 })();
 132 
 133 // Test fallback from toString to valueOf for string conversion when toString doesn't exist
 134 (function() {
 135     var obj = makeJSObjectWithMembers({
 136         toString: null,
 137         valueOf:  makeJSObjectConstantFunction("Hello1")
 138     });
 139     Assert.assertTrue("Hello1" === String(obj));
 140     Assert["assertEquals(String,String)"]("Hello1", obj);
 141 })();
 142 
 143 // Test fallback from toString to valueOf for string conversion when toString is not callable
 144 (function() {
 145     var obj = makeJSObjectWithMembers({
 146         toString: new JSObject(addIsFunction(false, {})),
 147         valueOf:  makeJSObjectConstantFunction("Hello2")
 148     });
 149     Assert["assertEquals(String,String)"]("Hello2", obj);
 150 })();
 151 
 152 // Test fallback from toString to valueOf for string conversion when toString returns non-primitive
 153 (function() {
 154     var obj = makeJSObjectWithMembers({
 155         toString: makeJSObjectConstantFunction({}),
 156         valueOf:  makeJSObjectConstantFunction("Hello3")
 157     });
 158     Assert["assertEquals(String,String)"]("Hello3", obj);
 159 })();
 160 
 161 // Test toBoolean for JSObject
 162 (function() {
 163     Assert["assertEquals(boolean,boolean)"](true, new JSObject({}));
 164 })();