Subscribe on changes!

`$setup.bar is not a function` with script setup

avatar
Sep 15th 2021

Version

3.2.11

Reproduction link

github.com

Steps to reproduce

Run npm run serve in the reproduction repository, go to http://localhost:8080/ and check the dev console

What is expected?

The code should work fine and we should see "Hello World" in the browser

What is actually happening?

I get an error about $setup.bar is not a function in the dev console

avatar
Sep 16th 2021

works fine in sfc, It's not a vue core bug. Maybe relate to vue-loader.

avatar
Sep 16th 2021

The compiler fails to detect that bar is actually used in the template. It seems to not handle the inline class expression correctly.

The error must be somewhere in this function:

https://github.com/vuejs/vue-next/blob/a6e5f82d8ea5fe55432d0277e88300045eca4237/packages/compiler-sfc/src/compileScript.ts#L1779-L1779

More specifically, it likely strips out the bar() call somewhere in this stripStrings function:

https://github.com/vuejs/vue-next/blob/a6e5f82d8ea5fe55432d0277e88300045eca4237/packages/compiler-sfc/src/compileScript.ts#L1824

It's not just the function signature though, as it works for a simple interpolation like {{ bar() }}.

PS: The repo project doesn't use the inlineTemplate compiler option while the SFC playground does, which explains why it works on the playground - in inlineTemplate mode, the compiler doesn't have to detect usage of imports in the template.

avatar
Sep 16th 2021

Okay, got it. It's actually the empty string that is tripping up stripStrings. If you use a non-empty Sting like so, it works:

<div
    :class="[
      foo ? 'xxx'  : bar(),
      'foo',
    ]"
  >

The issue is that the regex in stripStrings only matches if the quotation marks contain at least one character. This would be a fix to the issue but right now I'm not sure about potential side effects:

function stripStrings(exp) {
    return exp
-        .replace(/'[^']+'|"[^"]+"/g, '')
+        .replace(/'[^']*'|"[^"]*"/g, '')
        .replace(/`[^`]+`/g, stripTemplateString);
}