Skip to content

Commit

Permalink
Deparse RCall when re-throwing R errors in JS
Browse files Browse the repository at this point in the history
  • Loading branch information
georgestagg committed Feb 22, 2024
1 parent 7089386 commit c037d0e
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
18 changes: 18 additions & 0 deletions src/webR/robj-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,24 @@ export class RCall extends RObject {
capture(options: EvalROptions = {}) {
return Module.webr.captureR(this, options);
}

deparse(): string {
const prot = { n: 0 };
try {
const call = Module._Rf_lang2(
new RSymbol('deparse1').ptr,
Module._Rf_lang2(new RSymbol('quote').ptr, this.ptr)
);
protectInc(call, prot);

const val = RCharacter.wrap(safeEval(call, objs.baseEnv));
protectInc(val, prot);

return val.toString();
} finally {
unprotect(prot.n);
}
}
}

export class RList extends RObject {
Expand Down
9 changes: 5 additions & 4 deletions src/webR/webr-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { EmPtr, Module } from './emscripten';
import { IN_NODE } from './compat';
import { replaceInObject, throwUnreachable } from './utils';
import { WebRPayloadRaw, WebRPayloadPtr, WebRPayloadWorker, isWebRPayloadPtr } from './payload';
import { RObject, isRObject, REnvironment, RList, getRWorkerClass } from './robj-worker';
import { RObject, isRObject, REnvironment, RList, RCall, getRWorkerClass } from './robj-worker';
import { RCharacter, RString, keep, destroy, purge, shelters } from './robj-worker';
import { RLogical, RInteger, RDouble, initPersistentObjects, objs } from './robj-worker';
import { RPtr, RType, RTypeMap, WebRData, WebRDataRaw } from './robj';
Expand Down Expand Up @@ -711,9 +711,10 @@ function captureR(expr: string | RObject, options: EvalROptions = {}): {
(out) => out.get('type').toString() === 'error'
);
if (error) {
throw new Error(
error.pluck('data', 'message')?.toString() || 'An error occurred evaluating R code.'
);
const call = error.pluck('data','call') as RCall;
const source = call && call.type() === 'call' ? call.deparse() : 'Unknown source';
const message = error.pluck('data', 'message')?.toString() || 'An error occurred evaluating R code.';
throw new Error(`Error in ${source}: ${message}`);
}
}

Expand Down

0 comments on commit c037d0e

Please sign in to comment.