Subscribe on changes!

Multi statement on handlers without semicolon result in a parsing error

avatar
Jul 27th 2023

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#__DEV__eNqNUU1PAjEQ/StNL2IC2wOeCBKUcNDEj6jHvSzdAQrbj7RTloTw3227gCui8dZ5M/PevNcdvTMm23igAzpEkKYqEEa5ImQ484haxSchY14Jvr7NaVMSkurO9cWymUokk4iTJ0iErGEMjSFrSYXScSsMEgfoTUDmXnEUWh1pyS7u10KVus6KCix2rrTny6sguI9szf6IdqmQRlvsycJkK6dVcJV280PD5XTQsEUs2I51TpeIxg0Y46UKayVUYmMzBciUkWwcxpj1CoWEXqnluJ/1sxtWCodtOAMnezOrawc2kOS025JhAdyA7VlQJViw/5U9W2tLn7V+yEf1EM4+hIKOazUXi7NIuJZGhDRfTAz7ezRFVen6MWFoPZy88CXw9QV85baNp1cL6bKWfyzsArBpT9+fYRvep6bUpa8O3/BL8w2crny8sRm796oMZ7fm0rUP6YeFWny46RZBuaOpeGhKI82n/5j8Yf3r3JD2KcX9J3ZjDRU=

Steps to reproduce

After opening the link you will see an error in the editor pane that is copied below.

(3:13) Error parsing JavaScript expression: Unexpected token, expected "," (3:6)

What is expected?

The multi-statement on-handler will parse correctly and not fail as it is valid javascript.

These types of on-handler expressions work in the Vue 2.7 world.

What is actually happening?

The Vue template compiler is complaining about unexpected tokens, as a result, it does not function.

System Info

No response

Any additional comments?

I have established that if a semicolon is placed within the on-handler expression then it succeeds.

This can be seen in this reproduction-with-semicolon

This appears to be related to the simple check to see whether there are multiple statements in the on-handler based on the presence of a semicolon as found here https://github.com/vuejs/core/blame/3be4e3cbe34b394096210897c1be8deeb6d748d8/packages/compiler-core/src/transforms/vOn.ts#L91

Locally I have found that if I say the expression is always a multi-statement then things work as expected from the compiler point of view. What other implications there would be with always assuming the statement is a multi-statement I am unsure of.

A very narrow replication of the error can be done using the following code.

import {compileTemplate} from '@vue/compiler-sfc';

compileTemplate({
    id: 'tmp123',
    source: `
    <button
        @click="
          foo()
          foo()
        "
    >
    </button>
    `
})
avatar
Jul 27th 2023
<script setup>
function click() {
  window.alert('ouch');
}
</script>

<template>
  <button
    @click="
      click();
      click();
    "
  >
    Click Me
  </button>
</template>
avatar
Jul 27th 2023

@Shyam-Chen I am aware that adding semicolons will make it work.

I came across this when looking to port a vue2-based application to vue-3 that uses prettier formatting without semicolons.

An example formatting via prettier can be seen in this prettier-playground

I have seen there is an issue https://github.com/prettier/prettier/issues/14270 but it was not immediately clear that it was a prettier formatting issue.

avatar
Sep 7th 2023

Alternative solution if you want to keep semi rule to false:

<template>
  <button
    @click="[click(), click()]"
  >
    Click Me
  </button>
</template>