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

Catastrophic backtracking bug #235

Closed
eight04 opened this issue Feb 27, 2022 · 1 comment · Fixed by #238
Closed

Catastrophic backtracking bug #235

eight04 opened this issue Feb 27, 2022 · 1 comment · Fixed by #238

Comments

@eight04
Copy link
Contributor

eight04 commented Feb 27, 2022

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

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
Copy link
Contributor Author

eight04 commented Feb 28, 2022

After changing the regex, I found that some tests failed:

mountComponentsInHtml.default({
page,
html: `<div class="svelte-datepicker"><div class="ejs-component" data-ejs-component="Datepicker" data-ejs-props="{ "a": "b" }" data-ejs-options="{ "loading": "lazy" }"></div></div>`,
hydrateOptions: undefined,
});
expect(hydrated).toEqual(['{"name":"Datepicker","props":{"a":"b"},"hydrateOptions":{"loading":"lazy"}}']);

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.

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

Successfully merging a pull request may close this issue.

1 participant