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

Incorrect compiled code when usinig multiline v-if on template element as a slot renderer #9114

Closed
maguszoldik opened this issue Nov 27, 2018 · 5 comments · Fixed by #9119
Closed

Comments

@maguszoldik
Copy link

Version

2.5.17

Reproduction link

https://template-explorer.vuejs.org/#%3Cdiv%3E%0A%20%20%20%20%3Ctemplate%0A%20%20%20%20%20%20slot%3D%22row_expander%22%0A%20%20%20%20%20%20slot-scope%3D%22%7B%0A%20%20%20%20%20%20%20%20row%0A%20%20%20%20%20%20%7D%22%0A%20%20%20%20%20%20v-if%3D%22%0A%20%20%20%20%20%20%20%20longCondition1%20%26%26%0A%20%20%20%20%20%20%20%20anotherLongCondition%20%3D%3D%3D%20'my%20awesome%20result'%20%26%26%0A%20%20%20%20%20%20%20%20anotherWhichBreakTheLineLength%0A%20%20%20%20%20%20%22%0A%20%20%20%20%3E%0A%20%20%20%20%20%20%3Csomething%20%2F%3E%20%3Csomething%20%2F%3E%0A%20%20%20%20%3C%2Ftemplate%3E%0A%20%3C%2Fdiv%3E

Steps to reproduce

When using a v-if which match these 3 conditions:

  • written on multiple line (first condition on next line)
  • defined on a template element
  • the template use the slot property

…then the template compiler does not encapsulate the code in parenthesis, leading to improper condition.

See the provided Vue Template Explorer for the following code:

<div>
    <template
      slot="row_expander"
      slot-scope="{
        row
      }"
      v-if="
        longCondition1 &&
        anotherLongCondition === 'my awesome result' &&
        anotherWhichBreakTheLineLength
      "
    >
      <something /> <something />
    </template>
 </div>

What is expected?

The return of scopedSlots.fn must encapsulate the condition inside parenthesis.

function render() {
  with(this) {
    return _c('div', {
      scopedSlots: _u([{
        key: "row_expander",
        fn: function ({
          row
        }) {
          return (
            longCondition1 &&
            anotherLongCondition === 'my awesome result' &&
            anotherWhichBreakTheLineLength
           ) ? [_c('something'), _c('something')] : undefined
        }
      }])
    })
  }
}

What is actually happening?

The return statement is incorrect.

function render() {
  with(this) {
    return _c('div', {
      scopedSlots: _u([{
        key: "row_expander",
        fn: function ({
          row
        }) {
          return
          longCondition1 &&
            anotherLongCondition === 'my awesome result' &&
            anotherWhichBreakTheLineLength ?
            [_c('something'), _c('something')] : undefined
        }
      }])
    })
  }
}

This is related to the usage of Prettier which automatically break on multiple lines the condition if it is too long (see prettier/prettier#5561)

@posva posva changed the title Incorrect compiled code when usinig multiline v-if on template element as a slot renderer Incorrect compiled code when usinig multiline v-if on template element as a slot renderer in vue template explorer Nov 27, 2018
@posva posva changed the title Incorrect compiled code when usinig multiline v-if on template element as a slot renderer in vue template explorer Incorrect compiled code when usinig multiline v-if on template element as a slot renderer Nov 27, 2018
@posva
Copy link
Member

posva commented Nov 27, 2018

as a workaround, one can put parenthesis themselves. I think we could add wrapping parenthesis if the expression starts with a newline

@maguszoldik
Copy link
Author

In my case, I simply can't put the parenthesis, they are stripped out automatically by Prettier.
As a workaround I moved the v-if to children, where it worked fine and is probably a better option in my case.

But the issue is still valid and I think the same, the expression should be wrapped.

@subu28
Copy link
Contributor

subu28 commented Nov 28, 2018

I think i am missing something here. Will both return statements not evaluate to the same thing? I checked the operator precedence and checked the syntax tree generated(assuming http://esprima.org/demo/parse.html is reliable).

Would like to work on this once i understand what i am missing.

@posva
Copy link
Member

posva commented Nov 28, 2018 via email

@subu28
Copy link
Contributor

subu28 commented Nov 28, 2018

I got it. I will look at the code and get back with my thoughts.

I will check the side effects of trying to remove newlines or replacing them with spaces from the statement.
EDIT: I will go with adding the brackets.

subu28 pushed a commit to subu28/vue that referenced this issue Nov 28, 2018
…ng paranthesis for v-if conditi

the generated code for elements with template in scopedslots was wrong when multiline v-if starting
with a newline was used

fix vuejs#9114
subu28 pushed a commit to subu28/vue that referenced this issue Nov 29, 2018
…ng paranthesis for v-if conditi

the generated code for elements with template in scopedslots was wrong when multiline v-if starting
with a newline was used

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

Successfully merging a pull request may close this issue.

3 participants