inline-js icon indicating copy to clipboard operation
inline-js copied to clipboard

Segfault upon any JS exception

Open RichardWarfield opened this issue 4 years ago • 2 comments

First of all thank you for this amazing project which has been so useful to us.

Describe the bug Any exception in the JavaScript code now seems to result in a segfault in the Haskell application when using eval. This did not occur with older versions of inline-js; git bisect reports that the first bad commit is ef675745e84d23d51c50660d40acf9e684fbb2d6 .

To Reproduce Please see reproducer here (uses Nix flakes)

Expected behavior eval throws an exception instead of causing a segfault.

Environment

  • OS name + version: Arch Linux, building under Nix
  • Version of the code: master branch commit 0fc7444c552820e44ea54ae82eb1f8542dd56f36

RichardWarfield avatar Sep 12 '21 19:09 RichardWarfield

Thanks for this issue, @RichardWarfield! I was about to give up.

Commit 26c89ec30039445d6b3735cb58fda91b38400375 (i.e. the first commit before ef67574) worked like a charm for my project

hhefesto avatar Jan 11 '22 20:01 hhefesto

Even I am getting this issues. Is there a fix other than moving back few commits?

Code to reprduce this.

{-# OPTIONS_GHC -Werror #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Lib
    ( someFunc
    ) where

import Prelude
import Data.Aeson as A
import GHC.Generics
import Data.Maybe
import Language.JavaScript.Inline
import Data.String
import Data.ByteString.Lazy.Internal as LBS
import Foreign
import Control.Monad
import Control.Exception (try, catch, evaluate, bracketOnError, bracket, SomeException)

data DNSRecord = DNSRecord
  { address :: String
  , family :: Int
  } deriving (FromJSON, Generic, Show)


dnsLookup :: IO ()
dnsLookup = withDefaultSession $ \s -> do
    -- let hs = fromString @EncodedString hostname
    v <- eval s [js| 
                    const dns = (await import("dns")).promises;
                    var v;
                        v = (ws) => { 
                            
                                throw "SOME-ERROR";
                                return dns.lookup(ws, {all: true});
                            
                        }
                    return v;       
        |]
    let f = importJSFunc s v
    putStrLn "NO ERROR"
    eiResp :: (Either SomeException Int)
        <- try $ do 
            r <- f (fromString @EncodedString "www.google.com")
            putStrLn $ show ((fromMaybe [] $ decode $ getValue r) :: [DNSRecord])
            pure 1
    case eiResp of 
        Left ex -> putStrLn $ show ex
        Right _ -> putStrLn $ "SUCCESS"
    
    putStrLn "PASSED ERROR"        
    closeSession s
    where 
        getValue (EncodedJSON a) = a

newFunction :: IO ()
newFunction =  withDefaultSession $ \s -> do
                v <- eval s [js| () => 6 * 7 |]
                let f = importJSFunc s v
                r <- f
                putStrLn $ show (r :: EncodedJSON)

withDefaultSession :: (Session -> IO a) -> IO a
withDefaultSession = withSession defaultConfig

someFunc :: IO ()
someFunc = do
    newFunction
    dnsLookup

iamnewspecies avatar Jul 01 '22 08:07 iamnewspecies