Subscribe on changes!

(runtime-core): Runtime error when mistakenly converting symbols to a string during props validation

avatar
Jun 2nd 2023

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#eNqFjsEKgzAQRH9lyaUWiqFXiULxBwSvuViNNWCSJVkLRfz3Rm2hhUJvO7uzb2ZmF8T0PimWMRFar5EgKJqwkFYbdJ6gdAah987AIeWrWO0HaaVtnQ3R/jBXN0IO9TYkR2kF31EREgUpg2NDKioAMZyLqvHKkuBx3FZbQkYqUC7ZjpMMeDwK/vHMTuwd/6Ntp3ptVeUdhmSGFZZBTV7bGyz/K5WDHrtXo+/Q5QneXWVa

Steps to reproduce

Steps to reproduce the bug from scratch (repro already has this covered):

  1. Pass a symbol as a prop value to a component that expects another type.
  2. Observe a runtime error since symbols can't be converted to string or number.

What is expected?

A classic warning about type mismatch, e.g. Invalid prop: type check failed for prop "propName". Expected String, got Symbol

What is actually happening?

A runtime error because getInvalidTypeMessage function is trying to convert the symbol to a string/number.

System Info

System:
    OS: macOS 12.4
    CPU: (10) arm64 Apple M1 Pro
    Memory: 92.69 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
    npm: 8.19.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
  Browsers:
    Chrome: 114.0.5735.90
    Firefox: 112.0.2
    Safari: 15.5
  npmPackages:
    vue: ^3.3.4 => 3.3.4

Any additional comments?

The fix could be pretty straightforward: check if we have a symbol in styleValue function and do not convert a value to anything else since it won't be useful anyway.

I'm going to submit a PR that fixes this issue.

avatar
Jul 12th 2023

I was about to create an issue for this, but last minute i found this one. From my testing the bug was introduced in 3.3.0-alpha.13, alpha 12 was still working.

would love to see this fixed :)

avatar
Jul 12th 2023

@dodgex I believe that this bug has been around for a while since the affected part of the code hasn't been changed in ~4 years. It seems you can reproduce it on almost every 3.x version, not only 3.3.x.

avatar
Jul 12th 2023

@mattersj my project is on 3.2.45 and i have multiple components using symbols (InjectionKey to be accurate) as props. and with 3.3.4 i got this issue.

I tested alpha.1, .6, .12 and .13 aswell as .beta1 and the 3.3.0 release. with versions <= alpha.12 it worked; with >= alpha.13 I got the Cannot convert a Symbol value to a string runtime error.

I even had a project prepared to reproduce my issue working with .12 and failing with .13+, but then i found this issue and deleted it... if necessary i could recreate it later or tomorrow.

avatar
Jul 12th 2023

@dodgex I think you're talking about slightly different issue here:

Since 3.3 (probably, specifically alpha.13 as you mentioned) Vue has changed the way types get resolved and this is also true for InjectionKey. That means that previously (<= alpha.12), InjectionKey wasn't resolved properly and the type was null so you could pass basically anything and it worked fine, but from alpha.13 things changed and InjectionKey is now resolved to an Object constructor instead of a Symbol one, so when you pass a symbol and Vue expects an object, you hit the error we're talking about in this subject, because Vue tries to convert this symbol to a string.

That way, you just encountered another bug related to a type resolving, so feel free to open a new issue if one is not created yet.

P.S. as a temporary solution you can replace InjectionKey with just Symbol and it should work fine.

avatar
Jul 14th 2023

I tried to recreate the repro for a new issue as you suggested but now it seems to work in a blank vue project. No Idea what i did diffrent 2 days ago when testing it.

But what I found is that it somehow relates my tsconfig.json. When using my tsconfig in the blank project it fails; with the tsconfig(s) setup generated by npm init vue@latest it works. Sadly using the generated files breaks the whole project and sadly I currently do not have the time to fix the whole project (have to replace all import statements that import types to import type; and what ever comes after this).

For now i might have to abort and delay the upgrade to vue3.3; but in case you can see an issue and have a suggestion what could be causing this, i leave my tsconfig below.

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "lib": [
      "esnext",
      "dom"
    ],
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue"
  ]
}

Thanks and sorry for hijacking this issue.