Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Skaiir committed Mar 21, 2024
1 parent 2bdbc10 commit 3a2259f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 44 deletions.
12 changes: 12 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions packages/form-js-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
},
"dependencies": {
"@carbon/grid": "^11.11.0",
"@jetbrains/websandbox": "^1.0.10",
"big.js": "^6.2.1",
"classnames": "^2.3.1",
"didi": "^10.0.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,61 @@
import Sandbox from 'websandbox';
import { useCallback, useEffect, useState } from 'preact/hooks';
import { useExpressionEvaluation, useDeepCompareMemoize, usePrevious } from '../../hooks';
import { useExpressionEvaluation, useDeepCompareMemoize } from '../../hooks';
import { isObject } from 'min-dash';

const type = 'script';

export function JSFunctionField(props) {
const { field, onChange } = props;
const { jsFunction, functionParameters, onLoadOnly } = field;
const { jsFunction, functionParameters } = field;

const [ loadLatch, setLoadLatch ] = useState(false);
const [ sandbox, setSandbox ] = useState(null);

const paramsEval = useExpressionEvaluation(functionParameters);
const params = useDeepCompareMemoize(isObject(paramsEval) ? paramsEval : {});

const functionMemo = useCallback((params) => {

const cleanupCallbacks = [];

try {

setLoadLatch(true);
const func = new Function('data', 'setValue', 'onCleanup', jsFunction);
func(params, value => onChange({ field, value }), callback => cleanupCallbacks.push(callback));

} catch (error) {

// invalid expression definition, may happen during editing
if (error instanceof SyntaxError) {
return;
const rebuildSandbox = useCallback(() => {
const localApi = {
setValue: function(value) {
onChange({ field, value });
}

console.error('Error evaluating expression:', error);
onChange({ field, value: null });
}

return () => {
cleanupCallbacks.forEach(fn => fn());
};

}, [ jsFunction, field, onChange ]);

const previousFunctionMemo = usePrevious(functionMemo);
const previousParams = usePrevious(params);
const newSandbox = Sandbox.create(localApi, {
frameContainer: '.iframe__container',
frameClassName: 'simple__iframe'
});

useEffect(() => {
newSandbox.promise.then((sandboxInstance) => {
setSandbox(sandboxInstance);
sandboxInstance.run(`
Websandbox.connection.setLocalApi({
onInit: () => Websandbox.connection.remote.onInit(),
onData: (data) => Websandbox.connection.remote.onData(data),
});
// reset load latch
if (!onLoadOnly && loadLatch) {
setLoadLatch(false);
}
// Custom user code
${jsFunction}
`);

const functionChanged = previousFunctionMemo !== functionMemo;
const paramsChanged = previousParams !== params;
const alreadyLoaded = onLoadOnly && loadLatch;
sandboxInstance.connection.remote.onInit();
});
}, [ jsFunction, onChange, field ]);

const shouldExecute = functionChanged || paramsChanged && !alreadyLoaded;
useEffect(() => {
rebuildSandbox();
}, [ rebuildSandbox ]);

if (shouldExecute) {
return functionMemo(params);
useEffect(() => {
if (sandbox && sandbox.connection && sandbox.connection.remote.onData) {
sandbox.connection.remote.onData(params);
}

}, [ previousFunctionMemo, functionMemo, previousParams, params, loadLatch, onLoadOnly ]);
}, [ params, sandbox ]);

return null;
}

JSFunctionField.config = {
type,
type: 'script',
label: 'JS Function',
group: 'basic-input',
keyed: true,
Expand Down

0 comments on commit 3a2259f

Please sign in to comment.