diff --git a/ghcjs-base-stub.cabal b/ghcjs-base-stub.cabal
--- a/ghcjs-base-stub.cabal
+++ b/ghcjs-base-stub.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               ghcjs-base-stub
-version:            0.3.0.1
+version:            0.3.0.2
 synopsis:           Allow GHCJS projects to compile under GHC and develop using intero.
 description:        Allow GHCJS projects to compile under GHC and develop using intero. Please refer to README.md.
 homepage:           https://github.com/louispan/javascript-stub#readme
@@ -29,6 +29,16 @@
 
   if impl(ghcjs)
     other-extensions: JavaScriptFFI
+    js-sources:      ghcjs-base/jsbits/array.js
+                     ghcjs-base/jsbits/animationFrame.js
+                     ghcjs-base/jsbits/export.js
+                     ghcjs-base/jsbits/jsstring.js
+                     ghcjs-base/jsbits/jsstringRaw.js
+                     ghcjs-base/jsbits/foreign.js
+                     ghcjs-base/jsbits/text.js
+                     ghcjs-base/jsbits/utils.js
+                     ghcjs-base/jsbits/xhr.js
+                     ghcjs-base/jsbits/websocket.js
 
   other-modules:    GHCJS.Internal.Types
                     Data.JSString.Internal.Type
@@ -57,6 +67,7 @@
                     JavaScript.Object.Internal
                     JavaScript.Web.Location
                     JavaScript.Web.Storage
+                    JavaScript.Web.Storage.Internal
 
   if !impl(ghcjs)
     exposed-modules: GHCJS.Prim
diff --git a/src/JavaScript/Web/Storage.hs b/src/JavaScript/Web/Storage.hs
--- a/src/JavaScript/Web/Storage.hs
+++ b/src/JavaScript/Web/Storage.hs
@@ -10,40 +10,37 @@
     , clear
     ) where
 
-import Data.Map.Strict (Map)
-import qualified Data.Map.Strict as M
-import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)
-import Data.JSString
-import System.IO.Unsafe (unsafePerformIO)
-
-newtype Storage = Storage (IORef (Map JSString JSString))
+import GHCJS.Types
+import JavaScript.Web.Storage.Internal
 
 localStorage :: Storage
-localStorage = Storage . unsafePerformIO $ newIORef mempty
-{-# NOINLINE localStorage #-}
+localStorage = Storage nullRef
+{-# INLINE localStorage #-}
 
 sessionStorage :: Storage
-sessionStorage = Storage . unsafePerformIO $ newIORef mempty
-{-# NOINLINE sessionStorage #-}
+sessionStorage = Storage nullRef
+{-# INLINE sessionStorage #-}
 
 getLength :: Storage -> IO Int
-getLength (Storage s) = M.size <$> readIORef s
+getLength _ = pure 0
+{-# INLINE getLength #-}
 
 getIndex :: Int -> Storage -> IO (Maybe JSString)
-getIndex i (Storage s) = do
-    m <- readIORef s
-    if i >= 0 && i < M.size m
-        then pure $ Just $ fst $ M.elemAt i m
-        else pure Nothing
+getIndex _ _ = pure Nothing
+{-# INLINE getIndex #-}
 
 getItem :: JSString -> Storage -> IO (Maybe JSString)
-getItem key (Storage s) = M.lookup key <$> readIORef s
+getItem _ _ = pure Nothing
+{-# INLINE getItem #-}
 
 setItem :: JSString -> JSString -> Storage -> IO ()
-setItem key val (Storage s) = modifyIORef s $ M.insert key val
+setItem _ _ _ = pure ()
+{-# INLINE setItem #-}
 
 removeItem :: JSString -> Storage -> IO ()
-removeItem key (Storage s) = modifyIORef s $ M.delete key
+removeItem _ _ = pure ()
+{-# INLINE removeItem #-}
 
 clear :: Storage -> IO ()
-clear (Storage s) = writeIORef s mempty
+clear _ = pure ()
+{-# INLINE clear #-}
diff --git a/src/JavaScript/Web/Storage/Internal.hs b/src/JavaScript/Web/Storage/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/JavaScript/Web/Storage/Internal.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+
+module JavaScript.Web.Storage.Internal where
+
+import GHCJS.Types
+
+import Data.Typeable
+
+newtype Storage      = Storage JSVal deriving Typeable
+newtype StorageEvent = StorageEvent JSVal deriving Typeable
