Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exponential increase in generated code when there are multiple nested hiccup2.core/html calls #210

Open
luontola opened this issue Mar 11, 2024 · 2 comments

Comments

@luontola
Copy link
Contributor

luontola commented Mar 11, 2024

This is similar to #205 but less common. Consider the following code:

(ns example
  (:require [clojure.walk :as walk]
            [hiccup2.core :as h]))

(walk/macroexpand-all
 `(h/html
   [:p (identity "") "foo"]
   (identity (h/html
              [:p (identity "") "bar"]
              (identity (h/html
                         [:p (identity "") "gazonk"]

In the generated code, foo will appear 8 times, bar 64 times, and gazonk 512 times.

If you try to evaluate this code normally (i.e. without macroexpand-all), it will throw "IndexOutOfBoundsException: Method code too large!"

Each level of nesting multiplies the code by 8, because every h/html checks hiccup.util/*html-mode* and hiccup.util/*escape-strings?* again and generates the 8 code paths.

Is there a way for a Clojure macro to recognize that it's nested within itself? Then those 8 code paths could be generated at only the outermost h/html, and the inner macros could use the same html and escape mode as the outermost macro.

Hiccup version 2.0.0-RC3

Workaround

Extract the inner html macro call to a function, so that you won't have many nested html macros.

@weavejester
Copy link
Owner

Macros are evaluated from the outside in, so we could certainly look through the syntax tree and do something to reduce the nesting. There may also be a better solution to the problem, but keeping the API backward compatible ties our hands somewhat.

@luontola
Copy link
Contributor Author

luontola commented Mar 20, 2024

If html receives an options map with :mode and :escape-strings?, will it then generate only one code variant? Could then the outermost html insert matching options maps to the nested html forms?

Alternatively, create a new internal function similar to compile-html-with-bindings, but for generating only one code variant, and replace the nested html forms with that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants