diff --git a/apps/playground/src/App.tsx b/apps/playground/src/App.tsx index 1de85ed9..e0e74b71 100644 --- a/apps/playground/src/App.tsx +++ b/apps/playground/src/App.tsx @@ -8,6 +8,7 @@ import { onCleanup, } from 'solid-js'; import { createStore } from 'solid-js/store'; +import Alert from './components/Alert'; import Breadcrumbs from './components/Breadcrumbs'; import Menu from './components/Menu'; import MonacoEditor from './components/MonacoEditor'; @@ -180,16 +181,11 @@ function App() { ]); } - function onDeobfuscateError(error: unknown) { - console.error(error); - } - return ( -
@@ -251,6 +246,7 @@ function App() { />
+ ); } diff --git a/apps/playground/src/components/Alert.tsx b/apps/playground/src/components/Alert.tsx new file mode 100644 index 00000000..aad4f9e1 --- /dev/null +++ b/apps/playground/src/components/Alert.tsx @@ -0,0 +1,53 @@ +import { Show, createEffect, on } from 'solid-js'; +import { useDeobfuscateContext } from '../context/DeobfuscateContext'; + +export default function Alert() { + const { alert, setAlert } = useDeobfuscateContext(); + let divRef: HTMLDivElement | undefined; + + createEffect( + on(alert, () => { + divRef?.classList.add('translate-y-96', 'opacity-0'); + setTimeout(() => { + divRef?.classList.remove('translate-y-96', 'opacity-0'); + }, 0); + }), + ); + + return ( + + + + ); +} diff --git a/apps/playground/src/context/DeobfuscateContext.tsx b/apps/playground/src/context/DeobfuscateContext.tsx index c64b407b..806c742d 100644 --- a/apps/playground/src/context/DeobfuscateContext.tsx +++ b/apps/playground/src/context/DeobfuscateContext.tsx @@ -13,9 +13,16 @@ let worker = new WebcrackWorker(); const postMessage = (message: WorkerRequest) => worker.postMessage(message); +interface Props { + code: string | undefined; + options: Options; + onResult: (result: DeobfuscateResult) => void; +} + function useProviderValue(props: Props) { const [deobfuscating, setDeobfuscating] = createSignal(false); const [progress, setProgress] = createSignal(0); + const [alert, setAlert] = createSignal(null); function cancelDeobfuscate() { if (!deobfuscating()) return console.warn('Not deobfuscating...'); @@ -43,16 +50,18 @@ function useProviderValue(props: Props) { .then((result) => postMessage({ type: 'sandbox', result })) .catch((error) => { cancelDeobfuscate(); - props.onError(error); + setAlert(String(error)); + console.error(error); }); } else if (data.type === 'progress') { setProgress(data.value); } else if (data.type === 'result') { + setAlert(null); setDeobfuscating(false); props.onResult(data); } else if (data.type === 'error') { setDeobfuscating(false); - props.onError(data.error); + setAlert(data.error.toString()); } }; } @@ -62,18 +71,13 @@ function useProviderValue(props: Props) { cancelDeobfuscate, deobfuscate, progress, + alert, + setAlert, }; } const DeobfuscateContext = createContext>(); -interface Props { - code: string | undefined; - options: Options; - onResult: (result: DeobfuscateResult) => void; - onError: (error: unknown) => void; -} - export function DeobfuscateContextProvider(props: ParentProps) { const value = useProviderValue(props); return ( diff --git a/apps/playground/src/monaco/eval-selection.ts b/apps/playground/src/monaco/eval-selection.ts index ede4d8fc..c4889869 100644 --- a/apps/playground/src/monaco/eval-selection.ts +++ b/apps/playground/src/monaco/eval-selection.ts @@ -1,11 +1,14 @@ import generate from '@babel/generator'; import * as t from '@babel/types'; import * as monaco from 'monaco-editor'; +import { useDeobfuscateContext } from '../context/DeobfuscateContext'; import { evalCode } from '../sandbox'; export function registerEvalSelection( editor: monaco.editor.IStandaloneCodeEditor, ): monaco.IDisposable { + const { setAlert } = useDeobfuscateContext(); + const codeAction = monaco.languages.registerCodeActionProvider('javascript', { provideCodeActions(_model, range) { if (range.isEmpty()) return; @@ -94,15 +97,20 @@ export function registerEvalSelection( return `eval(${JSON.stringify(value)})`; }); const code = `[${expressions.join(',')}]`; - const values = (await evalCode(code)) as unknown[]; + try { + const values = (await evalCode(code)) as unknown[]; - const edits = ranges.map((range, index) => ({ - range, - text: mapper(values[index]), - })); + const edits = ranges.map((range, index) => ({ + range, + text: mapper(values[index]), + })); - editor.pushUndoStop(); - editor.executeEdits('evaluate-expression', edits); + editor.pushUndoStop(); + editor.executeEdits('evaluate-expression', edits); + setAlert(null); + } catch (error) { + setAlert(`${String(error)}, at ${ranges.join(', ')}`); + } } return { diff --git a/apps/playground/src/webcrack.worker.ts b/apps/playground/src/webcrack.worker.ts index 9e4cd4ba..74e04f5b 100644 --- a/apps/playground/src/webcrack.worker.ts +++ b/apps/playground/src/webcrack.worker.ts @@ -9,7 +9,7 @@ export type WorkerResponse = | { type: 'sandbox'; code: string } | ({ type: 'result' } & DeobfuscateResult) | { type: 'progress'; value: number } - | { type: 'error'; error: unknown }; + | { type: 'error'; error: Error }; export interface DeobfuscateResult { code: string; @@ -53,6 +53,6 @@ self.onmessage = async ({ data }: MessageEvent) => { postMessage({ type: 'result', code: result.code, files }); } catch (error) { - postMessage({ type: 'error', error }); + postMessage({ type: 'error', error: error as Error }); } };