webdriver-precore-0.2.0.0: src/WebDriverPreCore/BiDi/Script.hs
module WebDriverPreCore.BiDi.Script
( -- * ScriptCommand
AddPreloadScript (..),
ContextTarget (..),
RemoteValue (..),
PrimitiveProtocolValue (..),
SpecialNumber (..),
WindowProxyProperties (..),
CallFunction (..),
LocalValue (..),
ListLocalValue (..),
ArrayLocalValue (..),
DateLocalValue (..),
MappingLocalValue (..),
MapLocalValue (..),
ObjectLocalValue (..),
IncludeShadowTree (..),
RegExpValue (..),
RegExpLocalValue (..),
SetLocalValue (..),
ResultOwnership (..),
SerializationOptions (..),
RealmType (..),
Disown (..),
Target (..),
Realm (..),
RealmDestroyed (..),
Sandbox (..),
Evaluate (..),
GetRealms (..),
RemovePreloadScript (..),
-- * ScriptResult
AddPreloadScriptResult (..),
GetRealmsResult (..),
RealmInfo (..),
BaseRealmInfo (..),
EvaluateResult (..),
ExceptionDetails (..),
StackTrace (..),
StackFrame (..),
ScriptEvent (..),
Message (..),
Channel (..),
Source (..),
ChannelValue (..),
ChannelProperties (..),
-- * PreloadScript
PreloadScript (..),
RemoteReference (..),
SharedReference (..),
RemoteObjectReference (..),
)
where
import Control.Applicative ((<|>))
import Data.Aeson (FromJSON (..), ToJSON (..), Value (..), defaultOptions, genericToJSON, object, withObject, (.:), (.:?), (.=))
import Data.Aeson.Types (Parser, omitNothingFields)
import Data.Map.Strict qualified as Map
import Data.Maybe (catMaybes)
import Data.Text (Text, unpack)
import Data.Vector qualified as V
import GHC.Generics
import WebDriverPreCore.BiDi.CoreTypes (BrowsingContext, Handle, InternalId (..), JSUInt, NodeRemoteValue (..), SharedId, StringValue (..), UserContext)
import AesonUtils (jsonToText, opt, parseJSONOmitNothing, toJSONOmitNothing)
-- ######### REMOTE #########
-- AddPreloadScript command
data AddPreloadScript = MkAddPreloadScript
{ functionDeclaration :: Text,
arguments :: Maybe [ChannelValue],
contexts :: Maybe [BrowsingContext],
userContexts :: Maybe [UserContext],
sandbox :: Maybe Text
}
deriving (Show, Eq, Generic)
-- Remote Value types
data RemoteValue
= PrimitiveValue PrimitiveProtocolValue
| SymbolValue
{ -- "symbol"
handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| ArrayValue
{ -- "array"
handle :: Maybe Handle,
internalId :: Maybe InternalId,
value :: Maybe [RemoteValue]
}
| ObjectValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
-- change to value from / to JSON
values :: Maybe [(Either RemoteValue Text, RemoteValue)]
}
| FunctionValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| RegExpValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
pattern' :: Text,
flags :: Maybe Text
}
| DateValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
dateValue :: Text
}
| MapValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
values :: Maybe [(Either RemoteValue Text, RemoteValue)]
}
| SetValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
value :: Maybe [RemoteValue]
}
| WeakMapValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| WeakSetValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| GeneratorValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| ErrorValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| ProxyValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| PromiseValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| TypedArrayValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| ArrayBufferValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId
}
| NodeListValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
value :: Maybe [RemoteValue]
}
| HTMLCollectionValue
{ handle :: Maybe Handle,
internalId :: Maybe InternalId,
value :: Maybe [RemoteValue]
}
| NodeValue NodeRemoteValue
| WindowProxyValue
{ -- "window"
winProxyValue :: WindowProxyProperties,
handle :: Maybe Handle, -- Optional handle
internalId :: Maybe InternalId -- Optional internal ID
}
deriving (Show, Eq, Generic)
instance FromJSON RemoteValue where
parseJSON :: Value -> Parser RemoteValue
parseJSON = withObject "RemoteValue" $ \obj -> do
typ <- obj .: "type"
handle <- obj .:? "handle"
internalId <- obj .:? "internalId"
case typ of
"undefined" -> pure $ PrimitiveValue UndefinedValue
"null" -> pure $ PrimitiveValue NullValue
"string" -> PrimitiveValue . StringValue . MkStringValue <$> obj .: "value"
"number" ->
PrimitiveValue . NumberValue <$> do
v <- obj .: "value"
case v of
Number n -> pure $ Left (realToFrac n)
String s -> case s of
"NaN" -> pure $ Right NaN
"-0" -> pure $ Right NegativeZero
"Infinity" -> pure $ Right Infinity
"-Infinity" -> pure $ Right NegativeInfinity
_ -> fail $ "Unknown SpecialNumber string: " <> unpack s
_ -> fail $ "Expected number or special number string, got: " <> show v
"boolean" -> PrimitiveValue . BooleanValue <$> obj .: "value"
"bigint" -> PrimitiveValue . BigIntValue <$> obj .: "value"
"node" -> NodeValue <$> parseJSON (Object obj)
"array" -> do
value <- obj .:? "value"
pure $ ArrayValue {..}
"object" -> do
values <- obj .:? "values"
pure $ ObjectValue {..}
"regexp" -> do
value <- obj .: "value"
pattern' <- value .: "pattern"
flags <- value .:? "flags"
pure $ RegExpValue {..}
"date" -> do
dateValue <- obj .: "value"
pure $ DateValue {..}
"map" -> do
maybeValues <- obj .:? "value"
values <- traverse (mapM parseMapEntry) maybeValues
pure $ MapValue {..}
where
parseMapEntry :: Value -> Parser (Either RemoteValue Text, RemoteValue)
parseMapEntry val = case val of
Array arr -> case V.toList arr of
[keyVal, valueVal] -> do
-- try parse Text first, then RemoteValue
key <- (Right <$> parseJSON keyVal) <|> (Left <$> parseJSON keyVal)
value <- parseJSON valueVal
pure (key, value)
_ -> fail "Map entry must be an array with exactly 2 elements"
_ -> fail "Map entry must be an array"
"set" -> do
value <- obj .:? "value"
pure $ SetValue {..}
"window" -> do
winProxyValue <- obj .: "value"
pure $ WindowProxyValue {..}
"nodelist" -> do
value <- obj .:? "value"
pure $ NodeListValue {..}
"htmlcollection" -> do
value <- obj .:? "value"
pure $ HTMLCollectionValue {..}
"function" -> pure $ FunctionValue {..}
"symbol" -> pure $ SymbolValue {..}
"weakmap" -> pure $ WeakMapValue {..}
"weakset" -> pure $ WeakSetValue {..}
"generator" -> pure $ GeneratorValue {..}
"error" -> pure $ ErrorValue {..}
"proxy" -> pure $ ProxyValue {..}
"promise" -> pure $ PromiseValue {..}
"typedarray" -> pure $ TypedArrayValue {..}
"arraybuffer" -> pure $ ArrayBufferValue {..}
_ -> fail $ "Unknown RemoteValue type: " <> show typ <> "\n" <> (unpack $ jsonToText $ Object obj)
-- | WindowProxy remote value representation
data PrimitiveProtocolValue
= UndefinedValue
| NullValue
| StringValue StringValue
| NumberValue (Either Double SpecialNumber)
| BooleanValue Bool
| BigIntValue Text
deriving (Show, Eq, Generic)
data SpecialNumber
= NaN
| NegativeZero
| Infinity
| NegativeInfinity
deriving (Show, Eq, Generic)
instance FromJSON SpecialNumber
instance ToJSON SpecialNumber where
toJSON :: SpecialNumber -> Value
toJSON = \case
NaN -> "NaN"
NegativeZero -> "-0"
Infinity -> "Infinity"
NegativeInfinity -> "-Infinity"
-- | Properties of a WindowProxy remote value
newtype WindowProxyProperties = MkWindowProxyProperties
{ context :: BrowsingContext
}
deriving (Show, Eq, Generic)
instance FromJSON WindowProxyProperties
instance ToJSON WindowProxyProperties
-- CallFunction command
data CallFunction = MkCallFunction
{ functionDeclaration :: Text,
awaitPromise :: Bool,
target :: Target,
arguments :: Maybe [LocalValue],
resultOwnership :: Maybe ResultOwnership,
serializationOptions :: Maybe SerializationOptions,
this :: Maybe LocalValue
}
deriving (Show, Eq, Generic)
-- \| Local value representation
data LocalValue
= RemoteReference RemoteReference
| PrimitiveLocalValue PrimitiveProtocolValue
| ChannelValue ChannelValue
| ArrayLocalValue ArrayLocalValue
| DateLocalValue DateLocalValue
| MapLocalValue MapLocalValue
| ObjectLocalValue ObjectLocalValue
| RegExpLocalValue RegExpLocalValue
| SetLocalValue SetLocalValue
deriving (Show, Eq, Generic)
data RemoteReference = MkRemoteReference
{ sharedreference :: SharedReference,
remoteObjectReference :: RemoteObjectReference
}
deriving (Show, Eq, Generic)
data SharedReference = MkSharedReference
{ sharedId :: SharedId,
handle :: Maybe Handle,
extensions :: Maybe (Map.Map Text Value) -- "extensions" field is optional
}
deriving (Show, Eq, Generic)
instance FromJSON SharedReference where
parseJSON :: Value -> Parser SharedReference
parseJSON = parseJSONOmitNothing
data RemoteObjectReference = MkRemoteObjectReference
{ handle :: Handle,
shartedId :: Maybe SharedId,
extensions :: Maybe (Map.Map Text Value) -- "extensions" field is optional
}
deriving (Show, Eq, Generic)
-- | List of local values
newtype ListLocalValue = MkListLocalValue [LocalValue]
deriving (Show, Eq, Generic)
-- | Array local value
data ArrayLocalValue = MkArrayLocalValue
{ typ :: Text, -- "array"
value :: ListLocalValue
}
deriving (Show, Eq, Generic)
-- | Date local value
newtype DateLocalValue = MkDateLocalValue
{ value :: Text
}
deriving (Show, Eq, Generic)
-- | Mapping of local values
newtype MappingLocalValue = MkMappingLocalValue [(Either LocalValue Text, LocalValue)]
deriving (Show, Eq, Generic)
-- | Map local value
data MapLocalValue = MkMapLocalValue
{ value :: MappingLocalValue
}
deriving (Show, Eq, Generic)
-- | Object local value
data ObjectLocalValue = MkObjectLocalValue
{ value :: MappingLocalValue
}
deriving (Show, Eq, Generic)
-- | RegExp value
data RegExpValue = MkRegExpValue
{ regExpPattern :: Text,
flags :: Maybe Text
}
deriving (Show, Eq, Generic)
-- | RegExp local value
data RegExpLocalValue = MkRegExpLocalValue
{ value :: RegExpValue
}
deriving (Show, Eq, Generic)
-- | Set local value
data SetLocalValue = MkSetLocalValue
{ typ :: Text, -- "set"
value :: ListLocalValue
}
deriving (Show, Eq, Generic)
-- OwnershipNone ~ None - renamed to avoid clash with BrowsingContext None
data ResultOwnership = Root | OwnershipNone deriving (Show, Eq, Generic)
instance FromJSON ResultOwnership where
parseJSON :: Value -> Parser ResultOwnership
parseJSON = withObject "ResultOwnership" $ \obj -> do
typ <- obj .: "type"
case typ of
"root" -> pure Root
"none" -> pure OwnershipNone
_ -> fail $ "Unknown ResultOwnership type: " <> unpack typ
instance ToJSON ResultOwnership where
toJSON :: ResultOwnership -> Value
toJSON = \case
Root -> "root"
OwnershipNone -> "none"
-- | RealmType represents the different types of Realm
data RealmType
= WindowRealm
| DedicatedWorkerRealm
| SharedWorkerRealm
| ServiceWorkerRealm
| WorkerRealm
| PaintWorkletRealm
| AudioWorkletRealm
| WorkletRealm
deriving (Show, Eq, Generic)
instance FromJSON RealmType
instance ToJSON RealmType where
toJSON :: RealmType -> Value
toJSON = \case
WindowRealm -> "window"
DedicatedWorkerRealm -> "dedicated-worker"
SharedWorkerRealm -> "shared-worker"
ServiceWorkerRealm -> "service-worker"
WorkerRealm -> "worker"
PaintWorkletRealm -> "paint-worklet"
AudioWorkletRealm -> "audio-worklet"
WorkletRealm -> "worklet"
data SerializationOptions = MkSerializationOptions
{ maxDomDepth :: Maybe (Maybe JSUInt), -- .default 0
maxObjectDepth :: Maybe (Maybe JSUInt), -- .default null
includeShadowTree :: Maybe IncludeShadowTree -- "none", "open", "all" .default "none"
}
deriving (Show, Eq, Generic)
instance ToJSON SerializationOptions where
toJSON :: SerializationOptions -> Value
toJSON = genericToJSON defaultOptions {omitNothingFields = True}
data IncludeShadowTree = ShadowTreeNone | Open | All deriving (Show, Eq, Generic)
instance ToJSON IncludeShadowTree where
toJSON :: IncludeShadowTree -> Value
toJSON = \case
ShadowTreeNone -> "none" -- name changed to avoid clash with BrowsingContext None
Open -> "open"
All -> "all"
-- Disown command
data Disown = MkDisown
{ handles :: [Handle],
target :: Target
}
deriving (Show, Eq, Generic)
data Target
= RealmTarget Realm
| ContextTarget ContextTarget
deriving (Show, Eq, Generic)
newtype Realm = MkRealm {realm :: Text} deriving (Show, Eq, Generic, FromJSON)
data ContextTarget = MkContextTarget
{ context :: BrowsingContext,
sandbox :: Maybe Sandbox
}
deriving (Show, Eq, Generic)
instance FromJSON ContextTarget
instance ToJSON ContextTarget where
toJSON :: ContextTarget -> Value
toJSON = genericToJSON defaultOptions {omitNothingFields = True}
newtype Sandbox = MkSandbox Text
deriving (Show, Eq)
deriving newtype (ToJSON, FromJSON)
instance ToJSON Realm
-- Simple sum types
instance ToJSON Target where
toJSON :: Target -> Value
toJSON = \case
RealmTarget r -> toJSON r
ContextTarget ct -> toJSON ct
-- Evaluate command
data Evaluate = MkEvaluate
{ expression :: Text,
target :: Target,
awaitPromise :: Bool,
resultOwnership :: Maybe ResultOwnership,
serializationOptions :: Maybe SerializationOptions
}
deriving (Show, Eq, Generic)
instance ToJSON Evaluate where
toJSON :: Evaluate -> Value
toJSON = genericToJSON defaultOptions {omitNothingFields = True}
-- GetRealms command
data GetRealms = MkGetRealms
{ context :: Maybe BrowsingContext,
realmType :: Maybe RealmType
}
deriving (Show, Eq, Generic)
-- RemovePreloadScript command
newtype RemovePreloadScript = MkRemovePreloadScript
{ script :: PreloadScript
}
deriving (Show, Eq, Generic)
newtype PreloadScript = MkPreloadScript Text deriving (Show, Generic, Eq)
instance FromJSON PreloadScript
instance ToJSON PreloadScript
-- Target specification
-- ######### Local #########
newtype AddPreloadScriptResult = MkAddPreloadScriptResult
{ script :: PreloadScript
}
deriving (Show, Eq, Generic)
newtype GetRealmsResult = MkGetRealmsResult
{ realms :: [RealmInfo]
}
deriving (Show, Eq, Generic)
data RealmInfo
= WindowRealmInfo
{ base :: BaseRealmInfo,
context :: BrowsingContext,
sandbox :: Maybe Text
}
| DedicatedWorker {base :: BaseRealmInfo, owners :: [Realm]}
| SharedWorker {base :: BaseRealmInfo}
| ServiceWorker {base :: BaseRealmInfo}
| Worker {base :: BaseRealmInfo}
| PaintWorklet {base :: BaseRealmInfo}
| AudioWorklet {base :: BaseRealmInfo}
| Worklet {base :: BaseRealmInfo}
deriving (Show, Eq, Generic)
instance FromJSON RealmInfo where
parseJSON :: Value -> Parser RealmInfo
parseJSON = withObject "RealmInfo" $ \o -> do
typ <- o .: "type"
base <- BaseRealmInfo <$> o .: "realm" <*> o .: "origin"
case typ of
"window" -> do
context <- o .: "context"
sandbox <- o .:? "sandbox"
pure $ WindowRealmInfo {base, context, sandbox}
"dedicated-worker" -> do
owners <- o .: "owners"
pure $ DedicatedWorker {base, owners}
"shared-worker" -> pure $ SharedWorker {base}
"service-worker" -> pure $ ServiceWorker {base}
"worker" -> pure $ Worker {base}
"paint-worklet" -> pure $ PaintWorklet {base}
"audio-worklet" -> pure $ AudioWorklet {base}
"worklet" -> pure $ Worklet {base}
_ -> fail $ "Unknown RealmInfo type: " <> unpack typ
data BaseRealmInfo = BaseRealmInfo
{ realm :: Realm,
origin :: Text
}
deriving (Show, Eq, Generic)
data EvaluateResult
= EvaluateResultSuccess
{ result :: RemoteValue,
realm :: Realm
}
| EvaluateResultException
{ exceptionDetails :: ExceptionDetails,
realm :: Realm
}
deriving (Show, Eq, Generic)
instance FromJSON EvaluateResult where
parseJSON :: Value -> Parser EvaluateResult
parseJSON = withObject "EvaluateResult" $ \o -> do
typ <- o .: "type"
case typ of
"success" -> do
result <- o .: "result"
realm <- o .: "realm"
pure $ EvaluateResultSuccess {result, realm}
"exception" -> do
exceptionDetails <- o .: "exceptionDetails"
realm <- o .: "realm"
pure $ EvaluateResultException {exceptionDetails, realm}
_ -> fail $ "Unknown EvaluateResult type: " <> unpack typ
data ExceptionDetails = MkExceptionDetails
{ columnNumber :: JSUInt,
exception :: RemoteValue,
lineNumber :: JSUInt,
stackTrace :: StackTrace,
text :: Text
}
deriving (Show, Eq, Generic)
data StackTrace = MkStackTrace
{ callFrames :: [StackFrame]
}
deriving (Show, Eq, Generic)
data StackFrame = StackFrame
{ columnNumber :: JSUInt,
functionName :: Text,
lineNumber :: JSUInt,
url :: Text
}
deriving (Show, Eq, Generic)
-- ScriptEvent types
data ScriptEvent
= MessageEvent Message
| RealmCreatedEvent RealmInfo
| RealmDestroyed RealmDestroyed
deriving (Show, Eq, Generic)
instance FromJSON ScriptEvent where
parseJSON :: Value -> Parser ScriptEvent
parseJSON = withObject "ScriptEvent" $ \o -> do
typ <- o .: "method"
case typ of
"script.message" -> do
params <- o .: "params"
pure $ MessageEvent params
"script.realmCreated" -> do
params <- o .: "params"
realmInfo <- parseJSON params
pure $ RealmCreatedEvent realmInfo
"script.realmDestroyed" -> do
params <- o .: "params"
realmid <- params .: "realm"
pure . RealmDestroyed $ MkRealmDestroyed realmid
_ -> fail $ "Unknown ScriptEvent method: " <> unpack typ
data Message = MkMessage
{ channel :: Channel,
messageData :: RemoteValue,
source :: Source
}
deriving (Show, Eq, Generic)
instance FromJSON Message where
parseJSON :: Value -> Parser Message
parseJSON = withObject "Message" $ \o -> do
channel <- o .: "channel"
messageData <- o .: "data"
source <- o .: "source"
pure $ MkMessage {channel, messageData, source}
newtype Channel = Channel {channelId :: Text}
deriving newtype
( Show,
Eq,
ToJSON,
FromJSON
)
data Source = MkSource
{ realm :: Realm,
context :: Maybe BrowsingContext
}
deriving (Show, Eq, Generic)
instance FromJSON Source where
parseJSON :: Value -> Parser Source
parseJSON = parseJSONOmitNothing
newtype ChannelValue = MkChannelValue
{ value :: ChannelProperties
}
deriving (Show, Eq, Generic)
data ChannelProperties = MkChannelProperties
{ channel :: Channel,
serializationOptions :: Maybe SerializationOptions,
ownership :: Maybe ResultOwnership
}
deriving (Show, Eq, Generic)
-- ToJSON instances for Script module
-- Simple newtypes
-- ToJSON instances for missing command types
instance ToJSON AddPreloadScript where
toJSON :: AddPreloadScript -> Value
toJSON = toJSONOmitNothing
instance ToJSON CallFunction where
toJSON :: CallFunction -> Value
toJSON = toJSONOmitNothing
-- GetRealms has a typ field that needs special handling
instance ToJSON GetRealms where
toJSON :: GetRealms -> Value
toJSON MkGetRealms {context, realmType} =
object $
catMaybes
[ opt "context" context,
opt "type" realmType
]
-- RealmType uses specific string values as per spec
-- Command types
instance ToJSON Disown
instance ToJSON RemovePreloadScript
instance ToJSON PrimitiveProtocolValue where
toJSON :: PrimitiveProtocolValue -> Value
toJSON = \case
UndefinedValue -> object ["type" .= "undefined"]
NullValue -> object ["type" .= "null"]
StringValue str ->
object
[ "type" .= "string",
"value" .= str
]
NumberValue (Left num) ->
object
[ "type" .= "number",
"value" .= num
]
NumberValue (Right special) ->
object
[ "type" .= "number",
"value" .= special
]
BooleanValue bool ->
object
[ "type" .= "boolean",
"value" .= bool
]
BigIntValue str ->
object
[ "type" .= "bigint",
"value" .= str
]
-- Local Value types
instance ToJSON LocalValue where
toJSON :: LocalValue -> Value
toJSON = \case
RemoteReference ref -> toJSON ref
PrimitiveLocalValue prim -> toJSON prim
ChannelValue channel -> toJSON channel
ArrayLocalValue arr -> toJSON arr
DateLocalValue date -> toJSON date
MapLocalValue mapVal -> toJSON mapVal
ObjectLocalValue obj -> toJSON obj
RegExpLocalValue regex -> toJSON regex
SetLocalValue set -> toJSON set
instance ToJSON RemoteReference
instance ToJSON SharedReference where
toJSON :: SharedReference -> Value
toJSON = toJSONOmitNothing
instance ToJSON RemoteObjectReference
instance ToJSON ListLocalValue
-- Types with typ field that need manual handling
instance ToJSON ArrayLocalValue where
toJSON (MkArrayLocalValue _ value) =
object
[ "type" .= "array",
"value" .= value
]
instance ToJSON DateLocalValue where
toJSON (MkDateLocalValue value) =
object
[ "type" .= "date",
"value" .= value
]
instance ToJSON MappingLocalValue where
toJSON :: MappingLocalValue -> Value
toJSON (MkMappingLocalValue pairs) =
toJSON $ pairToArray <$> pairs
where
pairToArray :: (Either LocalValue Text, LocalValue) -> [Value]
pairToArray (key, value) = [keyToJson key, toJSON value]
keyToJson :: Either LocalValue Text -> Value
keyToJson (Left localVal) = toJSON localVal
keyToJson (Right text) = toJSON text
instance ToJSON MapLocalValue where
toJSON :: MapLocalValue -> Value
toJSON (MkMapLocalValue value) =
object
[ "type" .= "map",
"value" .= value
]
instance ToJSON ObjectLocalValue where
toJSON :: ObjectLocalValue -> Value
toJSON (MkObjectLocalValue value) =
object
[ "type" .= "object",
"value" .= value
]
instance ToJSON RegExpValue
instance ToJSON RegExpLocalValue where
toJSON (MkRegExpLocalValue value) =
object
[ "type" .= "regexp",
"value" .= value
]
instance ToJSON SetLocalValue where
toJSON (MkSetLocalValue _ value) =
object
[ "type" .= "set",
"value" .= value
]
-- ChannelValue has typ field that needs manual handling
instance ToJSON ChannelValue where
toJSON :: ChannelValue -> Value
toJSON (MkChannelValue value) =
object
[ "type" .= "channel",
"value" .= value
]
instance ToJSON ChannelProperties where
toJSON :: ChannelProperties -> Value
toJSON = toJSONOmitNothing
-- FromJSON instances for Script module
-- Basic types
instance FromJSON PrimitiveProtocolValue
-- Complex result types
instance FromJSON AddPreloadScriptResult
instance FromJSON GetRealmsResult
instance FromJSON BaseRealmInfo
instance FromJSON ExceptionDetails
instance FromJSON StackTrace
instance FromJSON StackFrame
newtype RealmDestroyed = MkRealmDestroyed {realm :: Realm} deriving (Show, Eq, Generic)
instance FromJSON RealmDestroyed