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

fix(v2): render issue #6610

Merged
merged 4 commits into from
Jun 29, 2024
Merged

fix(v2): render issue #6610

merged 4 commits into from
Jun 29, 2024

Conversation

Varixo
Copy link
Member

@Varixo Varixo commented Jun 26, 2024

This PR fixes render issue

@Varixo Varixo requested a review from a team as a code owner June 26, 2024 15:52
Comment on lines 461 to 462
let lastIdx = 0;
let openAngleBracketIdx: number = -1;
while ((openAngleBracketIdx = text.indexOf('<', openAngleBracketIdx + 1)) !== -1) {
this.write(text.substring(lastIdx, openAngleBracketIdx));
this.write('&lt;');
lastIdx = openAngleBracketIdx + 1;
}
this.write(lastIdx === 0 ? text : text.substring(lastIdx));
this.write(escapeContent(text));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhevery can we replace this code with just escapeContent?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the previous code was way more efficient. RegExp are a bit expensive. So it would be better for streaming if we could fix up the old code to take this into account (OR to rewrite the escapeContent to not use RegExp) Normally I would not care but invoking the RegExp for each text node will add up. Do you need help rewriting this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote this code:

    const escapeCharacterMap = new Map([
      ['<', '&lt;'],
      ['>', '&gt;'],
      ['&', '&amp;'],
      ['"', '&quot;'],
      ["'", '&#39;'],
    ]);
    let data = '';
    for (const character of text) {
      const escapeCharacter = escapeCharacterMap.get(character);
      if (escapeCharacter) {
        this.write(data);
        this.write(escapeCharacter);
        data = '';
      } else {
        data += character;
      }
    }
    if (data.length) {
      this.write(data);
    }

Do you have another idea how to do this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Map look ups are also expensive. You want to do a scan.

export function escapeHTML(html: string): string {
  let escapedHTML = "";
  const length = html.length;
  let idx = 0;
  let lastIdx = idx;
  for (; idx < length; idx++) {
    // We get the charCode NOT string. String would allocate memory.
    const ch = html.charCodeAt(idx);
    // Every time we cancat a string we allocate memory. We want to minimize that.
    if (ch === 60 /* < */) {
      escapedHTML += html.substring(lastIdx, idx) + '&lt;'
    } else if (ch === 62 /* > */) {
      escapedHTML += html.substring(lastIdx, idx) + '&gt;'
    } else if (ch === 38 /* & */) {
      escapedHTML += html.substring(lastIdx, idx) + '&amp;'
    } else if (ch === 34 /* " */) {
      escapedHTML += html.substring(lastIdx, idx) + '&quot;'
    } else if (ch === 39 /* ' */) {
      escapedHTML += html.substring(lastIdx, idx) + '&#39;'
    } else {
      continue;
    }
    lastIdx = idx + 1;
  }
  if (lastIdx === 0) {
    // This is most common case, just return previous string no memory allocation.
    return html;
  } else {
    // Add the tail of replacement.
    return escapedHTML + html.substring(lastIdx);
  }
}

it('escapeHTML', () => {
  expect(escapeHTML("text")).toEqual("text");
  expect(escapeHTML("<div a='b' c=\"d\">text")).toEqual("&lt;div a=&#39;b&#39; c=&quot;d&quot;&gt;text");
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is MORE code, but it will run way faster at runtime.

Comment on lines 461 to 462
let lastIdx = 0;
let openAngleBracketIdx: number = -1;
while ((openAngleBracketIdx = text.indexOf('<', openAngleBracketIdx + 1)) !== -1) {
this.write(text.substring(lastIdx, openAngleBracketIdx));
this.write('&lt;');
lastIdx = openAngleBracketIdx + 1;
}
this.write(lastIdx === 0 ? text : text.substring(lastIdx));
this.write(escapeContent(text));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the previous code was way more efficient. RegExp are a bit expensive. So it would be better for streaming if we could fix up the old code to take this into account (OR to rewrite the escapeContent to not use RegExp) Normally I would not care but invoking the RegExp for each text node will add up. Do you need help rewriting this?

Varixo and others added 2 commits June 29, 2024 21:07
---------

Co-authored-by: Miško Hevery <misko@hevery.com>
@Varixo Varixo merged commit 6f3818b into QwikDev:build/v2 Jun 29, 2024
18 checks passed
@Varixo Varixo deleted the v2-render-issue branch June 29, 2024 19:29
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 this pull request may close these issues.

2 participants