Skip to content

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

@mnixry

Description

@mnixry

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:

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

  • 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions