ghcjs / ghcjs-base

base library for GHCJS for JavaScript interaction and marshalling, used by higher level libraries like JSC
MIT License
45 stars 67 forks source link

Enable a isInstance method in JavaScript.Cast #86

Open louispan opened 7 years ago

louispan commented 7 years ago

Hi, I'm having trouble using Javascript.Cast for more complex types like React's SyntheticEvent

AFAIK there is no prototype exported by React for SyntheticEvent, so my logic for detecting if a javascript value is a SyntheticEvent is e && e.nativeEvent && e.nativeEvent instanceof Event

Unfortunately, this means I cannot use Javascript.Cast since the logic for detecting instance is hard-coded to use js_checkcast, which is:

foreign import javascript unsafe 
  "$1 instanceof $2" js_checkCast :: JSVal -> JSVal -> Bool

Would it be possible to invert the hard-coding and make the Cast class as follows?

class InstanceRef a where
  instanceRef :: a -> JSVal

class Cast a where
  unsafeWrap  :: JSVal -> a
  isInstance :: JSVal -> Maybe a
  default isInstance :: InstanceRef a => JSVal -> Maybe a
  isInstance x = js_checkCast x (instanceRef (undefined :: a))

cast :: forall a. Cast a => JSVal -> Maybe a
cast x | isInstance x = Just (unsafeWrap x)
           | otherwise     = Nothing
{-# INLINE cast #-}