[SOLVED] Help needed: Elm on Quickjs "TypeError" ?!?

I’m trying to run a small Elm script through Bellard’s Quickjs on Linux but the following error is produced during initialization:

debian@love >./qjstest
    TypeError: not a function

It is unclear which function this refers to. I’ve managed to trace the issue back to the “_Platform_worker” function which executes and returns correctly. The error happens some time after that but I’m not sure where.

The callsite looks like this:

#include "quickjspp.hpp" // wrapper for quickjs

// ... some time later:

context.eval("function setTimeout(a,b) { a(); return 42; } "
             "function clearTimeout(a) { } "
             "var app = Elm.Main.init(); "
             "app.ports.debugPr.subscript(jsDebug); ");

The “setTimeout” function is a stub for now, I don’t think that should cause a problem here. The “jsDebug” function is provided by this and is working correctly:

context.global().add(“jsDebug”, [](const std::string& str) { std::cout << str << std::endl; });

The “debugPr” function is a port and the “jsDebug” function is supposed to execute and print to the console.

Finally the Elm code is trivial:

port module Main exposing (main)

import Platform exposing (Program)

port debugPr : String -> Cmd msg

main : Program () () ()
main =
    { init = \() -> ( (), debugPr "Elm started" )
    , update = \() -> \() -> ( (), Cmd.none )
    , subscriptions = \() -> Sub.none

I was also looking into trying mujs as an alternative so far there appears to be the same problem and the code is similar. I can provide that code later if it can help identifying the issue.

Hope someone can help pointing me into the direction of how to deal with this!
Thank you in advance.


I think you mean to use the “subscribe” function instead of subscript. There may be other issues, but I’d start with that.

You are right! Changing subscript to subscribe fixed the type issue. I wonder how I missed that :thinking:

Some problems remain however:
debugPr does not get executed during init I suspect some concurrency issue here. It appears the init function is executed during


but the jsDebug that would allow us to print is only provided one line later:

app.ports.debugPr.subscribe(jsDebug); // now fixed!!

However it does work correctly later on when update is called.

port module Main exposing (main)

import Platform exposing (Program)

port debugPr : String -> Cmd msg
port handle : (Int -> msg) -> Sub msg

type Input
  = Recv Int

update : Input -> () -> ((), Cmd Input)
update input _ =
  case input of
    Recv val ->
      ( ()
      , debugPr ("Number: " ++ (String.fromInt val)) -- YES works!

subscriptions : () -> Sub Input
subscriptions _ =
  handle Recv

main : Program () () Input
main =
    { init = \() -> ( (), debugPr "Elm started" ) -- NO doesn't work
    ,  update = update 
    , subscriptions = subscriptions 

Here the string “Elm started” does NOT get printed, but the string “Number 888” DOES work. (called by this: app.ports.handle.send(888);)

It appears that ports cannot be called in the init function but I couldn’t find anything in the documentation about that.

Either way I consider this problem to be mostly solved and the topic can be closed. Thanks again @ jfmengels for help! At last I can run Elm on my peanut vending machine!!!

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.