Clear all window vars (#2159)

* Clear all window vars

* Cleanups
This commit is contained in:
Jaco Greeff 2020-01-21 11:39:11 +01:00 committed by GitHub
parent 6b2731bf48
commit 73758de7ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4,6 +4,7 @@
import { ApiPromise } from '@polkadot/api';
import { KeyringInstance } from '@polkadot/keyring/types';
import { ApiProps } from '@polkadot/react-api/types';
import { AppProps as Props } from '@polkadot/react-components/types';
import { Log, LogType, Snippet } from './types';
@ -30,24 +31,49 @@ interface Injected {
error: (...args: any[]) => void;
log: (...args: any[]) => void;
};
global: null;
hashing: typeof hashing;
keyring: KeyringInstance | null;
localStorage: null;
location: null;
setIsRunning: (isRunning: boolean) => void;
types: typeof types;
util: typeof util;
window: null;
[name: string]: any;
}
const ALLOWED_GLOBALS = ['atob', 'btoa'];
const snippets: Snippet[] = JSON.parse(JSON.stringify(allSnippets));
let hasSnippetWrappers = false;
function setupInjected ({ api, isDevelopment }: ApiProps, setIsRunning: (isRunning: boolean) => void, hookConsole: (type: LogType, args: any[]) => void): Injected {
const nullObject = Object
.keys(window)
.filter((key): boolean => !key.includes('-') && !ALLOWED_GLOBALS.includes(key))
.reduce((result: Record<string, null>, key): Record<string, null> => {
result[key] = null;
return result;
}, { global: null, window: null });
return {
...nullObject,
api: api.clone(),
console: {
error: (...args: any[]): void => hookConsole('error', args),
log: (...args: any[]): void => hookConsole('log', args)
},
hashing,
keyring: isDevelopment
? uiKeyring.keyring
: null,
setIsRunning,
types,
util
};
}
// FIXME This... ladies & gentlemen, is a mess that should be untangled
function Playground ({ className }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api, isDevelopment } = useApi();
const apiProps = useApi();
const injectedRef = useRef<Injected | null>(null);
const [code, setCode] = useState('');
const [isCustomExample, setIsCustomExample] = useState(false);
@ -62,7 +88,7 @@ function Playground ({ className }: Props): React.ReactElement<Props> {
// add snippets if not already available (global)
if (!hasSnippetWrappers) {
snippets.forEach((snippet): void => {
snippet.code = `${makeWrapper(isDevelopment)}${snippet.code}`;
snippet.code = `${makeWrapper(apiProps.isDevelopment)}${snippet.code}`;
});
hasSnippetWrappers = true;
@ -103,24 +129,7 @@ function Playground ({ className }: Props): React.ReactElement<Props> {
setIsRunning(true);
_clearConsole();
injectedRef.current = {
api: api.clone(),
console: {
error: (...args: any[]): void => _hookConsole('error', args),
log: (...args: any[]): void => _hookConsole('log', args)
},
global: null,
hashing,
keyring: isDevelopment
? uiKeyring.keyring
: null,
location: null,
localStorage: null,
setIsRunning,
types,
util,
window: null
};
injectedRef.current = setupInjected(apiProps, setIsRunning, _hookConsole);
await injectedRef.current.api.isReady;
@ -128,7 +137,7 @@ function Playground ({ className }: Props): React.ReactElement<Props> {
// squash into a single line so exceptions (with line numbers) maps to the
// same line/origin as we have in the editor view
// TODO: Make the console.error here actually return the full stack
const exec = `(async ({${Object.keys(injectedRef.current).join(',')}}) => { try { ${code} \n } catch (error) { console.error(error); setIsRunning(false); } })(injected);`;
const exec = `(async ({${Object.keys(injectedRef.current).sort().join(',')}}) => { try { ${code} \n } catch (error) { console.error(error); setIsRunning(false); } })(injected);`;
// eslint-disable-next-line no-new-func
new Function('injected', exec).bind({}, injectedRef.current)();