Skip to content

Add the typeclass IsSendable #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Notable changes to this project are documented in this file. The format is based
## [Unreleased]

Breaking changes:
- The data argument of functions `postMessage` and `postMessage'` must be instance of a new typeclass `IsSendable`
- Refactored `Worker` to better match the spec
- Refactored `Credentials`' `Show` instance to be more `Show`-like; use `printCredentials` now

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"scripts": {
"clean": "rimraf output && rimraf .pulp-cache",
"build": "eslint src && pulp build -- --censor-lib --strict"
"build": "eslint src && spago build"
},
"devDependencies": {
"eslint": "^8.15.0",
Expand Down
1 change: 1 addition & 0 deletions spago.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
, "foreign"
, "functions"
, "maybe"
, "newtype"
, "prelude"
, "unsafe-coerce"
, "web-events"
Expand Down
6 changes: 3 additions & 3 deletions src/Web/Worker/DedicatedWorkerGlobalScope.purs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import Effect (Effect)
import Effect.Uncurried (EffectFn1, EffectFn2, mkEffectFn1, runEffectFn1, runEffectFn2)
import Web.Worker.GlobalScope (importScripts, location, navigator, onError, onLanguageChange, onOffline, onOnline, onRejectionHandled, onUnhandledRejection) as GlobalScope
import Web.Worker.MessageEvent (MessageEvent)
import Web.Worker.Types (Transferable)
import Web.Worker.Types (class IsSendable, Transferable)

foreign import name :: Effect String

-- | sends a message to the main thread that spawned it.
postMessage :: forall msg. msg -> Effect Unit
postMessage :: forall msg. IsSendable msg => msg -> Effect Unit
postMessage msg = postMessage' msg []

postMessage' :: forall msg. msg -> Array Transferable -> Effect Unit
postMessage' :: forall msg. IsSendable msg => msg -> Array Transferable -> Effect Unit
postMessage' msg tr = runEffectFn2 postMessageImpl msg tr

foreign import postMessageImpl :: forall msg. EffectFn2 msg (Array Transferable) Unit
Expand Down
6 changes: 3 additions & 3 deletions src/Web/Worker/MessagePort.purs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Prelude

import Effect (Effect)
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, mkEffectFn1, runEffectFn1, runEffectFn2, runEffectFn3)
import Web.Worker.Types (MessageEvent, MessagePort, Transferable)
import Web.Worker.Types (class IsSendable, MessageEvent, MessagePort, Transferable)
import Web.Worker.Types (MessagePort) as Types

onMessage :: (MessageEvent -> Effect Unit) -> MessagePort -> Effect Unit
Expand All @@ -27,10 +27,10 @@ foreign import onMessageErrorImpl :: EffectFn2 MessagePort (EffectFn1 MessageEve

foreign import postMessageImpl :: forall msg. EffectFn3 MessagePort msg (Array Transferable) Unit

postMessage :: forall msg. msg -> MessagePort -> Effect Unit
postMessage :: forall msg. IsSendable msg => msg -> MessagePort -> Effect Unit
postMessage msg port = postMessage' msg [] port

postMessage' :: forall msg. msg -> Array Transferable -> MessagePort -> Effect Unit
postMessage' :: forall msg. IsSendable msg => msg -> Array Transferable -> MessagePort -> Effect Unit
postMessage' msg data_ port = runEffectFn3 postMessageImpl port msg data_

close :: MessagePort -> Effect Unit
Expand Down
48 changes: 47 additions & 1 deletion src/Web/Worker/Types.purs
Original file line number Diff line number Diff line change
@@ -1,5 +1,51 @@
module Web.Worker.Types where
module Web.Worker.Types
( MessageEvent
, MessagePort
, Transferable
, SendWrapper
, class IsSendable
, wrap
, unwrap
, unsafeWrap
) where

import Prelude

import Prim.RowList (class RowToList, RowList)
import Prim.RowList as Row
import Data.Newtype (class Newtype)

foreign import data Transferable :: Type
foreign import data MessagePort :: Type
foreign import data MessageEvent :: Type

class IsSendable (a :: Type)

instance IsSendable Boolean
instance IsSendable Int
instance IsSendable Number
instance IsSendable Char
instance IsSendable String
instance IsSendable a => IsSendable (Array a)
instance (RowToList r rl, IsSendableRowList rl) => IsSendable (Record r)
instance IsSendable Unit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there an instance for Unit? Can you clarify?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this instance and the instance for Void comes from the library workerbees but I can remove them if you want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok. I think I missed that.

instance IsSendable Void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify why you added an instance for Void? I'm not sure that's correct, but I'm not sure about that either.

instance IsSendable (SendWrapper a)

class IsSendableRowList (rl :: RowList Type)

instance IsSendableRowList Row.Nil
instance (IsSendable a, IsSendableRowList rest) => IsSendableRowList (Row.Cons sym a rest)

newtype SendWrapper a = SendWrapper a

wrap :: forall a b. Newtype a b => IsSendable b => a -> SendWrapper a
wrap = SendWrapper

unwrap :: forall a. SendWrapper a -> a
unwrap (SendWrapper a) = a

-- | Use with care. If you send something that isn't actually Sendable, it
-- | will raise an exception.
unsafeWrap :: forall a. a -> SendWrapper a
unsafeWrap = SendWrapper
6 changes: 3 additions & 3 deletions src/Web/Worker/Worker.purs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import Web.Internal.FFI (unsafeReadProtoTagged)
import Web.Worker.MessageEvent (MessageEvent)
import Web.Worker.Options (WorkerOptions, Credentials(..), WorkerType(..), defaultWorkerOptions) as Options
import Web.Worker.Options (WorkerOptions, toJsOptions)
import Web.Worker.Types (Transferable)
import Web.Worker.Types (class IsSendable, Transferable)

foreign import data Worker :: Type

Expand All @@ -44,10 +44,10 @@ new url options = runEffectFn2 newImpl url (toJsOptions options)
foreign import postMessageImpl :: forall msg. EffectFn3 Worker msg (Array Transferable) Unit

-- | sends a message to the worker's inner scope.
postMessage :: forall msg. msg -> Worker -> Effect Unit
postMessage :: forall msg. IsSendable msg => msg -> Worker -> Effect Unit
postMessage msg worker = postMessage' msg [] worker

postMessage' :: forall msg. msg -> Array Transferable -> Worker -> Effect Unit
postMessage' :: forall msg. IsSendable msg => msg -> Array Transferable -> Worker -> Effect Unit
postMessage' msg tr worker = runEffectFn3 postMessageImpl worker msg tr

-- | immediately terminates the worker.
Expand Down