Still, it works (no need to prefix the keys with this
). The main question is would it be possible to "hide" browser objects (window, document, location, ...). From the aspect of security, the script used in the function constructor will be visible only to the owner of the account. Hope this is safe.
As a side question, tried to use a few code editor libs: monaco-editor, react-simple-code-editor, @uiw/react-textarea-code-editor, @patternfly/react-code-editor... Haven't managed to run any of them (broken this, broken that in the next.js context). Please could you suggest any of them that works fine in the most recent version on NJS?
Update:
Based on @kelly's suggestion:
function evalContext(context: Record<string, unknown>) {
const injectContext = Object.keys(context).reduce(
(acc, key) => `${acc}${key}=context.${key};`,
'',
);
return Function(
'context',
'window',
'document',
'location',
'localStorage',
'navigation',
'fetch',
'frames',
'history',
`(function () {${injectContext}${script}}).call({})`,
)(context);
}
CodePudding user response:
I suppose you could just "override" the global names by adding parameters:
return Function(`context`, `window`, `globalThis`, `document`, ..., `${injectContext}${script}`)(context, undefined, undefined, undefined, ...);
Similar to this example:
function overridden(window) {
window.open("site");
}
overridden(undefined); // error will occur
Since not providing the parameter is basically the same as providing undefined
, you can omit the undefined
entirely:
return Function(`context`, `window`, `globalThis`, `document`, ..., `${injectContext}${script}`)(context);
Keep in mind that there are a lot of things in the global namespace.
Object.keys(window)
will give you an idea...