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