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 ;
3536import rprocessing .util .RScriptReader ;
3637
38+ import com .jogamp .newt .opengl .GLWindow ;
39+
3740/**
3841 * RlangPApplet PApplet for R language, powered by Renjin.
3942 *
@@ -61,6 +64,8 @@ public class RLangPApplet extends BuiltinApplet {
6164
6265 private final CountDownLatch finishedLatch = new CountDownLatch (1 );
6366
67+ private RSketchError terminalException = null ;
68+
6469 /**
6570 * Mode for Processing.
6671 *
@@ -144,7 +149,7 @@ public void addPAppletToRContext() {
144149 this .renjinEngine .put ("stdout" , stdout );
145150 }
146151
147- public void runBlock (final String [] arguments ) {
152+ public void runBlock (final String [] arguments ) throws RSketchError {
148153 log ("runBlock" );
149154 PApplet .runSketch (arguments , this );
150155 try {
@@ -161,8 +166,7 @@ public void runBlock(final String[] arguments) {
161166 }
162167 } finally {
163168 Thread .setDefaultUncaughtExceptionHandler (null );
164- if (PApplet .platform == PConstants .MACOSX
165- && Arrays .asList (arguments ).contains ("fullScreen" )) {
169+ if (PApplet .platform == PConstants .MACOSX && Arrays .asList (arguments ).contains ("fullScreen" )) {
166170 // Frame should be OS-X fullscreen, and it won't stop being that unless the jvm
167171 // exits or we explicitly tell it to minimize.
168172 // (If it's disposed, it'll leave a gray blank window behind it.)
@@ -182,9 +186,9 @@ public void runBlock(final String[] arguments) {
182186 surface .setVisible (false );
183187 }
184188 }
185- // if (terminalException != null) {
186- // throw terminalException;
187- // }
189+ if (terminalException != null ) {
190+ throw terminalException ;
191+ }
188192 }
189193
190194 private static void macosxFullScreenToggle (final Window window ) {
@@ -242,6 +246,28 @@ public void exitActual() {
242246 finishedLatch .countDown ();
243247 }
244248
249+ /**
250+ * @see processing.core.PApplet#start()
251+ */
252+ @ Override
253+ public void start () {
254+ // I want to quit on runtime exceptions.
255+ // Processing just sits there by default.
256+ Thread .setDefaultUncaughtExceptionHandler (new UncaughtExceptionHandler () {
257+ @ Override
258+ public void uncaughtException (final Thread t , final Throwable e ) {
259+ terminalException = toSketchException (e );
260+ try {
261+ handleMethods ("dispose" );
262+ } catch (final Exception noop ) {
263+ // give up
264+ }
265+ finishedLatch .countDown ();
266+ }
267+ });
268+ super .start ();
269+ }
270+
245271 /**
246272 * @see processing.core.PApplet#settings()
247273 */
@@ -270,7 +296,8 @@ public void setup() {
270296 try {
271297 this .renjinEngine .eval (this .programText );
272298 } catch (ScriptException exception ) {
273- log (exception .toString ());
299+ terminalException = toSketchException (exception );
300+ exitActual ();
274301 }
275302 } else if (this .mode == Mode .ACTIVE ) {
276303 Object obj = this .renjinEngine .get (Constant .SETUP_NAME );
@@ -348,4 +375,19 @@ protected void wrapProcessingVariables() {
348375 private static boolean isSameClass (Object obj , Class clazz ) {
349376 return obj .getClass ().equals (clazz );
350377 }
378+
379+ private static RSketchError toSketchException (Throwable t ) {
380+ if (t instanceof RuntimeException && t .getCause () != null ) {
381+ t = t .getCause ();
382+ }
383+ if (t instanceof RSketchError ) {
384+ return (RSketchError ) t ;
385+ }
386+ if (t instanceof EvalException ) {
387+ final RSketchError e = (RSketchError ) t ;
388+ return e ;
389+ }
390+ log ("No exception type detected." );
391+ return null ;
392+ }
351393}
0 commit comments