jsaddle-wasm 0.1.0.0 → 0.1.1.0
raw patch · 3 files changed
+39/−20 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +10/−0
- jsaddle-wasm.cabal +1/−1
- src-wasm/Language/Javascript/JSaddle/Wasm/Internal.hs +28/−19
CHANGELOG.md view
@@ -1,5 +1,15 @@ # Revision history for jsaddle-wasm +## 0.1.1.0 -- 2025-05-01++ * Bug fix: make GHCJS helpers globally available.++ This bug manifested itself in error messages like+ ```+ TypeError: jsaddle_values.get(...) is undefined+ ```+ when calling certain JSaddle functions like `jsTypeOf` or `createFromArrayBuffer`.+ ## 0.1.0.0 -- 2025-03-06 * Add support for synchronous callbacks (when using `run`, but not `runWorker`) using the new synchronous Wasm JSFFI exports feature.
jsaddle-wasm.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: jsaddle-wasm-version: 0.1.0.0+version: 0.1.1.0 synopsis: Run JSaddle JSM with the GHC Wasm backend description: Run JSaddle @JSM@ with the GHC Wasm backend. category: Web, Javascript
src-wasm/Language/Javascript/JSaddle/Wasm/Internal.hs view
@@ -7,7 +7,7 @@ import Control.Concurrent.STM import Control.Exception (evaluate)-import Control.Monad ((<=<))+import Control.Monad ((<=<), (>=>)) import Data.Aeson qualified as A import Data.ByteString (ByteString) import Data.ByteString.Internal qualified as BI@@ -18,7 +18,7 @@ import GHC.Wasm.Prim qualified import Language.Javascript.JSaddle.Run (runJavaScript) import Language.Javascript.JSaddle.Run.Files qualified as JSaddle.Files-import Language.Javascript.JSaddle.Types (Batch, JSM)+import Language.Javascript.JSaddle.Types (Batch, JSM, Results) -- Note: It is also possible to implement this succinctly on top of 'runWorker' -- and 'jsaddleScript' (using MessageChannel), but then e.g.@@ -39,8 +39,7 @@ jsaddleRunner processResultCallback processResultSyncCallback = do s <- byteStringToJSString . BLC8.toStrict . BLC8.unlines $- [ JSaddle.Files.ghcjsHelpers,- JSaddle.Files.initState,+ [ JSaddle.Files.initState, "(async () => {", " while (true) {", " const batch = JSON.parse(await readBatch());",@@ -50,8 +49,16 @@ " }", "})();" ]- evaluate =<< js_eval s processResultCallback processResultSyncCallback readBatchCallback+ evaluate+ =<< js_eval_jsaddle+ s+ processResultCallback+ processResultSyncCallback+ readBatchCallback + -- The GHCJS helpers need to be available in the global scope.+ js_global_eval =<< byteStringToJSString (BLC8.toStrict JSaddle.Files.ghcjsHelpers)+ runHelper entryPoint sendOutgoingMessage jsaddleRunner runWorker :: JSM () -> JSVal -> IO ()@@ -74,18 +81,10 @@ runJavaScript sendBatch entryPoint let receiveBatch :: JSString -> IO ()- receiveBatch s = do- bs <- jsStringToByteString s- case A.eitherDecodeStrict bs of- Left e -> fail $ "jsaddle: received invalid JSON: " <> show e- Right r -> processResult r+ receiveBatch = decodeResults >=> processResult processBatchSync :: JSString -> IO JSString- processBatchSync s = do- bs <- jsStringToByteString s- case A.eitherDecodeStrict bs of- Left e -> fail $ "jsaddle: received invalid JSON: " <> show e- Right r -> byteStringToJSString . BLC8.toStrict . A.encode =<< processSyncResult r+ processBatchSync = decodeResults >=> processSyncResult >=> encodeBatch processResultCallback <- mkPullCallback receiveBatch processResultSyncCallback <- mkSyncCallback processBatchSync@@ -95,10 +94,18 @@ start where sendBatch :: Batch -> IO ()- sendBatch batch = do- encodedBatch <- byteStringToJSString $ BLC8.toStrict $ A.encode batch- sendOutgoingMessage encodedBatch+ sendBatch = encodeBatch >=> sendOutgoingMessage + encodeBatch :: Batch -> IO JSString+ encodeBatch = byteStringToJSString . BLC8.toStrict . A.encode++ decodeResults :: JSString -> IO Results+ decodeResults s = do+ bs <- jsStringToByteString s+ case A.eitherDecodeStrict bs of+ Left e -> fail $ "jsaddle: received invalid JSON: " <> show e+ Right r -> pure r+ -- Utilities: foreign import javascript "wrapper" mkPullCallback :: (JSString -> IO ()) -> IO JSVal@@ -107,8 +114,10 @@ foreign import javascript "wrapper" mkPushCallback :: IO JSString -> IO JSVal +foreign import javascript unsafe "eval.call(globalThis, $1)" js_global_eval :: JSString -> IO ()+ foreign import javascript safe "new Function('processResult','processResultSync','readBatch',`(()=>{${$1}})()`)($2, $3, $4)"- js_eval :: JSString -> JSVal -> JSVal -> JSVal -> IO ()+ js_eval_jsaddle :: JSString -> JSVal -> JSVal -> JSVal -> IO () -- Worker