Subscribe on changes!

compiler-sfc: invalid declaration while using multiple variables with `defineEmits` and `defineProps`

avatar
Dec 28th 2022

Vue version

3.2.45

Link to minimal reproduction

https://sfc.vuejs.org/#eNqlkMFuwjAQRH/F8gWQcFykigMEpB567wf4EpINuIrt1doJQlH+vesArdQe69u8WXvGO8o3xGLoQe5kGWuymESE1OPReOswUBKjIGjFJFoKTix4dGF8HXxMwsWzOGR3udo/GVLAyLSB1nr4yGq5Whsv5gPOph/3PSt2hdan50TF7ksm9ZOcMtkzaYwv9b0jt2ORwGFXJWAlRHnZHMdx7jRNpWY1U+uxT2JQLjTQHYxk30i2Sv19W67l/avKVVh8xuB5GWO+bR5GNHInZpIZryBrIy8pYdxxMcAu3BQSDBauavu63SjFUyq2teKM25lC75vCQ+pseysqRM12Qb1P1kEB0akThWsE4ngjH+uakzTDAUgR+AYI6P/Jvx78k57DJ+MnOX0Byzq2CA==

Steps to reproduce

Define a set of variable with multiple declarations in SFC with <script setup>:

const props = defineProps(),
      emits = defineEmits(), //b
      a = 0, //c
      b = 0; //d

It will lead to wrong transpile result:

const , //b
      a = 0, //c
      b = 0; //d

What is expected?

It should be compiled into:

const a = 0, //c
    b = 0; //d

Without any syntax error.

What is actually happening?

This bug is introduced in #6778, compiler-sfc fixed a bug #6757, which is also related to multiple variable declaration. Can reproduce in #6778's sfc-playgroound preview, but works perfectly in #6777 and older version.

Briefly, it occurs while we're processing a macro token with define*, with the following steps: https://github.com/vuejs/core/blob/c6e5bda27d13554675d68dbe33b07f3474467aa6/packages/compiler-sfc/src/compileScript.ts#L1222-L1228

  • Get the actual position of the declaration of macros
  • Remove the variable declaration of macros, based on the position, it has different behavior in multiple declarations:
    • If the variable declaration is the first one, remove all the characters between the begin of current declaration and begin of next declaration
    • If the variable declaration is not the first one, remove all the characters between the end of previous declaration and end of current declaration

We can notice that, if the declaration is the last macro but not the last variable declaration, it will keep the redundant part of the declaration, which leads to the final syntax error.

To fix this issue, we can make the characters between the beginning of current and begin of next (if have) are unconditionally removed:

if (i < total - 1) {
    // not the last one, locate the start of the next
    end = node.declarations[i + 1].start + startOffset
}
if (i != 0) {
    // not first one, locate the end of the prev
    start = node.declarations[i - 1].end + startOffset
}

I will submit a PR trying to fix that if you like this solution.

System Info

No response

Any additional comments?

No response

avatar
Dec 28th 2022

@mnixry PR welcome.