diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
index 8f0f513b5c7f3caaed7217d6668f7b97b57f04ac..55d968d8d5e47747aef3c697dfda3622a207b1e8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
@@ -30,6 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
@@ -38,13 +39,16 @@ import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNodeGen;
+import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.SubstituteVirtualFrame;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState.HelperState;
@@ -55,6 +59,7 @@ public class BrowserFunctions {
     public abstract static class BrowserNode extends RBuiltinNode.Arg4 {
 
         @Child private BrowserInteractNode browserInteractNode = BrowserInteractNodeGen.create();
+        @Child private GetCallerFrameNode getCallerFrame;
 
         @Override
         public Object[] getDefaultParameterValues() {
@@ -78,8 +83,18 @@ public class BrowserFunctions {
                     browserState.push(new HelperState(text, condition));
                     MaterializedFrame mFrame = frame.materialize();
                     RCaller caller = RArguments.getCall(mFrame);
+                    RFunction fun = RArguments.getFunction(mFrame);
+                    VirtualFrame actualFrame = frame;
+                    if (fun != null && fun.isBuiltin() && fun.getRBuiltin().getBuiltinNodeClass() == BrowserNode.class) {
+                        if (getCallerFrame == null) {
+                            CompilerDirectives.transferToInterpreterAndInvalidate();
+                            getCallerFrame = insert(new GetCallerFrameNode());
+                        }
+                        actualFrame = SubstituteVirtualFrame.create(getCallerFrame.execute(mFrame));
+                        caller = caller.getParent();
+                    }
                     doPrint(caller);
-                    browserInteractNode.execute(frame);
+                    browserInteractNode.execute(actualFrame, caller);
                 } finally {
                     browserState.pop();
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
index 310290392d35cedc807fe9e4fc6893f3a3f51fed..d6e1d063a37b2c4ba96c5b24f5c95b958aedfebd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
@@ -139,9 +139,8 @@ public class DebugFunctions {
             casts.arg("clear").asLogicalVector().findFirst().map(toBoolean());
         }
 
-        @SuppressWarnings("unused")
         @Specialization
-        protected Object setBreakpoint(String fileLine, RMissing lineNr, boolean clear) {
+        protected Object setBreakpoint(String fileLine, @SuppressWarnings("unused") RMissing lineNr, boolean clear) {
 
             int hashIdx = fileLine.lastIndexOf('#');
             if (hashIdx != -1) {
@@ -156,13 +155,16 @@ public class DebugFunctions {
             throw error(RError.Message.GENERIC, "Line number missing");
         }
 
-        @SuppressWarnings("unused")
         @Specialization
         protected Object setBreakpoint(String fileName, int lineNr, boolean clear) {
 
             try {
                 Source fromSrcfile = RSource.fromFileName(fileName, false);
-                DebugHandling.enableLineDebug(fromSrcfile, lineNr);
+                if (!clear) {
+                    DebugHandling.enableLineDebug(fromSrcfile, lineNr);
+                } else {
+                    DebugHandling.disableLineDebug(fromSrcfile, lineNr);
+                }
                 return RDataFactory.createStringVectorFromScalar(fileName + "#" + lineNr);
             } catch (IOException e) {
                 return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
index af83fd603a56f75d1caf484a3af591f654851582..a39f869d19371c557d545744c2b9d36f315a4699 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -48,7 +49,6 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
-import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -62,7 +62,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * </ol>
  *
  */
-public abstract class BrowserInteractNode extends RNode {
+public abstract class BrowserInteractNode extends Node {
 
     public static final int STEP = 0;
     public static final int NEXT = 1;
@@ -72,8 +72,10 @@ public abstract class BrowserInteractNode extends RNode {
     @Child private GetFixedAttributeNode getSrcRefAttrNode;
     @Child private GetFixedAttributeNode getSrcFileAttrNode;
 
+    public abstract int execute(VirtualFrame frame, RCaller caller);
+
     @Specialization
-    protected int interact(VirtualFrame frame) {
+    protected int interact(VirtualFrame frame, RCaller caller) {
         CompilerDirectives.transferToInterpreter();
         MaterializedFrame mFrame = frame.materialize();
         ConsoleHandler ch = RContext.getInstance().getConsoleHandler();
@@ -81,9 +83,9 @@ public abstract class BrowserInteractNode extends RNode {
         String savedPrompt = ch.getPrompt();
         RFunction callerFunction = RArguments.getFunction(frame);
         // we may be at top level where there is not caller
-        boolean callerIsDebugged = callerFunction == null ? false : DebugHandling.isDebugged(callerFunction);
+        boolean callerIsDebugged = callerFunction == null || DebugHandling.isDebugged(callerFunction);
         int exitMode = NEXT;
-        RCaller currentCaller = RArguments.getCall(mFrame);
+        RCaller currentCaller = caller;
         if (currentCaller == null) {
             currentCaller = RCaller.topLevel;
         }
@@ -92,7 +94,7 @@ public abstract class BrowserInteractNode extends RNode {
         try {
             browserState.setInBrowser(browserCaller);
             LW: while (true) {
-                ch.setPrompt(browserPrompt(RArguments.getDepth(frame)));
+                ch.setPrompt(browserPrompt(currentCaller.getDepth()));
                 String input = ch.readLine();
                 if (input != null) {
                     input = input.trim();
@@ -130,7 +132,7 @@ public abstract class BrowserInteractNode extends RNode {
                     case "Q":
                         throw new JumpToTopLevelException();
                     case "where": {
-                        if (RArguments.getDepth(mFrame) > 1) {
+                        if (currentCaller.getDepth() > 1) {
                             Object stack = Utils.createTraceback(0);
                             // browser inverts frame depth
                             int idepth = 1;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index df64350f8341122a6ac76b962c8682a261631019..ff6f5b36d84fa8799557ff7c295026fcd2f53472 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -211,9 +211,13 @@ public class DebugHandling {
     @TruffleBoundary
     public static void disableLineDebug(Source fdn, int line) {
         LineBreakpointEventListener l = getLineBreakpointEventListener(fdn, line);
-        l.disable();
-        l.fser.setParentListener(null);
-        l.fser.disable();
+        if (l != null) {
+            l.disable();
+            if (l.fser != null) {
+                l.fser.setParentListener(null);
+                l.fser.disable();
+            }
+        }
     }
 
     private static FunctionStatementsEventListener ensureSingleStep(FunctionDefinitionNode fdn, LineBreakpointEventListener parentListener) {
@@ -286,7 +290,7 @@ public class DebugHandling {
         }
 
         protected void browserInteract(Node node, VirtualFrame frame) {
-            int exitMode = (int) browserInteractNode.execute(frame);
+            int exitMode = browserInteractNode.execute(frame, RArguments.getCall(frame));
             switch (exitMode) {
                 case BrowserInteractNode.NEXT:
                     break;
@@ -602,12 +606,16 @@ public class DebugHandling {
 
         @Override
         public void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
-            fser.enableChildren();
+            if (fser != null) {
+                fser.enableChildren();
+            }
         }
 
         @Override
         public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
-            fser.enableChildren();
+            if (fser != null) {
+                fser.enableChildren();
+            }
         }
 
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R
index c3ccdbf25e546383613bc73d2b2437cf16a421ee..690fa8cf1384a1e6349532f93838cf094cd5777f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R
@@ -26,7 +26,7 @@ setBreakpoint <- function (srcfile, line, nameonly = TRUE, envir = parent.frame(
 {
     res <- .fastr.setBreakpoint(srcfile, line, clear)
     if(is.null(res))
-    	res <- structure(result, class="findLineNumResult")
+    	res <- structure(list(), class="findLineNumResult")
     if (verbose) 
         print(res, steps = !clear)
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
index 3e3baf9305fc7532108f54053b3b2303fc7d52ef..9ee4692f3279091588feab1d1cbea31452ddb916 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
@@ -164,7 +164,7 @@ public class RSource {
      * Create an (external) source from the file system path {@code path}.
      */
     public static Source fromFileName(String path, boolean internal) throws IOException {
-        Source.Builder<IOException, RuntimeException, RuntimeException> builder = Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME);
+        Source.Builder<IOException, RuntimeException, RuntimeException> builder = Source.newBuilder(new File(path)).mimeType(RRuntime.R_APP_MIME);
         if (internal) {
             builder.internal();
         }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 855f7a4f5b1b688cad7304c617382f06ae0fed96..f619f3bbf734d21d66af179b62dd72a86cb43fe2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -147031,6 +147031,26 @@ x + x ~ y + log(y)
 #update.formula(x ~ y, ~ . + x2)
 x ~ y + x2
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#browser()<<<NEWLINE>>>where<<<NEWLINE>>>c<<<NEWLINE>>>
+Called from: top level
+
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#do.call('browser', list())<<<NEWLINE>>>c<<<NEWLINE>>>
+Called from: do.call("browser", list())
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#foo <- function() { stop('error msg') }; tryCatch(foo(), error=browser)<<<NEWLINE>>>print(msg)<<<NEWLINE>>>c<<<NEWLINE>>>
+Called from: tryCatchOne(expr, names, parentenv, handlers[[1L]])
+[1] "error msg"
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#options(error=browser); prod('a')<<<NEWLINE>>>where<<<NEWLINE>>>c<<<NEWLINE>>>
+Error in prod("a") : invalid 'type' (character) of argument
+Called from: top level
+
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testConditionalBreakpoint#
 #fun <- function(x) { cat('x='); cat(x); cat('\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)<<<NEWLINE>>>; fun(11)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
 [1] "fun"
@@ -147245,6 +147265,33 @@ debug at #1: cat(x)
 
 exiting from: fun(3)
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSetBreakpoint#Output.IgnoreDebugCallString#Output.IgnoreDebugPath#
+#source('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r'); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F); fun(10)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debug.r#4
+Called from: fun(10)
+debug: print("Hello")
+[1] "Hello"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: for (i in seq(3)) print(i)
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 1
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 2
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 3
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#6: bar("World")
+[1] "World"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#7: print(x)
+[1] 10
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSetBreakpoint#
+#source('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r'); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F, clear=T); fun(10)<<<NEWLINE>>>
+[1] "Hello"
+[1] 1
+[1] 2
+[1] 3
+[1] "World"
+[1] 10
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSimple#
 #f <- function(x) {<<<NEWLINE>>>  t <- x + 1<<<NEWLINE>>>  print(t)<<<NEWLINE>>>  t}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>t<<<NEWLINE>>>n<<<NEWLINE>>>n
 debugging in: f(5)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 7c5e2b8fd0c558ecd15f8bba64459cee3c8a4f2a..05eeefd99daa132306adc2489903c7daf1da93ed 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -12,8 +12,10 @@ package com.oracle.truffle.r.test;
 
 import static org.junit.Assert.fail;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
+import java.io.StringReader;
 import java.net.URL;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
@@ -29,6 +31,7 @@ import java.util.Map.Entry;
 import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -92,7 +95,8 @@ public class TestBase {
         IgnoreWhitespace, // removes all whitespace from the whole output
         IgnoreCase, // ignores upper/lower case differences
         IgnoreDebugPath, // ignores <path> in debug output like "debug at <path> #..."
-        IgnoreDebugDepth; // ignores call depth printed by the debugger ("Browse[<call depth>]")
+        IgnoreDebugDepth, // ignores call depth printed by the debugger ("Browse[<call depth>]")
+        IgnoreDebugCallString; // ignores the caller string like "debugging in:" or "Called from:"
 
         @Override
         public String getName() {
@@ -600,22 +604,26 @@ public class TestBase {
         }
 
         String preprocessOutput(String out) {
+            String s = out;
             if (output.contains(Output.IgnoreWhitespace)) {
-                return out.replaceAll("\\s+", "");
+                return s.replaceAll("\\s+", "");
             }
             if (output.contains(Output.IgnoreCase)) {
-                return out.toLowerCase();
+                return s.toLowerCase();
             }
             if (output.contains(Output.ContainsReferences)) {
-                return convertReferencesInOutput(out);
+                return convertReferencesInOutput(s);
             }
             if (output.contains(Output.IgnoreDebugPath)) {
-                return convertDebugOutput(out);
+                s = convertDebugOutput(s);
             }
             if (output.contains(Output.IgnoreDebugDepth)) {
-                return removeDebugCallDepth(out);
+                s = removeDebugCallDepth(s);
             }
-            return out;
+            if (output.contains(Output.IgnoreDebugCallString)) {
+                s = removeDebugCallString(s);
+            }
+            return s;
         }
     }
 
@@ -806,6 +814,10 @@ public class TestBase {
         return removeAllOccurrencesBetween(out, prefix, prefix.length(), "]", 0);
     }
 
+    private static String removeDebugCallString(String out) {
+        return removeLines(out, line -> line.startsWith("debugging in:") || line.startsWith("Called from:"));
+    }
+
     private static String removeAllOccurrencesBetween(String out, String prefix, int prefixOffset, String suffix, int suffixOffset) {
         StringBuilder sb = new StringBuilder(out);
 
@@ -819,6 +831,28 @@ public class TestBase {
         return sb.toString();
     }
 
+    /**
+     * Removes the lines from the test output string matching the provided predicate.
+     */
+    private static String removeLines(String out, Predicate<String> pred) {
+        StringBuilder sb = new StringBuilder();
+
+        BufferedReader r = new BufferedReader(new StringReader(out));
+        String line;
+        try {
+            while ((line = r.readLine()) != null) {
+                if (!pred.test(line)) {
+                    sb.append(line);
+                    sb.append(System.lineSeparator());
+                }
+            }
+        } catch (IOException e) {
+            // won't happen
+        }
+
+        return sb.toString();
+    }
+
     private boolean searchWhiteLists(WhiteList[] whiteLists, String input, String expected, String result, TestTraitsSet testTraits) {
         if (whiteLists == null) {
             return false;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index 0d5d1b076f0246c735de9e0f352deeefa0c75d38..c9b996f5905708159264f679708f2c0f5f829d62 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -22,6 +22,12 @@
  */
 package com.oracle.truffle.r.test.library.utils;
 
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
@@ -88,4 +94,28 @@ public class TestInteractiveDebug extends TestBase {
         assertEval("fun0 <- function() { print('fun0') }; fun1 <- function() { print('en'); fun0(); fun0(); print('ex') }; debugonce(fun0); fun1()\nc\n");
         assertEval("fun0 <- function() { print('fun0') }; debugonce(fun0); fun0()\nc\n");
     }
+
+    @Test
+    public void testBrowser() {
+        assertEval("foo <- function() { stop('error msg') }; tryCatch(foo(), error=browser)\nprint(msg)\nc\n");
+        assertEval("do.call('browser', list())\nc\n");
+        assertEval("browser()\nwhere\nc\n");
+        assertEval("options(error=browser); prod('a')\nwhere\nc\n");
+    }
+
+    private static Path debugFile;
+
+    @BeforeClass
+    public static void setup() throws IOException {
+        Path testDir = TestBase.createTestDir("com.oracle.truffle.r.test.library.utils.rsrc");
+        String content = "bar <- function(x) print(x)\n\nfun <- function(x) {\nprint('Hello')\nfor(i in seq(3)) print(i)\nbar('World')\nprint(x)\n}";
+        debugFile = testDir.resolve("debug.r");
+        Files.write(debugFile, content.getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+    }
+
+    @Test
+    public void testSetBreakpoint() {
+        assertEval(Output.IgnoreDebugCallString, Output.IgnoreDebugPath, String.format("source('%s'); setBreakpoint('%s', 4, verbose=F); fun(10)\n\n\n\n\n\n\n\n", debugFile, debugFile));
+        assertEval(String.format("source('%s'); setBreakpoint('%s', 4, verbose=F); setBreakpoint('%s', 4, verbose=F, clear=T); fun(10)\n", debugFile, debugFile, debugFile));
+    }
 }