Skip to content

Commit

Permalink
Flush incomplete lines when capturing streams (#419)
Browse files Browse the repository at this point in the history
  • Loading branch information
georgestagg committed Apr 24, 2024
1 parent 00b83db commit d480931
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 0 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Expand Up @@ -12,6 +12,8 @@

* Fix installing packages via shim with `character.only = TRUE` (#413).

* WebR will now flush incomplete lines when capturing output streams with `Shelter.captureR()` (#412).

# webR 0.3.2

## New features
Expand Down
4 changes: 4 additions & 0 deletions packages/webr/R/eval.R
Expand Up @@ -117,6 +117,10 @@ eval_r <- function(expr,
res <- efun(expr)
}

# Ensure incomplete lines are flushed to output vector
if (isIncomplete(out$stdout)) cat(fill = TRUE, file = out$stdout)
if (isIncomplete(out$stderr)) cat(fill = TRUE, file = out$stderr)

# Output vector out$vec expands exponentially, return only the valid subset
list(result = res, output = utils::head(out$vec, out$n))
}
Expand Down
4 changes: 4 additions & 0 deletions packages/webr/src/outputconnection.c
Expand Up @@ -56,6 +56,7 @@ void init_output_connection(Rconnection con, SEXP out) {
con->close = &output_close;
con->vfprintf = &output_vfprintf;
con->destroy = &output_destroy;
con->incomplete = FALSE;
con->canread = FALSE;
con->canwrite = TRUE;
con->isopen = TRUE;
Expand Down Expand Up @@ -129,6 +130,9 @@ int output_vfprintf(Rconnection con, const char *format, va_list ap) {
// If we're not in the middle of a line, reset to start of buffer
if (data->line == data->cur) {
data->cur = data->line = data->buf;
con->incomplete = FALSE;
} else {
con->incomplete = TRUE;
}
return res;
}
14 changes: 14 additions & 0 deletions src/tests/webR/webr-main.test.ts
Expand Up @@ -145,6 +145,20 @@ describe('Evaluate R code', () => {
void shelter.purge();
});

test('Capture incomplete lines of output while capturing R code', async () => {
const shelter = await new webR.Shelter();
const incomplete = await shelter.captureR(`
cat("foo")
cat("bar", file = stderr())
`, {
withAutoprint: true,
captureStreams: true,
});
expect(incomplete.output[0]).toEqual({ type: 'stdout', data: 'foo' });
expect(incomplete.output[1]).toEqual({ type: 'stderr', data: 'bar' });
void shelter.purge();
});

test('Capture conditions while capturing R code', async () => {
const shelter = await new webR.Shelter();
const res = await shelter.captureR('warning("This is a warning message")', {
Expand Down

0 comments on commit d480931

Please sign in to comment.