# Proposal: directly calling JS functions

**URL:** https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956
**Category:** Request Feedback
**Created:** [June 23, 2020, 2:59am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956 "2020-06-23T02:59:13Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)
#### Post date: [June 23, 2020, 2:59am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/1 "2020-06-23T02:59:14Z")

</div>

This is a random idea that might not be useful but I will give it anyway.

It might be useful to be able to conveniently call a JS function from Elm. Ports kinda do this, but it does not give Elm a lot of control over how the function gets called. This might be preventing some Elm package from being simple to set up, such as [this one](https://package.elm-lang.org/packages/bburdette/websocket/latest/).

Defining this function in a core library seems like an obvious solution (first argument is function name, second is the argument list, and third makes a msg from the return value):

```auto
callFunction : String -> List Value -> ( Value -> msg ) -> Cmd msg

```

But I think the first argument here is a problem. It causes a security risk since any Elm package could call any function without you providing that function. And it’s better to explicitly control how a JS function becomes accessible from the Elm application.

A better solution would be to allow Json `Value` to represent a JS function since it is a first class value in JS. The only way for this function to enter the Elm application would be through flags (the best way) or through a port. Then you can use these things which would be defined in some core elm/\* package:

```auto
callFunction : Value -> List Value -> (Result FuncError Value -> msg) -> Cmd msg

type FuncError
  = Exception Value

```

There also needs to be a way to construct a `new` object when given a constructor

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 23, 2020, 3:35am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/2 "2020-06-23T03:35:07Z")

</div>

The question of ports vs FFI is a common topic that comes up. Ports are a pretty fundamental part of Elm’s design. It’s worth doing some searching through discourse and YouTube, and other resources like the Elm guide, for some more background on the design considerations behind not allowing FFI in Elm. Here’s one good discussion where it comes up:

https://simplecast.com/card/b06499a6

---

<div class="post-metadata">

### Author: ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)
#### Post date: [June 23, 2020, 4:23am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/3 "2020-06-23T04:23:25Z")

</div>

> [@DullBananas](#):
>
> Defining this function in a core library seems like an obvious solution (first argument is function name, second is the argument list, and third makes a msg from the return value):

You can find discussions about this kind of functionality by searching for “task ports”. In short, it has been discussed multiple times and it was decided against it.

The most recent position of Evan is [here](https://discourse.elm-lang.org/t/chadtech-mail-making-ports-act-like-http-requests/1200/4) and I expect that this is the current position too.

If you look into the previous discussions you will understand more of the concerns around this kind of functionality.

---

<div class="post-metadata">

### Author: ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)
#### Post date: [June 23, 2020, 4:49am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/4 "2020-06-23T04:49:19Z")

</div>

Yeah this idea was really a shower thought that I posted just in case it’s a good idea. The long term solution will be to have Elm be able to do more things that reduces the need for ports (such as creation of elm/websockets package).

---

<div class="post-metadata">

### Author: ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)
#### Post date: [June 23, 2020, 5:05am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/5 "2020-06-23T05:05:54Z")

</div>

> [@DullBananas](#):
>
> The long term solution will be to have Elm be able to do more things that reduces the need for ports (such as creation of elm/websockets package).

Implementation of more of the web api would reduce the needs for ports but, to be honest, ports get an unfair bad reputation. It is not all that hard to work with ports, especially if you use an Actor model-like port architecture. [Murphy’s talk](https://www.youtube.com/watch?v=P3pL85n9_5s) has more details about this approach.

---

<div class="post-metadata">

### Author: ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)
#### Post date: [June 23, 2020, 6:10am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/6 "2020-06-23T06:10:46Z")

</div>

Yes. Ports work perfect for me and will always be useful if Elm is only suitable for part of an application. Completely replacing ports with something else in Elm would be such an Apple move. Just like removing something every darn update :)

---

<div class="post-metadata">

### Author: ![hans-helmut](https://avatars.discourse-cdn.com/v4/letter/h/d9b06d/32.png) [@hans-helmut](https://discourse.elm-lang.org/u/hans-helmut)
#### Post date: [June 23, 2020, 6:26am UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/7 "2020-06-23T06:26:19Z")

</div>

I had already implemented a similar API trough Elm’s ports named [SimpleJs](https://github.com/hans-helmut/SimpleJs) and discussed [here](https://discourse.elm-lang.org/t/simplejs-calling-js-from-elm/5874)

> [@DullBananas](#):
>
> There also needs to be a way to construct a `new` object when given a constructor

I was also thinking of such an API for `new`, but so far I just call JS-functions, and can not create objects without using helper functions, like in [here for a JS Date](https://github.com/hans-helmut/SimpleJs/blob/master/src/myjsfunctions.js). This works for me.

I do not expect, that JS-objects are equal to Elms `Json.Decode.Value`, because the do not include the functions / object methods, or at least this is an implementation detail, which can change with every new version, so I have not tried it. I do not expecting the compiler, when copying a variable of `Json.Decode.Value` type to copy also the included functions. So a special new type additional to `Value` is necessary, let call it `JsObject`. Without extending the compiler to support `JsObject`, `JsObject` can be a reference, like a Elm `Int` to a real JS-object. So the parameters of the function need to change from `List Value` to `List JsObject`. But then you need the encoders creating a `JsObject`, which need call JS trough ports again. For me, it seems to difficult to implement using Elm ports, and programming with (references to) objects this way in Elm would not help me to create clean code.

---

<div class="post-metadata">

### Author: ![hans-helmut](https://avatars.discourse-cdn.com/v4/letter/h/d9b06d/32.png) [@hans-helmut](https://discourse.elm-lang.org/u/hans-helmut)
#### Post date: [June 23, 2020, 3:43pm UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/8 "2020-06-23T15:43:23Z")

</div>

Crazy idea:

Introduce JsParam:

```auto
type alias JsObject
  = Int

type JsParam
  = Obj JsObject
  | Val Json.Decode.Value

```

and define

```auto
callFunction : List String -> List JsParam -> ( Json.Decode.Value -> msg ) -> Cmd msg
callMethod: (JsObject, String) -> List JsParam -> ( Json.Decode.Value -> msg ) -> Cmd msg
new: List String -> List JsParam -> ( JsObject -> msg ) -> Cmd msg
delete: JsObject -> msg -> Cmd msg

```

As the JS-objects must be stored in a JS-array, so `delete` is necessary, buy you can easy forgot to call it, causing memory leaks on JS side. Reminds me to some old JNI (Java native interface, calling “C” from Java) implementation. It is not a nice solution, but could be implemented using Elm-ports.

---

<div class="post-metadata">

### Author: ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)
#### Post date: [July 3, 2020, 3:43pm UTC](https://discourse.elm-lang.org/t/proposal-directly-calling-js-functions/5956/9 "2020-07-03T15:43:25Z")

</div>

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