44import java .awt .Window ;
55import java .awt .event .ComponentAdapter ;
66import java .awt .event .ComponentEvent ;
7+ import java .lang .Thread .UncaughtExceptionHandler ;
78import java .lang .reflect .Method ;
89import java .util .Arrays ;
910import java .util .concurrent .CountDownLatch ;
1213import javax .script .ScriptEngineManager ;
1314import javax .script .ScriptException ;
1415
16+ import org .renjin .eval .EvalException ;
1517import org .renjin .parser .RParser ;
1618import org .renjin .script .RenjinScriptEngine ;
1719import org .renjin .sexp .Closure ;
2022import org .renjin .sexp .SEXP ;
2123import org .renjin .sexp .Symbol ;
2224
23- import com .jogamp .newt .opengl .GLWindow ;
24-
2525import processing .awt .PSurfaceAWT ;
2626import processing .core .PApplet ;
2727import processing .core .PConstants ;
3030import processing .opengl .PSurfaceJOGL ;
3131import rprocessing .applet .BuiltinApplet ;
3232import rprocessing .exception .NotFoundException ;
33+ import rprocessing .exception .RSketchError ;
3334import rprocessing .util .Constant ;
3435import rprocessing .util .Printer ;
3536
37+ import com .jogamp .newt .opengl .GLWindow ;
38+
3639/**
3740 * RlangPApplet PApplet for R language, powered by Renjin.
3841 *
@@ -57,6 +60,8 @@ public class RLangPApplet extends BuiltinApplet {
5760
5861 private final CountDownLatch finishedLatch = new CountDownLatch (1 );
5962
63+ private RSketchError terminalException = null ;
64+
6065 /**
6166 * Mode for Processing.
6267 *
@@ -136,7 +141,7 @@ public void addPAppletToRContext() {
136141 this .renjinEngine .put ("stdout" , stdout );
137142 }
138143
139- public void runBlock (final String [] arguments ) {
144+ public void runBlock (final String [] arguments ) throws RSketchError {
140145 log ("runBlock" );
141146 PApplet .runSketch (arguments , this );
142147 try {
@@ -153,8 +158,7 @@ public void runBlock(final String[] arguments) {
153158 }
154159 } finally {
155160 Thread .setDefaultUncaughtExceptionHandler (null );
156- if (PApplet .platform == PConstants .MACOSX
157- && Arrays .asList (arguments ).contains ("fullScreen" )) {
161+ if (PApplet .platform == PConstants .MACOSX && Arrays .asList (arguments ).contains ("fullScreen" )) {
158162 // Frame should be OS-X fullscreen, and it won't stop being that unless the jvm
159163 // exits or we explicitly tell it to minimize.
160164 // (If it's disposed, it'll leave a gray blank window behind it.)
@@ -174,9 +178,9 @@ public void runBlock(final String[] arguments) {
174178 surface .setVisible (false );
175179 }
176180 }
177- // if (terminalException != null) {
178- // throw terminalException;
179- // }
181+ if (terminalException != null ) {
182+ throw terminalException ;
183+ }
180184 }
181185
182186 private static void macosxFullScreenToggle (final Window window ) {
@@ -234,6 +238,28 @@ public void exitActual() {
234238 finishedLatch .countDown ();
235239 }
236240
241+ /**
242+ * @see processing.core.PApplet#start()
243+ */
244+ @ Override
245+ public void start () {
246+ // I want to quit on runtime exceptions.
247+ // Processing just sits there by default.
248+ Thread .setDefaultUncaughtExceptionHandler (new UncaughtExceptionHandler () {
249+ @ Override
250+ public void uncaughtException (final Thread t , final Throwable e ) {
251+ terminalException = toSketchException (e );
252+ try {
253+ handleMethods ("dispose" );
254+ } catch (final Exception noop ) {
255+ // give up
256+ }
257+ finishedLatch .countDown ();
258+ }
259+ });
260+ super .start ();
261+ }
262+
237263 /**
238264 * @see processing.core.PApplet#settings()
239265 */
@@ -262,7 +288,8 @@ public void setup() {
262288 try {
263289 this .renjinEngine .eval (this .programText );
264290 } catch (ScriptException exception ) {
265- log (exception .toString ());
291+ terminalException = toSketchException (exception );
292+ exitActual ();
266293 }
267294 } else if (this .mode == Mode .ACTIVE ) {
268295 Object obj = this .renjinEngine .get (Constant .SETUP_NAME );
@@ -341,4 +368,19 @@ protected void wrapProcessingVariables() {
341368 private static boolean isSameClass (Object obj , Class clazz ) {
342369 return obj .getClass ().equals (clazz );
343370 }
371+
372+ private static RSketchError toSketchException (Throwable t ) {
373+ if (t instanceof RuntimeException && t .getCause () != null ) {
374+ t = t .getCause ();
375+ }
376+ if (t instanceof RSketchError ) {
377+ return (RSketchError ) t ;
378+ }
379+ if (t instanceof EvalException ) {
380+ final RSketchError e = (RSketchError ) t ;
381+ return e ;
382+ }
383+ log ("No exception type detected." );
384+ return null ;
385+ }
344386}
0 commit comments