The _js
operator can evaluate or create a JavaScript function. The JavaScript function can return any primitives or JSON data. Since operators are synchronous functions, the JavaScript function should be synchronous.
To make this as secure as possible, the JavaScript is evaluated inside a JavaScript WebAssembly VM. The JavaScript engine is QuickJS, a small and fast JavaScript implementation.
As a result, the following applies to the JavaScript function definitions:
- The
code
operator argument requires a function definition. - Function arguments can be used inside the function, and are passed via the
args
operator argument as a array. - A primitive or JSON result will be returned, so the function result must be JSON serializable.
- Only a limited subset of the browser JavaScript APIs are available, in particular the JavaScript inside the VM will not have network access.
- Dependencies and file imports are not supported.
- The function should be a pure function with no side effects. The function should be stateless, and should always return the same result if given the same input.
The JavaScript function can be passed to the
code
argument during build using the_ref.eval
method. See the examples below and the_ref
operator for more details.
Operator methods:
_js.evaluate
({
code: string,
args?: any[]
}): any
The _js.evaluate
method evaluates JavaScript, takes an array of args
as input for parameters, and returns the evaluated result.
A JavaScript function string must be provided to the code
argument.
Arguments
code
The JavaScript function as a string to evaluate.
args
An array of input arguments to pass to the JavaScript function in the order in which the function arguments are defined.
Examples
JavaScript evaluate a inline function:
_js.evaluate:
code: |
function makePrimes(to) {
return [...Array(to-1).keys()].map(i=>i+2).filter(n =>
[...Array(n-2).keys()].map(i=>i+2).reduce((acc,x)=> acc && n % x !== 0, true)
}
args:
- 50
Returns:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
JavaScript evaluate loaded from a JavaScript file:
Operator definition:
_js.evaluate:
code:
_ref:
eval: myMath/makePrimes.js
args:
- 50
JavaScript loaded from a file using the _ref.eval
operator method:
// myMath/makePrimes.js
function makePrimes(to) {
return [...Array(to-1).keys()].map(i=>i+2).filter(n =>
[...Array(n-2).keys()].map(i=>i+2).reduce((acc,x)=> acc && n % x !== 0, true)
}
module.exports = makePrimes;
Returns:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
_js.function
({
code: string,
}): any
The _js.function
method returns a JavaScript function. The JavaScript function definition is be provided as a string to the code
operator argument.
Arguments
code
The JavaScript function as a string to evaluate.
Examples
_js.function to create a label.formatter function for an EChart block:
id: chart
type: EChart
properties:
height: 600
option:
series:
- radius:
- '15%'
- '80%'
type: 'sunburst'
sort: null
emphasis:
focus: 'ancestor'
data:
- value: 8,
children:
- value: 4,
children:
- value: 2
- value: 1
- value: 1
- value: 0.5
- value: 2
- value: 4
children:
- children:
- value: 2
- value: 4
children:
- children:
- value: 2
- value: 3
children:
- children:
- value: 1
label:
color: '#000'
textBorderColor: '#fff'
textBorderWidth: 2
formatter:
_js.function:
code: |
function (param) {
var depth = param.treePathInfo.length;
if (depth === 2) {
return 'radial';
}
else if (depth === 3) {
return 'tangential';
}
else if (depth === 4) {
return '0';
}
}
levels:
- {}
- itemStyle:
color: '#CD4949'
label:
rotate: 'radial'
- itemStyle:
color: '#F47251'
label:
rotate: 'tangential'
- itemStyle:
color: '#FFC75F'
label:
rotate: 0
_js.function to create a label.formatter function for an EChart block loaded using the _ref.eval
operator:
The chart config:
id: chart
type: EChart
properties:
height: 600
option:
series:
- radius:
- '15%'
- '80%'
type: 'sunburst'
sort: null
emphasis:
focus: 'ancestor'
data:
- value: 8,
children:
- value: 4,
children:
- value: 2
- value: 1
- value: 1
- value: 0.5
- value: 2
- value: 4
children:
- children:
- value: 2
- value: 4
children:
- children:
- value: 2
- value: 3
children:
- children:
- value: 1
label:
color: '#000'
textBorderColor: '#fff'
textBorderWidth: 2
formatter:
_js.function:
code:
_ref:
eval: 'foo/fooFormatter.js'
levels:
- {}
- itemStyle:
color: '#CD4949'
label:
rotate: 'radial'
- itemStyle:
color: '#F47251'
label:
rotate: 'tangential'
- itemStyle:
color: '#FFC75F'
label:
rotate: 0
JavaScript loaded from a file using the _ref.eval
operator method:
// foo/fooFormatter.js
function fooFormatter(param) {
var depth = param.treePathInfo.length;
if (depth === 2) {
return 'radial';
}
else if (depth === 3) {
return 'tangential';
}
else if (depth === 4) {
return '0';
}
}
module.exports = fooFormatter;