Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compiler-core): allow directive modifiers to be dynamic (fix #8281) #12913

Open
wants to merge 5 commits into
base: minor
Choose a base branch
from

Conversation

Fuzzyma
Copy link

@Fuzzyma Fuzzyma commented Feb 19, 2025

fix #8281

This PR adds dynamic modifiers for directives

<div v-foo.[myModifiers]="5" />

const myModifiers = {
  mod1: true,
  mod2: false
}

It also adds error states for empty modifiers (v-foo.="5") and handles empty dynamic modifiers or invalid values e.g. v-foo.[]="5", v-foo.[123]="5".

I skipped modifiers with invalid values. I am not sure if that is a problem. Otherwise codegen would be corrupted (it was before for empty values already. That's also fixed with that).

I also had to change modifiers to be an Expression instead of SimpleExpression so that I can use parseExpression with it. That means I had to cast to SimpleExpression at a few places

@Fuzzyma Fuzzyma changed the title Allow dynamic directive modifiers feat(compiler-core): allow directive modifiers to be dynamic (fix #8281) Feb 19, 2025
@Fuzzyma
Copy link
Author

Fuzzyma commented Feb 19, 2025

I developed on top of the main branch but the guidelines say to submit against minor. Now I have this extra commits in my history. Not sure how to handle this

@edison1105 edison1105 changed the base branch from minor to main February 20, 2025 05:50
@edison1105 edison1105 changed the base branch from main to minor February 20, 2025 05:51
@edison1105
Copy link
Member

I developed on top of the main branch but the guidelines say to submit against minor. Now I have this extra commits in my history. Not sure how to handle this

fixed by merging main into the minor branch.

Copy link

github-actions bot commented Feb 20, 2025

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 102 kB 38.4 kB 34.6 kB
vue.global.prod.js 160 kB (+838 B) 58.5 kB (+230 B) 52.1 kB (+288 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 47.1 kB 18.5 kB 16.9 kB
createApp 55.7 kB 21.6 kB 19.7 kB
createSSRApp 59.9 kB 23.3 kB 21.2 kB
defineCustomElement 60.5 kB 23.2 kB 21.1 kB
overall 69.8 kB 26.7 kB 24.3 kB

Copy link

pkg-pr-new bot commented Feb 20, 2025

Open in Stackblitz

@vue/compiler-core

npm i https://pkg.pr.new/@vue/compiler-core@12913

@vue/compiler-dom

npm i https://pkg.pr.new/@vue/compiler-dom@12913

@vue/compiler-ssr

npm i https://pkg.pr.new/@vue/compiler-ssr@12913

@vue/compiler-sfc

npm i https://pkg.pr.new/@vue/compiler-sfc@12913

@vue/reactivity

npm i https://pkg.pr.new/@vue/reactivity@12913

@vue/runtime-core

npm i https://pkg.pr.new/@vue/runtime-core@12913

@vue/runtime-dom

npm i https://pkg.pr.new/@vue/runtime-dom@12913

@vue/server-renderer

npm i https://pkg.pr.new/@vue/server-renderer@12913

@vue/shared

npm i https://pkg.pr.new/@vue/shared@12913

vue

npm i https://pkg.pr.new/vue@12913

@vue/compat

npm i https://pkg.pr.new/@vue/compat@12913

commit: e4fd227

@edison1105
Copy link
Member

Thank you very much for your contribution. This PR is really great. I did a quick test and found the following issues.

  • v-model dynamic modifiers on component

the following template

<template>
  <Comp v-model.[mod]="msg"/>
</template>

should be compiled to:

_createVNode($setup["Comp"], {
      modelValue: $setup.msg,
      "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => (($setup.msg) = $event)),
-      modelModifiers: { "$setup.mod": true }
+      modelModifiers: Object.assign({}, $setup.mod)
    }, null, 8 /* PROPS */, ["modelValue"])

  • v-model static modifiers + dynamic modifiers on component

the following template

<template>
 <Comp v-model.number.[mod]="msg"/>
</template>

should be compiled to:

_createVNode($setup["Comp"], {
      modelValue: $setup.msg,
      "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => (($setup.msg) = $event)),
-      modelModifiers: { number: true, "$setup.mod": true }
+      modelModifiers: Object.assign({number:true}, $setup.mod)
    }, null, 8 /* PROPS */, ["modelValue"])

  • v-model dynamic modifiers with plain object on component

the following template should not cause a compilation error. see Playground with this PR

<Comp v-model.[{ number: true }]="msg"/>

@Fuzzyma
Copy link
Author

Fuzzyma commented Feb 20, 2025

@edison1105 thanks for the super fast feedback. Am I correct to assume, that your failing cases are specific to the v-model directive or does it happen with any other? (it shouldnt)

For the last error: The "expression missing" error shadows the "whitespace forbidden" error. The same happens if you use whitespaces in the dynamic argument:

Playground link

When I tried try this with the template-explorer it correctly showed the error for other directives that are not v-on or v-model: End bracket for dynamic directive modifier was not found. Note that dynamic directive modifier cannot contain spaces.:

Playground link

Since this is already bahavior thats valid for args, maybe its ok for modifiers as well? Wdyt?

I am not against allowing spaces in dynamic args and modifiers but I am pretty sure it would break formatters and syntax highlighters. I guess thats also the reason why its not supported.

I would have written a test for that as well but I couldnt find where to put it.

@Fuzzyma
Copy link
Author

Fuzzyma commented Feb 20, 2025

I have a bit of duplicated code now. Let me know if I should refactor that and if so, where I put helper functions for such things

@edison1105
Copy link
Member

I have a bit of duplicated code now. Let me know if I should refactor that and if so, where I put helper functions for such things

We can just put them in transformElement.ts, which will be fine.

@edison1105 edison1105 linked an issue Feb 24, 2025 that may be closed by this pull request
@Fuzzyma
Copy link
Author

Fuzzyma commented Feb 24, 2025

Had to complicate the if statements a bit to deduplicate the logic but I think its all good now.
The shared function also has the benefit of reusing the SimpleExpression case for all modifiers. So if those mods are ever checked for its patch flags, they will be constant (currently they are always patched i think?).

@edison1105
Copy link
Member

/ecosystem-ci run

@vue-bot
Copy link
Contributor

vue-bot commented Feb 24, 2025

📝 Ran ecosystem CI: Open

suite result latest scheduled
language-tools failure success
nuxt success success
pinia success success
primevue success success
quasar success success
radix-vue success success
router success success
test-utils success success
vant success success
vite-plugin-vue success success
vitepress success success
vue-i18n success success
vue-macros failure failure
vuetify failure success
vueuse success success
vue-simple-compiler success success

@edison1105 edison1105 added the ready for review This PR requires more reviews label Feb 24, 2025
@edison1105
Copy link
Member

Thanks @Fuzzyma
Nick work and LGTM~

@Fuzzyma
Copy link
Author

Fuzzyma commented Feb 24, 2025

Seems like I broke some runtime directive in vuetify :D. Have to check that...
language-tools is mostly ast problems i think.

Guess I have some more work to do. What is the process for this? Do I open a PR in language tools to support the new ast shape and get that merged before this PR gets merged?

@Fuzzyma
Copy link
Author

Fuzzyma commented Feb 24, 2025

@edison1105 can i somehow checkout this PR ins vue-sfc to test it easily?

@edison1105
Copy link
Member

edison1105 commented Feb 24, 2025

@Fuzzyma

can i somehow checkout this PR ins vue-sfc to test it easily?

We can use the following version to install the PR preview package

npm i https://pkg.pr.new/vue@12913 
// or 
npm i https://pkg.pr.new/vue@e4fd227 // latest commit 

Do I open a PR in language tools to support the new ast shape and get that merged before this PR gets merged?

We should wait for this PR to be shipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready for review This PR requires more reviews ✨ feature request New feature or request version: minor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow to pass an object of modelModifiers to native inputs
3 participants