mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-04-06 15:30:30 +08:00
Merge pull request #616 from lowdefy/fix-remove-js-wasm
Remove deprecated _js wasm
This commit is contained in:
commit
cd967c46b3
10
.pnp.cjs
generated
10
.pnp.cjs
generated
@ -4973,7 +4973,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["jest", "npm:26.6.3"],
|
||||
["js-yaml", "npm:4.1.0"],
|
||||
["mingo", "npm:4.1.2"],
|
||||
["quickjs-emscripten", "npm:0.11.0"],
|
||||
["uuid", "npm:8.3.2"]
|
||||
],
|
||||
"linkType": "SOFT",
|
||||
@ -22219,15 +22218,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["quickjs-emscripten", [
|
||||
["npm:0.11.0", {
|
||||
"packageLocation": "./.yarn/cache/quickjs-emscripten-npm-0.11.0-4f09eb00c3-a5cf45a1fd.zip/node_modules/quickjs-emscripten/",
|
||||
"packageDependencies": [
|
||||
["quickjs-emscripten", "npm:0.11.0"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["raf", [
|
||||
["npm:3.4.1", {
|
||||
"packageLocation": "./.yarn/cache/raf-npm-3.4.1-c25d48d76e-567b0160be.zip/node_modules/raf/",
|
||||
|
Binary file not shown.
@ -36,20 +36,6 @@ _ref:
|
||||
- A list of arguments can be passed to the JavaScript function which will be spread as function parameters.
|
||||
- The returned value of the custom JavaScript function will be the operator result.
|
||||
|
||||
-----------
|
||||
|
||||
> DEPRECATION WARNING: The QuickJS JavaScript operators are depreciated and will be removed in the next version. Instead native browser functions can now be loaded at build time by registering the operator function with `window.lowdefy.registerJsOperator(name: string, operatorFunction: function)`. See the [Custom Code](/custom-code) section for details.
|
||||
|
||||
For depreciated `evaluate`, and `function`, 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`](/_ref) operator for more details.
|
||||
|
||||
methods:
|
||||
- name: '{{ method_name }}'
|
||||
types: |
|
||||
@ -201,232 +187,3 @@ _ref:
|
||||
label:
|
||||
rotate: 0
|
||||
````
|
||||
|
||||
- name: evaluate [DEPRECATED]
|
||||
types: |
|
||||
```
|
||||
({
|
||||
code: string,
|
||||
args?: any[]
|
||||
}): any
|
||||
```
|
||||
description: |
|
||||
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:
|
||||
```yaml
|
||||
_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:
|
||||
```yaml
|
||||
_js.evaluate:
|
||||
code:
|
||||
_ref:
|
||||
eval: myMath/makePrimes.js
|
||||
args:
|
||||
- 50
|
||||
```
|
||||
JavaScript loaded from a file using the `_ref.eval` operator method:
|
||||
```js
|
||||
// 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]
|
||||
```
|
||||
- name: function [DEPRECATED]
|
||||
types: |
|
||||
```
|
||||
({
|
||||
code: string,
|
||||
}): any
|
||||
```
|
||||
description: |
|
||||
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:
|
||||
```yaml
|
||||
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:
|
||||
```yaml
|
||||
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:
|
||||
```js
|
||||
// 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;
|
||||
```
|
||||
|
@ -42,7 +42,6 @@
|
||||
"deep-diff": "1.0.2",
|
||||
"js-yaml": "4.1.0",
|
||||
"mingo": "4.1.2",
|
||||
"quickjs-emscripten": "0.11.0",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -16,126 +16,14 @@
|
||||
|
||||
import { type } from '@lowdefy/helpers';
|
||||
|
||||
// ! ---------------
|
||||
// ! DEPRECATED
|
||||
// ! ---------------
|
||||
import { serializer } from '@lowdefy/helpers';
|
||||
import { getQuickJS, shouldInterruptAfterDeadline } from 'quickjs-emscripten';
|
||||
let QuickJsVm;
|
||||
|
||||
function createFunction({ params, location, methodName }) {
|
||||
if (!params.code || !type.isString(params.code)) {
|
||||
throw new Error(
|
||||
`Operator Error: _js.${methodName} "code" argument should be a string at ${location}.`
|
||||
);
|
||||
}
|
||||
const fn = (...args) => {
|
||||
const jsFnString = `
|
||||
var logs = [];
|
||||
function log(...item) {
|
||||
logs.push(item);
|
||||
}
|
||||
var console = {
|
||||
log,
|
||||
};
|
||||
function dateReviver(key, value) {
|
||||
if (typeof value === 'object' && value !== null && value.hasOwnProperty('_date')) {
|
||||
var date = new Date(value._date);
|
||||
if (date instanceof Date && !Number.isNaN(date.getTime())) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function dateSerialize(key, value) {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
Object.keys(value).forEach((k) => {
|
||||
if (value[k] instanceof Date && !Number.isNaN(value[k].getTime())) {
|
||||
value[k] = { "_date": value[k].valueOf() };
|
||||
}
|
||||
})
|
||||
}
|
||||
return value;
|
||||
}
|
||||
var args = JSON.parse(decodeURIComponent("${encodeURIComponent(
|
||||
serializer.serializeToString(args)
|
||||
)}"), dateReviver);
|
||||
var fnResult = (${params.code})(...(args || []));
|
||||
var result = encodeURIComponent(JSON.stringify([fnResult, logs], dateSerialize));
|
||||
`;
|
||||
const codeHandle = QuickJsVm.unwrapResult(
|
||||
QuickJsVm.evalCode(jsFnString, {
|
||||
shouldInterrupt: shouldInterruptAfterDeadline(Date.now() + 1000),
|
||||
memoryLimitBytes: 1024 * 1024,
|
||||
})
|
||||
);
|
||||
const resultHandle = QuickJsVm.getProp(QuickJsVm.global, 'result');
|
||||
codeHandle.dispose();
|
||||
const result = serializer.deserializeFromString(
|
||||
decodeURIComponent(QuickJsVm.getString(resultHandle))
|
||||
);
|
||||
result[1].forEach((item) => {
|
||||
console.log(...item);
|
||||
});
|
||||
return result[0];
|
||||
};
|
||||
return fn;
|
||||
}
|
||||
|
||||
function evaluate({ params, location, methodName }) {
|
||||
if (!type.isArray(params.args) && !type.isNone(params.args)) {
|
||||
throw new Error(
|
||||
`Operator Error: _js.evaluate "args" argument should be an array, null or undefined at ${location}.`
|
||||
);
|
||||
}
|
||||
const fn = createFunction({ params, location, methodName });
|
||||
return fn(...(params.args || []));
|
||||
}
|
||||
|
||||
const methods = { evaluate, function: createFunction };
|
||||
|
||||
function _DEPRECATED_js({ params, location, methodName }) {
|
||||
if (!QuickJsVm) {
|
||||
throw new Error(
|
||||
`Operator Error: _js is not initialized. Received: ${JSON.stringify(params)} at ${location}.`
|
||||
);
|
||||
}
|
||||
|
||||
return methods[methodName]({ params, location, methodName });
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const QuickJs = await getQuickJS();
|
||||
QuickJsVm = QuickJs.createVm();
|
||||
}
|
||||
async function clear() {
|
||||
QuickJsVm = null;
|
||||
}
|
||||
|
||||
_js.init = init;
|
||||
_js.clear = clear;
|
||||
// ! ---------------
|
||||
|
||||
function _js({ context, params, location, methodName }) {
|
||||
// ! DEPRECATED methods
|
||||
if (!type.isFunction(context.lowdefy.imports.jsOperators[methodName]) && !methods[methodName]) {
|
||||
if (!type.isFunction(context.lowdefy.imports.jsOperators[methodName])) {
|
||||
throw new Error(`Operator Error: _js.${methodName} is not a function.`);
|
||||
}
|
||||
if (context.lowdefy.imports.jsOperators[methodName]) {
|
||||
if (!type.isNone(params) && !type.isArray(params)) {
|
||||
throw new Error(`Operator Error: _js.${methodName} takes an array as input at ${location}.`);
|
||||
}
|
||||
return context.lowdefy.imports.jsOperators[methodName](...(params || []));
|
||||
if (!type.isNone(params) && !type.isArray(params)) {
|
||||
throw new Error(`Operator Error: _js.${methodName} takes an array as input at ${location}.`);
|
||||
}
|
||||
// ! DEPRECATED ---------------
|
||||
console.warn(
|
||||
'WARNING: _js.evaluate and _js.function will has been deprecated and will be removed in the next version. Please see: https://docs.lowdefy.com/_js for more details.'
|
||||
);
|
||||
if (!type.isObject(params)) {
|
||||
throw new Error(`Operator Error: _js.${methodName} takes an object as input at ${location}.`);
|
||||
}
|
||||
return _DEPRECATED_js({ params, location, methodName });
|
||||
// ! ---------------
|
||||
return context.lowdefy.imports.jsOperators[methodName](...(params || []));
|
||||
}
|
||||
|
||||
export default _js;
|
||||
|
@ -499,19 +499,18 @@ describe('parse operators', () => {
|
||||
expect(errors).toEqual([]);
|
||||
});
|
||||
|
||||
test('parse _js operator', async () => {
|
||||
test.only('parse _js operator retuning a function', async () => {
|
||||
const test_fn = () => (a, b) => a + b;
|
||||
const mockFn = jest.fn().mockImplementation(test_fn);
|
||||
context.lowdefy.imports.jsOperators.test_fn = mockFn;
|
||||
const input = {
|
||||
'_js.function': {
|
||||
code: `function (a, b){
|
||||
return a + b;
|
||||
}`,
|
||||
},
|
||||
'_js.test_fn': [],
|
||||
};
|
||||
const parser = new WebParser({ context, contexts });
|
||||
await parser.init();
|
||||
const { output, errors } = parser.parse({ input, location: 'locationId' });
|
||||
expect(output).toBeInstanceOf(Function);
|
||||
expect(output(1, 2)).toEqual(3);
|
||||
expect(output(4, 2)).toEqual(6);
|
||||
expect(errors).toEqual([]);
|
||||
});
|
||||
|
||||
|
@ -18,9 +18,6 @@ import _js from '../../src/web/js';
|
||||
import { context } from '../testContext';
|
||||
|
||||
const location = 'location';
|
||||
beforeAll(async () => {
|
||||
await _js.init();
|
||||
});
|
||||
|
||||
test('_js.test_fn and params to return a value', () => {
|
||||
const params = [12, 14];
|
||||
@ -59,302 +56,12 @@ test('_js.test_fn params not an array', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// ! --------------
|
||||
// ! DEPRECATED
|
||||
// ! --------------
|
||||
test('_js with code and args specified', () => {
|
||||
const params = {
|
||||
code: `function (one, two) {
|
||||
return one + two;
|
||||
}`,
|
||||
args: [12, 14],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
expect(fn(1, 2)).toEqual(3);
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual(26);
|
||||
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
|
||||
null
|
||||
test('_js.not_a_function', () => {
|
||||
const params = 10;
|
||||
const test_fn = (a, b) => a + b;
|
||||
const mockFn = jest.fn().mockImplementation(test_fn);
|
||||
context.lowdefy.imports.jsOperators.test_fn = mockFn;
|
||||
expect(() => _js({ context, location, params, methodName: 'not_a_function' })).toThrow(
|
||||
new Error('Operator Error: _js.not_a_function is not a function.')
|
||||
);
|
||||
});
|
||||
|
||||
test('_js with code and args specified to return json object', () => {
|
||||
const params = {
|
||||
code: `function (one, two) {
|
||||
return { a: one, b: two, c: [1,2,3, one, two, "three"]};
|
||||
}`,
|
||||
args: [12, 14],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
expect(fn(1, 2)).toEqual({ a: 1, b: 2, c: [1, 2, 3, 1, 2, 'three'] });
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual({
|
||||
a: 12,
|
||||
b: 14,
|
||||
c: [1, 2, 3, 12, 14, 'three'],
|
||||
});
|
||||
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
|
||||
{
|
||||
c: [1, 2, 3, null, null, 'three'],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('_js with code and args specified to return json array', () => {
|
||||
const params = {
|
||||
code: `function (one, two) {
|
||||
return [1,2,3, one, two, "three"];
|
||||
}`,
|
||||
args: [12, 14],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
expect(fn(1, 2)).toEqual([1, 2, 3, 1, 2, 'three']);
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual([
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
12,
|
||||
14,
|
||||
'three',
|
||||
]);
|
||||
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
|
||||
[1, 2, 3, null, null, 'three']
|
||||
);
|
||||
});
|
||||
|
||||
test('_js with open "\'" in result', () => {
|
||||
const str = `<div style=\"test: one;\">one's result</div>`;
|
||||
const params = {
|
||||
code: `function chars(input) {
|
||||
return [{x: input, b: 1}];
|
||||
}`,
|
||||
args: [str],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
expect(fn(str)).toEqual([{ x: str, b: 1 }]);
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual([{ x: str, b: 1 }]);
|
||||
});
|
||||
|
||||
test('_js with date in input and result', () => {
|
||||
const params = {
|
||||
code: `function duration(from, to) {
|
||||
return {
|
||||
from,
|
||||
to,
|
||||
fromIsDate: from instanceof Date,
|
||||
toIsDate: from instanceof Date,
|
||||
duration: to - from,
|
||||
};
|
||||
}`,
|
||||
args: [new Date(0), new Date(10)],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual({
|
||||
from: new Date(0),
|
||||
to: new Date(10),
|
||||
duration: 10,
|
||||
fromIsDate: true,
|
||||
toIsDate: true,
|
||||
});
|
||||
expect(fn(new Date(0), new Date(10))).toEqual({
|
||||
from: new Date(0),
|
||||
to: new Date(10),
|
||||
duration: 10,
|
||||
fromIsDate: true,
|
||||
toIsDate: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('_js with undefined result returns null', () => {
|
||||
const params = {
|
||||
code: `function add(one, two) {
|
||||
return;
|
||||
}`,
|
||||
args: [12, 14],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
expect(fn()).toEqual(null);
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual(null);
|
||||
expect(_js({ context, location, params: { code: params.code }, methodName: 'evaluate' })).toEqual(
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
test('_js with console.log', () => {
|
||||
const logger = console.log;
|
||||
console.log = jest.fn();
|
||||
const params = {
|
||||
code: `function logTest(one, two) {
|
||||
console.log(one)
|
||||
console.log(two)
|
||||
console.log(one, two, null, 123, 'abc', true, false);
|
||||
return;
|
||||
}`,
|
||||
args: [12, new Date(1)],
|
||||
};
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
_js({ context, location, params, methodName: 'evaluate' });
|
||||
expect(console.log.mock.calls).toEqual([
|
||||
[12],
|
||||
[new Date(1)],
|
||||
[12, new Date(1), null, 123, 'abc', true, false],
|
||||
]);
|
||||
console.log = logger;
|
||||
});
|
||||
|
||||
test('_js with code with args that needs escaped characters', () => {
|
||||
const params = {
|
||||
code: `function (obj) {
|
||||
return "<div>" + obj.html + "</html>";
|
||||
}`,
|
||||
args: [
|
||||
{
|
||||
html: '<a href="https://lowdefy.com">Lowdefy Website</a>',
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(_js({ context, location, params, methodName: 'evaluate' })).toEqual(
|
||||
'<div><a href="https://lowdefy.com">Lowdefy Website</a></html>'
|
||||
);
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
expect(
|
||||
fn({
|
||||
html: '<a href="https://lowdefy.com">Lowdefy Website</a>',
|
||||
})
|
||||
).toEqual('<div><a href="https://lowdefy.com">Lowdefy Website</a></html>');
|
||||
});
|
||||
|
||||
test('_js with code and no "function" specified to throw', () => {
|
||||
const params = {
|
||||
code: `
|
||||
var value = "world";
|
||||
var result = 'a new ' + 'vm for Hello ' + value;
|
||||
`,
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(`"unexpected token in expression: 'var'"`);
|
||||
expect(() => {
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
fn();
|
||||
}).toThrowErrorMatchingInlineSnapshot(`"unexpected token in expression: 'var'"`);
|
||||
});
|
||||
|
||||
test('_js invalid js code', () => {
|
||||
const params = {
|
||||
code: 'Hello',
|
||||
};
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(`"'Hello' is not defined"`);
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(() => fn()).toThrowErrorMatchingInlineSnapshot(`"'Hello' is not defined"`);
|
||||
});
|
||||
|
||||
test('_js not a function', () => {
|
||||
const params = {
|
||||
code: '"Hello"',
|
||||
};
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(`"not a function"`);
|
||||
const fn = _js({ context, location, params, methodName: 'function' });
|
||||
expect(() => fn()).toThrowErrorMatchingInlineSnapshot(`"not a function"`);
|
||||
});
|
||||
|
||||
test('_js params not a object', () => {
|
||||
const params = [];
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'function' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.function takes an object as input at location."`
|
||||
);
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.evaluate takes an object as input at location."`
|
||||
);
|
||||
});
|
||||
|
||||
test('_js.invalid methodName', () => {
|
||||
const params = {
|
||||
code: `function () {
|
||||
return args[0] + args[1]
|
||||
}`,
|
||||
};
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'invalid' })
|
||||
).toThrowErrorMatchingInlineSnapshot(`"Operator Error: _js.invalid is not a function."`);
|
||||
});
|
||||
|
||||
test('_js invalid js code', () => {
|
||||
const params = {
|
||||
code: 1,
|
||||
};
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'function' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.function \\"code\\" argument should be a string at location."`
|
||||
);
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.evaluate \\"code\\" argument should be a string at location."`
|
||||
);
|
||||
});
|
||||
|
||||
test('_js no body or file', () => {
|
||||
const params = {};
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'function' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.function \\"code\\" argument should be a string at location."`
|
||||
);
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.evaluate \\"code\\" argument should be a string at location."`
|
||||
);
|
||||
});
|
||||
|
||||
test('_js.evaluate, args not an array', () => {
|
||||
const params = {
|
||||
args: 1,
|
||||
body: `function () {
|
||||
return args[0] + args[1]
|
||||
}`,
|
||||
};
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js.evaluate \\"args\\" argument should be an array, null or undefined at location."`
|
||||
);
|
||||
});
|
||||
|
||||
test('_js with undefined vm', () => {
|
||||
const params = {
|
||||
code: `{
|
||||
return args[0] + args[1]
|
||||
}`,
|
||||
};
|
||||
_js.clear();
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'function' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js is not initialized. Received: {\\"code\\":\\"{\\\\n return args[0] + args[1]\\\\n }\\"} at location."`
|
||||
);
|
||||
expect(() =>
|
||||
_js({ context, location, params, methodName: 'evaluate' })
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Operator Error: _js is not initialized. Received: {\\"code\\":\\"{\\\\n return args[0] + args[1]\\\\n }\\"} at location."`
|
||||
);
|
||||
});
|
||||
// ! --------------
|
||||
|
@ -3422,7 +3422,6 @@ __metadata:
|
||||
jest: 26.6.3
|
||||
js-yaml: 4.1.0
|
||||
mingo: 4.1.2
|
||||
quickjs-emscripten: 0.11.0
|
||||
uuid: 8.3.2
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
@ -16738,13 +16737,6 @@ fsevents@^1.2.7:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"quickjs-emscripten@npm:0.11.0":
|
||||
version: 0.11.0
|
||||
resolution: "quickjs-emscripten@npm:0.11.0"
|
||||
checksum: a5cf45a1fdf570decbfd7f224f8cd5b36d838a669232d27cdc9f6ec5c617af1301a36c2c1e3fc4228bed1b65a347256ea0cb62774a00f1ff4d1edd172f101952
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raf@npm:^3.4.0, raf@npm:^3.4.1":
|
||||
version: 3.4.1
|
||||
resolution: "raf@npm:3.4.1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user