|
12 | 12 | import static org.truffleruby.core.array.ArrayHelpers.createArray;
|
13 | 13 |
|
14 | 14 | import java.io.IOException;
|
| 15 | +import java.io.PrintStream; |
15 | 16 | import java.util.EnumSet;
|
16 | 17 |
|
17 | 18 | import com.oracle.truffle.api.interop.InvalidBufferOffsetException;
|
|
22 | 23 | import org.truffleruby.core.array.RubyArray;
|
23 | 24 | import org.truffleruby.core.binding.RubyBinding;
|
24 | 25 | import org.truffleruby.core.encoding.RubyEncoding;
|
| 26 | +import org.truffleruby.core.exception.ExceptionOperations.ExceptionFormatter; |
25 | 27 | import org.truffleruby.core.klass.RubyClass;
|
26 | 28 | import org.truffleruby.core.module.ModuleOperations;
|
27 | 29 | import org.truffleruby.core.module.RubyModule;
|
@@ -90,11 +92,16 @@ public void showExceptionIfDebug(RubyClass rubyClass, Object message, Backtrace
|
90 | 92 | if (backtrace != null && backtrace.getStackTrace().length > 0) {
|
91 | 93 | from = " at " + debugBacktraceFormatter.formatLine(backtrace.getStackTrace(), 0, null);
|
92 | 94 | }
|
93 |
| - Object stderr = context.getCoreLibrary().getStderr(); |
94 |
| - String output = "Exception `" + exceptionClass + "'" + from + " - " + message + "\n"; |
95 |
| - RubyString outputString = StringOperations |
96 |
| - .createString(context, language, StringOperations.encodeRope(output, UTF8Encoding.INSTANCE)); |
97 |
| - RubyContext.send(stderr, "write", outputString); |
| 95 | + final String output = "Exception `" + exceptionClass + "'" + from + " - " + message + "\n"; |
| 96 | + if (context.getCoreLibrary().isLoaded()) { |
| 97 | + RubyString outputString = StringOperations |
| 98 | + .createString(context, language, StringOperations.encodeRope(output, UTF8Encoding.INSTANCE)); |
| 99 | + Object stderr = context.getCoreLibrary().getStderr(); |
| 100 | + RubyContext.send(stderr, "write", outputString); |
| 101 | + } else { |
| 102 | + final PrintStream printStream = BacktraceFormatter.printStreamFor(context.getEnv().err()); |
| 103 | + printStream.println(output); |
| 104 | + } |
98 | 105 | }
|
99 | 106 | }
|
100 | 107 |
|
@@ -316,20 +323,17 @@ public RubyException runtimeError(String message, Backtrace backtrace) {
|
316 | 323 | // SystemStackError
|
317 | 324 |
|
318 | 325 | @TruffleBoundary
|
319 |
| - public RubyException systemStackErrorStackLevelTooDeep(Node currentNode, StackOverflowError javaThrowable) { |
320 |
| - RubyClass exceptionClass = context.getCoreLibrary().systemStackErrorClass; |
321 |
| - StackTraceElement[] stackTrace = javaThrowable.getStackTrace(); |
322 |
| - String topOfTheStack = stackTrace.length > 0 |
| 326 | + public RubyException systemStackErrorStackLevelTooDeep(Node currentNode, StackOverflowError javaThrowable, |
| 327 | + boolean showExceptionIfDebug) { |
| 328 | + final StackTraceElement[] stackTrace = javaThrowable.getStackTrace(); |
| 329 | + final String topOfTheStack = stackTrace.length > 0 |
323 | 330 | ? BacktraceFormatter.formatJava(stackTrace[0])
|
324 | 331 | : "<empty Java stacktrace>";
|
325 | 332 | final String message = coreStrings().STACK_LEVEL_TOO_DEEP + "\n\tfrom " + topOfTheStack;
|
326 |
| - return ExceptionOperations.createRubyException( |
327 |
| - context, |
328 |
| - exceptionClass, |
329 |
| - StringOperations |
330 |
| - .createString(context, language, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE)), |
331 |
| - currentNode, |
332 |
| - javaThrowable); |
| 333 | + final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode, 0, javaThrowable); |
| 334 | + final RubyString messageString = StringOperations |
| 335 | + .createString(context, language, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE)); |
| 336 | + return ExceptionOperations.createSystemStackError(context, messageString, backtrace, showExceptionIfDebug); |
333 | 337 | }
|
334 | 338 |
|
335 | 339 | // NoMemoryError
|
@@ -794,65 +798,75 @@ public RubyNameError nameError(String message, Object receiver, String name, Nod
|
794 | 798 | language.getSymbol(name));
|
795 | 799 | }
|
796 | 800 |
|
797 |
| - public RubyNameError nameErrorFromMethodMissing(RubyProc formatter, Object receiver, String name, |
| 801 | + @TruffleBoundary |
| 802 | + public RubyNameError nameErrorFromMethodMissing(ExceptionFormatter formatter, Object receiver, String name, |
798 | 803 | Node currentNode) {
|
799 | 804 | // omit = 1 to skip over the call to `method_missing'. MRI does not show this is the backtrace.
|
800 | 805 | final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode, 1);
|
801 | 806 | final Object cause = ThreadGetExceptionNode.getLastException(context);
|
| 807 | + |
| 808 | + final RubyProc formatterProc = formatter.getProc(context); |
| 809 | + final String message = formatter.getMessage(formatterProc, name, receiver); |
| 810 | + |
802 | 811 | final RubyNameError exception = new RubyNameError(
|
803 | 812 | context.getCoreLibrary().nameErrorClass,
|
804 | 813 | language.nameErrorShape,
|
805 |
| - null, |
| 814 | + message, |
806 | 815 | backtrace,
|
807 | 816 | cause,
|
808 | 817 | receiver,
|
809 | 818 | language.getSymbol(name));
|
810 |
| - exception.formatter = formatter; |
| 819 | + exception.formatter = formatterProc; |
811 | 820 | showExceptionIfDebug(exception, backtrace);
|
812 | 821 | return exception;
|
813 | 822 | }
|
814 | 823 |
|
815 | 824 | // NoMethodError
|
816 | 825 |
|
817 |
| - public RubyNoMethodError noMethodError(String message, Object receiver, String name, Object[] args, |
818 |
| - Node currentNode) { |
819 |
| - final RubyString messageString = StringOperations |
820 |
| - .createString(context, language, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE)); |
| 826 | + @TruffleBoundary |
| 827 | + public RubyNoMethodError noMethodErrorFromMethodMissing(ExceptionFormatter formatter, Object receiver, String name, |
| 828 | + Object[] args, Node currentNode) { |
821 | 829 | final RubyArray argsArray = createArray(context, language, args);
|
822 |
| - final RubyClass exceptionClass = context.getCoreLibrary().noMethodErrorClass; |
823 |
| - final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode); |
| 830 | + |
| 831 | + // omit = 1 to skip over the call to `method_missing'. MRI does not show this is the backtrace. |
| 832 | + final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode, 1); |
824 | 833 | final Object cause = ThreadGetExceptionNode.getLastException(context);
|
825 |
| - showExceptionIfDebug(exceptionClass, messageString, backtrace); |
826 |
| - return new RubyNoMethodError( |
| 834 | + |
| 835 | + final RubyProc formatterProc = formatter.getProc(context); |
| 836 | + final String message = formatter.getMessage(formatterProc, name, receiver); |
| 837 | + |
| 838 | + final RubyNoMethodError exception = new RubyNoMethodError( |
827 | 839 | context.getCoreLibrary().noMethodErrorClass,
|
828 | 840 | language.noMethodErrorShape,
|
829 |
| - messageString, |
| 841 | + message, |
830 | 842 | backtrace,
|
831 | 843 | cause,
|
832 | 844 | receiver,
|
833 | 845 | language.getSymbol(name),
|
834 | 846 | argsArray);
|
| 847 | + exception.formatter = formatterProc; |
| 848 | + showExceptionIfDebug(exception, backtrace); |
| 849 | + return exception; |
835 | 850 | }
|
836 | 851 |
|
837 |
| - public RubyNoMethodError noMethodErrorFromMethodMissing(RubyProc formatter, Object receiver, String name, |
838 |
| - Object[] args, Node currentNode) { |
| 852 | + public RubyNoMethodError noMethodError(String message, Object receiver, String name, Object[] args, |
| 853 | + Node currentNode) { |
| 854 | + final RubyString messageString = StringOperations |
| 855 | + .createString(context, language, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE)); |
839 | 856 | final RubyArray argsArray = createArray(context, language, args);
|
840 |
| - |
841 |
| - // omit = 1 to skip over the call to `method_missing'. MRI does not show this is the backtrace. |
842 |
| - final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode, 1); |
| 857 | + final RubyClass exceptionClass = context.getCoreLibrary().noMethodErrorClass; |
| 858 | + final Backtrace backtrace = context.getCallStack().getBacktrace(currentNode); |
843 | 859 | final Object cause = ThreadGetExceptionNode.getLastException(context);
|
844 |
| - final RubyNoMethodError exception = new RubyNoMethodError( |
| 860 | + showExceptionIfDebug(exceptionClass, messageString, backtrace); |
| 861 | + return new RubyNoMethodError( |
845 | 862 | context.getCoreLibrary().noMethodErrorClass,
|
846 | 863 | language.noMethodErrorShape,
|
847 |
| - null, |
| 864 | + messageString, |
848 | 865 | backtrace,
|
849 | 866 | cause,
|
850 | 867 | receiver,
|
851 | 868 | language.getSymbol(name),
|
852 | 869 | argsArray);
|
853 |
| - exception.formatter = formatter; |
854 |
| - showExceptionIfDebug(exception, backtrace); |
855 |
| - return exception; |
856 | 870 | }
|
857 | 871 |
|
858 | 872 | @TruffleBoundary
|
|
0 commit comments