phoenixframework / phoenix_html

Building blocks for working with HTML in Phoenix
MIT License
402 stars 220 forks source link

phoenix_html < 2.10.3 is not compatible with Elixir 1.8.0+ #247

Closed axelson closed 5 years ago

axelson commented 5 years ago

I've spent some time investigating an error in an example Phoenix app for ueberauth: https://github.com/ueberauth/ueberauth_example/issues/43

It appears that when the following code is run under Elixir 1.8.1 and phoenix_html < 2.10.3 (tested with 2.10.2 and 2.9.2) you get a relatively cryptic error. Code:

<section class="phx-hero"></section>

<%= form_tag("/", method: "post") do %>
  <div class='control-group'></div>
<% end %>

Error:

== Compilation error in file lib/my_example_web/views/page_view.ex ==
** (BadMapError) expected a map, got: {:safe, [{:|, [], ["", "<section class=\"phx-hero\"></section>\n\n"]}]}
    (eex) lib/eex/engine.ex:161: EEx.Engine.handle_begin/1
    (eex) lib/eex/compiler.ex:54: EEx.Compiler.generate_buffer/4
    (phoenix) lib/phoenix/template.ex:349: Phoenix.Template.compile/3
    (phoenix) lib/phoenix/template.ex:160: anonymous fn/4 in Phoenix.Template."MACRO-__before_compile__"/2
    (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
    (phoenix) expanding macro: Phoenix.Template.__before_compile__/1
    lib/my_example_web/views/page_view.ex:1: MyExampleWeb.PageView (module)
    (elixir) lib/kernel/parallel_compiler.ex:208: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

With the same client code running with phoenix_html 2.10.3 (and the latest version 2.13.1) it works as expected. Additionally on Elixir 1.7.4 everything works as expected. Here is a minimal reproduction: https://github.com/axelson/phoenix_html_repro

It is my assumption that Elixir 1.8.0 made backend improvements to EEx rendering that enhance it's performance without changing it's described public interface. However it appears that phoenix_html 2.10.2 and lower depended on part of the implementation that has been changed (here's a post by Jose that supports this).

Thoughts on a "fix"

Since this issue has long been fixed on the latest master of phoenix_html, this is an issue that mainly applies to fairly outdated (phoenix_html 2.10.2 was released July 24, 2017) this issue affects mainly existing phoenix-based projects that haven't been updating their dependencies but have updated the version of Elixir that they are using (intentionally or unintentionally). In practice I feel that this most often affects fairly unmaintained example phoenix projects (such as ueberauth_example), however as seen on https://github.com/ueberauth/ueberauth_example/issues/43 this means that beginners to the language who understandably often run a current version may run into this issue and not understand what to do. So I am filing this issue mainly as a way to document this incompatibility. In addition I will file a PR that updates ueberauth_example to work with Elixir 1.8.

Since the error message is so vague and is quite difficult to trace down to the line in question (since the form_tag line does not appear anywhere in the stacktrace rendered above) I am not sure that there is anything else to do besides fixing any example phoenix projects. If this condition could reasonably be detected within the Elixir EEx implementation itself we could emit a more useful warning but my gut feeling (without looking at the code) is that it would be too difficult to do so.

After reading this please feel free to mark this issue as closed if there is no further action to be taken.

josevalim commented 5 years ago

Let's go with the issue on Elixir.