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

Throw error if closing tag contains Muststache Statement #982

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

camerondubas
Copy link

@camerondubas camerondubas commented Oct 23, 2019

Edit: Changed entire description since it was no longer relevant.

This PR resolves #978 by Checking the state of the the tokenizer whenever it hits a MustacheStatement and throws a SyntaxError if the tokenizer is in in an EndTag

Quite open to feedback on this approach! As well as what the error message should be say exactly.


assert.throws(() => {
parse('\nbefore <div><span></span {{some-modifier}}></div>');
}, 'Error: Invalid end tag `div` (on line 2). (closing tags cannot contain modifiers).');
Copy link
Contributor

Choose a reason for hiding this comment

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

should error point into span instead of div?

Copy link
Author

Choose a reason for hiding this comment

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

@lifeart Thanks for this! You're absolutely right. This comment made me realize my tests weren't actually testing correctly, which lead me down the path the determining how to solve this whole issue much more elegantly.

@@ -148,6 +148,15 @@ export abstract class HandlebarsNodeVisitors extends Parser {
);

case TokenizerState.beforeAttributeName:
if (this.currentNode && this.currentNode.type === 'EndTag') {
Copy link
Member

Choose a reason for hiding this comment

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

I'm surprised we enter this state during a close tag 🤔

Copy link
Author

Choose a reason for hiding this comment

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

I was surprised as well. This state is hit in this scenario: <div></div {{some-modifier}}>, and it was actually already throwing this error"Error: expected start tag" which is triggered in the this.currentStartTag call on line 160, but doesn't really describe the error accurately.

currentStartTag snippet:

  get currentStartTag(): Tag<'StartTag'> {
    let node = this.currentNode;
    assert(node && node.type === 'StartTag', 'expected start tag');
    return node as Tag<'StartTag'>;
  }

If you comment out this if check, two of the tests I added will fail, throwing the expected start tag error instead of the one added in this PR.

Copy link
Member

Choose a reason for hiding this comment

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

OK, gotcha, thank you for explaining.

I believe what is going on is that the HTML spec requires the tagname immediately after the </.

See the spec info here:

https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state

And our implementation here:

https://github.com/tildeio/simple-html-tokenizer/blob/691662c9f00aec719d0eec8e622ed99935119c55/src/evented-tokenizer.ts#L482-L491

I think essentially we want an else to the if above that throws a useful error (RE: invalid end tag). I think that would look something like:

    endTagOpen() {
      let char = this.consume();

      if (char === '@' || char === ':' || isAlpha(char)) {
        this.transitionTo(TokenizerState.endTagName);
        this.tagNameBuffer = '';
        this.delegate.beginEndTag();
        this.appendToTagName(char);
      } else {
        this.delegate.reportSyntaxError('invalid closing tag');
      }
    }

Would you be interested in working on a fix over in simple-html-tokenizer also?

Copy link
Member

Choose a reason for hiding this comment

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

I also think this is a bit wrong:

https://github.com/tildeio/simple-html-tokenizer/blob/691662c9f00aec719d0eec8e622ed99935119c55/src/evented-tokenizer.ts#L266-L282

We have created the endTagName state, and made it essentially the same as the tagName state (the spec actually says to use the tagName state (see here), but thats a tad bit difficult for us). But honestly, I don't think we actually are allowed to enter those other states (beforeAttributeName and selfClosingStartTag). We should probably add errors there too.

Copy link
Author

Choose a reason for hiding this comment

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

I'll make an attempt at fixing those issues in Simple HTML Tokenizer this weekend. I'll open a PR with the fixes, or an issue, if I'm unable to come up with solutions

Thanks for looking into this!

Copy link
Author

Choose a reason for hiding this comment

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

Made a PR here tildeio/simple-html-tokenizer#73 would love feedback 😄

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.

[@glimmer/syntax] disallow modifier usage in closing tag
3 participants