Yes, I know this, and that’s why I suggest that a solution to this is to have a safe html type that will not allow the general attribute function, only safe attributes. Let’s say the solution is to crash if the string is unsafe. You can have an additional “unsafe” package that doesn’t crash on these strings, that published packages are not allowed to use.
Ah hah! You just sneaked back in the idea of having unsafe
in Elm…
I’ve got no problem with having unsafe flags, in fact I am also a fan of Rust in its handling of unsafe in regards to memory management etc.
But Elm aims to be a safe language which means that it tries to have no runtime exceptions; that is what safe means.
But you are confusing two completely different meanings of safe here. The event attributes are perfectly safe in that they won’t crash your elm program. Yes they may do sneaky things but not within the running elm code. That’s completely different from run time exceptions (which you will get in the “safe” html when trying to create a script node).
I’m not sure if I understand this right, but you’re saying this is not Elm throwing a runtime exeption? Please clarify
EDIT: here’s another one where I download the google-website.
I tried to embed the entire minified Webpack-output for a React program that creates a dom-node and mounts itself to it, but I had some trouble embedding that into the multiline string that I would pass to attribute "onclick"
I tried running it and I am not sure that the exception had any effect on the Elm program? Normally when an Elm program crashes, the update loop does not run any more afterwards. Does that happen with exceptions in inline handlers too?
Possibly there is a mechanism by which these runtimes are caught and discarded. In my view, there is only one thing worse than a runtime exception, and that is swallowing (ignoring) runtime exceptions. After a runtime exception you no longer know what state your program is in, therefore its behaviour after that time can be unpredictable. It is much better to simply terminate the program, or at the very least to terminate the current unit-of-work. It is also a good idea to let someone know that an error occurred rather than to silently fail. For these reasons, I would regard the behaviour of this program as unsafe.
Let’s understand a bit what is going on.
When you declare an inline event handler, that code will only run when that handler is invoked. As far as I know, it will always run asynchronously on a different JavaScript stack than the one rendering to the HTML. So, as far as I can see, this code is completely isolated from the Elm runtime, the same way that ports invoked code is (I’m not sure about custom elements as they are new for me).
For example, see https://ellie-app.com/9nYTC2635a1/0 If you click the button, an exception is thrown in JS land (it shows in ellie because it has an onerror handler attached). If you click it again, the alert
shows again, so the world didn’t break, both Elm and JavaScript continue to work fine.
As far as I can see, this approach seems safe to use, comparing with the other approaches of running JS code, so I wouldn’t consider these programs any unsafer or different that a program that sends a message through a port asynchronously and then in JS an exception is thrown.
If I’m missing something please chime in, I’d love to be corrected!
@joakin, right, its no un-safer than using ports, or other uses of JS in Elm projects like web components. The Elm and JS code run independently, and while its possible for JS them to step on each others toes (like if the JS tries to modify the DOM), its no more possible than ports or web components.
But I do think you are missing something. If you can put JS into an Elm Html element, then you can put it into a package that you can publish into the Elm package manager, which means you are putting hard-to-detect side effects into public Elm packages. If I were really malicious, I could sneak an http request into some inline JavaScript as part of an innocuous looking Html a
function.
Ok, I agree with this and it makes sense, thanks for the explanations.
But we are not allowed to publish port modules, would the same reasoning not apply to inline handlers too?
My argument would be that on : String -> String -> Html.Attribute
leaks an interface that allows you to execute arbitrary JS, which is not the case of ports, as that interface was designed to give you exactly that. But I do understand how useful it is to have an event-handler execute arbitrary javascript from within Elm.
Exactly, this is JavaScript throwing an exception in the event handler. The elm app runs unaffected.