Elderjs / elderjs

Elder.js is an opinionated static site generator and web framework for Svelte built with SEO in mind.
https://elderguide.com/tech/elderjs/
MIT License
2.11k stars 53 forks source link

Catastrophic backtracking bug #235

Closed eight04 closed 2 years ago

eight04 commented 2 years ago

https://github.com/Elderjs/elderjs/blob/bf528f1a20da10586467ce6c891d5bf3eafe3c79/src/partialHydration/mountComponentsInHtml.ts#L17 This runs forever when:

  1. There are many ejs components.
  2. The last item <\/\1> doesn't match.

This happens naturally when there is another tag stick with ejs component. Here is an example:

<p><div class="ejs-component" data-ejs-component="Fumen" data-ejs-props="{blabla}" data-ejs-options="{blabla}"></div>
... and more ejs components ...
  1. The first capturing group matches p><div.
  2. The last item </p><div> can't match </div> in the file.
  3. All [^]*? expand down to the entire file.
  4. Still doesn't match. So it backtracks and test the previous [^]*? down to the entire file...

I think it will be better to write it as:

 /<([^<]+) class="ejs-component[^"]*" data-ejs-component="([A-Za-z]+)" data-ejs-props="({[^"]*})" data-ejs-options="({[^"]*})"><\/\1>/gim

Ensure that:

  1. The last item is a valid tag.
  2. Even if the last item doesn't match, it doesn't expand down to the entire file.

After the fix, the build time reduces from 5 minutes to 9 seconds.

eight04 commented 2 years ago

After changing the regex, I found that some tests failed: https://github.com/Elderjs/elderjs/blob/bf528f1a20da10586467ce6c891d5bf3eafe3c79/src/partialHydration/__tests__/mountComponentsInHtml.spec.ts#L36-L41 It this a valid use case? While debugging the server, I saw data like " were encoded into &quote; to produce valid HTML. But the test file doesn't seem to quote them. It is not valid svelte syntax either.