1 /*
   2  * Copyright (c) 2014, 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-8044798: API for debugging Nashorn
  26  *
  27  * @test
  28  * @option -Dnashorn.mirror.always=false
  29  * @fork
  30  */
  31 
  32 // basic API exercise checks
  33 
  34 var Arrays = Java.type("java.util.Arrays");
  35 var CharArray = Java.type("char[]");
  36 var Reflector = Java.type("jdk.nashorn.test.models.Reflector");
  37 var DebuggerSupport = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport");
  38 var DebuggerValueDesc = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.DebuggerValueDesc");
  39 
  40 var valueDescFields = DebuggerValueDesc.class.declaredFields;
  41 Arrays.sort(valueDescFields, function(f1, f2) f1.name.compareTo(f2.name));
  42 for each (var f in valueDescFields) {
  43     Reflector.setAccessible(f);
  44 }
  45 
  46 var debuggerSupportMethods = DebuggerSupport.class.declaredMethods;
  47 
  48 // methods of DebuggerSupport that we use
  49 var evalMethod, valueInfoMethod, valueInfosMethod;
  50 var getSourceInfoMethod, valueAsStringMethod;
  51 
  52 for each (var m in debuggerSupportMethods) {
  53     Reflector.setAccessible(m);
  54     switch (m.name) {
  55         case "eval":
  56             evalMethod = m;
  57             break;
  58         case "valueInfo":
  59             if (m.parameterCount == 3) {
  60                 valueInfoMethod = m;
  61             }
  62             break;
  63         case "valueInfos":
  64             valueInfosMethod = m;
  65             break;
  66         case "valueAsString":
  67             valueAsStringMethod = m;
  68             break;
  69         case "getSourceInfo":
  70             getSourceInfoMethod = m;
  71             break;
  72     }
  73 }
  74 
  75 // eval
  76 var value = evalMethod.invoke(null, null, null, "33 + 55", false);
  77 print(value);
  78 
  79 // valueInfo
  80 var info = valueInfoMethod.invoke(null, "apply", Function, true);
  81 for each (var f in valueDescFields) {
  82     print(f.name, "=", f.get(info));
  83 }
  84 
  85 // valueInfo - user defined object
  86 var info = valueInfoMethod.invoke(null, "foo", { foo: 343 }, true);
  87 for each (var f in valueDescFields) {
  88     print(f.name, "=", f.get(info));
  89 }
  90 
  91 // valueInfos
  92 var infos = valueInfosMethod.invoke(null, Object, true);
  93 for each (var info in infos) {
  94     for each (var f in valueDescFields) {
  95         print(f.name, "=", f.get(info));
  96     }
  97 }
  98 
  99 // valueInfos - user defined object
 100 var infos = valueInfosMethod.invoke(null, { foo: 34, bar: "hello" }, true);
 101 for each (var info in infos) {
 102     for each (var f in valueDescFields) {
 103         print(f.name, "=", f.get(info));
 104     }
 105 }
 106 
 107 // valueAsString
 108 function printValue(value) {
 109     print(valueAsStringMethod.invoke(null, value));
 110 }
 111 
 112 printValue(undefined);
 113 printValue(null);
 114 printValue("hello");
 115 printValue(Math.PI);
 116 printValue(this);
 117 
 118 // The below are not part of DebuggerSupport. But we need these to
 119 // test DebuggerSupport.getSourceInfo etc. which need compiled script class
 120 
 121 var Source = Java.type("jdk.nashorn.internal.runtime.Source");
 122 var Context = Java.type("jdk.nashorn.internal.runtime.Context");
 123 var ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context.ThrowErrorManager");
 124 var contextCls = java.lang.Class.forName("jdk.nashorn.internal.runtime.Context");
 125 var sourceCls = Source.class;
 126 var errorMgrCls = Java.type("jdk.nashorn.internal.runtime.ErrorManager").class;
 127 var booleanCls = Java.type("java.lang.Boolean").TYPE;
 128 var stringCls = Java.type("java.lang.String").class;
 129 
 130 // private compile method of Context class
 131 var compileMethod = contextCls.getDeclaredMethod("compile",
 132                 sourceCls, errorMgrCls, booleanCls, booleanCls);
 133 Reflector.setAccessible(compileMethod);
 134 
 135 var getContextMethod = contextCls.getMethod("getContext");
 136 Reflector.setAccessible(getContextMethod);
 137 
 138 var sourceForMethod = sourceCls.getMethod("sourceFor", stringCls, stringCls);
 139 var scriptCls = compileMethod.invoke(getContextMethod.invoke(null),
 140     sourceForMethod.invoke(null, "test", "print('hello')"),
 141     ThrowErrorManager.class.newInstance(), false, false);
 142 
 143 var SCRIPT_CLASS_NAME_PREFIX = "jdk.nashorn.internal.scripts.Script$";
 144 print("script class name pattern satisfied? " +
 145     scriptCls.name.startsWith(SCRIPT_CLASS_NAME_PREFIX));
 146 
 147 var srcInfo = getSourceInfoMethod.invoke(null, scriptCls);
 148 var srcInfoFields = srcInfo.class.declaredFields;
 149 Arrays.sort(srcInfoFields, function(f1, f2) f1.name.compareTo(f2.name));
 150 
 151 print("Source info");
 152 for each (var f in srcInfoFields) {
 153     Reflector.setAccessible(f);
 154     var fieldValue = f.get(srcInfo);
 155     if (fieldValue instanceof CharArray) {
 156         fieldValue = new java.lang.String(fieldValue);
 157     }
 158 
 159     print(f.name, "=", fieldValue);
 160 }