diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Changelog for quickjs-hs
 
+### 0.1.2
+
+* removed `DerivingVia` for better backwards compatibility
+
+
 ### 0.1.1
 
 * relaxed bounds on packages
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # quickjs-hs
 
-![Tests CI](https://github.com/goodlyrottenapple/quickjs-hs/workflows/Tests%20CI/badge.svg)
+![Tests Cabal](https://github.com/goodlyrottenapple/quickjs-hs/workflows/Tests%20Cabal/badge.svg)
 
 
 This package provides a Haskell wrapper for the [QuickJS](https://bellard.org/quickjs/) Javascript Engine.
diff --git a/quickjs-hs.cabal b/quickjs-hs.cabal
--- a/quickjs-hs.cabal
+++ b/quickjs-hs.cabal
@@ -1,6 +1,6 @@
 cabal-version:  1.12
 name:           quickjs-hs
-version:        0.1.1
+version:        0.1.2
 homepage:       https://github.com/goodlyrottenapple/quickjs-hs#readme
 bug-reports:    https://github.com/goodlyrottenapple/quickjs-hs/issues
 author:         Sam Balco
@@ -31,39 +31,42 @@
   hs-source-dirs:
       src
   build-depends:
-      base                 >=4.7       && <5
-    , aeson                >=1.4.7.1   && <1.5
-    , bytestring           >=0.10.10.0 && <0.11
-    , containers           >=0.6.2.1   && <0.7
-    , exceptions           >=0.10.4    && <0.11
-    , inline-c             >=0.9.1.0   && <0.10
-    , mtl                  >=2.2.2     && <2.3
-    , scientific           >=0.3.6.2   && <0.4
-    , string-conv          >=0.1.2     && <0.2
-    , text                 >=1.2.0     && <1.3
-    , time                 >=1.9.3     && <1.10
-    , transformers         >=0.5.6.2   && <0.6
-    , unliftio-core        >=0.1.2.0   && <0.2.1
-    , unordered-containers >=0.2.10.0  && <0.3
-    , vector               >=0.12.1.2  && <0.13
+      base                 >=4.9   && <5
+    , aeson                >=1.1   && <1.6
+    , bytestring           >=0.10  && <0.11
+    , containers           >=0.5   && <0.7
+    , exceptions           >=0.8   && <0.11
+    , inline-c             >=0.5   && <0.10
+    , mtl                  >=2.2.2 && <2.3
+    , scientific           >=0.3.5 && <0.4
+    , string-conv          >=0.1.2 && <0.2
+    , text                 >=1.2.0 && <1.3
+    , time                 >=1.8   && <1.10
+    , transformers         >=0.5   && <0.6
+    , unliftio-core        >=0.1   && <0.2.1
+    , unordered-containers >=0.2.8 && <0.3
+    , vector               >=0.12  && <0.13
   default-language: Haskell2010
   include-dirs: quickjs
-  -- Order matters for dynamic linking, see GHC#12152.
-  -- To make both `cabal repl` and `stack ghci` work, we have to
-  -- make "a.cpp" come alphabetically before "main.cpp".
   c-sources: 
-      quickjs/cutils.h
-    , quickjs/cutils.c
-    , quickjs/libbf.h
+      quickjs/cutils.c
     , quickjs/libbf.c
-    , quickjs/libregexp.h
-    , quickjs/libregexp.c
-    , quickjs/libunicode.h
     , quickjs/libunicode.c
+    , quickjs/libregexp.c
     , quickjs/quickjs.h
     , quickjs/quickjs.c
     , quickjs/quickjs-libc.h
     , quickjs/quickjs-libc.c
+  includes: 
+      quickjs/cutils.h
+    , quickjs/libbf.h
+    , quickjs/libunicode-table.h
+    , quickjs/libunicode.h
+    , quickjs/libregexp-opcode.h
+    , quickjs/libregexp.h
+    , quickjs/list.h
+    , quickjs/quickjs-atom.h
+    , quickjs/quickjs-opcode.h
   cc-options: 
     -static -D_GNU_SOURCE 
     -DCONFIG_VERSION="2020-07-05"
@@ -71,23 +74,23 @@
 
 
 test-suite quickjs-hs-test
-    type:             exitcode-stdio-1.0
-    main-is:          Spec.hs
-    hs-source-dirs:   test
-    other-modules:    Paths_quickjs_hs
-    default-language: Haskell2010
-    ghc-options:      -threaded -rtsopts -with-rtsopts=-N
-    build-depends:
-        base
-      , quickjs-hs           -any
-      , aeson
-      , exceptions
-      , HUnit                >=1.6.0.0  && <1.7
-      , QuickCheck           >=2.13.2   && <2.14
-      , tasty                >=1.2.3    && <1.3
-      , tasty-hunit          >=0.10.0.2 && <0.11
-      , tasty-quickcheck     >=0.10.1.1 && <0.11
-      , text
-      , unordered-containers
-      , vector
+  type:             exitcode-stdio-1.0
+  main-is:          Spec.hs
+  hs-source-dirs:   test
+  other-modules:    Paths_quickjs_hs
+  default-language: Haskell2010
+  ghc-options:      -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base
+    , quickjs-hs           -any
+    , aeson
+    , exceptions
+    , HUnit                >=1.6.0.0  && <1.7
+    , QuickCheck           >=2.9  && <2.14
+    , tasty                >=1.0  && <1.3
+    , tasty-hunit          >=0.10 && <0.11
+    , tasty-quickcheck     >=0.9  && <0.11
+    , text
+    , unordered-containers
+    , vector
 
diff --git a/quickjs/cutils.h b/quickjs/cutils.h
deleted file mode 100644
--- a/quickjs/cutils.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * C utilities
- * 
- * Copyright (c) 2017 Fabrice Bellard
- * Copyright (c) 2018 Charlie Gordon
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef CUTILS_H
-#define CUTILS_H
-
-#include <stdlib.h>
-#include <inttypes.h>
-
-/* set if CPU is big endian */
-#undef WORDS_BIGENDIAN
-
-#define likely(x)       __builtin_expect(!!(x), 1)
-#define unlikely(x)     __builtin_expect(!!(x), 0)
-#define force_inline inline __attribute__((always_inline))
-#define no_inline __attribute__((noinline))
-#define __maybe_unused __attribute__((unused))
-
-#define xglue(x, y) x ## y
-#define glue(x, y) xglue(x, y)
-#define stringify(s)    tostring(s)
-#define tostring(s)     #s
-
-#ifndef offsetof
-#define offsetof(type, field) ((size_t) &((type *)0)->field)
-#endif
-#ifndef countof
-#define countof(x) (sizeof(x) / sizeof((x)[0]))
-#endif
-
-typedef int BOOL;
-
-#ifndef FALSE
-enum {
-    FALSE = 0,
-    TRUE = 1,
-};
-#endif
-
-void pstrcpy(char *buf, int buf_size, const char *str);
-char *pstrcat(char *buf, int buf_size, const char *s);
-int strstart(const char *str, const char *val, const char **ptr);
-int has_suffix(const char *str, const char *suffix);
-
-static inline int max_int(int a, int b)
-{
-    if (a > b)
-        return a;
-    else
-        return b;
-}
-
-static inline int min_int(int a, int b)
-{
-    if (a < b)
-        return a;
-    else
-        return b;
-}
-
-static inline uint32_t max_uint32(uint32_t a, uint32_t b)
-{
-    if (a > b)
-        return a;
-    else
-        return b;
-}
-
-static inline uint32_t min_uint32(uint32_t a, uint32_t b)
-{
-    if (a < b)
-        return a;
-    else
-        return b;
-}
-
-static inline int64_t max_int64(int64_t a, int64_t b)
-{
-    if (a > b)
-        return a;
-    else
-        return b;
-}
-
-static inline int64_t min_int64(int64_t a, int64_t b)
-{
-    if (a < b)
-        return a;
-    else
-        return b;
-}
-
-/* WARNING: undefined if a = 0 */
-static inline int clz32(unsigned int a)
-{
-    return __builtin_clz(a);
-}
-
-/* WARNING: undefined if a = 0 */
-static inline int clz64(uint64_t a)
-{
-    return __builtin_clzll(a);
-}
-
-/* WARNING: undefined if a = 0 */
-static inline int ctz32(unsigned int a)
-{
-    return __builtin_ctz(a);
-}
-
-/* WARNING: undefined if a = 0 */
-static inline int ctz64(uint64_t a)
-{
-    return __builtin_ctzll(a);
-}
-
-struct __attribute__((packed)) packed_u64 {
-    uint64_t v;
-};
-
-struct __attribute__((packed)) packed_u32 {
-    uint32_t v;
-};
-
-struct __attribute__((packed)) packed_u16 {
-    uint16_t v;
-};
-
-static inline uint64_t get_u64(const uint8_t *tab)
-{
-    return ((const struct packed_u64 *)tab)->v;
-}
-
-static inline int64_t get_i64(const uint8_t *tab)
-{
-    return (int64_t)((const struct packed_u64 *)tab)->v;
-}
-
-static inline void put_u64(uint8_t *tab, uint64_t val)
-{
-    ((struct packed_u64 *)tab)->v = val;
-}
-
-static inline uint32_t get_u32(const uint8_t *tab)
-{
-    return ((const struct packed_u32 *)tab)->v;
-}
-
-static inline int32_t get_i32(const uint8_t *tab)
-{
-    return (int32_t)((const struct packed_u32 *)tab)->v;
-}
-
-static inline void put_u32(uint8_t *tab, uint32_t val)
-{
-    ((struct packed_u32 *)tab)->v = val;
-}
-
-static inline uint32_t get_u16(const uint8_t *tab)
-{
-    return ((const struct packed_u16 *)tab)->v;
-}
-
-static inline int32_t get_i16(const uint8_t *tab)
-{
-    return (int16_t)((const struct packed_u16 *)tab)->v;
-}
-
-static inline void put_u16(uint8_t *tab, uint16_t val)
-{
-    ((struct packed_u16 *)tab)->v = val;
-}
-
-static inline uint32_t get_u8(const uint8_t *tab)
-{
-    return *tab;
-}
-
-static inline int32_t get_i8(const uint8_t *tab)
-{
-    return (int8_t)*tab;
-}
-
-static inline void put_u8(uint8_t *tab, uint8_t val)
-{
-    *tab = val;
-}
-
-static inline uint16_t bswap16(uint16_t x)
-{
-    return (x >> 8) | (x << 8);
-}
-
-static inline uint32_t bswap32(uint32_t v)
-{
-    return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >>  8) |
-        ((v & 0x0000ff00) <<  8) | ((v & 0x000000ff) << 24);
-}
-
-static inline uint64_t bswap64(uint64_t v)
-{
-    return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) | 
-        ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) | 
-        ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) | 
-        ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) | 
-        ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) | 
-        ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) | 
-        ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) | 
-        ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
-}
-
-/* XXX: should take an extra argument to pass slack information to the caller */
-typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
-
-typedef struct DynBuf {
-    uint8_t *buf;
-    size_t size;
-    size_t allocated_size;
-    BOOL error; /* true if a memory allocation error occurred */
-    DynBufReallocFunc *realloc_func;
-    void *opaque; /* for realloc_func */
-} DynBuf;
-
-void dbuf_init(DynBuf *s);
-void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
-int dbuf_realloc(DynBuf *s, size_t new_size);
-int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
-int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
-int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
-int dbuf_putc(DynBuf *s, uint8_t c);
-int dbuf_putstr(DynBuf *s, const char *str);
-static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
-{
-    return dbuf_put(s, (uint8_t *)&val, 2);
-}
-static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
-{
-    return dbuf_put(s, (uint8_t *)&val, 4);
-}
-static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
-{
-    return dbuf_put(s, (uint8_t *)&val, 8);
-}
-int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
-                                                      const char *fmt, ...);
-void dbuf_free(DynBuf *s);
-static inline BOOL dbuf_error(DynBuf *s) {
-    return s->error;
-}
-static inline void dbuf_set_error(DynBuf *s)
-{
-    s->error = TRUE;
-}
-
-#define UTF8_CHAR_LEN_MAX 6
-
-int unicode_to_utf8(uint8_t *buf, unsigned int c);
-int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
-
-static inline int from_hex(int c)
-{
-    if (c >= '0' && c <= '9')
-        return c - '0';
-    else if (c >= 'A' && c <= 'F')
-        return c - 'A' + 10;
-    else if (c >= 'a' && c <= 'f')
-        return c - 'a' + 10;
-    else
-        return -1;
-}
-
-void rqsort(void *base, size_t nmemb, size_t size,
-            int (*cmp)(const void *, const void *, void *),
-            void *arg);
-
-#endif  /* CUTILS_H */
diff --git a/quickjs/libbf.h b/quickjs/libbf.h
deleted file mode 100644
--- a/quickjs/libbf.h
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Tiny arbitrary precision floating point library
- * 
- * Copyright (c) 2017-2020 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef LIBBF_H
-#define LIBBF_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#if defined(__x86_64__)
-#define LIMB_LOG2_BITS 6
-#else
-#define LIMB_LOG2_BITS 5
-#endif
-
-#define LIMB_BITS (1 << LIMB_LOG2_BITS)
-
-#if LIMB_BITS == 64
-typedef __int128 int128_t;
-typedef unsigned __int128 uint128_t;
-typedef int64_t slimb_t;
-typedef uint64_t limb_t;
-typedef uint128_t dlimb_t;
-#define BF_RAW_EXP_MIN INT64_MIN
-#define BF_RAW_EXP_MAX INT64_MAX
-
-#define LIMB_DIGITS 19
-#define BF_DEC_BASE UINT64_C(10000000000000000000)
-
-#else
-
-typedef int32_t slimb_t;
-typedef uint32_t limb_t;
-typedef uint64_t dlimb_t;
-#define BF_RAW_EXP_MIN INT32_MIN
-#define BF_RAW_EXP_MAX INT32_MAX
-
-#define LIMB_DIGITS 9
-#define BF_DEC_BASE 1000000000U
-
-#endif
-
-/* in bits */
-/* minimum number of bits for the exponent */
-#define BF_EXP_BITS_MIN 3
-/* maximum number of bits for the exponent */
-#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
-/* extended range for exponent, used internally */
-#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
-/* minimum possible precision */
-#define BF_PREC_MIN 2
-/* minimum possible precision */
-#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
-/* some operations support infinite precision */
-#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
-
-#if LIMB_BITS == 64
-#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
-#else
-#define BF_CHKSUM_MOD 975620677U
-#endif
-
-#define BF_EXP_ZERO BF_RAW_EXP_MIN
-#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
-#define BF_EXP_NAN BF_RAW_EXP_MAX
-
-/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
-   +/-infinity is represented with expn = BF_EXP_INF and len = 0,
-   NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
- */
-typedef struct {
-    struct bf_context_t *ctx;
-    int sign;
-    slimb_t expn;
-    limb_t len;
-    limb_t *tab;
-} bf_t;
-
-typedef struct {
-    /* must be kept identical to bf_t */
-    struct bf_context_t *ctx;
-    int sign;
-    slimb_t expn;
-    limb_t len;
-    limb_t *tab;
-} bfdec_t;
-
-typedef enum {
-    BF_RNDN, /* round to nearest, ties to even */
-    BF_RNDZ, /* round to zero */
-    BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
-    BF_RNDU, /* round to +inf */
-    BF_RNDNA, /* round to nearest, ties away from zero */
-    BF_RNDA, /* round away from zero */
-    BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
-                inexact flag is always set)  */
-} bf_rnd_t;
-
-/* allow subnormal numbers. Only available if the number of exponent
-   bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
-#define BF_FLAG_SUBNORMAL (1 << 3)
-/* 'prec' is the precision after the radix point instead of the whole
-   mantissa. Can only be used with bf_round() and
-   bfdec_[add|sub|mul|div|sqrt|round](). */
-#define BF_FLAG_RADPNT_PREC (1 << 4)
-
-#define BF_RND_MASK 0x7
-#define BF_EXP_BITS_SHIFT 5
-#define BF_EXP_BITS_MASK 0x3f
-
-/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
-#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
-
-/* contains the rounding mode and number of exponents bits */
-typedef uint32_t bf_flags_t;
-
-typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
-
-typedef struct {
-    bf_t val;
-    limb_t prec;
-} BFConstCache;
-
-typedef struct bf_context_t {
-    void *realloc_opaque;
-    bf_realloc_func_t *realloc_func;
-    BFConstCache log2_cache;
-    BFConstCache pi_cache;
-    struct BFNTTState *ntt_state;
-} bf_context_t;
-
-static inline int bf_get_exp_bits(bf_flags_t flags)
-{
-    int e;
-    e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
-    if (e == BF_EXP_BITS_MASK)
-        return BF_EXP_BITS_MAX + 1;
-    else
-        return BF_EXP_BITS_MAX - e;
-}
-
-static inline bf_flags_t bf_set_exp_bits(int n)
-{
-    return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
-}
-
-/* returned status */
-#define BF_ST_INVALID_OP  (1 << 0)
-#define BF_ST_DIVIDE_ZERO (1 << 1)
-#define BF_ST_OVERFLOW    (1 << 2)
-#define BF_ST_UNDERFLOW   (1 << 3)
-#define BF_ST_INEXACT     (1 << 4)
-/* indicate that a memory allocation error occured. NaN is returned */
-#define BF_ST_MEM_ERROR   (1 << 5) 
-
-#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
-
-static inline slimb_t bf_max(slimb_t a, slimb_t b)
-{
-    if (a > b)
-        return a;
-    else
-        return b;
-}
-
-static inline slimb_t bf_min(slimb_t a, slimb_t b)
-{
-    if (a < b)
-        return a;
-    else
-        return b;
-}
-
-void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
-                     void *realloc_opaque);
-void bf_context_end(bf_context_t *s);
-/* free memory allocated for the bf cache data */
-void bf_clear_cache(bf_context_t *s);
-
-static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
-{
-    return s->realloc_func(s->realloc_opaque, ptr, size);
-}
-
-/* 'size' must be != 0 */
-static inline void *bf_malloc(bf_context_t *s, size_t size)
-{
-    return bf_realloc(s, NULL, size);
-}
-
-static inline void bf_free(bf_context_t *s, void *ptr)
-{
-    /* must test ptr otherwise equivalent to malloc(0) */
-    if (ptr)
-        bf_realloc(s, ptr, 0);
-}
-
-void bf_init(bf_context_t *s, bf_t *r);
-
-static inline void bf_delete(bf_t *r)
-{
-    bf_context_t *s = r->ctx;
-    /* we accept to delete a zeroed bf_t structure */
-    if (s && r->tab) {
-        bf_realloc(s, r->tab, 0);
-    }
-}
-
-static inline void bf_neg(bf_t *r)
-{
-    r->sign ^= 1;
-}
-
-static inline int bf_is_finite(const bf_t *a)
-{
-    return (a->expn < BF_EXP_INF);
-}
-
-static inline int bf_is_nan(const bf_t *a)
-{
-    return (a->expn == BF_EXP_NAN);
-}
-
-static inline int bf_is_zero(const bf_t *a)
-{
-    return (a->expn == BF_EXP_ZERO);
-}
-
-static inline void bf_memcpy(bf_t *r, const bf_t *a)
-{
-    *r = *a;
-}
-
-int bf_set_ui(bf_t *r, uint64_t a);
-int bf_set_si(bf_t *r, int64_t a);
-void bf_set_nan(bf_t *r);
-void bf_set_zero(bf_t *r, int is_neg);
-void bf_set_inf(bf_t *r, int is_neg);
-int bf_set(bf_t *r, const bf_t *a);
-void bf_move(bf_t *r, bf_t *a);
-int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
-int bf_set_float64(bf_t *a, double d);
-
-int bf_cmpu(const bf_t *a, const bf_t *b);
-int bf_cmp_full(const bf_t *a, const bf_t *b);
-int bf_cmp(const bf_t *a, const bf_t *b);
-static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
-{
-    return bf_cmp(a, b) == 0;
-}
-
-static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
-{
-    return bf_cmp(a, b) <= 0;
-}
-
-static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
-{
-    return bf_cmp(a, b) < 0;
-}
-
-int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
-int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
-int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
-int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
-int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
-int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, 
-              bf_flags_t flags);
-int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
-int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
-#define BF_DIVREM_EUCLIDIAN BF_RNDF
-int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
-              limb_t prec, bf_flags_t flags, int rnd_mode);
-int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
-           bf_flags_t flags, int rnd_mode);
-int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
-              bf_flags_t flags, int rnd_mode);
-/* round to integer with infinite precision */
-int bf_rint(bf_t *r, int rnd_mode);
-int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
-int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
-int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-slimb_t bf_get_exp_min(const bf_t *a);
-int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
-int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
-int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
-
-/* additional flags for bf_atof */
-/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
-#define BF_ATOF_NO_HEX       (1 << 16)
-/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
-#define BF_ATOF_BIN_OCT      (1 << 17)
-/* Do not parse NaN or Inf */
-#define BF_ATOF_NO_NAN_INF   (1 << 18)
-/* return the exponent separately */
-#define BF_ATOF_EXPONENT       (1 << 19)
-
-int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
-            limb_t prec, bf_flags_t flags);
-/* this version accepts prec = BF_PREC_INF and returns the radix
-   exponent */
-int bf_atof2(bf_t *r, slimb_t *pexponent,
-             const char *str, const char **pnext, int radix,
-             limb_t prec, bf_flags_t flags);
-int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
-                     slimb_t expn, limb_t prec, bf_flags_t flags);
-
-
-/* Conversion of floating point number to string. Return a null
-   terminated string or NULL if memory error. *plen contains its
-   length if plen != NULL.  The exponent letter is "e" for base 10,
-   "p" for bases 2, 8, 16 with a binary exponent and "@" for the other
-   bases. */
-
-#define BF_FTOA_FORMAT_MASK (3 << 16)
-
-/* fixed format: prec significant digits rounded with (flags &
-   BF_RND_MASK). Exponential notation is used if too many zeros are
-   needed.*/
-#define BF_FTOA_FORMAT_FIXED (0 << 16)
-/* fractional format: prec digits after the decimal point rounded with
-   (flags & BF_RND_MASK) */
-#define BF_FTOA_FORMAT_FRAC  (1 << 16)
-/* free format: 
-   
-   For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
-   number of digits to represent 'a'. The precision and the rounding
-   mode are ignored.
-   
-   For the non binary radices with bf_ftoa(): use as many digits as
-   necessary so that bf_atof() return the same number when using
-   precision 'prec', rounding to nearest and the subnormal
-   configuration of 'flags'. The result is meaningful only if 'a' is
-   already rounded to 'prec' bits. If the subnormal flag is set, the
-   exponent in 'flags' must also be set to the desired exponent range.
-*/
-#define BF_FTOA_FORMAT_FREE  (2 << 16)
-/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
-   (takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
-   binary radices with bf_ftoa() and for bfdec_ftoa(). */
-#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
-
-/* force exponential notation for fixed or free format */
-#define BF_FTOA_FORCE_EXP    (1 << 20)
-/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
-   base 2 if non zero value */
-#define BF_FTOA_ADD_PREFIX   (1 << 21)
-/* return "Infinity" instead of "Inf" and add a "+" for positive
-   exponents */
-#define BF_FTOA_JS_QUIRKS    (1 << 22)
-
-char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
-              bf_flags_t flags);
-
-/* modulo 2^n instead of saturation. NaN and infinity return 0 */
-#define BF_GET_INT_MOD (1 << 0) 
-int bf_get_int32(int *pres, const bf_t *a, int flags);
-int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
-int bf_get_uint64(uint64_t *pres, const bf_t *a);
-
-/* the following functions are exported for testing only. */
-void mp_print_str(const char *str, const limb_t *tab, limb_t n);
-void bf_print_str(const char *str, const bf_t *a);
-int bf_resize(bf_t *r, limb_t len);
-int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
-int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
-int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
-slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
-                          int is_ceil1);
-int mp_mul(bf_context_t *s, limb_t *result, 
-           const limb_t *op1, limb_t op1_size, 
-           const limb_t *op2, limb_t op2_size);
-limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, 
-              limb_t n, limb_t carry);
-limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
-int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
-int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
-limb_t bf_isqrt(limb_t a);
-
-/* transcendental functions */
-int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
-int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
-int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
-int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
-int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
-             limb_t prec, bf_flags_t flags);
-int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
-
-/* decimal floating point */
-
-static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
-{
-    bf_init(s, (bf_t *)r);
-}
-static inline void bfdec_delete(bfdec_t *r)
-{
-    bf_delete((bf_t *)r);
-}
-
-static inline void bfdec_neg(bfdec_t *r)
-{
-    r->sign ^= 1;
-}
-
-static inline int bfdec_is_finite(const bfdec_t *a)
-{
-    return (a->expn < BF_EXP_INF);
-}
-
-static inline int bfdec_is_nan(const bfdec_t *a)
-{
-    return (a->expn == BF_EXP_NAN);
-}
-
-static inline int bfdec_is_zero(const bfdec_t *a)
-{
-    return (a->expn == BF_EXP_ZERO);
-}
-
-static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
-{
-    bf_memcpy((bf_t *)r, (const bf_t *)a);
-}
-
-int bfdec_set_ui(bfdec_t *r, uint64_t a);
-int bfdec_set_si(bfdec_t *r, int64_t a);
-
-static inline void bfdec_set_nan(bfdec_t *r)
-{
-    bf_set_nan((bf_t *)r);
-}
-static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
-{
-    bf_set_zero((bf_t *)r, is_neg);
-}
-static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
-{
-    bf_set_inf((bf_t *)r, is_neg);
-}
-static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
-{
-    return bf_set((bf_t *)r, (bf_t *)a);
-}
-static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
-{
-    bf_move((bf_t *)r, (bf_t *)a);
-}
-static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
-{
-    return bf_cmpu((const bf_t *)a, (const bf_t *)b);
-}
-static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
-{
-    return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
-}
-static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
-{
-    return bf_cmp((const bf_t *)a, (const bf_t *)b);
-}
-static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
-{
-    return bfdec_cmp(a, b) == 0;
-}
-static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
-{
-    return bfdec_cmp(a, b) <= 0;
-}
-static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
-{
-    return bfdec_cmp(a, b) < 0;
-}
-
-int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
-              bf_flags_t flags);
-int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
-              bf_flags_t flags);
-int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
-                 bf_flags_t flags);
-int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
-              bf_flags_t flags);
-int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
-                 bf_flags_t flags);
-int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
-              bf_flags_t flags);
-int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
-                 limb_t prec, bf_flags_t flags, int rnd_mode);
-int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
-              bf_flags_t flags, int rnd_mode);
-int bfdec_rint(bfdec_t *r, int rnd_mode);
-int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
-int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
-int bfdec_get_int32(int *pres, const bfdec_t *a);
-int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
-
-char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
-int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
-               limb_t prec, bf_flags_t flags);
-
-/* the following functions are exported for testing only. */
-extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
-void bfdec_print_str(const char *str, const bfdec_t *a);
-static inline int bfdec_resize(bfdec_t *r, limb_t len)
-{
-    return bf_resize((bf_t *)r, len);
-}
-int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
-
-#endif /* LIBBF_H */
diff --git a/quickjs/libregexp.h b/quickjs/libregexp.h
deleted file mode 100644
--- a/quickjs/libregexp.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Regular Expression Engine
- * 
- * Copyright (c) 2017-2018 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef LIBREGEXP_H
-#define LIBREGEXP_H
-
-#include <stddef.h>
-
-#include "libunicode.h"
-
-#define LRE_BOOL  int       /* for documentation purposes */
-
-#define LRE_FLAG_GLOBAL     (1 << 0)
-#define LRE_FLAG_IGNORECASE (1 << 1)
-#define LRE_FLAG_MULTILINE  (1 << 2)
-#define LRE_FLAG_DOTALL     (1 << 3)
-#define LRE_FLAG_UTF16      (1 << 4)
-#define LRE_FLAG_STICKY     (1 << 5)
-
-#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
-
-uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
-                     const char *buf, size_t buf_len, int re_flags,
-                     void *opaque);
-int lre_get_capture_count(const uint8_t *bc_buf);
-int lre_get_flags(const uint8_t *bc_buf);
-int lre_exec(uint8_t **capture,
-             const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
-             int cbuf_type, void *opaque);
-
-int lre_parse_escape(const uint8_t **pp, int allow_utf16);
-LRE_BOOL lre_is_space(int c);
-
-/* must be provided by the user */
-LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); 
-void *lre_realloc(void *opaque, void *ptr, size_t size);
-
-/* JS identifier test */
-extern uint32_t const lre_id_start_table_ascii[4];
-extern uint32_t const lre_id_continue_table_ascii[4];
-
-static inline int lre_js_is_ident_first(int c)
-{
-    if ((uint32_t)c < 128) {
-        return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
-    } else {
-#ifdef CONFIG_ALL_UNICODE
-        return lre_is_id_start(c);
-#else
-        return !lre_is_space(c);
-#endif
-    }
-}
-
-static inline int lre_js_is_ident_next(int c)
-{
-    if ((uint32_t)c < 128) {
-        return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
-    } else {
-        /* ZWNJ and ZWJ are accepted in identifiers */
-#ifdef CONFIG_ALL_UNICODE
-        return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
-#else
-        return !lre_is_space(c) || c == 0x200C || c == 0x200D;
-#endif
-    }
-}
-
-#undef LRE_BOOL
-
-#endif /* LIBREGEXP_H */
diff --git a/quickjs/libunicode.h b/quickjs/libunicode.h
deleted file mode 100644
--- a/quickjs/libunicode.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Unicode utilities
- * 
- * Copyright (c) 2017-2018 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef LIBUNICODE_H
-#define LIBUNICODE_H
-
-#include <inttypes.h>
-
-#define LRE_BOOL  int       /* for documentation purposes */
-
-/* define it to include all the unicode tables (40KB larger) */
-#define CONFIG_ALL_UNICODE
-
-#define LRE_CC_RES_LEN_MAX 3
-
-typedef enum {
-    UNICODE_NFC,
-    UNICODE_NFD,
-    UNICODE_NFKC,
-    UNICODE_NFKD,
-} UnicodeNormalizationEnum;
-
-int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
-LRE_BOOL lre_is_cased(uint32_t c);
-LRE_BOOL lre_is_case_ignorable(uint32_t c);
-
-/* char ranges */
-
-typedef struct {
-    int len; /* in points, always even */
-    int size;
-    uint32_t *points; /* points sorted by increasing value */
-    void *mem_opaque;
-    void *(*realloc_func)(void *opaque, void *ptr, size_t size);
-} CharRange;
-
-typedef enum {
-    CR_OP_UNION,
-    CR_OP_INTER,
-    CR_OP_XOR,
-} CharRangeOpEnum;
-
-void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
-void cr_free(CharRange *cr);
-int cr_realloc(CharRange *cr, int size);
-int cr_copy(CharRange *cr, const CharRange *cr1);
-
-static inline int cr_add_point(CharRange *cr, uint32_t v)
-{
-    if (cr->len >= cr->size) {
-        if (cr_realloc(cr, cr->len + 1))
-            return -1;
-    }
-    cr->points[cr->len++] = v;
-    return 0;
-}
-
-static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
-{
-    if ((cr->len + 2) > cr->size) {
-        if (cr_realloc(cr, cr->len + 2))
-            return -1;
-    }
-    cr->points[cr->len++] = c1;
-    cr->points[cr->len++] = c2;
-    return 0;
-}
-
-int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
-
-static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
-{
-    uint32_t b_pt[2];
-    b_pt[0] = c1;
-    b_pt[1] = c2 + 1;
-    return cr_union1(cr, b_pt, 2);
-}
-
-int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
-          const uint32_t *b_pt, int b_len, int op);
-
-int cr_invert(CharRange *cr);
-
-#ifdef CONFIG_ALL_UNICODE
-
-LRE_BOOL lre_is_id_start(uint32_t c);
-LRE_BOOL lre_is_id_continue(uint32_t c);
-
-int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
-                      UnicodeNormalizationEnum n_type,
-                      void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
-
-/* Unicode character range functions */
-
-int unicode_script(CharRange *cr,
-                   const char *script_name, LRE_BOOL is_ext);
-int unicode_general_category(CharRange *cr, const char *gc_name);
-int unicode_prop(CharRange *cr, const char *prop_name);
-
-#endif /* CONFIG_ALL_UNICODE */
-
-#undef LRE_BOOL
-
-#endif /* LIBUNICODE_H */
diff --git a/src/Quickjs/Error.hs b/src/Quickjs/Error.hs
--- a/src/Quickjs/Error.hs
+++ b/src/Quickjs/Error.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE ExistentialQuantification, DuplicateRecordFields, GeneralizedNewtypeDeriving, DerivingStrategies, DeriveGeneric, DerivingVia, RecordWildCards #-}
+{-# LANGUAGE ExistentialQuantification, DuplicateRecordFields, GeneralizedNewtypeDeriving, DerivingStrategies, DeriveGeneric, RecordWildCards #-}
 
 module Quickjs.Error where
 import           Control.Exception   (Exception(..), SomeException)
@@ -32,32 +32,28 @@
     cast a
 
 
-newtype JSRuntimeException e = JSRuntimeException e 
-  deriving Generic
-  deriving newtype Show
 
-instance (Show e, Typeable e) => Exception (JSRuntimeException e)
-  where
-    toException = jsRuntimeExceptionToException
-    fromException = jsRuntimeExceptionFromException
-
-
-
 instance ToJSON CLong where
   toJSON cl = toJSON (fromIntegral cl :: Integer)
 
 data UnknownJSTag = UnknownJSTag {raw_tag :: !CLong} 
   deriving (Generic, Typeable)
-  deriving Exception via (JSRuntimeException UnknownJSTag)
 
+instance Exception UnknownJSTag where
+  toException   = jsRuntimeExceptionToException
+  fromException = jsRuntimeExceptionFromException
+
+
 instance Show UnknownJSTag where
   show UnknownJSTag{..} = "Uknown JS tag: " ++ show raw_tag
 
 
 data UnsupportedTypeTag = UnsupportedTypeTag {_tag :: JSTagEnum} 
   deriving (Generic, Typeable)
-  deriving Exception via (JSRuntimeException UnsupportedTypeTag)
 
+instance Exception UnsupportedTypeTag where
+  toException   = jsRuntimeExceptionToException
+  fromException = jsRuntimeExceptionFromException
 
 instance Show UnsupportedTypeTag where
   show UnsupportedTypeTag{..} = "Unsupported type tag: " ++ show _tag
@@ -65,8 +61,12 @@
 
 data JSException = JSException {location :: Text, message :: Text} 
   deriving (Generic, Typeable)
-  deriving Exception via (JSRuntimeException JSException)
 
+instance Exception JSException where
+  toException   = jsRuntimeExceptionToException
+  fromException = jsRuntimeExceptionFromException
+
+
 instance Show JSException where
     show JSException{..} = "JS runtime threw an exception in " ++ toS location ++ ":\n=================\n" ++ toS message ++ "\n=================\n"
 
@@ -74,8 +74,12 @@
 
 data JSValueUndefined = JSValueUndefined {value :: Text} 
   deriving (Generic, Typeable)
-  deriving Exception via (JSRuntimeException JSValueUndefined)
 
+instance Exception JSValueUndefined where
+  toException   = jsRuntimeExceptionToException
+  fromException = jsRuntimeExceptionFromException
+
+
 instance Show JSValueUndefined where
   show JSValueUndefined{..} =  "The JS value '" ++ toS value ++ "' is undefined."
 
@@ -87,15 +91,22 @@
   , found :: JSTypeEnum
   } 
   deriving (Generic, Typeable)
-  deriving Exception via (JSRuntimeException JSValueIncorrectType)
 
+instance Exception JSValueIncorrectType where
+  toException   = jsRuntimeExceptionToException
+  fromException = jsRuntimeExceptionFromException
+
+
 instance Show JSValueIncorrectType where
   show JSValueIncorrectType{..} = "Type mismatch of the JS value '" ++ toS name ++ "'. Expected: " ++ show expected ++ ", found: " ++ show found
 
 
 data InternalError = InternalError { message :: Text } 
   deriving (Generic, Typeable)
-  deriving Exception via (JSRuntimeException InternalError)
+
+instance Exception InternalError where
+  toException   = jsRuntimeExceptionToException
+  fromException = jsRuntimeExceptionFromException
 
 instance Show InternalError where
   show InternalError{..} = "Internal error occured:\n" ++ toS message
