From d426848cab5c2a772168ce9141ef801e9bf94132 Mon Sep 17 00:00:00 2001 From: printfn Date: Thu, 2 May 2024 12:25:00 +0000 Subject: [PATCH] Fix wasm initialisation --- web/src/App.tsx | 120 ++++++++++++++++---------------------------- web/src/lib/wasm.ts | 32 ++++++++++++ 2 files changed, 76 insertions(+), 76 deletions(-) create mode 100644 web/src/lib/wasm.ts diff --git a/web/src/App.tsx b/web/src/App.tsx index e689d018..33f43075 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,20 +1,5 @@ -import { - evaluateFendWithTimeout, - evaluateFendWithVariablesJson, - default as initWasm, - initialiseWithHandlers, -} from 'fend-wasm'; -import { - type FormEvent, - type KeyboardEvent, - type ReactNode, - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from 'react'; -import { getExchangeRates } from './lib/exchange-rates'; +import { type FormEvent, type KeyboardEvent, type ReactNode, useCallback, useEffect, useRef, useState } from 'react'; +import { fend } from './lib/wasm'; const examples = ` > 5'10" to cm @@ -46,36 +31,22 @@ const exampleContent = (

); -async function load() { - try { - await initWasm(); - initialiseWithHandlers(await getExchangeRates()); - - const result = evaluateFendWithTimeout('1 + 2', 500); - if (result !== '3') { - alert('Failed to initialise WebAssembly'); - return; - } - } catch (e) { - console.error(e); - alert('Failed to initialise WebAssembly'); - return; - } -} -await load(); - export default function App({ widget = false }: { widget?: boolean }) { const [currentInput, setCurrentInput] = useState(''); const [output, setOutput] = useState(widget ? <> : exampleContent); const [history, setHistory] = useState([]); const [variables, setVariables] = useState(''); const [navigation, setNavigation] = useState(0); - const hint = useMemo(() => { - const result = JSON.parse(evaluateFendWithVariablesJson(currentInput, 100, variables)); - if (!result.ok) { - return ''; - } - return result.result; + const [hint, setHint] = useState(''); + useEffect(() => { + (async () => { + const result = await fend(currentInput, 100, variables); + if (!result.ok) { + setHint(''); + } else { + setHint(result.result); + } + })(); }, [currentInput, variables]); const inputText = useRef(null); const inputHint = useRef(null); @@ -93,37 +64,39 @@ export default function App({ widget = false }: { widget?: boolean }) { }, []); const evaluate = useCallback( (event: KeyboardEvent) => { - // allow multiple lines to be entered if shift, ctrl - // or meta is held, otherwise evaluate the expression - if (!(event.key === 'Enter' && !event.shiftKey && !event.ctrlKey && !event.metaKey)) { - return; - } - event.preventDefault(); - if (currentInput.trim() === 'clear') { + (async () => { + // allow multiple lines to be entered if shift, ctrl + // or meta is held, otherwise evaluate the expression + if (!(event.key === 'Enter' && !event.shiftKey && !event.ctrlKey && !event.metaKey)) { + return; + } + event.preventDefault(); + if (currentInput.trim() === 'clear') { + setCurrentInput(''); + setOutput(null); + return; + } + const request =

{`> ${currentInput}`}

; + if (currentInput.trim().length > 0) { + setHistory(h => [...h, currentInput]); + } + setNavigation(0); + const fendResult = await fend(currentInput, 500, variables); setCurrentInput(''); - setOutput(null); - return; - } - const request =

{`> ${currentInput}`}

; - if (currentInput.trim().length > 0) { - setHistory(h => [...h, currentInput]); - } - setNavigation(0); - const fendResult = JSON.parse(evaluateFendWithVariablesJson(currentInput, 500, variables)); - setCurrentInput(''); - console.log(fendResult); - const result =

{fendResult.ok ? fendResult.result : fendResult.message}

; - if (fendResult.ok && fendResult.variables.length > 0) { - setVariables(fendResult.variables); - } - setOutput(o => ( - <> - {o} - {request} - {result} - - )); - inputHint.current?.scrollIntoView(); + console.log(fendResult); + const result =

{fendResult.ok ? fendResult.result : fendResult.message}

; + if (fendResult.ok && fendResult.variables.length > 0) { + setVariables(fendResult.variables); + } + setOutput(o => ( + <> + {o} + {request} + {result} + + )); + inputHint.current?.scrollIntoView(); + })(); }, [currentInput, variables], ); @@ -147,11 +120,6 @@ export default function App({ widget = false }: { widget?: boolean }) { }, [currentInput, navigation, history], ); - useEffect(() => { - (async () => { - await load(); - })(); - }, []); useEffect(() => { document.addEventListener('click', focus); return () => { diff --git a/web/src/lib/wasm.ts b/web/src/lib/wasm.ts new file mode 100644 index 00000000..ab260f49 --- /dev/null +++ b/web/src/lib/wasm.ts @@ -0,0 +1,32 @@ +import { + evaluateFendWithTimeout, + evaluateFendWithVariablesJson, + default as initWasm, + initialiseWithHandlers, +} from 'fend-wasm'; +import { getExchangeRates } from './exchange-rates'; + +async function load() { + try { + const [, exchangeRates] = await Promise.all([initWasm(), getExchangeRates()]); + initialiseWithHandlers(exchangeRates); + + const result = evaluateFendWithTimeout('1 + 2', 500); + if (result !== '3') { + alert('Failed to initialise WebAssembly'); + return; + } + } catch (e) { + console.error(e); + alert('Failed to initialise WebAssembly'); + return; + } +} +await load(); + +type FendResult = { ok: true; result: string; variables: string } | { ok: false; message: string }; + +export async function fend(input: string, timeout: number, variables: string) { + const res: FendResult = JSON.parse(evaluateFendWithVariablesJson(input, timeout, variables)); + return res; +}