Skip to content

Commit

Permalink
Try evaling js code client-side both with and without parentheses (#332)
Browse files Browse the repository at this point in the history
* Try evaling jsHook verbatim. If that fails, try evaling in parentheses. Fixes #329

* throw existing error object rather than creating new ones

* tweak documentation of jsCode parameter

* if second try at eval is SyntaxError, then throw original error

* wrap eval strategy in a reusable function and leverage in evaluateStringMember

* update news; better comment; roxygenize
  • Loading branch information
cpsievert authored and jcheng5 committed Mar 13, 2019
1 parent 5db27ad commit c998fae
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 11 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Expand Up @@ -25,4 +25,4 @@ Suggests:
Enhances: shiny (>= 1.1)
URL: https://github.com/ramnathv/htmlwidgets
BugReports: https://github.com/ramnathv/htmlwidgets/issues
RoxygenNote: 6.0.1
RoxygenNote: 6.1.1
4 changes: 2 additions & 2 deletions R/htmlwidgets.R
Expand Up @@ -94,8 +94,8 @@ appendContent <- function(x, ...) {
#' multiple objects to pass to the function, use a named list.
#' @return The modified widget object
#'
#' @details The \code{jsCode} parameter must be a valid JavaScript expression
#' that returns a function.
#' @details The \code{jsCode} parameter must contain valid JavaScript code which
#' when evaluated returns a function.
#'
#' The function will be invoked with three arguments: the first is the widget's
#' main HTML element, and the second is the data to be rendered (the \code{x}
Expand Down
6 changes: 6 additions & 0 deletions inst/NEWS
@@ -1,3 +1,9 @@
htmlwidgets 1.4
-----------------------------------------------------------------------

* JavaScript statements can now be passed along to `onRender()` and `JS()` (#329).


htmlwidgets 1.3
-----------------------------------------------------------------------

Expand Down
29 changes: 27 additions & 2 deletions inst/www/htmlwidgets.js
Expand Up @@ -233,7 +233,7 @@
theseArgs = theseArgs.concat([task.data]);
task = task.code;
}
var taskFunc = eval("(" + task + ")");
var taskFunc = tryEval(task);
if (typeof(taskFunc) !== "function") {
throw new Error("Task must be a function! Source:\n" + task);
}
Expand All @@ -242,6 +242,31 @@
}
}

// Attempt eval() both with and without enclosing in parentheses.
// Note that enclosing coerces a function declaration into
// an expression that eval() can parse
// (otherwise, a SyntaxError is thrown)
function tryEval(code) {
var result = null;
try {
result = eval(code);
} catch(error) {
if (!error instanceof SyntaxError) {
throw error;
}
try {
result = eval("(" + code + ")");
} catch(e) {
if (e instanceof SyntaxError) {
throw error;
} else {
throw e;
}
}
}
return result;
}

function initSizing(el) {
var sizing = sizingPolicy(el);
if (!sizing)
Expand Down Expand Up @@ -732,7 +757,7 @@
if (o !== null && typeof o === "object" && part in o) {
if (i == (l - 1)) { // if we are at the end of the line then evalulate
if (typeof o[part] === "string")
o[part] = eval("(" + o[part] + ")");
o[part] = tryEval(o[part]);
} else { // otherwise continue to next embedded object
o = o[part];
}
Expand Down
4 changes: 2 additions & 2 deletions man/onRender.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/saveWidget.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions man/sizingPolicy.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c998fae

Please sign in to comment.