1 /* 2 * Copyright (c) 2010, 2013, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime; 27 28 import java.text.MessageFormat; 29 import java.util.Locale; 30 import java.util.ResourceBundle; 31 import jdk.nashorn.api.scripting.NashornException; 32 import jdk.nashorn.internal.scripts.JS; 33 import jdk.nashorn.internal.codegen.CompilerConstants; 34 35 /** 36 * Helper class to throw various standard "ECMA error" exceptions such as Error, ReferenceError, TypeError etc. 37 */ 38 public final class ECMAErrors { 39 private static final String MESSAGES_RESOURCE = "jdk.nashorn.internal.runtime.resources.Messages"; 40 41 private static final ResourceBundle MESSAGES_BUNDLE; 42 static { 43 MESSAGES_BUNDLE = ResourceBundle.getBundle(MESSAGES_RESOURCE, Locale.getDefault()); 44 } 45 46 /** We assume that compiler generates script classes into the known package. */ 47 private static final String scriptPackage; 48 static { 49 String name = JS.class.getName(); 50 scriptPackage = name.substring(0, name.lastIndexOf('.')); 51 } 52 53 private ECMAErrors() { 54 } 55 56 private static ECMAException error(final Object thrown, final Throwable cause) { 57 return new ECMAException(thrown, cause); 58 } 59 60 /** 61 * Error dispatch mechanism. 62 * Create a {@link ParserException} as the correct JavaScript error 63 * 64 * @param e {@code ParserException} for error dispatcher 65 * 66 * @return the resulting {@link ECMAException} 67 */ 68 public static ECMAException asEcmaException(final ParserException e) { 69 return asEcmaException(Context.getGlobalTrusted(), e); 70 } 71 72 /** 73 * Error dispatch mechanism. 74 * Create a {@link ParserException} as the correct JavaScript error 75 * 76 * @param global global scope object 77 * @param e {@code ParserException} for error dispatcher 78 * 79 * @return the resulting {@link ECMAException} 80 */ 81 public static ECMAException asEcmaException(final ScriptObject global, final ParserException e) { 82 final JSErrorType errorType = e.getErrorType(); 83 assert errorType != null : "error type for " + e + " was null"; 84 85 final GlobalObject globalObj = (GlobalObject)global; 86 final String msg = e.getMessage(); 87 88 // translate to ECMAScript Error object using error type 89 switch (errorType) { 90 case ERROR: 91 return error(globalObj.newError(msg), e); 92 case EVAL_ERROR: 93 return error(globalObj.newEvalError(msg), e); 94 case RANGE_ERROR: 95 return error(globalObj.newRangeError(msg), e); 96 case REFERENCE_ERROR: 97 return error(globalObj.newReferenceError(msg), e); 98 case SYNTAX_ERROR: 99 return error(globalObj.newSyntaxError(msg), e); 100 case TYPE_ERROR: 101 return error(globalObj.newTypeError(msg), e); 102 case URI_ERROR: 103 return error(globalObj.newURIError(msg), e); 104 default: 105 // should not happen - perhaps unknown error type? 106 throw new AssertionError(e.getMessage()); 107 } 108 } 109 110 /** 111 * Create a syntax error (ECMA 15.11.6.4) 112 * 113 * @param msgId resource tag for error message 114 * @param args arguments to resource 115 * 116 * @return the resulting {@link ECMAException} 117 */ 118 public static ECMAException syntaxError(final String msgId, final String... args) { 119 return syntaxError(Context.getGlobalTrusted(), msgId, args); 120 } 121 122 /** 123 * Create a syntax error (ECMA 15.11.6.4) 124 * 125 * @param global global scope object 126 * @param msgId resource tag for error message 127 * @param args arguments to resource 128 * 129 * @return the resulting {@link ECMAException} 130 */ 131 public static ECMAException syntaxError(final ScriptObject global, final String msgId, final String... args) { 132 return syntaxError(global, null, msgId, args); 133 } 134 135 /** 136 * Create a syntax error (ECMA 15.11.6.4) 137 * 138 * @param cause native Java {@code Throwable} that is the cause of error 139 * @param msgId resource tag for error message 140 * @param args arguments to resource 141 * 142 * @return the resulting {@link ECMAException} 143 */ 144 public static ECMAException syntaxError(final Throwable cause, final String msgId, final String... args) { 145 return syntaxError(Context.getGlobalTrusted(), cause, msgId, args); 146 } 147 148 /** 149 * Create a syntax error (ECMA 15.11.6.4) 150 * 151 * @param global global scope object 152 * @param cause native Java {@code Throwable} that is the cause of error 153 * @param msgId resource tag for error message 154 * @param args arguments to resource 155 * 156 * @return the resulting {@link ECMAException} 157 */ 158 public static ECMAException syntaxError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) { 159 final String msg = getMessage("syntax.error." + msgId, args); 160 return error(((GlobalObject)global).newSyntaxError(msg), cause); 161 } 162 163 /** 164 * Create a type error (ECMA 15.11.6.5) 165 * 166 * @param msgId resource tag for error message 167 * @param args arguments to resource 168 * 169 * @return the resulting {@link ECMAException} 170 */ 171 public static ECMAException typeError(final String msgId, final String... args) { 172 return typeError(Context.getGlobalTrusted(), msgId, args); 173 } 174 175 /** 176 * Create a type error (ECMA 15.11.6.5) 177 * 178 * @param global global scope object 179 * @param msgId resource tag for error message 180 * @param args arguments to resource 181 * 182 * @return the resulting {@link ECMAException} 183 */ 184 public static ECMAException typeError(final ScriptObject global, final String msgId, final String... args) { 185 return typeError(global, null, msgId, args); 186 } 187 188 /** 189 * Create a type error (ECMA 15.11.6.5) 190 * 191 * @param cause native Java {@code Throwable} that is the cause of error 192 * @param msgId resource tag for error message 193 * @param args arguments to resource 194 * 195 * @return the resulting {@link ECMAException} 196 */ 197 public static ECMAException typeError(final Throwable cause, final String msgId, final String... args) { 198 return typeError(Context.getGlobalTrusted(), cause, msgId, args); 199 } 200 201 /** 202 * Create a type error (ECMA 15.11.6.5) 203 * 204 * @param global global scope object 205 * @param cause native Java {@code Throwable} that is the cause of error 206 * @param msgId resource tag for error message 207 * @param args arguments to resource 208 * 209 * @return the resulting {@link ECMAException} 210 */ 211 public static ECMAException typeError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) { 212 final String msg = getMessage("type.error." + msgId, args); 213 return error(((GlobalObject)global).newTypeError(msg), cause); 214 } 215 216 /** 217 * Create a range error (ECMA 15.11.6.2) 218 * 219 * @param msgId resource tag for error message 220 * @param args arguments to resource 221 * 222 * @return the resulting {@link ECMAException} 223 */ 224 public static ECMAException rangeError(final String msgId, final String... args) { 225 return rangeError(Context.getGlobalTrusted(), msgId, args); 226 } 227 228 /** 229 * Create a range error (ECMA 15.11.6.2) 230 * 231 * @param global global scope object 232 * @param msgId resource tag for error message 233 * @param args arguments to resource 234 * 235 * @return the resulting {@link ECMAException} 236 */ 237 public static ECMAException rangeError(final ScriptObject global, final String msgId, final String... args) { 238 return rangeError(global, null, msgId, args); 239 } 240 241 /** 242 * Create a range error (ECMA 15.11.6.2) 243 * 244 * @param cause native Java {@code Throwable} that is the cause of error 245 * @param msgId resource tag for error message 246 * @param args arguments to resource 247 * 248 * @return the resulting {@link ECMAException} 249 */ 250 public static ECMAException rangeError(final Throwable cause, final String msgId, final String... args) { 251 return rangeError(Context.getGlobalTrusted(), cause, msgId, args); 252 } 253 254 /** 255 * Create a range error (ECMA 15.11.6.2) 256 * 257 * @param global global scope object 258 * @param cause native Java {@code Throwable} that is the cause of error 259 * @param msgId resource tag for error message 260 * @param args arguments to resource 261 * 262 * @return the resulting {@link ECMAException} 263 */ 264 public static ECMAException rangeError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) { 265 final String msg = getMessage("range.error." + msgId, args); 266 return error(((GlobalObject)global).newRangeError(msg), cause); 267 } 268 269 /** 270 * Create a reference error (ECMA 15.11.6.3) 271 * 272 * @param msgId resource tag for error message 273 * @param args arguments to resource 274 * 275 * @return the resulting {@link ECMAException} 276 */ 277 public static ECMAException referenceError(final String msgId, final String... args) { 278 return referenceError(Context.getGlobalTrusted(), msgId, args); 279 } 280 281 /** 282 * Create a reference error (ECMA 15.11.6.3) 283 * 284 * @param global global scope object 285 * @param msgId resource tag for error message 286 * @param args arguments to resource 287 * 288 * @return the resulting {@link ECMAException} 289 */ 290 public static ECMAException referenceError(final ScriptObject global, final String msgId, final String... args) { 291 return referenceError(global, null, msgId, args); 292 } 293 294 /** 295 * Create a reference error (ECMA 15.11.6.3) 296 * 297 * @param cause native Java {@code Throwable} that is the cause of error 298 * @param msgId resource tag for error message 299 * @param args arguments to resource 300 * 301 * @return the resulting {@link ECMAException} 302 */ 303 public static ECMAException referenceError(final Throwable cause, final String msgId, final String... args) { 304 return referenceError(Context.getGlobalTrusted(), cause, msgId, args); 305 } 306 307 /** 308 * Create a reference error (ECMA 15.11.6.3) 309 * 310 * @param global global scope object 311 * @param cause native Java {@code Throwable} that is the cause of error 312 * @param msgId resource tag for error message 313 * @param args arguments to resource 314 * 315 * @return the resulting {@link ECMAException} 316 */ 317 public static ECMAException referenceError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) { 318 final String msg = getMessage("reference.error." + msgId, args); 319 return error(((GlobalObject)global).newReferenceError(msg), cause); 320 } 321 322 /** 323 * Create a URI error (ECMA 15.11.6.6) 324 * 325 * @param msgId resource tag for error message 326 * @param args arguments to resource 327 * 328 * @return the resulting {@link ECMAException} 329 */ 330 public static ECMAException uriError(final String msgId, final String... args) { 331 return uriError(Context.getGlobalTrusted(), msgId, args); 332 } 333 334 /** 335 * Create a URI error (ECMA 15.11.6.6) 336 * 337 * @param global global scope object 338 * @param msgId resource tag for error message 339 * @param args arguments to resource 340 * 341 * @return the resulting {@link ECMAException} 342 */ 343 public static ECMAException uriError(final ScriptObject global, final String msgId, final String... args) { 344 return uriError(global, null, msgId, args); 345 } 346 347 /** 348 * Create a URI error (ECMA 15.11.6.6) 349 * 350 * @param cause native Java {@code Throwable} that is the cause of error 351 * @param msgId resource tag for error message 352 * @param args arguments to resource 353 * 354 * @return the resulting {@link ECMAException} 355 */ 356 public static ECMAException uriError(final Throwable cause, final String msgId, final String... args) { 357 return uriError(Context.getGlobalTrusted(), cause, msgId, args); 358 } 359 360 /** 361 * Create a URI error (ECMA 15.11.6.6) 362 * 363 * @param global global scope object 364 * @param cause native Java {@code Throwable} that is the cause of error 365 * @param msgId resource tag for error message 366 * @param args arguments to resource 367 * 368 * @return the resulting {@link ECMAException} 369 */ 370 public static ECMAException uriError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) { 371 final String msg = getMessage("uri.error." + msgId, args); 372 return error(((GlobalObject)global).newURIError(msg), cause); 373 } 374 375 /** 376 * Get the exception message by placing the args in the resource defined 377 * by the resource tag. This is visible to, e.g. the {@link jdk.nashorn.internal.parser.Parser} 378 * can use it to generate compile time messages with the correct locale 379 * 380 * @param msgId the resource tag (message id) 381 * @param args arguments to error string 382 * 383 * @return the filled out error string 384 */ 385 public static String getMessage(final String msgId, final String... args) { 386 try { 387 return new MessageFormat(MESSAGES_BUNDLE.getString(msgId)).format(args); 388 } catch (final java.util.MissingResourceException e) { 389 throw new RuntimeException("no message resource found for message id: "+ msgId); 390 } 391 } 392 393 394 /** 395 * Check if a stack trace element is in JavaScript 396 * 397 * @param frame frame 398 * 399 * @return true if frame is in the script 400 */ 401 public static boolean isScriptFrame(final StackTraceElement frame) { 402 final String className = frame.getClassName(); 403 404 // Look for script package in class name (into which compiler puts generated code) 405 if (className.startsWith(scriptPackage) && !frame.getMethodName().startsWith(CompilerConstants.INTERNAL_METHOD_PREFIX)) { 406 final String source = frame.getFileName(); 407 /* 408 * Make sure that it is not some Java code that Nashorn has in that package! 409 * also, we don't want to report JavaScript code that lives in script engine implementation 410 * We want to report only user's own scripts and not any of our own scripts like "engine.js" 411 */ 412 return source != null && !source.endsWith(".java") && !source.contains(NashornException.ENGINE_SCRIPT_SOURCE_NAME); 413 } 414 return false; 415 } 416 } --- EOF ---