From 6af2bd1a4bb5dacfa0862b9efdaf9dcc60e23e3f Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 20 Jan 2020 17:57:45 +0100 Subject: [PATCH 1/2] Clear all window vars --- packages/app-js/src/Playground.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/app-js/src/Playground.tsx b/packages/app-js/src/Playground.tsx index 7745715133f6..9434e48e8f86 100644 --- a/packages/app-js/src/Playground.tsx +++ b/packages/app-js/src/Playground.tsx @@ -30,15 +30,14 @@ 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; + global: null; window: null; + [name: string]: any; } const snippets: Snippet[] = JSON.parse(JSON.stringify(allSnippets)); @@ -109,26 +108,30 @@ function Playground ({ className }: Props): React.ReactElement { 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, + global: null, window: null }; + Object.keys(window).forEach((key): void => { + if (!key.includes('-') && !['atob', 'btoa', 'setImmediate', 'setTimeout'].includes(key) && injectedRef.current) { + injectedRef.current[key] = null; + } + }); + await injectedRef.current.api.isReady; try { // 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)(); From adade6286bbe059e06e605a679e848bd998a3ae0 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 21 Jan 2020 11:30:26 +0100 Subject: [PATCH 2/2] Cleanups --- packages/app-js/src/Playground.tsx | 58 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/packages/app-js/src/Playground.tsx b/packages/app-js/src/Playground.tsx index 9434e48e8f86..167b8cf0364e 100644 --- a/packages/app-js/src/Playground.tsx +++ b/packages/app-js/src/Playground.tsx @@ -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'; @@ -35,18 +36,44 @@ interface Injected { setIsRunning: (isRunning: boolean) => void; types: typeof types; util: typeof util; - global: null; - 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, key): Record => { + 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 { const { t } = useTranslation(); - const { api, isDevelopment } = useApi(); + const apiProps = useApi(); const injectedRef = useRef(null); const [code, setCode] = useState(''); const [isCustomExample, setIsCustomExample] = useState(false); @@ -61,7 +88,7 @@ function Playground ({ className }: Props): React.ReactElement { // 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; @@ -102,28 +129,7 @@ function Playground ({ className }: Props): React.ReactElement { setIsRunning(true); _clearConsole(); - injectedRef.current = { - 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, - global: null, - window: null - }; - - Object.keys(window).forEach((key): void => { - if (!key.includes('-') && !['atob', 'btoa', 'setImmediate', 'setTimeout'].includes(key) && injectedRef.current) { - injectedRef.current[key] = null; - } - }); + injectedRef.current = setupInjected(apiProps, setIsRunning, _hookConsole); await injectedRef.current.api.isReady;