Compare commits

...

556 Commits
v3.5.4 ... main

Author SHA1 Message Date
daiwei c68bebfa6d release: v3.5.26
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-12-18 20:09:04 +08:00
linzhe e857e12c0a
fix(runtime-core): pass component instance to flushPreFlushCbs on unmount (#14221)
close #14215
2025-12-18 16:31:08 +08:00
edison f33b308102
types(defineProps): avoid never props becoming boolean flags (#14059)
close #14056
2025-12-18 16:30:07 +08:00
linzhe 94aeb64ccd
fix(runtime-core): handle patch stable fragment edge case (#12411)
close #12410
2025-12-18 16:28:23 +08:00
yangxiuxiu ed85953e28
fix(compat): fix compat handler of draggable (#12445)
fix #12444
2025-12-18 16:26:16 +08:00
edison 4783118919
fix(compiler-ssr): handle ssr attr fallthrough when preserve whitespace (#12304)
close #8072
2025-12-18 16:25:23 +08:00
Michael Cozzolino 6611dda298
types(runtime-core): export DirectiveModifiers type (#14198) 2025-12-18 16:24:44 +08:00
edison e24ff7d302
fix(compiler-sfc): demote const reactive bindings used in v-model (#14214)
close #11265
close #11275
2025-12-18 16:24:07 +08:00
edison 69ce3c7d75
fix(hmr): handle cached text node update (#14134)
close #14127
2025-12-18 16:23:25 +08:00
一寸灰 1904053f1f
perf(compiler-core): use binary-search to get line and column (#14222) 2025-12-18 16:19:36 +08:00
linzhe f5b3bf264d
fix(runtime-core): ensure correct anchor el for deeper unresolved async components (#14182)
close #14173
2025-12-18 16:15:25 +08:00
edison 945a543152
fix(compat): handle v-model deprecation warning with missing appContext (#14203)
close #14202
2025-12-18 16:14:53 +08:00
huangxiuqi dfe667c856
fix(KeepAlive): use resolved component name for async components in cache pruning (#14212)
close #14210
2025-12-18 16:14:22 +08:00
renovate[bot] d8a2de4485
chore(deps): update dependency vite to v5.4.21 [security] (#13556)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
2025-12-15 15:48:22 +08:00
Konstantin Telyakov 1e34871149
chore(deps): update entities to latest for Node.js 24 compatibility (#14160)
Co-authored-by: Konstantin <ktelyakov@gmail.com>
Co-authored-by: daiwei <daiwei521@126.com>
2025-12-15 15:47:56 +08:00
renovate[bot] 965641af39
chore(deps): update actions/checkout action to v6 (#14131) 2025-12-15 15:46:44 +08:00
renovate[bot] 918fd5a029
chore(deps): update test (#14068) 2025-12-15 15:46:00 +08:00
renovate[bot] f5adc4b8cd
chore(deps): update lint (#13671)
* chore(deps): update lint

* chore: format

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: edison <daiwei521@126.com>
2025-12-15 15:37:29 +08:00
renovate[bot] 9a51742176
fix(deps): update dependency monaco-editor to ^0.55.1 (#14130) 2025-12-15 15:29:15 +08:00
renovate[bot] 8c605cc3ef
chore(deps): update build (#14071) 2025-12-15 15:28:10 +08:00
renovate[bot] 22cd4a399a
fix(deps): update all non-major dependencies (#14070)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 15:15:07 +08:00
renovate[bot] 9d481f826d
chore(deps): update build (#14069)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 15:07:17 +08:00
renovate[bot] 5c461352fc
chore(deps): update dependency @types/node to v24 (#14072)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 15:01:33 +08:00
linzhe edbd5ec81b
chore: update warning message for missing temp dts files (#14186) 2025-12-15 09:22:24 +08:00
btea f51d3e2789
ci: `pkg-pr-new` publish add pm option (#14175)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
2025-12-08 10:47:00 +08:00
daiwei 44ee43848f docs: add Ben Zimmermann to the list of security researchers in SECURITY.md
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-12-05 08:32:19 +08:00
edison 92019e4a2d
chore(deps): update @vue/repl to version 4.7.1 (#14169)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-12-04 20:49:55 +08:00
daiwei 25ebe3a42c release: v3.5.25
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-11-24 15:38:02 +08:00
linzhe c0f63ddbfa
fix(suspense): defer clearing fallback vnode el in case it has dirs (#14080)
close #14078
2025-11-24 15:20:45 +08:00
edison 301020b481
fix(reactivity): correctly wrap iterated array items to preserve their readonly status (#14120) 2025-11-24 15:20:23 +08:00
skirtle 0d2357e697
fix(reactivity): toRef edge cases for ref unwrapping (#12420) 2025-11-24 15:19:41 +08:00
skirtle 247b2c2067
fix(provide): warn when using `provide` after mounting (#13954)
close #13921
close #13924
2025-11-24 14:54:12 +08:00
skirtle b50eb68c50
dx(runtime-core): check current and parent components in formatComponentName (#7220) 2025-11-24 14:50:43 +08:00
skirtle 5af3dd9b45
refactor(runtime-core): check `props` rather than `propsOptions[0]` (#13514) 2025-11-24 14:38:03 +08:00
skirtle 2214f7ab29
fix(compiler): share logic for comments and whitespace (#13550) 2025-11-24 11:18:11 +08:00
SerKo 8f82f23846
fix(runtime-core): keep options API typing intact when expose is used (#14118)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
Fixed: #14117
Fixed: vuejs/language-tools#5069
2025-11-20 08:59:42 +08:00
Vida Xie 83f6ab686d
chore(compiler-ssr): move `defaultProps` initialization into `input` tag branch (#14115)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-11-19 13:42:16 +08:00
Sean Wang 3942dbe613
types(jsx): add new HTML attributes for improved JSX support (#13370)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-11-18 08:53:01 +08:00
shuang f40baa2d50
types(jsx): correct the naming of the enterKeyHint property (#14090) 2025-11-18 08:33:44 +08:00
Stefano Nepa e9c676ff2b
chore(runtime-dom): export nodeOps and patchProp for better accessibility (#13753) 2025-11-10 09:38:05 +08:00
daiwei e131369833 release: v3.5.24
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-11-07 16:02:40 +08:00
殷谊辉 90ce838a94
chore(reactivity): remove duplicated ReactiveEffectRunner interface (#14063) 2025-11-07 14:04:03 +08:00
edison 11ec51aa5a
Revert "fix(compiler-core): correctly handle ts type assertions in expression…" (#14062)
This reverts commit e6544ac292.
Close #14060
2025-11-07 08:52:07 +08:00
daiwei 5cf0097f33 release: v3.5.23
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-11-06 08:27:08 +08:00
edison f411c6604c
fix(suspense): clear placeholder and fallback el after resolve to enable GC (#13928)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-11-05 21:53:06 +08:00
Jooies dc4dd594fb
fix(TransitionGroup): use offsetLeft and offsetTop instead of getBoundingClientRect to avoid transform scale affect animation (#6108)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
close #6105
2025-11-05 17:20:25 +08:00
indykoning 40c4b2a876
fix(runtime-core): pass props and children to loadingComponent (#13997) 2025-11-05 17:18:20 +08:00
zhiyuanzmj e6544ac292
fix(compiler-core): correctly handle ts type assertions in expressions (#13397)
similar to #13395
2025-11-05 17:17:49 +08:00
山吹色御守 75d44c7189
fix(compiler-sfc): resolve numeric literals and template literals without expressions as static property key (#13998) 2025-11-05 17:13:04 +08:00
沈青川 dcc6f36257
fix(compiler): using guard instead of non-nullish assertion (#13982) 2025-11-05 17:12:23 +08:00
rzzf 8fbe48fe39
fix(v-model): handle number modifier on change (#13959)
close #13958
2025-11-05 17:11:35 +08:00
edison 6cbdf7823b
fix(hydration): avoid mismatch during hydrate text with newlines in interpolation (#9232)
close #9229
2025-11-05 17:05:50 +08:00
Alex Snezhko 006a0c1011
fix(compiler-ssr): textarea with v-text directive SSR (#13975) 2025-11-05 17:05:29 +08:00
skirtle b8aab3d209
refactor(runtime-core): check feature flag when forwarding `data` properties (#13966) 2025-11-05 17:04:55 +08:00
edison 84ca349fef
fix(custom-element): optimize slot retrieval to avoid duplicates (#13961)
close #13955
2025-11-05 17:04:33 +08:00
Vida Xie 8ca2b3fbb7
chore(lint): replace deprecated `tseslint.config` and `prefer-ts-expect-error` (#13942) 2025-11-05 17:04:12 +08:00
clay jenson 5689884c8e
fix(runtime-dom): ensure iframe sandbox is handled as an attribute to prevent unintended behavior (#13950)
close #13946
2025-11-05 16:53:58 +08:00
edison b3cca2611c
fix(compiler-core): fix v-bind shorthand handling for in-DOM templates (#13933)
close #13930
2025-11-05 16:51:29 +08:00
Dylan Lathrum 8ec7cb12e4
types(runtime-core): add `undefined` to `NativeType` type (#13594)
close #13593
2025-11-05 16:50:58 +08:00
Alex Snezhko c13e674fb9
fix(custom-element): batch custom element prop patching (#13478)
close #12619
2025-11-05 16:50:00 +08:00
zhiyuanzmj 1df8990504
types(jsx-runtime): use interface instead of type for ReservedProps (#12385) 2025-11-05 16:35:37 +08:00
renovate[bot] d715e5f6f1
fix(deps): update dependency monaco-editor to ^0.54.0 (#13985)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:28:30 +08:00
renovate[bot] 475539c154
chore(deps): update actions/setup-node action to v6 (#13999)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:27:57 +08:00
renovate[bot] cd7c9a371c
chore(deps): update dependency pretty-bytes to v7 (#13968)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:27:35 +08:00
renovate[bot] c35e880f7f
chore(deps): update actions/upload-artifact action to v5 (#14022)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:27:10 +08:00
renovate[bot] 90d3ff4dec
chore(deps): update compiler (#14021)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:26:42 +08:00
renovate[bot] 7065cee4fd
chore(deps): update build (#13939)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:21:53 +08:00
renovate[bot] f00e5c7885
chore(deps): update all non-major dependencies (#13967)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:12:05 +08:00
renovate[bot] 2d65306949
chore(deps): update test (#13940)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:06:23 +08:00
edison 45547e69b2
docs: remove COMPILER_V_BIND_PROP (#13986)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
.prop was removed in 3.0. It was reintroduced in 3.2. 
see vuejs/core@1c7d737
2025-10-13 15:03:10 +08:00
skirtle 079010a38c
test(v-model): mutating an array or set checkbox value (#13974)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-10-09 10:16:11 +08:00
abeer0 2dbe30177f
chore: fix typo (#13973) 2025-10-09 09:28:26 +08:00
王二狗 c16f8a94c7
chore: fix typo. (#13948)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-10-04 09:46:30 +08:00
daiwei 5a8aa0b2ba release: v3.5.22
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-09-25 09:05:13 +08:00
Tobias Messner 1be5ddfe87
fix(transition-group): run `forceReflow` on the correct document (fix #13849) (#13853)
close #13849
2025-09-25 08:42:52 +08:00
renovate[bot] d44a5a98c8
chore(deps): update build (#13856)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-24 21:46:10 +08:00
renovate[bot] c8a99172cc
chore(deps): update dependency jsdom to v27 (#13913)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-24 21:45:42 +08:00
renovate[bot] b46481a47f
chore(deps): update compiler (#13857)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-24 21:40:59 +08:00
renovate[bot] 8593647e37
chore(deps): update test (#13882)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-24 21:40:29 +08:00
renovate[bot] f2487d86ea
chore(deps): update actions/github-script action to v8 (#13885) 2025-09-24 21:37:46 +08:00
renovate[bot] b374ec7ca9
chore(deps): update actions/setup-node action to v5 (#13912)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-24 21:36:44 +08:00
renovate[bot] 9612b95220
chore(deps): update all non-major dependencies (#13883)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-24 21:34:31 +08:00
Tony Wang 5953c9ff90
fix(compiler-core): identifiers in switch-case should not be inferred as references (#13923) 2025-09-24 21:33:48 +08:00
edison 565741a9b2
refactor(compiler): add separate transform for vbind shorthand (#13438)
close #13169
close #13170
close #11321
close #12298
close #12828

use tests from #13170 and #12298 and #12828
2025-09-24 21:23:07 +08:00
Matthias Hryniszak 47e628df1c
feat(custom-element): allow specifying additional options for `shadowRoot` in custom elements (#12965)
close #12964
2025-09-24 21:14:54 +08:00
edison 6b68f72673
Revert "fix(hmr): prevent __VUE_HMR_RUNTIME__ from being overwritten by vue runtime in 3rd-party libraries" (#13925)
This reverts commit 1392734ae5.
2025-09-24 18:02:05 +08:00
Massimiliano Torromeo 8bb8fb2362
fix(types): more precise types for Events and added missing definitions (#9675) 2025-09-24 17:56:28 +08:00
Alex Snezhko c4a88cdd0d
fix(custom-element): set prop runs pending mutations before disconnect (#13897)
close #13315
2025-09-24 17:42:11 +08:00
edison e388f1a09f
fix(compiler-sfc): enhance inferRuntimeType to support TSMappedType with indexed access (#13848)
close #13847
2025-09-24 17:29:38 +08:00
Arthur Darkstone fda47ac702
chore(types): improve type safety in watch functions and instanceWatch (#13918) 2025-09-24 17:21:41 +08:00
linzhe 5e1e791880
fix(custom-element): properly mount multiple Teleports in custom element component w/ shadowRoot false (#13900)
close #13899
2025-09-24 17:15:36 +08:00
Arman Tang 95c1975604
fix(compiler-dom): nodes with v-once shouldn't be stringified (#13878) 2025-09-24 17:13:44 +08:00
czhlin 4b7170625d
fix(types): widen directive arg type from string to any (#13758)
closes #13757
2025-09-24 17:12:25 +08:00
Daniel Roe 9c279517b9
fix(compiler-sfc): ensure css custom properties do not start with a digit (#13870) 2025-09-24 17:11:36 +08:00
edison aba7feda17
fix(reactivity): respect readonly during ref unwrapping (#13905)
close #13903
2025-09-24 17:10:49 +08:00
edison ba7f7f90f6
fix(compiler-sfc): add support for @vue-ignore in runtime type resolution (#13906) 2025-09-24 17:10:20 +08:00
edison 5358bca4a8
fix(custom-element): use PatchFlags.BAIL for slot when props are present (#13907)
close #13904
2025-09-24 17:08:25 +08:00
linzhe 836b82976f
fix(compiler-ssr): ensure v-show has a higher priority in SSR (#12171)
close #12162
2025-09-24 17:06:03 +08:00
山吹色御守 8620a616eb
fix(types): set dom stub type to `never` instead of `{}` (#13915)
re-fix #11564
2025-09-24 17:04:51 +08:00
yangdan8 2078f8b756
fix(reactivity): update iterator to check for completion instead of value presence (#13761) 2025-09-24 17:04:15 +08:00
edison abd563822a
fix(compiler-sfc): ensure props bindings register before compiling template (#13922)
close #13920
2025-09-24 17:03:47 +08:00
renovate[bot] b555f02eed
fix(deps): update playground (#13884) 2025-09-15 10:41:09 +08:00
daiwei 8c1f61d050 chore: format 2025-09-15 10:18:59 +08:00
codelo e5a6fe42ea
chore(docs): add missing commas 2025-09-15 10:08:36 +08:00
edison 75220c7995
fix(runtime-core): simplify block-tracking disabling in h() (#13841) 2025-09-03 09:13:09 +08:00
daiwei 4b6cb1f52a release: v3.5.21 2025-09-02 17:59:45 +08:00
yangxiuxiu 5d75a170c8
fix(Suspence): handle Suspense + KeepAlive HMR updating edge case (#13076)
close #13075
2025-09-02 17:44:13 +08:00
Alex Snezhko 55922ff316
fix(compiler-sfc): check lang before attempt to compile script (#13508)
close #8368
2025-09-02 17:39:29 +08:00
山吹色御守 1e8b65aa49
perf: improve regexp performance with non-capturing groups (#13567) 2025-09-02 17:30:02 +08:00
skirtle f2699a5cb3
fix(watch): use maximum depth for duplicates (#13434) 2025-09-02 17:29:08 +08:00
edison 99d54b28b4
fix(compiler-core): force dynamic slots when slot referencing scope vars (#9427)
close #9380
2025-09-02 17:24:56 +08:00
Red Huang 15fc75f403
fix(runtime-core): use separate emits caches for components and mixins (#11661) 2025-09-02 17:15:46 +08:00
Yang Mingshan 4810f1489f
chore(types): compatible with TS 5.8 (#12973) 2025-09-02 17:13:08 +08:00
edison 7171defb45
refactor: remove canary release workflows (#13794)
now using continuous release with pkg.pr.new
2025-09-02 17:12:42 +08:00
edison 26bce3dc6c
chore: update side effect annotations to use standardized format (#13839) 2025-09-02 17:12:19 +08:00
Andrei L 842a392ae5
types(jsx): add undefined to optional properties (#12771)
close #6068
2025-09-02 17:11:18 +08:00
edison 1392734ae5
fix(hmr): prevent __VUE_HMR_RUNTIME__ from being overwritten by vue runtime in 3rd-party libraries (#13817)
close vitejs/vite-plugin-vue#644
2025-09-02 17:10:30 +08:00
edison 8696e346b4
fix(compiler-sfc): support `${configDir}` in paths for TypeScript 5.5+ (#13491)
close #13484
2025-09-02 17:09:44 +08:00
edison 93ba107672
fix(templateRef): prevent unnecessary set ref on dynamic ref change or component unmount (#12642)
close #12639
2025-09-02 17:08:53 +08:00
linzhe 00978f7d14
fix(Teleport): hydrate disabled Teleport with undefined target (#11235)
close #11230
2025-09-02 17:08:15 +08:00
edison ef20b86b36
fix(hmr): prevent update unmounting component during HMR reload (#13815)
close vitejs/vite-plugin-vue#599
2025-09-02 17:07:36 +08:00
Daniel Roe 35da3c6dcb
fix(compiler-sfc): support global augments with named exports (#13789) 2025-09-02 17:03:16 +08:00
edison 8f6b505051
fix(runtime-core): disable tracking block in h function (#8213)
close #6913
2025-09-02 16:59:57 +08:00
Folee e322436887
fix(custom-element): prevent defineCustomElement from mutating the options object (#13791) 2025-09-02 16:56:33 +08:00
renovate[bot] d11cdd4a01
chore(deps): update build (#13799)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-01 16:44:46 +08:00
renovate[bot] ce9e6d1f4c
chore(deps): update test (#13801)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-01 16:44:14 +08:00
renovate[bot] bbf0f4cc44
chore(deps): update dependency npm-run-all2 to v8 (#13802)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-01 16:43:40 +08:00
renovate[bot] a28794edfa
chore(deps): update dependency magic-string to ^0.30.18 (#13800)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-01 15:32:53 +08:00
王二狗 63279661e8
chore: fix typo (#13833) 2025-09-01 14:37:31 +08:00
Ari Perkkiö 233b1250ce
chore(test): migrate to Vitest inline projects (#13838) 2025-09-01 13:59:34 +08:00
Zhong 24fccb4ee4
types(runtime-dom): improve event types (#13804)
close #13796
2025-08-25 15:25:10 +08:00
daiwei 3aa782df38 release: v3.5.20 2025-08-25 15:08:32 +08:00
edison 1031e8de08
fix(runtime-dom): add name to vShow for prop mismatch check (#13806)
close #13805
re-fix #13744
revert #13777

The implementation in #13777 requires users to configure __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__, otherwise errors like #13805 will occur.
2025-08-25 14:52:50 +08:00
Zhong 0f916d8c39
types(compiler-sfc): add explicit return type to genModelProps (#13441) 2025-08-23 21:32:53 +08:00
Zhong 952886e299
chore(compat): rename legacyresolveScopedSlots to legacyResolveScopedSlots
The changes correct the casing of a function name from legacyresolveScopedSlots to legacyResolveScopedSlots in both its definition and usage. No logic, control flow, or public API behavior is altered; only the symbol's casing is updated for consistency.
2025-08-23 21:30:50 +08:00
yangdan8 a48ffdad65
chore(reactivity): optimize size retrieval in createInstrumentations (#13759) 2025-08-21 17:52:55 +08:00
吴杨帆 cde15b07bf
chore: fix typo 2025-08-21 17:39:55 +08:00
daiwei 20b888bd59 release: v3.5.19 2025-08-21 10:29:08 +08:00
equt 0a202d890f
fix(compiler-ssr): disable v-memo transform in ssr vdom fallback branch (#13725)
close #13724
2025-08-21 10:03:16 +08:00
edison d9dd628800
fix(compiler-sfc): improve type inference for generic type aliases types (#12876)
close #12872
2025-08-21 09:48:40 +08:00
Alex Snezhko 4a2953f57b
fix(runtime-core): avoid setting direct ref of useTemplateRef in dev (#13449)
close 12852
2025-08-21 08:46:10 +08:00
renovate[bot] 19a0cbd431
chore(deps): update build (#13748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:21:14 +08:00
renovate[bot] 40d8d61c64
chore(deps): update test (#13734)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:20:44 +08:00
renovate[bot] 5bdb2b4693
chore(deps): update dawidd6/action-download-artifact action to v11 (#13774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:15:44 +08:00
renovate[bot] be7c7e57ac
chore(deps): update actions/checkout action to v5 (#13773)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:14:57 +08:00
renovate[bot] 40654d4aa4
chore(deps): update compiler (#13713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:14:32 +08:00
renovate[bot] 10edfb5fc0
chore(deps): update all non-major dependencies (#13733)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:14:18 +08:00
renovate[bot] 2a0382ca7a
chore(deps): update build (#13712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:14:03 +08:00
renovate[bot] 5eed143dd1
fix(deps): update dependency @vue/repl to ^4.6.3 (#13747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 22:13:36 +08:00
edison a8713159ee
fix(suspense): don't immediately resolve suspense on last dep unmount (#13456)
close #13453
2025-08-20 22:11:16 +08:00
Adrian Cerbaro 0562548ab3
fix(compiler-sfc): throw mismatched script langs error before invoking babel (#13194)
Close #13193
2025-08-20 21:05:52 +08:00
skirtle d7283f3b7f
fix(runtime-core): improve consistency of `PublicInstanceProxyHandlers.has` (#13507) 2025-08-20 21:05:26 +08:00
edison 3190b179b0
fix(Transition): handle KeepAlive + transition leaving edge case (#13152)
close #13153
2025-08-20 20:56:08 +08:00
edison 7f60ef83e7
fix(compiler-core): prevent cached array children from retaining detached dom nodes (#13691)
fix element-plus/element-plus#21408
Re-fix #13211
2025-08-20 20:51:04 +08:00
edison 6e5143d963
fix(hmr): prevent updating unmounting component during HMR rerender (#13775)
close #13771
close #13772
2025-08-20 20:49:59 +08:00
Tycho 1498821ed9
fix(reactivity): warn on nested readonly ref update during unwrapping (#12141) 2025-08-20 20:45:01 +08:00
edison 439e1a543e
fix(hydration): also set vShow name if __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__ flag is enabled (#13777)
close #13744
2025-08-20 20:41:07 +08:00
edison 7420564b20
chore(ci): trusted publisher (#13768)
Related to e18e/ecosystem-issues#201
2025-08-20 20:39:07 +08:00
alentide 8963b7979a
test(runtime-core): remove incorrect suspense test in vnode spec (#13782) 2025-08-20 20:36:37 +08:00
awaken1ng c875019d49
fix(devtools): clear performance measures (#13701)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
canary release / canary (push) Has been cancelled Details
canary minor release / canary (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
close #13700
2025-07-25 08:48:57 +08:00
zhangenming 31f798581c
chore(runtime-core): use NO instead of ()=>false (#13695) 2025-07-25 08:45:38 +08:00
linzhe 911e67045e
fix(compiler-core): adjacent v-else should cause a compiler error (#13699)
close #13698
2025-07-25 08:30:05 +08:00
daiwei c486536105 release: v3.5.18
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-07-23 08:57:59 +08:00
Alex Snezhko 7343f7c95f
dx(runtime-core): fix warning message for useSlots, useAttrs invocation with missing instance (#13647)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-07-23 08:42:50 +08:00
edison 8cfc10a80b
fix(ssr): ensure empty slots render as a comment node in Transition (#13396)
close #13394
2025-07-23 08:42:34 +08:00
linzhe 7f2994393d
fix(runtime-core): ensure correct anchor el for unresolved async components (#13560)
close #13559
2025-07-23 08:42:10 +08:00
zhiyuanzmj 9b029239ed
fix(compiler-core): identifiers in function parameters should not be inferred as references (#13548) 2025-07-23 08:41:50 +08:00
edison d8e40ef7e1
fix(compiler-sfc): transform empty srcset w/ includeAbsolute: true (#13639)
close vitejs/vite-plugin-vue#631
2025-07-23 08:41:17 +08:00
linzhe 90573b06bf
fix(custom-element): ensure exposed methods are accessible from custom elements by making them enumerable (#13634)
close #13632
2025-07-23 08:40:40 +08:00
edison c5f7db1154
fix(slots): refine internal key checking to support slot names starting with an underscore (#13612)
close #13611
2025-07-23 08:40:20 +08:00
edison a9269c642b
fix(hydration): prevent lazy hydration for updated components (#13511)
close #13510
2025-07-23 08:36:47 +08:00
edison 00695a5b41
fix(compiler-core): avoid cached text vnodes retaining detached DOM nodes (#13662)
close #13661
2025-07-23 08:36:15 +08:00
renovate[bot] da1f8d7987
chore(deps): update all non-major dependencies (#13627)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-22 15:01:21 +08:00
renovate[bot] 0b6616a9c1
chore(deps): update dependency @babel/types to ^7.28.1 (#13628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-22 15:01:02 +08:00
renovate[bot] 42b272da57
chore(deps): update build (#13670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-22 14:58:11 +08:00
山吹色御守 e60edc06f2
chore(test): report correct value of `__EXTEND_POINT__` when subsequent error codes is less than it (#13213)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
canary release / canary (push) Has been cancelled Details
canary minor release / canary (push) Has been cancelled Details
2025-07-18 16:24:29 +08:00
山吹色御守 21b685ad9d
fix(compiler-core): avoid self updates of `v-pre` (#12556) 2025-07-18 16:22:56 +08:00
山吹色御守 ce933390ad
fix(compiler-core): recognize empty string as non-identifier (#12553) 2025-07-18 15:58:50 +08:00
山吹色御守 d3af67e878
fix(compiler-core): transform empty `v-bind` dynamic argument content correctly (#12554) 2025-07-18 15:56:01 +08:00
edison e0e8221d7f
chore(sfc-playground): import vaporInteropPlugin only if Vapor mode is supported (#13645)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-07-17 10:03:13 +08:00
山吹色御守 347ef1d3f5
chore(compiler-sfc): optimize the regular expression for matching `@keyframes` (#13566)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
2025-07-09 10:31:20 +08:00
renovate[bot] f97c4d4e6e
chore(deps): update compiler to ^7.28.0 (#13575)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: edison <daiwei521@126.com>
2025-07-09 09:38:17 +08:00
Wick a0bd1f518e
refactor: migrate to getCurrentInstance API (#12958)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-07-08 14:30:43 +08:00
renovate[bot] 01a122283f
chore(deps): update build (#13574)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 14:20:35 +08:00
renovate[bot] eca0e1ccff
chore(deps): update build (#13542)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:47:51 +08:00
GU Yiling c85f1b5a13
fix(css-vars): nullish v-bind in style should not lead to unexpected inheritance (#12461)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
close #12434
close #12439
close #7474
close #7475
2025-07-03 16:20:28 +08:00
renovate[bot] 7e133dbe01
chore(deps): update all non-major dependencies (#13541)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-03 08:16:56 +08:00
renovate[bot] ba391f5fdf
chore(deps): update dependency vite to v5.4.19 [security] (#13517)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:33:04 +08:00
renovate[bot] 50a1c30899
chore(deps): update build (#13516)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:32:41 +08:00
renovate[bot] b8b926cdee
chore(deps): update all non-major dependencies (#13515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:04:52 +08:00
daiwei 5f8314cb7f release: v3.5.17
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-06-18 21:14:18 +08:00
edison 15520954f9
fix(ssr): handle initial selected state for select with v-model + v-for/v-if option (#13487)
close #13486
2025-06-18 20:54:32 +08:00
Tycho f3479aac96
fix(compiler-sfc): improved type resolution for function type aliases (#13452)
close #13444
2025-06-18 20:54:09 +08:00
edison 919c44744b
fix(slots): make cache indexes marker non-enumerable (#13469)
close #13468
2025-06-18 20:53:48 +08:00
Mark Florian cb14b860f1
fix(compat): allow v-model built in modifiers on component (#12654)
close #12652
2025-06-18 20:53:25 +08:00
renovate[bot] 9818456f20
fix(deps): update compiler (#13480)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 15:08:15 +08:00
renovate[bot] 52571655f8
chore(deps): update dependency vite to v5.4.19 [security] (#13281)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 15:08:00 +08:00
renovate[bot] c0c9c5baea
chore(deps): update build (#13479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 15:02:46 +08:00
renovate[bot] 532cfae349
chore(deps): update autofix-ci/action digest to 635ffb0 (#13450)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 09:42:04 +08:00
renovate[bot] c91afec9c2
fix(deps): update dependency @vue/repl to ^4.6.1 (#13471)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-13 11:54:02 +08:00
edison 4e9e9ceeb1
chore(deps): update @vue/repl to version 4.6.0 (#13470) 2025-06-13 11:03:48 +08:00
renovate[bot] a6e2032f43
chore(deps): update all non-major dependencies (#13451)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-13 08:26:12 +08:00
xiejiahe 6c68421e4d
chore(build): replace node:fs repeated import (#13467) 2025-06-13 08:24:57 +08:00
linzhe c7d3207cde
chore: export `jsxs` type (#13463) 2025-06-13 08:24:27 +08:00
pengbo cdffaf6b9e
chore(compile-core): removed the optional tag parameter from condenseWhitespace's signature (#13437)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
canary release / canary (push) Has been cancelled Details
canary minor release / canary (push) Has been cancelled Details
2025-06-06 08:25:02 +08:00
renovate[bot] a47832e75e
chore(deps): update dependency esbuild to ^0.25.5 (#13427)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 10:39:31 +08:00
renovate[bot] e416f84d74
chore(deps): update all non-major dependencies (#13426)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 10:38:49 +08:00
daiwei 1b98aafa05 chore: update snap 2025-06-05 10:26:52 +08:00
Alex Snezhko 55dad625ac
fix(compiler-core): prevent comments from blocking static node hoisting (#13345)
close #13344
2025-06-05 10:23:00 +08:00
inottn 47ddf98602
fix(runtime-core): unset old ref during patching when new ref is absent (#12900)
fix #12898
2025-06-05 10:19:48 +08:00
SerKo e8d8f5f604
fix(reactivity): add `__v_skip` flag to `Dep` to prevent reactive conversion (#12804)
close #12803
2025-06-05 10:19:16 +08:00
edison 5ba1afba09
fix(custom-element): ensure configureApp is applied to async component (#12607)
close #12448
2025-06-05 10:10:52 +08:00
edison 73055d8d95
fix(custom-element): prevent injecting child styles if shadowRoot is false (#12769)
close #12630
2025-06-05 10:02:26 +08:00
Arman Tang 4aa7a4aba3
chore(shared): update patch flag name (#12831) 2025-06-05 10:01:51 +08:00
edison 4eb46e443f
fix(compile-sfc): handle mapped types work with omit and pick (#12648)
close #12647
2025-06-05 10:01:22 +08:00
edison 10ebcef8c8
fix(compiler-core): ignore whitespace when matching adjacent v-if (#12321)
close #9173
2025-06-05 09:44:25 +08:00
山吹色御守 f05a8d613b
fix(compiler-core): do not increase newlines in `InEntity` state (#13362) 2025-06-05 09:39:05 +08:00
山吹色御守 762fae4b57
fix(types): typo of `vOnce` and `vSlot` (#13343) 2025-06-05 09:36:47 +08:00
skirtle e53a4ffbe0
chore(hydration): reuse existing variable (#13412)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
canary release / canary (push) Has been cancelled Details
canary minor release / canary (push) Has been cancelled Details
2025-05-30 14:43:23 +08:00
btea 62f2aa11a2
test(compiler-sfc): direct descendant wildcard rule selector (#13411)
add test case for #13387
2025-05-30 10:35:27 +08:00
daiwei a60f2bd371 chore: update changelog
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-05-29 09:04:53 +08:00
daiwei e7381761cc release: v3.5.16 2025-05-29 08:24:16 +08:00
edison 19f23b180b
Revert "fix(compiler-sfc): add scoping tag to trailing universal selector (#1…" (#13406)
This reverts commit 949df80880.
2025-05-29 08:21:19 +08:00
Arpit Jain d9bd436b1a
chore: fix typos
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-05-28 08:26:28 +08:00
edison 42f879fcab
Revert "fix(compiler-sfc): add error handling for defineModel() without varia…" (#13390)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
This reverts commit 00734afef5.
2025-05-27 18:49:34 +08:00
daiwei d5ada3d235 release: v3.5.15
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-05-26 20:38:56 +08:00
renovate[bot] c017c7b8d3
chore(deps): update dependency lint-staged to v16 (#13381)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 09:45:16 +08:00
renovate[bot] 004f488a67
chore(deps): update dependency eslint-plugin-import-x to ^4.13.1 (#13380)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 09:41:35 +08:00
renovate[bot] 1ee3fcf929
chore(deps): update dependency @vitest/eslint-plugin to ^1.2.1 (#13379)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 09:28:23 +08:00
renovate[bot] c46d9f37ae
chore(deps): update build (#13378)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 09:27:29 +08:00
edison 9fa787cfd2
chore(workflow): add TypeScript type checking step to CI pipeline (#13367)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
2025-05-22 15:48:20 +08:00
edison 2c6c0794a1
chore: fix type check error (#13366)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-05-22 11:38:58 +08:00
yangxiuxiu 93949e6587
fix(compat): should not warn COMPILER_V_BIND_OBJECT_ORDER when using v-bind together with v-for (#12993)
fix #12992
2025-05-22 08:44:34 +08:00
thecodewarrior 949df80880
fix(compiler-sfc): add scoping tag to trailing universal selector (#12918)
close #12906
2025-05-22 08:41:27 +08:00
edison a683c80cf4
fix(custom-element): properly resolve props for sync component defs (#12855)
close #12854
2025-05-22 08:38:27 +08:00
edison 1d41d4de7f
fix(custom-element): ensure proper remount and prevent redundant slot parsing with shadowRoot false (#13201)
close #13199
2025-05-22 08:05:39 +08:00
Tycho 5179d328d9
fix(types): exclude `undefined` from inferred prop types with default values (#13007)
close #13006
2025-05-22 08:03:33 +08:00
renovate[bot] d53daf1f29
chore(deps): update all non-major dependencies (#13353)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 09:20:45 +08:00
renovate[bot] 2b894746bd
chore(deps): update test (#13354)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 09:17:42 +08:00
renovate[bot] 64d2ba9f47
chore(deps): update dependency rollup to ^4.41.0 (#13356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 09:07:01 +08:00
renovate[bot] dc18a159e8
chore(deps): update lint (#13357)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 09:06:37 +08:00
Runyasak Chaengnaimuang 00734afef5
fix(compiler-sfc): add error handling for defineModel() without variable assignment (#13352)
close #13280
2025-05-21 09:06:05 +08:00
edison 89edc6cdcb
fix(compile-sfc): handle inline template source map in prod build (#12701)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
close #12682
close vitejs/vite-plugin-vue#500
2025-05-20 08:46:01 +08:00
Tycho f44feed6fa
fix(types): avoid merging component instance into `$props` in `ComponentInstance` (#12870)
close #12751
2025-05-20 08:44:35 +08:00
Tycho c69c4bb59c
fix(watch): update `oldValue` before running `cb` to prevent stale value (#12296)
close #12294
2025-05-20 08:44:13 +08:00
edison 1a664749d4
fix(compat): ensure false value on input retains value attribute (#13216)
close #13205
2025-05-20 08:43:51 +08:00
edison 013749e75e
fix(custom-element): preserve appContext during update (#12455)
close #12453
2025-05-20 08:34:36 +08:00
edison 35aeae7fa3
fix(hydration): handle transition appear hydration edge case (#13339)
close #13335
2025-05-20 08:28:43 +08:00
edison d15dce3142
fix(teleport): handle deferred teleport updates before and after mount (#13350)
close #13349
2025-05-20 08:27:54 +08:00
edison 163b3651d1
fix(compiler-dom): improve HTML nesting validation to allow any child element within template tag (#13320)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
close #13318
2025-05-16 09:05:31 +08:00
Teages f7ce5ae666
fix(compiler-sfc): simulate `allowArbitraryExtensions` on resolving type (#13301)
close #13295
2025-05-16 08:38:47 +08:00
edison 772b0087cb
fix(suspense): handle edge case in patching list nodes within Suspense (#13306)
close #13305
2025-05-16 08:32:55 +08:00
linzhe cf5a5e0edf
fix(compiler-sfc): improve type inference for TSTypeAliasDeclaration with better runtime type detection (#13245)
close #13240
2025-05-16 08:32:13 +08:00
edison d37a2ac59d
fix(compiler-core): ensure mapping is added only if node source is available (#13285)
close #13261
close vitejs/vite-plugin-vue#368
2025-05-16 08:22:37 +08:00
edison 80055fddfb
fix(hydration): skip lazy hydration for patched components (#13283)
close #13255
2025-05-16 08:22:01 +08:00
Adrian Cerbaro b9910755a5
fix(custom-element): allow injecting values ​​from app context in nested elements (#13219)
close #13212)
2025-05-16 08:07:32 +08:00
daiwei d0253a0b7e release: v3.5.14
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
2025-05-15 11:13:02 +08:00
edison 1f98a9c493
fix(hmr): avoid hydration for hmr root reload (#12450)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
close vitejs/vite-plugin-vue#146
close vitejs/vite-plugin-vue#477
2025-05-13 22:23:23 +08:00
tonicli 626450590d
fix(runtime-core): inherit comment nodes during block patch in production build (#10748)
close #10747
close #12650
2025-05-13 22:18:28 +08:00
edison 8e3435779a
fix(compiler-sfc): fix scope handling for props destructure in function parameters and catch clauses
close #12790
2025-05-13 22:17:24 +08:00
yangxiuxiu 343c891224
fix(transition): fix KeepAlive with transition out-in mode behavior in production (#12468)
close #12465
2025-05-13 22:16:45 +08:00
edison 9c4dbbc518
fix(hmr): avoid hydration for hmr updating (#12262)
close #7706
close #8170
2025-05-13 22:15:50 +08:00
renovate[bot] f7dad6da2f
chore(deps): update dependency @babel/parser to ^7.27.2 (#13310)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-13 15:29:08 +08:00
renovate[bot] 258f78b643
chore(deps): update test (#13311)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-13 11:44:59 +08:00
btea 3cb4db21ef
chore: add pnpm setting to pnpm-workspace (#13268)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Lock Closed Issues / action (push) Has been cancelled Details
Auto close issues with "can't reproduce" label / close-issues (push) Has been cancelled Details
2025-05-10 22:19:53 +08:00
renovate[bot] d79aa70c61
chore(deps): update build (#13276)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-10 16:07:50 +08:00
edison f556c925ac
chore: fix typo (#13290) [ci skip]
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
2025-05-07 20:35:45 +08:00
renovate[bot] 56be3dd4db
chore(deps): update compiler to ^7.27.1 (#13277)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 20:53:19 +08:00
Tycho 3f27c58ffb
fix(runtime-core): respect immutability for readonly reactive arrays in `v-for` (#13091)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
close #13087
2025-05-02 02:55:24 -07:00
yangxiuxiu 9196222ae1
fix(slots): properly warn if slot invoked in setup (#12195)
close #12194
2025-05-02 02:53:14 -07:00
edison 2206cd235a
fix(ssr): properly init slots during ssr rendering (#12441)
close #12438
2025-05-02 02:48:03 -07:00
edison 5e37dd0095
fix(hmr/teleport): adjust static children traversal for HMR in dev mode (#12819)
close #12816
2025-05-02 02:18:01 -07:00
edison 0b23fd2383
fix(reactivity): should not recompute if computed does not track reactive data (#12341)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
close #12337
2025-05-01 07:02:17 -07:00
edison 8b848cbbd2
fix(TransitionGroup): reset prevChildren to prevent memory leak (#13183)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details
size data / upload (push) Waiting to run Details
close #13181
2025-05-01 02:58:07 -07:00
dopamine 016c472bd2
fix(runtime-core): stop tracking deps in setRef during unmount (#13210) 2025-05-01 02:56:42 -07:00
edison 5d166f3796
fix(compiler-core): remove slot cache from parent renderCache during unmounting (#13215)
* fix(compiler-core): remove slot cache from parent renderCache during unmounting

* chore: update
2025-05-01 02:55:36 -07:00
dopamine b3ecee3da8
fix(runtime-core): update __vnode of static nodes when patching along the optimized path (#13223)
* fix(runtime-core):  update __vnode of static nodes when patching along the optimized path

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-05-01 02:54:40 -07:00
renovate[bot] e4d9e7ee52
chore(deps): update lint (#13250)
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details
size data / upload (push) Has been cancelled Details
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 16:27:44 +08:00
renovate[bot] bfc458f7bf
chore(deps): update build (#13249)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 16:27:30 +08:00
renovate[bot] d9923c3503
chore(deps): update dependency vite to v5.4.18 [security] (#13237)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 15:59:20 +08:00
renovate[bot] a23fb59e83
chore(deps): update dependency vite to v5.4.18 [security] (#13235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 08:11:14 +08:00
renovate[bot] c3e3396475
chore(deps): update dependency vite to v5.4.18 [security] (#13229)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: edison <daiwei521@126.com>
2025-04-23 08:31:15 +08:00
Jasper Kisro b92ae84ce5
chore: update CHANGELOG.md (#13230) 2025-04-23 07:58:31 +08:00
renovate[bot] b782cd6c3c
chore(deps): update dependency vite to ^6.3.2 (#13225)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 08:15:50 +08:00
renovate[bot] 4085ed9052
chore(deps): update pnpm to v10.9.0 (#13224)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 08:15:32 +08:00
renovate[bot] 4f792535e2
chore(deps): update build (#13195)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 08:17:57 +08:00
renovate[bot] c15ed52030
chore(deps): update dependency vite to v5.4.18 [security] (#13198)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 08:17:42 +08:00
renovate[bot] 9d84d64fee
chore(deps): update dependency @types/node to ^22.14.1 (#13196)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-14 17:08:59 +08:00
山吹色御守 8ae11226e8
fix(compiler-sfc): treat the return value of `useTemplateRef` as a definite ref (#13197) 2025-04-14 17:08:06 +08:00
renovate[bot] 32bc647fab
chore(deps): update build (#13165)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-10 15:51:53 +08:00
renovate[bot] 4f6ef92ad9
chore(deps): update dependency vite to v5.4.17 [security] (#13173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 08:10:43 +08:00
bornkiss 347c7849ad
chore: add bsky link (#13175) 2025-04-08 20:47:02 +08:00
renovate[bot] 1faca599cd
chore(deps): update all non-major dependencies (#13166)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 15:11:17 +08:00
linzhe 466b30f404
fix(compat): correct deprecation message for v-bind.sync usage (#13137)
close #13133
2025-04-02 11:12:29 +08:00
renovate[bot] f6e84af30a
chore(deps): update all non-major dependencies (#13120)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 15:10:54 +08:00
renovate[bot] 5f14669d29
chore(deps): update lint (#13122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 15:02:15 +08:00
renovate[bot] 25e803773a
chore(deps): update compiler to ^7.27.0 (#13123)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 15:01:57 +08:00
Ecco 1499135c22
fix(runtime-dom): always treat autocorrect as attribute (#13001)
close #5705
2025-03-31 14:31:11 +08:00
renovate[bot] 733e266cdd
chore(deps): update build (#13121)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 11:13:43 +08:00
Leedom c97cc4cdb0
chore: fix typo (#13117) 2025-03-29 22:00:36 +08:00
renovate[bot] 93d663a046
chore(deps): update dawidd6/action-download-artifact action to v9 (#13098)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 08:14:10 +08:00
renovate[bot] 60b7bf50e6
fix(deps): update dependency @vue/repl to ^4.5.1 (#13097)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 08:13:07 +08:00
renovate[bot] 40fd95ffd3
chore(deps): update all non-major dependencies (#13092)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 08:12:49 +08:00
renovate[bot] d65b25cdda
chore(deps): update build (#13093)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 10:59:40 +08:00
renovate[bot] 07064f3522
chore(deps): update lint (#13096)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 10:59:05 +08:00
renovate[bot] c65b8d1519
chore(deps): update test (#13095)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 10:54:07 +08:00
Eduardo San Martin Morote 7278d35213
docs(tsdoc): remove extra () in link tag (#13086) 2025-03-24 08:20:35 +08:00
Tycho de7959ea47
chore(sfc-playground): dynamically set Vue version in downloaded project (#13074) 2025-03-20 16:09:51 +08:00
edison 021f8f3b69
fix(readme): update contributors image (#13068)
The current image is too large to load.
see github.com/orgs/community/discussions/116471
2025-03-19 15:14:12 +08:00
Tycho f6f64befb8
types: enhance plugin type inference for better IDE support (#13063)
* types: enhance plugin type inference for better JSDoc and IDE support

* test: clean up

* chore: tweaks
2025-03-19 11:44:32 +08:00
Buer Yang 10e54dcc86
fix(types): the directive's modifiers should be optional (#12605)
* fix(types): the directive's modifiers should be optional

* fix: test

---------

Co-authored-by: edison <daiwei521@126.com>
2025-03-19 11:38:59 +08:00
renovate[bot] 4fea167b57
fix(deps): update compiler (#13051)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 13:27:17 +08:00
renovate[bot] fbf88b6062
chore(deps): update dependency @vitejs/plugin-vue to ^5.2.2 (#13050)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 13:27:00 +08:00
renovate[bot] 1722090022
chore(deps): update test (#13048)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 11:01:54 +08:00
renovate[bot] 36509d8561
chore(deps): update lint (#13049)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 09:29:53 +08:00
renovate[bot] 4eba2c53bb
chore(deps): update pnpm to v10.6.3 (#13047)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 09:03:00 +08:00
renovate[bot] d2c8c19ae8
chore(deps): update build (#13046)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 09:02:37 +08:00
Bald-M 388295b27f
fix(compiler): fix spelling error in domTagConfig (#13043) 2025-03-17 08:18:09 +08:00
edison fdbd026583
fix(customFormatter): properly accessing ref value during debugger (#12948) 2025-03-14 08:19:06 +08:00
Shinigami 636a8619f0
feat(types): add type TemplateRef (#12645)
* feat(types): add type TemplateRef

* chore: simplify

Co-authored-by: jh-leong <jh.leong@outlook.com>

---------

Co-authored-by: jh-leong <jh.leong@outlook.com>
2025-03-14 08:17:49 +08:00
@beer d48937fb95
chore: update node v22 on netlify (#12613) 2025-03-12 08:30:29 +08:00
renovate[bot] fb0c3ca519
chore(deps): update all non-major dependencies (#13014)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 15:46:47 +08:00
renovate[bot] 87e0cd71c2
chore(deps): update build (#13015)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 15:46:31 +08:00
renovate[bot] 4b1931cf89
chore(deps): update all non-major dependencies (#12983)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 20:15:44 +08:00
renovate[bot] 9b708cf5f7
chore(deps): update test (#12984)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 08:26:16 +08:00
edison 8bd9cdb77e
Revert "ci(pkg-pr-new): add 'vapor' branch for pull-request" (#12943)
This reverts commit d18c248691.
2025-02-25 20:39:50 +08:00
zhiyuanzmj d18c248691
ci(pkg-pr-new): add 'vapor' branch for pull-request (#12941) 2025-02-25 15:24:18 +08:00
renovate[bot] 2dd2feab9c
chore(deps): update dependency @types/node to ^22.13.5 (#12932)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 09:37:17 +08:00
renovate[bot] 79d5d6cf4d
chore(deps): update build (#12931)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 09:36:45 +08:00
Sunny 604d08760e
test(reactivity): add tests for reactive and non-reactive objects (#12576) 2025-02-20 17:00:31 +08:00
btea 5e776ae97e
chore: add `onlyBuiltDependencies` list (#12912) 2025-02-19 20:49:51 +08:00
FatRadish 295b5ec19b
fix(reactivity): ensure markRaw objects are not reactive (#12824)
close #12807
2025-02-19 14:25:30 +08:00
inottn 0c8dd94ef9
fix(ci): use `with` instead of `assert` syntax (#12901) 2025-02-18 08:18:34 +08:00
renovate[bot] efed3ebee6
chore(deps): update pnpm to v10 (#12892)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: edison <daiwei521@126.com>
2025-02-17 16:58:53 +08:00
edison 2785d70382
chore(deps): upgrade node to 22.14.0 (#12895)
to fix Netlify deploy error, see https://github.com/pnpm/pnpm/issues/9029#issuecomment-2650658230
2025-02-17 16:50:47 +08:00
edison cbf5821028
chore(deps): fix MappingItem type (#12891) 2025-02-17 15:07:10 +08:00
renovate[bot] 4a1884f8dc
chore(deps): update all non-major dependencies (#12886)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 14:50:22 +08:00
renovate[bot] ce0554fc2c
chore(deps): update test (#12885)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 14:42:37 +08:00
renovate[bot] 633327e14d
chore(deps): update build (#12884)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 14:27:25 +08:00
renovate[bot] 4f4425e0df
chore(deps): update lint (#12887)
* chore(deps): update lint

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-02-17 14:26:56 +08:00
edison d6a6ec13ce
fix(runtime-core): prevent unmounted vnode from being inserted during transition leave (#12862)
close #12860
2025-02-12 15:30:08 +08:00
Bob 263f63f735
chore(tsconfig): remove repeated global.d.ts (#12850)
Co-authored-by: zhangqihui <zhangqihui@gigacloudtech.com>
2025-02-11 15:44:54 +08:00
Aaron-zon 99551e387a
chore(compiler-sfc): change `let start` to `const start` (#12849) 2025-02-11 15:18:09 +08:00
renovate[bot] 2ab70c202f
chore(deps): update build (#12834)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 09:43:09 +08:00
renovate[bot] de0bf335cb
chore(deps): update test (#12835)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 09:38:39 +08:00
renovate[bot] 119f18c773
chore(deps): update test (#12806)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 08:31:25 +08:00
renovate[bot] a117a7a84b
chore(deps): update build (#12805)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 08:27:54 +08:00
renovate[bot] 992a05dd48
chore(deps): update dependency vitest to v3.0.5 [security] (#12812)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 08:25:10 +08:00
renovate[bot] 22f359bdbe
chore(deps): update dependency vite to v5.4.12 [security] (#12793)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 21:12:38 +08:00
Jeff Muizelaar 7ecd2a22c7
test(e2e): Replace deprecated 'clickCount' property with 'count' (#12778)
This fixes double clicks when using WebDriver BiDi.
See https://github.com/puppeteer/puppeteer/issues/13550
2025-01-29 20:22:20 +08:00
renovate[bot] 4650715197
chore(deps): update build (#12783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-29 20:18:58 +08:00
renovate[bot] a63679f2ef
chore(deps): update dependency @types/node to ^22.12.0 (#12784)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-29 20:18:26 +08:00
Tycho 29216853d4
chore(compiler-sfc): remove unused variable (#12750) 2025-01-21 09:28:04 +08:00
renovate[bot] 0f12fb7ea9
fix(deps): update dependency postcss to ^8.5.1 (#12747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 09:43:23 +08:00
renovate[bot] 08e153c48c
chore(deps): update lint (#12746)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 09:43:06 +08:00
renovate[bot] f2263229ff
chore(deps): update dependency puppeteer to ~24.1.0 (#12745)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 09:42:48 +08:00
renovate[bot] 50b7aa17e9
chore(deps): update all non-major dependencies (#12742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 08:41:00 +08:00
renovate[bot] 26162b4999
chore(deps): update build (#12743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 08:31:16 +08:00
renovate[bot] c48a00d85e
chore(deps): update test to v3 (major) (#12744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 08:31:00 +08:00
edison 82da43d167
fix(test): use LaunchOptions instead of PuppeteerLaunchOptions (#12734)
ref puppeteer/puppeteer#13426
2025-01-17 09:26:12 +08:00
renovate[bot] 2e6ec39811
chore(deps): update test (major) (#12692)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 10:15:44 +08:00
edison c950b4c0c4
chore(deps): manually update puppeteer + @vitest/eslint-plugin (#12706) 2025-01-14 10:09:08 +08:00
renovate[bot] f399dd3588
chore(deps): update autofix-ci/action digest to 551dded (#12696)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 08:33:14 +08:00
renovate[bot] 2d6bcc4537
chore(deps): update all non-major dependencies (#12685)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 09:57:53 +08:00
renovate[bot] 4170dec5a1
chore(deps): update dawidd6/action-download-artifact action to v7 (#12690)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 09:39:39 +08:00
renovate[bot] 18555fa7b2
chore(deps): update build (#12686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 09:39:06 +08:00
renovate[bot] 23d2f453d1
chore(deps): update dependency minimatch to v10 (#12691)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 09:38:25 +08:00
renovate[bot] fbdd084acc
chore(deps): update lint (#12689)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 09:38:06 +08:00
renovate[bot] db57d21c17
fix(deps): update dependency @vue/repl to ^4.4.3 (#12688)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 09:37:55 +08:00
Evan You 22dcbf3e20
fix(reactivity): ensure multiple effectScope on() and off() calls maintains correct active scope
close #12631
close #12632

This is a combination of changes from both 8dec243 and #12641
2025-01-08 18:07:44 +08:00
我想静静 e8e842241a
chore: remove unused `configDefaults` (#12643) 2025-01-03 15:20:25 +08:00
renovate[bot] 5a6e98ca32
chore(deps): update pnpm to v9.15.2 (#12628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-30 09:57:28 +08:00
renovate[bot] eb618fd889
chore(deps): update build (#12627)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-30 09:57:12 +08:00
edison 21f8d9dba9
chore(deps): update test (#12600) 2024-12-23 11:25:58 +08:00
renovate[bot] 3faa0a3a9e
chore(deps): update build (major) (#12562)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 11:17:34 +08:00
renovate[bot] b7085a85f1
chore(deps): update dependency magic-string to ^0.30.17 (#12597)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 11:15:11 +08:00
renovate[bot] 289f4bd94f
chore(deps): update lint (#12598)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 11:14:51 +08:00
renovate[bot] 234b6cbb74
chore(deps): update build (#12595)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 11:08:56 +08:00
renovate[bot] 6da11a7d22
chore(deps): update all non-major dependencies (#12594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 11:05:25 +08:00
Marc Bernard bc688434af
docs: remove 3.3 info from 3.4 changelog (#12565)[ci-skip]
Some clean-up. All removed info is already included in [3.3 changelog](https://github.com/vuejs/core/blob/main/changelogs/CHANGELOG-3.3.md)
2024-12-19 14:58:05 +08:00
renovate[bot] 833f9ea1f7
chore(deps): update lint (#12561)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 11:26:37 +08:00
renovate[bot] ec22b79fd4
chore(deps): update build (#12558)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 10:49:38 +08:00
renovate[bot] 76bdd78f17
chore(deps): update dependency magic-string to ^0.30.15 (#12559)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 10:49:21 +08:00
renovate[bot] f74146f40e
fix(deps): update dependency monaco-editor to ^0.52.2 (#12560)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 10:49:05 +08:00
renovate[bot] d07cdead2c
chore(deps): update all non-major dependencies (#12557)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 10:48:44 +08:00
LiquidAssContainer 11c053a542
fix(typos): fix comments referencing transformElement.ts (#12551)[ci-skip] 2024-12-16 10:43:01 +08:00
renovate[bot] 201936f9a3
chore(deps): update build (#12512)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 09:30:58 +08:00
renovate[bot] 11f76741fb
chore(deps): update dependency magic-string to ^0.30.14 (#12493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-05 09:23:28 +08:00
renovate[bot] c86a08b946
chore(deps): update all non-major dependencies (#12492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-05 09:22:52 +08:00
renovate[bot] 5a5406d002
chore(deps): update all non-major dependencies (#12463)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 08:49:07 +08:00
renovate[bot] d82fb465a6
chore(deps): update build (#12464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 08:42:42 +08:00
renovate[bot] fc4bbf95c1
chore(deps): update test (#12002)
* chore(deps): update test

* chore: pin puppeteer

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: daiwei <daiwei521@126.com>
2024-11-22 14:51:15 +08:00
Liu Bo 06310e82f5
fix(types): allow return any for Options API lifecycle hooks (#5914)
Co-authored-by: edison <daiwei521@126.com>
2024-11-19 20:29:08 +08:00
renovate[bot] 14f6917c3c
chore(deps): update all non-major dependencies (#12423)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 11:30:02 +08:00
renovate[bot] 01057fc74c
chore(deps): update build (#12421)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 11:29:29 +08:00
renovate[bot] fdaff720d7
fix(deps): update compiler (#12422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 10:31:14 +08:00
renovate[bot] c028aeafa9
chore(deps): update lint (#12424)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 10:28:12 +08:00
Evan You 6eb29d345a
release: v3.5.13 2024-11-15 22:45:28 +08:00
edison 4f8d807822
fix(ssr): handle initial selected state for select with v-model + v-for option (#12399)
close #12395
2024-11-15 22:32:39 +08:00
edison 983eb50a17
fix(templateRef): set ref on cached async component which wrapped in KeepAlive (#12290)
close #4999
close #5004
2024-11-15 22:32:22 +08:00
edison da7ad5e3d2
fix(ssr): avoid updating subtree of async component if it is resolved (#12363)
close #12362
2024-11-15 22:11:21 +08:00
Bulat Aikaev 1f75d4e6df
fix(ssr): ensure v-text updates correctly with custom directives in SSR output (#12311)
close #12309
2024-11-15 22:02:50 +08:00
Tadas 4b479db61d
fix(transition): reflow before leave-active class after leave-from (#12288)
re-fix #2593
2024-11-15 21:36:21 +08:00
linzhe a20a4cb36a
fix(hydration): the component vnode's el should be updated when a mismatch occurs. (#12255)
close #12253
2024-11-15 18:18:58 +08:00
Evan You 352bc88c1b
fix(custom-element): avoid triggering mutationObserver when relecting props
close #12214
close #12215
2024-11-15 17:21:49 +08:00
Evan You 10ab8c0e7b
chore(playground): reset version when opening local playground from reproduction 2024-11-15 17:04:25 +08:00
zhangenming d637bd6c01
perf(reactivity): do not track inner key `__v_skip`` (#11690) 2024-11-15 11:00:24 +08:00
edison 2d78539da3
fix(compiler-dom): properly stringify template string style (#12392)
close #12391
2024-11-15 10:56:08 +08:00
Evan You 54812eacaa
test: add test case for transition memory leaks
from https://github.com/vuejs/core/pull/12190
2024-11-15 10:50:26 +08:00
edison 1022eabaa1
fix(types): defineEmits w/ interface declaration (#12343)
close #8457
2024-11-15 10:46:59 +08:00
edison 660132df6c
fix(Transition): fix transition memory leak edge case (#12182)
close #12181
2024-11-15 10:40:26 +08:00
edison 4aeff318bd
chore(deps): update dependency postcss-selector-parser to v7 (#12289) 2024-11-15 10:37:55 +08:00
edison 70b44ca835
chore(reactivity): remove unecessary array copy (#12400) 2024-11-15 10:37:24 +08:00
Evan You a49858f3ee
build: strip pure comments in minified builds 2024-11-14 23:33:58 +08:00
edison 8bff142f99
fix(teleport): handle deferred teleport update before mounted (#12168)
close #12161
2024-11-14 20:55:18 +08:00
linzhe c4312f9c71
fix(runtime-dom): set css vars on update to handle child forcing reflow in onMount (#11561) 2024-11-14 15:58:28 +08:00
Evan You 2d5c5e25e9
fix(runtime-dom): set css vars before user onMounted hooks
close #11533
2024-11-14 15:50:19 +08:00
linzhe 99009eee0e
fix(compiler-core): handle v-memo + v-for with functional key (#12014)
close #12013
2024-11-14 15:14:29 +08:00
edison 37300fc261
fix(v-once): setting hasOnce to current block only when in v-once (#12374)
close #12371
2024-11-14 14:53:55 +08:00
edison bee2f5ee62
fix(reactivity): release nested effects/scopes on effect scope stop (#12373)
close #12370
2024-11-14 14:24:22 +08:00
Evan You 21932840ea
fix(reactiivty): avoid unnecessary watcher effect removal from inactive scope
close #5783
close #5806
2024-11-14 14:12:41 +08:00
Evan You e9f3e6b546
workflow: bench against bundled dist file to avoid import access overhead
ref https://github.com/vitest-dev/vitest/issues/6903
2024-11-14 08:38:48 +08:00
Evan You 3656364b06
chore: add well-known funding manifest urls [ci skip] 2024-11-14 00:22:44 +08:00
Evan You 506ed4e75f
chore: enable format on save in workspace settings 2024-11-13 15:31:17 +08:00
Evan You 83430a35f4
workflow: improve bench scripts 2024-11-13 14:13:32 +08:00
renovate[bot] b5ff930089
fix(deps): update dependency postcss to ^8.4.48 (#12356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 10:20:54 +08:00
renovate[bot] 852642729a
chore(deps): update build (#12357)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 10:17:49 +08:00
renovate[bot] a0901756da
chore: migrate renovate config (#12354)
* chore(config): migrate config .github/renovate.json5

* chore: fix lint

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
2024-11-11 03:17:52 +08:00
renovate[bot] 76c43c6040
chore(deps): update dependency @types/node to v22 (#12320)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-04 14:38:05 +08:00
renovate[bot] e81ecc9a9d
chore(deps): update lint (#12319)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-04 14:19:14 +08:00
renovate[bot] 7d0dc7394f
chore(deps): update all non-major dependencies (#12316)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-04 09:25:09 +08:00
renovate[bot] 394902c2e9
chore(deps): update build (#12317)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-04 09:09:02 +08:00
renovate[bot] 664d2e553d
chore(deps): update pnpm to v9.12.3 (#12278)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 13:44:08 +08:00
renovate[bot] 3a043e8c16
chore(deps): update dependency typescript-eslint to ^8.11.0 (#12276)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 09:23:54 +08:00
renovate[bot] 6c0f4741ed
chore(deps): update dependency npm-run-all2 to v7 (#12277)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 09:23:14 +08:00
renovate[bot] ad247b3323
chore(deps): update all non-major dependencies (#12275)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 09:17:49 +08:00
renovate[bot] 5652c5ad83
chore(deps): update build (#12274)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 09:17:21 +08:00
renovate[bot] ed01d92571
chore(deps): update all non-major dependencies (#12222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 09:53:31 +08:00
renovate[bot] 1222437ec2
chore(deps): update lint (#12226)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-21 10:31:21 +08:00
renovate[bot] 536d600199
chore(deps): update build (#12223)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-21 10:25:22 +08:00
Tycho 657603d7b7
docs: update package name to `@vue/compiler-core` (#12192)[ci skip] 2024-10-17 12:00:03 +08:00
renovate[bot] 2442c3b061
chore(deps): update dependency typescript-eslint to ^8.8.1 (#12167)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: edison <daiwei521@126.com>
2024-10-14 15:14:41 +08:00
renovate[bot] 5b17afa89d
chore(deps): update dependency magic-string to ^0.30.12 (#12166)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: edison <daiwei521@126.com>
2024-10-14 15:14:27 +08:00
edison 828d4a4439
fix(test): update snapshot (#12169) 2024-10-14 11:24:13 +08:00
btea a038505c65
chore: improve `renderComponentRoot` warn message (#10914) 2024-10-14 10:14:32 +08:00
远方os 4e19a99461
test(shared): improve test coverage (#8456)
Co-authored-by: edison <daiwei521@126.com>
2024-10-14 10:10:27 +08:00
zr 3b5d8d2511
test(defineProps): add intersection type test (#8684)
Co-authored-by: daiwei <daiwei521@126.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-10-14 10:09:13 +08:00
renovate[bot] aa6879f987
chore(deps): update dependency @swc/core to ^1.7.35 (#12165)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-14 10:07:11 +08:00
renovate[bot] be9eed2593
chore(deps): update all non-major dependencies (#12164)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-14 10:06:33 +08:00
skirtle 1755ac0a10
perf(runtime-core): use feature flag for call to resolveMergedOptions (#12163)
Reduce bundle size when using `__VUE_OPTIONS_API__: false`
2024-10-14 08:18:18 +08:00
Evan You 770ea67a9c
release: v3.5.12 2024-10-11 21:12:32 +08:00
skirtle c82b66214b
refactor(reactivity): reduce size of collectionHandlers (#12152) 2024-10-11 21:10:09 +08:00
Tycho ea943afe40
fix(runtime-dom): prevent unnecessary updates in v-model checkbox when value is unchanged (#12146)
close #12144
2024-10-11 21:00:08 +08:00
Evan You d82fa611e8
chore: format 2024-10-11 11:25:48 +08:00
KevinXi d96883cf7d
test(reactivity): test for verifying no unnecessary calls of reactive array identity methods (#11328)
related: #9511
2024-10-11 11:24:03 +08:00
Michael Brevard 1ae545a378
fix(hydration): provide compat fallback for idle callback hydration strategy (#11935) 2024-10-11 11:22:01 +08:00
edison 05685a9d7c
fix(types): retain union type narrowing with defaults applied (#12108)
close #12106
2024-10-11 11:17:48 +08:00
山吹色御守 cde2c0671b
fix(compiler): clone loc to `ifNode` (#12131)
fix vuejs/language-tools#4911
2024-10-11 11:07:07 +08:00
山吹色御守 4474c113d1
fix(compiler-sfc): use sass modern api if available and avoid deprecation warning (#11992) 2024-10-11 11:05:54 +08:00
YangLGggggggggg 9da1ac1565
fix(runtime-core): fix required prop check false positive for kebab-case edge cases (#12034)
close #12011
2024-10-11 11:02:58 +08:00
edison 10a46f43c0
chore(runtime-core): warn if use a non-ref to hold the element reference in DEV (#12051)
close #12029
2024-10-11 10:53:45 +08:00
linzhe d3ecde8a69
fix(compiler-sfc): do not skip TSInstantiationExpression when transforming props destructure (#12064) 2024-10-11 10:51:57 +08:00
linzhe 76a8223199
fix(teleport): handle disabled teleport with updateCssVars (#12113)
close #12112
2024-10-11 10:50:36 +08:00
yangxiuxiu b4d35349d8
fix(useId): ensure useId consistency when using serverPrefetch (#12128)
close #12102
2024-10-11 10:49:14 +08:00
skirtle ec917cfdb9
perf(reactivity): avoid unnecessary recursion in removeSub (#12135) 2024-10-11 10:48:54 +08:00
edison f6d9926236
fix(compiler-dom): avoid stringify option with null value (#12096)
close #12093
2024-10-11 10:41:55 +08:00
Tycho 7ad289e1e7
fix(reactivity): trigger reactivity for Map key `undefined` (#12055)
close #12054
2024-10-11 10:39:08 +08:00
山吹色御守 c0418a3b8f
fix(defineModel): handle kebab-case model correctly (#12063)
close #12060
2024-10-11 10:35:57 +08:00
edison f1a4f67aed
fix(transition/ssr): make transition appear work with Suspense in SSR (#12047)
close #12046
2024-10-11 10:34:28 +08:00
w2xi e0a591e1cd
chore(sfc-playground): adjust the tooltip text for toggling the theme (#12116)
* chore(sfc-playground): adjust the tooltip text for toggling the theme

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-10-11 10:31:01 +08:00
Tycho 704173e242
fix(types): ensure `this.$props` type does not include `string` (#12123)
close #12122
2024-10-11 10:30:09 +08:00
Tycho d9d4d4e158
fix(runtime-core): allow symbol values for slot prop key (#12069)
close #12068
2024-10-11 10:28:54 +08:00
edison e16e9a7341
fix(custom-element): properly remove hyphenated attribute (#12143)
close #12139
2024-10-11 09:52:06 +08:00
renovate[bot] 35785f3cd7
chore(deps): update lint (#12118)
* chore(deps): update lint

* chore: update package name

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: daiwei <daiwei521@126.com>
2024-10-07 10:45:41 +08:00
dependabot[bot] 723f588716
chore(deps-dev): bump vite from 5.4.0 to 5.4.8 (#12121)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.0 to 5.4.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.8/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 10:45:08 +08:00
renovate[bot] 73a3666dee
chore(deps): update dependency @rollup/plugin-commonjs to v28 (#12120)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-07 10:42:31 +08:00
renovate[bot] f7cbea2111
fix(deps): update dependency monaco-editor to ^0.52.0 (#12119)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-07 10:33:18 +08:00
skirtle b094c72b3d
fix(watch): watchEffect clean-up with SSR (#12097)
close #11956
2024-10-04 16:09:23 +08:00
Evan You 6e4de8d75e
release: v3.5.11 2024-10-03 23:49:47 +08:00
山吹色御守 6f85894376
fix(type): should not intersect `PublicProps` with `Props` (#12077) 2024-10-03 23:24:09 +08:00
山吹色御守 c97bb84d0b
fix(types): infer the first generic type of `Ref` correctly (#12094) 2024-10-03 23:22:57 +08:00
山吹色御守 57315ab968
fix(types): correctly infer `TypeProps` when it is `any` (#12073)
close #12058
2024-10-03 23:22:27 +08:00
skirtle 577edca8e7
fix(scheduler): job ordering when the post queue is flushing (#12090) 2024-10-03 23:21:31 +08:00
renovate[bot] 3a55c3e421
chore(deps): update dependency rollup to ^4.24.0 (#12081)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 23:17:36 +08:00
renovate[bot] 435e4fefad
chore(deps): update all non-major dependencies (#12080)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 23:17:22 +08:00
Tycho d3f5e6e531
fix(reactivity): prevent overwriting `next` property during batch processing (#12075)
close #12072
2024-10-03 23:16:52 +08:00
Evan You 29de6f8b0b
chore: remove no longer used property on Dep 2024-09-28 19:25:16 +08:00
山吹色御守 2328b051f4
fix(compiler-sfc): do not skip `TSSatisfiesExpression` when transforming props destructure (#12062)
close #12061
2024-09-28 09:56:09 +08:00
Evan You 4b09ab2074
release: v3.5.10 2024-09-27 23:16:33 +08:00
Evan You 93c95dd4cd
fix(reactivity): fix nested batch edge case 2024-09-27 23:10:20 +08:00
Evan You aa9ef2386a
fix(reactivity): only clear notified flags for computed in first batch iteration
close #12045
2024-09-27 11:25:58 +08:00
Evan You 60c2029f77
test: add test case for #11928 2024-09-27 11:06:34 +08:00
Tycho e2c19c20cf
fix(types/ref): handle nested refs in UnwrapRef (#12049)
close #12044
2024-09-27 10:23:01 +08:00
Evan You ea3efa09e0
fix(custom-element): properly set kebab-case props on Vue custom elements
close #12030
close #12032
2024-09-27 09:25:00 +08:00
Evan You a77b95992a
workflow: link to release workflow in release script [ci skip] 2024-09-26 19:30:19 +08:00
Evan You 01f15beeb0
release: v3.5.9 2024-09-26 19:28:03 +08:00
Evan You 10ff159240
fix(reactivity): fix recursive sync watcher on computed edge case
close #12033
close #12037
2024-09-26 18:38:13 +08:00
edison cb34b28a4a
fix(runtime-core): avoid rendering plain object as VNode (#12038)
close #12035
close vitejs/vite-plugin-vue#353
2024-09-26 17:08:48 +08:00
renovate[bot] faf55a15d7
chore(deps): update build (#12001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-26 17:07:20 +08:00
edison fa0ba24b3a
fix(vue): properly cache runtime compilation (#12019) 2024-09-26 17:05:37 +08:00
山吹色御守 4da688141d
fix(types): correct type inference of union event names (#12022) 2024-09-26 17:00:05 +08:00
Evan You 6001e5c81a
fix(reactivity): fix property dep removal regression
close #12020
close #12021
2024-09-26 16:58:38 +08:00
yangxiuxiu c0e9434414
refactor(reactivity): avoid optional chaining in getDepFromReactive (#12007) 2024-09-24 18:02:01 +08:00
btea 7a00f6f093
chore: remove unused argument (#12006) 2024-09-24 18:01:20 +08:00
Boshen 5d9e81d3da
chore(types): disambiguate the `Comment` type in hydration.ts (#12009) 2024-09-24 18:00:39 +08:00
Evan You a177092754
fix(runtime-core): make useId() always return a string 2024-09-23 08:38:38 +08:00
Evan You 5e8898572f
release: v3.5.8 2024-09-22 11:53:14 +08:00
Jürg Lehni 0267a58801
fix(reactivity): do not remove dep from depsMap when cleaning up deps of computed (#11995) 2024-09-22 11:49:35 +08:00
Evan You d1764a142a
test: simplify computed last sub test case 2024-09-22 11:24:10 +08:00
Evan You 6fcb80172f
release: v3.5.7 2024-09-20 23:50:05 +08:00
Evan You 960706eebf
fix(reactivity): do not remove dep from depsMap when unsubbed by computed
follow up of 235ea4772 after discovering regression in vant ecosystem-ci tests
2024-09-20 23:39:59 +08:00
linzhe b030c8bc73
fix(reactivity): fix triggerRef call on ObjectRefImpl returned by toRef (#11986)
close #11982
2024-09-20 20:48:15 +08:00
山吹色御守 9eca65ee98
fix(types): correct type inference of all-optional props (#11644)
fix #11733
fix vuejs/language-tools#4704
2024-09-20 20:36:57 +08:00
Evan You 235ea4772e
fix(reactivity): fix memory leak from dep instances of garbage collected objects
close #11979
close #11971
2024-09-20 20:32:40 +08:00
Evan You 5c8b76ed6c
fix(reactivity): fix dev-only memory leak by updating dep.subsHead on sub removal
ref #11956
2024-09-20 20:06:39 +08:00
Alex Liu f927a4ae6f
fix(transition): respect `duration` setting even when it is `0` (#11967) 2024-09-20 16:47:01 +08:00
edison a2f6edeb02
fix(ssr): don't render comments in TransitionGroup (#11961)
close #11958
2024-09-20 16:46:45 +08:00
edison 62242886d7
fix(compile-core): fix v-model with newlines edge case (#11960)
close #8306
2024-09-20 16:45:47 +08:00
Hongkun 902bd9c438
chore(sfc-playground): resolve autosave conflict issue (#11970) 2024-09-20 16:44:49 +08:00
山吹色御守 215e154072
fix(compiler-sfc): initialize scope with null prototype object (#11963) 2024-09-20 16:44:14 +08:00
skirtle d18d6aa1b2
fix(scheduler): ensure recursive jobs can't be queued twice (#11955) 2024-09-20 16:43:35 +08:00
linzhe 7257e6a342
fix(hydration): avoid observing non-Element node (#11954)
close #11952
2024-09-20 16:41:58 +08:00
Michael Brevard e075dfad5c
perf(hydration): avoid observer if element is in viewport (#11639) 2024-09-18 15:45:31 +08:00
Evan You 9a36f2a0b8
release: v3.5.6 2024-09-16 16:11:38 +08:00
Evan You c74bb8c2dd
fix(reactivity): avoid exponential perf cost and reduce call stack depth for deeply chained computeds (#11944)
close #11928
2024-09-16 16:00:31 +08:00
renovate[bot] cbc39d54f0
fix(deps): update playground (#11939)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 15:00:53 +08:00
edison 3db0a0f979
chore(deps): update vitest to ^2.1.1 (#11943) 2024-09-16 15:00:41 +08:00
Evan You 8492c3c49a
fix(compiler-sfc): preserve old behavior when using withDefaults with desutructure
close #11930
2024-09-16 11:25:04 +08:00
renovate[bot] fbae210d9d
chore(deps): update dependency eslint-plugin-import-x to v4 (#11942)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 11:13:23 +08:00
renovate[bot] 726db0ad2c
chore(deps): update lint (#11940)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 10:59:58 +08:00
renovate[bot] 47bda40653
fix(deps): update dependency postcss to ^8.4.47 (#11938)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 10:59:38 +08:00
renovate[bot] 732a38ef63
chore(deps): update dependency npm-run-all2 to ^6.2.3 (#11937)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 10:59:26 +08:00
renovate[bot] 6b07244dd5
chore(deps): update build (#11936)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 10:59:15 +08:00
edison 85c138ced1
fix(compile-dom): should be able to stringify mathML (#11891) 2024-09-16 10:58:23 +08:00
Yang Mingshan 49fa673493
fix(watch): `once` option should be ignored by watchEffect (#11884) 2024-09-16 10:56:32 +08:00
Matt Garrett 2d6adf78a0
fix(watch): unwatch should be callable during SSR (#11925)
close #11924
2024-09-16 10:49:16 +08:00
Tycho bc3ddca9d0
chore(types): migrate global types to packages-private (#11904) 2024-09-16 10:30:58 +08:00
ML 1bad606eb3
types: improve app.directive type generics (#11926) 2024-09-16 10:30:04 +08:00
Tycho aa5dafd2b5
fix(reactivity): rely on dirty check only when computed has deps (#11931)
close #11929
2024-09-16 10:28:46 +08:00
Tycho 346bfaf760
refactor(reactivity): simplify isDirty condition (#11933) 2024-09-16 09:59:13 +08:00
2nofa11 817dca8712
chore:fix-issue-id (#11927) [ci skip] 2024-09-14 12:00:10 +08:00
edison effcccd258
docs: avoid pre rendering as html[ci skip] (#11922) 2024-09-13 22:05:01 +08:00
Evan You 7f2de3f53e
release: v3.5.5 2024-09-13 21:38:17 +08:00
Evan You a5f3c2eb4d
fix(hydration): fix mismatch of leading newline in <textarea> and <pre>
close #11873
close #11874
2024-09-13 21:24:59 +08:00
Evan You 3c4bf76276
fix(compiler-dom): should ignore leading newline in <textarea> per spec 2024-09-13 21:24:59 +08:00
edison 10a2c6053b
fix(hmr): reload async child wrapped in Suspense + KeepAlive (#11907)
close #11868
2024-09-13 20:19:47 +08:00
linzhe f2d8019188
fix(custom-element): handle nested customElement mount w/ shadowRoot false (#11861)
close #11851
close #11871
2024-09-13 20:18:10 +08:00
Evan You 1d99d61c1b
fix(compiler-dom): fix stringify static edge for partially eligible chunks in cached parent
close #11879
close #11890
2024-09-13 20:08:40 +08:00
edison 7571f20bc3
fix(TransitionGroup): not warn unkeyed text children with whitespece preserve (#11888)
close #11885
2024-09-13 18:37:42 +08:00
Evan You 8ea5d6d698
fix(reactivity): properly clean up deps, fix memory leak
close #11901
2024-09-13 18:35:16 +08:00
Evan You 11eebcb4df
refactor(reactivity): use class for Link 2024-09-13 18:35:16 +08:00
edison 7fe6c795a1
fix(runtime-core): properly update async component nested in KeepAlive (#11917)
close #11916
2024-09-13 17:17:56 +08:00
linzhe 0e7bc717e6
fix(compiler-sfc): nested css supports atrule and comment (#11899)
close #11896
2024-09-13 16:53:49 +08:00
edison 706d4ac1d0
fix(compiler-core): fix handling of delimiterOpen in VPre (#11915)
close #11913
2024-09-13 16:46:01 +08:00
Hongkun d0b513eb46
chore(sfc-playground): editor can modify whether auto-save is enabled (#11428) 2024-09-10 19:15:29 +08:00
Evan You f599321a65
chore: refactor scripts to js, remove need for tsx 2024-09-10 19:13:42 +08:00
313 changed files with 14928 additions and 4943 deletions

View File

@ -38,7 +38,6 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
### Pull Request Checklist ### Pull Request Checklist
- Vue core has two primary work branches: `main` and `minor`. - Vue core has two primary work branches: `main` and `minor`.
- If your pull request is a feature that adds new API surface, it should be submitted against the `minor` branch. - If your pull request is a feature that adds new API surface, it should be submitted against the `minor` branch.
- Otherwise, it should be submitted against the `main` branch. - Otherwise, it should be submitted against the `main` branch.
@ -46,12 +45,10 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
- [Make sure to tick the "Allow edits from maintainers" box](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork). This allows us to directly make minor edits / refactors and saves a lot of time. - [Make sure to tick the "Allow edits from maintainers" box](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork). This allows us to directly make minor edits / refactors and saves a lot of time.
- If adding a new feature: - If adding a new feature:
- Add accompanying test case. - Add accompanying test case.
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it. - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
- If fixing a bug: - If fixing a bug:
- If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`. - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`.
- Provide a detailed description of the bug in the PR. Live demo preferred. - Provide a detailed description of the bug in the PR. Live demo preferred.
- Add appropriate test coverage if applicable. You can check the coverage of your code addition by running `nr test-coverage`. - Add appropriate test coverage if applicable. You can check the coverage of your code addition by running `nr test-coverage`.
@ -69,9 +66,7 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
- The PR should fix the intended bug **only** and not introduce unrelated changes. This includes unnecessary refactors - a PR should focus on the fix and not code style, this makes it easier to trace changes in the future. - The PR should fix the intended bug **only** and not introduce unrelated changes. This includes unnecessary refactors - a PR should focus on the fix and not code style, this makes it easier to trace changes in the future.
- Consider the performance / size impact of the changes, and whether the bug being fixes justifies the cost. If the bug being fixed is a very niche edge case, we should try to minimize the size / perf cost to make it worthwhile. - Consider the performance / size impact of the changes, and whether the bug being fixes justifies the cost. If the bug being fixed is a very niche edge case, we should try to minimize the size / perf cost to make it worthwhile.
- Is the code perf-sensitive (e.g. in "hot paths" like component updates or the vdom patch function?) - Is the code perf-sensitive (e.g. in "hot paths" like component updates or the vdom patch function?)
- If the branch is dev-only, performance is less of a concern. - If the branch is dev-only, performance is less of a concern.
- Check how much extra bundle size the change introduces. - Check how much extra bundle size the change introduces.
@ -265,7 +260,6 @@ This repository employs a [monorepo](https://en.wikipedia.org/wiki/Monorepo) set
- `vue`: The public facing "full build" which includes both the runtime AND the compiler. - `vue`: The public facing "full build" which includes both the runtime AND the compiler.
- Private utility packages: - Private utility packages:
- `dts-test`: Contains type-only tests against generated dts files. - `dts-test`: Contains type-only tests against generated dts files.
- `sfc-playground`: The playground continuously deployed at https://play.vuejs.org. To run the playground locally, use [`nr dev-sfc`](#nr-dev-sfc). - `sfc-playground`: The playground continuously deployed at https://play.vuejs.org. To run the playground locally, use [`nr dev-sfc`](#nr-dev-sfc).

View File

@ -48,7 +48,6 @@ Depending on the type of the PR, different considerations need to be taken into
- Performance: if a refactor PR claims to improve performance, there should be benchmarks showcasing said performance unless the improvement is self-explanatory. - Performance: if a refactor PR claims to improve performance, there should be benchmarks showcasing said performance unless the improvement is self-explanatory.
- Code quality / stylistic PRs: we should be conservative on merging this type PRs because (1) they can be subjective in many cases, and (2) they often come with large git diffs, causing merge conflicts with other pending PRs, and leading to unwanted noise when tracing changes through git history. Use your best judgement on this type of PRs on whether they are worth it. - Code quality / stylistic PRs: we should be conservative on merging this type PRs because (1) they can be subjective in many cases, and (2) they often come with large git diffs, causing merge conflicts with other pending PRs, and leading to unwanted noise when tracing changes through git history. Use your best judgement on this type of PRs on whether they are worth it.
- For PRs in this category that are approved, do not merge immediately. Group them before releasing a new minor, after all feature-oriented PRs are merged. - For PRs in this category that are approved, do not merge immediately. Group them before releasing a new minor, after all feature-oriented PRs are merged.
### Reviewing a Feature ### Reviewing a Feature
@ -56,7 +55,6 @@ Depending on the type of the PR, different considerations need to be taken into
- Feature PRs should always have clear context and explanation on why the feature should be added, ideally in the form of an RFC. If the PR doesn't explain what real-world problem it is solving, ask the contributor to clarify. - Feature PRs should always have clear context and explanation on why the feature should be added, ideally in the form of an RFC. If the PR doesn't explain what real-world problem it is solving, ask the contributor to clarify.
- Decide if the feature should require an RFC process. The line isn't always clear, but a rough criteria is whether it is augmenting an existing API vs. adding a new API. Some examples: - Decide if the feature should require an RFC process. The line isn't always clear, but a rough criteria is whether it is augmenting an existing API vs. adding a new API. Some examples:
- Adding a new built-in component or directive is "significant" and definitely requires an RFC. - Adding a new built-in component or directive is "significant" and definitely requires an RFC.
- Template syntax additions like adding a new `v-on` modifier or a new `v-bind` syntax sugar are "substantial". It would be nice to have an RFC for it, but a detailed explanation on the use case and reasoning behind the design directly in the PR itself can be acceptable. - Template syntax additions like adding a new `v-on` modifier or a new `v-bind` syntax sugar are "substantial". It would be nice to have an RFC for it, but a detailed explanation on the use case and reasoning behind the design directly in the PR itself can be acceptable.
- Small, low-impact additions like exposing a new utility type or adding a new app config option can be self-explanatory, but should still provide enough context in the PR. - Small, low-impact additions like exposing a new utility type or adding a new app config option can be self-explanatory, but should still provide enough context in the PR.
@ -70,7 +68,6 @@ Depending on the type of the PR, different considerations need to be taken into
- Implementation: code style should be consistent with the rest of the codebase, follow common best practices. Prefer code that is boring but easy to understand over "clever" code. - Implementation: code style should be consistent with the rest of the codebase, follow common best practices. Prefer code that is boring but easy to understand over "clever" code.
- Size: bundle size matters. We have a GitHub action that compares the size change for every PR. We should always aim to realize the desired changes with the smallest amount of code size increase. - Size: bundle size matters. We have a GitHub action that compares the size change for every PR. We should always aim to realize the desired changes with the smallest amount of code size increase.
- Sometimes we need to compare the size increase vs. perceived benefits to decide whether a change is justifiable. Also take extra care to make sure added code can be tree-shaken if not needed. - Sometimes we need to compare the size increase vs. perceived benefits to decide whether a change is justifiable. Also take extra care to make sure added code can be tree-shaken if not needed.
- Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable. - Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.
@ -80,7 +77,6 @@ Depending on the type of the PR, different considerations need to be taken into
- Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in @vue/shared are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`. - Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in @vue/shared are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.
- Performance - Performance
- Be careful about code changes in "hot paths", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code. - Be careful about code changes in "hot paths", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code.
- Potential Breakage - Potential Breakage

View File

@ -1,18 +1,17 @@
{ {
$schema: 'https://docs.renovatebot.com/renovate-schema.json', $schema: 'https://docs.renovatebot.com/renovate-schema.json',
extends: ['config:base', 'schedule:weekly', 'group:allNonMajor'], extends: ['config:recommended', 'schedule:weekly', 'group:allNonMajor'],
labels: ['dependencies'], labels: ['dependencies'],
ignorePaths: ['**/__tests__/**'], ignorePaths: ['**/__tests__/**'],
rangeStrategy: 'bump', rangeStrategy: 'bump',
packageRules: [ packageRules: [
{ {
depTypeList: ['peerDependencies'], matchDepTypes: ['peerDependencies'],
enabled: false, enabled: false,
}, },
{ {
groupName: 'test', groupName: 'test',
matchPackageNames: ['vitest', 'jsdom', 'puppeteer'], matchPackageNames: ['vitest', 'jsdom', 'puppeteer', '@vitest{/,}**'],
matchPackagePrefixes: ['@vitest'],
}, },
{ {
groupName: 'playground', groupName: 'playground',
@ -23,18 +22,28 @@
}, },
{ {
groupName: 'compiler', groupName: 'compiler',
matchPackageNames: ['magic-string'], matchPackageNames: ['magic-string', '@babel{/,}**', 'postcss{/,}**'],
matchPackagePrefixes: ['@babel', 'postcss'],
}, },
{ {
groupName: 'build', groupName: 'build',
matchPackageNames: ['vite', '@swc/core'], matchPackageNames: [
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs'], 'vite',
'@swc/core',
'rollup{/,}**',
'esbuild{/,}**',
'@rollup{/,}**',
'@vitejs{/,}**',
],
}, },
{ {
groupName: 'lint', groupName: 'lint',
matchPackageNames: ['simple-git-hooks', 'lint-staged'], matchPackageNames: [
matchPackagePrefixes: ['typescript-eslint', 'eslint', 'prettier'], 'simple-git-hooks',
'lint-staged',
'typescript-eslint{/,}**',
'eslint{/,}**',
'prettier{/,}**',
],
}, },
], ],
ignoreDeps: [ ignoreDeps: [
@ -58,9 +67,5 @@
// pinned // pinned
// only used in example for e2e tests // only used in example for e2e tests
'marked', 'marked',
// pinned, 5.0+ has exports issues
// https://github.com/vuejs/core/issues/11603
'entities',
], ],
} }

View File

@ -11,13 +11,13 @@ jobs:
env: env:
PUPPETEER_SKIP_DOWNLOAD: 'true' PUPPETEER_SKIP_DOWNLOAD: 'true'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
@ -31,4 +31,4 @@ jobs:
- name: Run prettier - name: Run prettier
run: pnpm run format run: pnpm run format
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c - uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27

View File

@ -1,33 +0,0 @@
name: canary minor release
on:
# Runs every Monday at 1 AM UTC (9:00 AM in Singapore)
schedule:
- cron: 0 1 * * MON
workflow_dispatch:
jobs:
canary:
# prevents this action from running on forks
if: github.repository == 'vuejs/core'
runs-on: ubuntu-latest
environment: Release
steps:
- uses: actions/checkout@v4
with:
ref: minor
- name: Install pnpm
uses: pnpm/action-setup@v4.0.0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
- run: pnpm install
- run: pnpm release --canary --publish --tag minor
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@ -1,31 +0,0 @@
name: canary release
on:
# Runs every Monday at 1 AM UTC (9:00 AM in Singapore)
schedule:
- cron: 0 1 * * MON
workflow_dispatch:
jobs:
canary:
# prevents this action from running on forks
if: github.repository == 'vuejs/core'
runs-on: ubuntu-latest
environment: Release
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4.0.0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
- run: pnpm install
- run: pnpm release --canary --publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@ -20,13 +20,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
@ -39,4 +39,4 @@ jobs:
run: pnpm build --withTypes run: pnpm build --withTypes
- name: Release - name: Release
run: pnpx pkg-pr-new publish --compact --pnpm './packages/*' run: pnpx pkg-pr-new publish --compact --pnpm './packages/*' --packageManager=pnpm,npm,yarn

View File

@ -10,7 +10,7 @@ jobs:
if: github.repository == 'vuejs/core' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run') if: github.repository == 'vuejs/core' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')
steps: steps:
- name: Check user permission - name: Check user permission
uses: actions/github-script@v7 uses: actions/github-script@v8
with: with:
script: | script: |
const user = context.payload.sender.login const user = context.payload.sender.login
@ -45,7 +45,7 @@ jobs:
throw new Error('not allowed') throw new Error('not allowed')
} }
- name: Get PR info - name: Get PR info
uses: actions/github-script@v7 uses: actions/github-script@v8
id: get-pr-data id: get-pr-data
with: with:
script: | script: |
@ -62,7 +62,7 @@ jobs:
commit: pr.head.sha commit: pr.head.sha
} }
- name: Trigger run - name: Trigger run
uses: actions/github-script@v7 uses: actions/github-script@v8
id: trigger id: trigger
env: env:
COMMENT: ${{ github.event.comment.body }} COMMENT: ${{ github.event.comment.body }}

View File

@ -21,13 +21,13 @@ jobs:
environment: Release environment: Release
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
@ -36,12 +36,13 @@ jobs:
- name: Install deps - name: Install deps
run: pnpm install run: pnpm install
- name: Update npm
run: npm i -g npm@latest
- name: Build and publish - name: Build and publish
id: publish id: publish
run: | run: |
pnpm release --publishOnly pnpm release --publishOnly
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub release - name: Create GitHub release
id: release_tag id: release_tag

View File

@ -22,13 +22,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: pnpm cache: pnpm
@ -45,7 +45,7 @@ jobs:
echo ${{ github.base_ref }} > ./temp/size/base.txt echo ${{ github.base_ref }} > ./temp/size/base.txt
- name: Upload Size Data - name: Upload Size Data
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: size-data name: size-data
path: temp/size path: temp/size

View File

@ -22,13 +22,13 @@ jobs:
github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success' github.event.workflow_run.conclusion == 'success'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: pnpm cache: pnpm
@ -37,7 +37,7 @@ jobs:
run: pnpm install run: pnpm install
- name: Download Size Data - name: Download Size Data
uses: dawidd6/action-download-artifact@v6 uses: dawidd6/action-download-artifact@v11
with: with:
name: size-data name: size-data
run_id: ${{ github.event.workflow_run.id }} run_id: ${{ github.event.workflow_run.id }}
@ -56,7 +56,7 @@ jobs:
path: temp/size/base.txt path: temp/size/base.txt
- name: Download Previous Size Data - name: Download Previous Size Data
uses: dawidd6/action-download-artifact@v6 uses: dawidd6/action-download-artifact@v11
with: with:
branch: ${{ steps.pr-base.outputs.content }} branch: ${{ steps.pr-base.outputs.content }}
workflow: size-data.yml workflow: size-data.yml
@ -66,7 +66,7 @@ jobs:
if_no_artifact_found: warn if_no_artifact_found: warn
- name: Prepare report - name: Prepare report
run: pnpm tsx scripts/size-report.ts > size-report.md run: node scripts/size-report.js > size-report.md
- name: Read Size Report - name: Read Size Report
id: size-report id: size-report

View File

@ -11,13 +11,13 @@ jobs:
env: env:
PUPPETEER_SKIP_DOWNLOAD: 'true' PUPPETEER_SKIP_DOWNLOAD: 'true'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@ -32,13 +32,13 @@ jobs:
env: env:
PUPPETEER_SKIP_DOWNLOAD: 'true' PUPPETEER_SKIP_DOWNLOAD: 'true'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@ -54,7 +54,7 @@ jobs:
e2e-test: e2e-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Setup cache for Chromium binary - name: Setup cache for Chromium binary
uses: actions/cache@v4 uses: actions/cache@v4
@ -63,10 +63,10 @@ jobs:
key: chromium-${{ hashFiles('pnpm-lock.yaml') }} key: chromium-${{ hashFiles('pnpm-lock.yaml') }}
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@ -85,13 +85,13 @@ jobs:
env: env:
PUPPETEER_SKIP_DOWNLOAD: 'true' PUPPETEER_SKIP_DOWNLOAD: 'true'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4.2.0
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@ -104,5 +104,8 @@ jobs:
- name: Run prettier - name: Run prettier
run: pnpm run format-check run: pnpm run format-check
- name: Run tsc
run: pnpm run check
- name: Run type declaration tests - name: Run type declaration tests
run: pnpm run test-dts run: pnpm run test-dts

View File

@ -1 +1 @@
20 22.14.0

View File

@ -4,7 +4,7 @@
"cSpell.enabledLanguageIds": ["markdown", "plaintext", "text", "yml"], "cSpell.enabledLanguageIds": ["markdown", "plaintext", "text", "yml"],
// Use prettier to format typescript, javascript and JSON files // Use prettier to format TypeScript, JavaScript and JSON files
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
@ -13,5 +13,6 @@
}, },
"[json]": { "[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
} },
"editor.formatOnSave": true
} }

View File

@ -0,0 +1 @@
https://vuejs.org/funding.json

View File

@ -1,3 +1,446 @@
## [3.5.26](https://github.com/vuejs/core/compare/v3.5.25...v3.5.26) (2025-12-18)
### Bug Fixes
* **compat:** fix compat handler of draggable ([#12445](https://github.com/vuejs/core/issues/12445)) ([ed85953](https://github.com/vuejs/core/commit/ed85953e28741ae1913cfc92b7b66e1a8da47f8c)), closes [#12444](https://github.com/vuejs/core/issues/12444)
* **compat:** handle v-model deprecation warning with missing appContext ([#14203](https://github.com/vuejs/core/issues/14203)) ([945a543](https://github.com/vuejs/core/commit/945a543152e8d80903d4f7a18a84ebe8d36e56f8)), closes [#14202](https://github.com/vuejs/core/issues/14202)
* **compiler-sfc:** demote const reactive bindings used in v-model ([#14214](https://github.com/vuejs/core/issues/14214)) ([e24ff7d](https://github.com/vuejs/core/commit/e24ff7d302a887ea532571c231a385362fa17279)), closes [#11265](https://github.com/vuejs/core/issues/11265) [#11275](https://github.com/vuejs/core/issues/11275)
* **compiler-ssr:** handle ssr attr fallthrough when preserve whitespace ([#12304](https://github.com/vuejs/core/issues/12304)) ([4783118](https://github.com/vuejs/core/commit/47831189196b62b12dd17f6e909efc51d9d22fd2)), closes [#8072](https://github.com/vuejs/core/issues/8072)
* **hmr:** handle cached text node update ([#14134](https://github.com/vuejs/core/issues/14134)) ([69ce3c7](https://github.com/vuejs/core/commit/69ce3c7d755db868cfa66d67ab5b3f383a44e053)), closes [#14127](https://github.com/vuejs/core/issues/14127)
* **keep-alive:** use resolved component name for async components in cache pruning ([#14212](https://github.com/vuejs/core/issues/14212)) ([dfe667c](https://github.com/vuejs/core/commit/dfe667c8567d48167c250062483d2d2cfc7bdc03)), closes [#14210](https://github.com/vuejs/core/issues/14210)
* **runtime-core:** ensure correct anchor el for deeper unresolved async components ([#14182](https://github.com/vuejs/core/issues/14182)) ([f5b3bf2](https://github.com/vuejs/core/commit/f5b3bf264d2e12725381bed1c492069437069b03)), closes [#14173](https://github.com/vuejs/core/issues/14173)
* **runtime-core:** handle patch stable fragment edge case ([#12411](https://github.com/vuejs/core/issues/12411)) ([94aeb64](https://github.com/vuejs/core/commit/94aeb64ccdf20d541059b533c9780977c14db9cb)), closes [#12410](https://github.com/vuejs/core/issues/12410)
* **runtime-core:** pass component instance to flushPreFlushCbs on unmount ([#14221](https://github.com/vuejs/core/issues/14221)) ([e857e12](https://github.com/vuejs/core/commit/e857e12c0aff03c0148e3e52d92935918872dc33)), closes [#14215](https://github.com/vuejs/core/issues/14215)
### Performance Improvements
* **compiler-core:** use binary-search to get line and column ([#14222](https://github.com/vuejs/core/issues/14222)) ([1904053](https://github.com/vuejs/core/commit/1904053f1f7986c2d6dbe858ee1b594b4b229c17))
## [3.5.25](https://github.com/vuejs/core/compare/v3.5.24...v3.5.25) (2025-11-24)
### Bug Fixes
* **compiler:** share logic for comments and whitespace ([#13550](https://github.com/vuejs/core/issues/13550)) ([2214f7a](https://github.com/vuejs/core/commit/2214f7ab2940bcb751cd20130c020d895db6c042))
* **provide:** warn when using `provide` after mounting ([#13954](https://github.com/vuejs/core/issues/13954)) ([247b2c2](https://github.com/vuejs/core/commit/247b2c2067afc4dee52f9f7bc194f3aab347ac55)), closes [#13921](https://github.com/vuejs/core/issues/13921) [#13924](https://github.com/vuejs/core/issues/13924)
* **reactivity:** correctly wrap iterated array items to preserve their readonly status ([#14120](https://github.com/vuejs/core/issues/14120)) ([301020b](https://github.com/vuejs/core/commit/301020b481e85d03b0c96000f3221372063c41c6))
* **reactivity:** toRef edge cases for ref unwrapping ([#12420](https://github.com/vuejs/core/issues/12420)) ([0d2357e](https://github.com/vuejs/core/commit/0d2357e6974678d5484751c869f429dc6ea85582))
* **runtime-core:** keep options API typing intact when expose is used ([#14118](https://github.com/vuejs/core/issues/14118)) ([8f82f23](https://github.com/vuejs/core/commit/8f82f238463160284e504d1751d61b72dabb395e)), closes [#14117](https://github.com/vuejs/core/issues/14117) [vuejs/language-tools#5069](https://github.com/vuejs/language-tools/issues/5069)
* **suspense:** defer clearing fallback vnode el in case it has dirs ([#14080](https://github.com/vuejs/core/issues/14080)) ([c0f63dd](https://github.com/vuejs/core/commit/c0f63ddbfa8fa221d66b683b5c26e471851c2b50)), closes [#14078](https://github.com/vuejs/core/issues/14078)
## [3.5.24](https://github.com/vuejs/core/compare/v3.5.23...v3.5.24) (2025-11-07)
### Reverts
* Revert "fix(compiler-core): correctly handle ts type assertions in expression…" (#14062) ([11ec51a](https://github.com/vuejs/core/commit/11ec51aa5a7914745fee10ed2b9f9464fab4d02c)), closes [#14062](https://github.com/vuejs/core/issues/14062) [#14060](https://github.com/vuejs/core/issues/14060)
## [3.5.23](https://github.com/vuejs/core/compare/v3.5.22...v3.5.23) (2025-11-06)
### Bug Fixes
* **compiler-core:** correctly handle ts type assertions in expressions ([#13397](https://github.com/vuejs/core/issues/13397)) ([e6544ac](https://github.com/vuejs/core/commit/e6544ac292b5b473274f87cdb83ebeac3e7e61a4)), closes [#13395](https://github.com/vuejs/core/issues/13395)
* **compiler-core:** fix v-bind shorthand handling for in-DOM templates ([#13933](https://github.com/vuejs/core/issues/13933)) ([b3cca26](https://github.com/vuejs/core/commit/b3cca2611c656b85f0c4e737b9ec248d2627dded)), closes [#13930](https://github.com/vuejs/core/issues/13930)
* **compiler-sfc:** resolve numeric literals and template literals without expressions as static property key ([#13998](https://github.com/vuejs/core/issues/13998)) ([75d44c7](https://github.com/vuejs/core/commit/75d44c718981f91843e197265cc68e82fe2532dd))
* **compiler-ssr:** textarea with v-text directive SSR ([#13975](https://github.com/vuejs/core/issues/13975)) ([006a0c1](https://github.com/vuejs/core/commit/006a0c1011a224bcbf21195c6df76812c3a7e757))
* **compiler:** using guard instead of non-nullish assertion ([#13982](https://github.com/vuejs/core/issues/13982)) ([dcc6f36](https://github.com/vuejs/core/commit/dcc6f362577ed86ccad31c2623c6cf75137dd27a))
* **custom-element:** batch custom element prop patching ([#13478](https://github.com/vuejs/core/issues/13478)) ([c13e674](https://github.com/vuejs/core/commit/c13e674fb9f92ab9339d28a862d18de460faf56e)), closes [#12619](https://github.com/vuejs/core/issues/12619)
* **custom-element:** optimize slot retrieval to avoid duplicates ([#13961](https://github.com/vuejs/core/issues/13961)) ([84ca349](https://github.com/vuejs/core/commit/84ca349fef73f6f55fc98299fcfa5c1eeef721db)), closes [#13955](https://github.com/vuejs/core/issues/13955)
* **hydration:** avoid mismatch during hydrate text with newlines in interpolation ([#9232](https://github.com/vuejs/core/issues/9232)) ([6cbdf78](https://github.com/vuejs/core/commit/6cbdf7823b0c961190bee5b7c117b7f2bbeb832f)), closes [#9229](https://github.com/vuejs/core/issues/9229)
* **runtime-core:** pass props and children to loadingComponent ([#13997](https://github.com/vuejs/core/issues/13997)) ([40c4b2a](https://github.com/vuejs/core/commit/40c4b2a876ce606973521dfc3024e26bfc10953a))
* **runtime-dom:** ensure iframe sandbox is handled as an attribute to prevent unintended behavior ([#13950](https://github.com/vuejs/core/issues/13950)) ([5689884](https://github.com/vuejs/core/commit/5689884c8e32cda6a802ac36b4d23218f67b38ed)), closes [#13946](https://github.com/vuejs/core/issues/13946)
* **suspense:** clear placeholder and fallback el after resolve to enable GC ([#13928](https://github.com/vuejs/core/issues/13928)) ([f411c66](https://github.com/vuejs/core/commit/f411c6604c12c531883aa0d30b81a7f69092f8a6))
* **transition-group:** use offsetLeft and offsetTop instead of getBoundingClientRect to avoid transform scale affect animation ([#6108](https://github.com/vuejs/core/issues/6108)) ([dc4dd59](https://github.com/vuejs/core/commit/dc4dd594fbecce6ed7f44ffa69dc8b5d022287b6)), closes [#6105](https://github.com/vuejs/core/issues/6105)
* **v-model:** handle number modifier on change ([#13959](https://github.com/vuejs/core/issues/13959)) ([8fbe48f](https://github.com/vuejs/core/commit/8fbe48fe396d830999afd07f9413d899157d5f5e)), closes [#13958](https://github.com/vuejs/core/issues/13958)
## [3.5.22](https://github.com/vuejs/core/compare/v3.5.21...v3.5.22) (2025-09-25)
### Bug Fixes
* **compiler-core:** identifiers in switch-case should not be inferred as references ([#13923](https://github.com/vuejs/core/issues/13923)) ([5953c9f](https://github.com/vuejs/core/commit/5953c9ff90090e128372f645d377bd99137a5fb4))
* **compiler-dom:** nodes with v-once shouldn't be stringified ([#13878](https://github.com/vuejs/core/issues/13878)) ([95c1975](https://github.com/vuejs/core/commit/95c197560409f5d39a0d376c0a43d89a47a604e8))
* **compiler-sfc:** add support for `@vue-ignore` in runtime type resolution ([#13906](https://github.com/vuejs/core/issues/13906)) ([ba7f7f9](https://github.com/vuejs/core/commit/ba7f7f90f689f6e7e0417a192d081db542de28ec))
* **compiler-sfc:** enhance inferRuntimeType to support TSMappedType with indexed access ([#13848](https://github.com/vuejs/core/issues/13848)) ([e388f1a](https://github.com/vuejs/core/commit/e388f1a09fde78cf006450f060813d972ac8c23d)), closes [#13847](https://github.com/vuejs/core/issues/13847)
* **compiler-sfc:** ensure css custom properties do not start with a digit ([#13870](https://github.com/vuejs/core/issues/13870)) ([9c27951](https://github.com/vuejs/core/commit/9c279517b9bc1f4c250c555ec9b9eb6104756d56))
* **compiler-sfc:** ensure props bindings register before compiling template ([#13922](https://github.com/vuejs/core/issues/13922)) ([abd5638](https://github.com/vuejs/core/commit/abd563822abafe63047f7b599bff266380ee2b64)), closes [#13920](https://github.com/vuejs/core/issues/13920)
* **compiler-ssr:** ensure v-show has a higher priority in SSR ([#12171](https://github.com/vuejs/core/issues/12171)) ([836b829](https://github.com/vuejs/core/commit/836b82976ffb7aa0ea9cbe417bef07deae3ca47c)), closes [#12162](https://github.com/vuejs/core/issues/12162)
* **custom-element:** properly mount multiple Teleports in custom element component w/ shadowRoot false ([#13900](https://github.com/vuejs/core/issues/13900)) ([5e1e791](https://github.com/vuejs/core/commit/5e1e791880238380a1038ae2c505e206ceb34d77)), closes [#13899](https://github.com/vuejs/core/issues/13899)
* **custom-element:** set prop runs pending mutations before disconnect ([#13897](https://github.com/vuejs/core/issues/13897)) ([c4a88cd](https://github.com/vuejs/core/commit/c4a88cdd0dfed3ef46a8aa9be448c01781fdc4f0)), closes [#13315](https://github.com/vuejs/core/issues/13315)
* **custom-element:** use `PatchFlags.BAIL` for slot when props are present ([#13907](https://github.com/vuejs/core/issues/13907)) ([5358bca](https://github.com/vuejs/core/commit/5358bca4a80cf52d19ed91967eeaa025a786083d)), closes [#13904](https://github.com/vuejs/core/issues/13904)
* **reactivity:** respect readonly during ref unwrapping ([#13905](https://github.com/vuejs/core/issues/13905)) ([aba7fed](https://github.com/vuejs/core/commit/aba7feda1703e69e5a7c37f784718de0371adadc)), closes [#13903](https://github.com/vuejs/core/issues/13903)
* **reactivity:** update iterator to check for completion instead of value presence ([#13761](https://github.com/vuejs/core/issues/13761)) ([2078f8b](https://github.com/vuejs/core/commit/2078f8b7565cf637f47fcd5b0abdfb2b264225bb))
* **runtime-core:** simplify block-tracking disabling in `h` helper ([#13841](https://github.com/vuejs/core/issues/13841)) ([75220c7](https://github.com/vuejs/core/commit/75220c7995a13a483ae9599a739075be1c8e17f8))
* **transition-group:** run `forceReflow` on the correct document (fix [#13849](https://github.com/vuejs/core/issues/13849)) ([#13853](https://github.com/vuejs/core/issues/13853)) ([1be5ddf](https://github.com/vuejs/core/commit/1be5ddfe878c8bfddaa2c50e82105b247f50b9ba))
* **types:** more precise types for Events and added missing definitions ([#9675](https://github.com/vuejs/core/issues/9675)) ([8bb8fb2](https://github.com/vuejs/core/commit/8bb8fb236257c03bfa0bccadcfffe3eb4592f71b))
* **types:** set dom stub type to `never` instead of `{}` ([#13915](https://github.com/vuejs/core/issues/13915)) ([8620a61](https://github.com/vuejs/core/commit/8620a616eb02a64fe32dd52d9be68e360687ef9d)), closes [#11564](https://github.com/vuejs/core/issues/11564)
* **types:** widen directive arg type from string to any ([#13758](https://github.com/vuejs/core/issues/13758)) ([4b71706](https://github.com/vuejs/core/commit/4b7170625d0bc93b26a3343aeda98850c1138f82)), closes [#13757](https://github.com/vuejs/core/issues/13757)
### Features
* **custom-element:** allow specifying additional options for `shadowRoot` in custom elements ([#12965](https://github.com/vuejs/core/issues/12965)) ([47e628d](https://github.com/vuejs/core/commit/47e628df1ce1914c5677010ad5bddd18d037cb3c)), closes [#12964](https://github.com/vuejs/core/issues/12964)
### Reverts
* Revert "fix(hmr): prevent __VUE_HMR_RUNTIME__ from being overwritten by vue runtime in 3rd-party libraries" (#13925) ([6b68f72](https://github.com/vuejs/core/commit/6b68f72673dac5db349f26eeefb2f2e0e342586b)), closes [#13925](https://github.com/vuejs/core/issues/13925)
## [3.5.21](https://github.com/vuejs/core/compare/v3.5.20...v3.5.21) (2025-09-02)
### Bug Fixes
* **compiler-core:** force dynamic slots when slot referencing scope vars ([#9427](https://github.com/vuejs/core/issues/9427)) ([99d54b2](https://github.com/vuejs/core/commit/99d54b28b46dbea006205dff71c383a31dd1b87a)), closes [#9380](https://github.com/vuejs/core/issues/9380)
* **compiler-sfc:** check lang before attempt to compile script ([#13508](https://github.com/vuejs/core/issues/13508)) ([55922ff](https://github.com/vuejs/core/commit/55922ff3168a1397ad72f18946eb1c4051cdab3b)), closes [#8368](https://github.com/vuejs/core/issues/8368)
* **compiler-sfc:** support `${configDir}` in paths for TypeScript 5.5+ ([#13491](https://github.com/vuejs/core/issues/13491)) ([8696e34](https://github.com/vuejs/core/commit/8696e346b4780d88247464490f1a992cc0c3658c)), closes [#13484](https://github.com/vuejs/core/issues/13484)
* **compiler-sfc:** support global augments with named exports ([#13789](https://github.com/vuejs/core/issues/13789)) ([35da3c6](https://github.com/vuejs/core/commit/35da3c6dcb30030ef60fa22e30aa83a56e396c60))
* **custom-element:** prevent defineCustomElement from mutating the options object ([#13791](https://github.com/vuejs/core/issues/13791)) ([e322436](https://github.com/vuejs/core/commit/e322436887549c129e61eb58a0084167103451bb))
* **hmr:** prevent `__VUE_HMR_RUNTIME__` from being overwritten by vue runtime in 3rd-party libraries ([#13817](https://github.com/vuejs/core/issues/13817)) ([1392734](https://github.com/vuejs/core/commit/1392734ae5d5a3b2be124753e198eafa324f6815)), closes [vitejs/vite-plugin-vue#644](https://github.com/vitejs/vite-plugin-vue/issues/644)
* **hmr:** prevent update unmounting component during HMR reload ([#13815](https://github.com/vuejs/core/issues/13815)) ([ef20b86](https://github.com/vuejs/core/commit/ef20b86b36a127e317f8981df970dc8efd277053)), closes [vitejs/vite-plugin-vue#599](https://github.com/vitejs/vite-plugin-vue/issues/599)
* **runtime-core:** disable tracking block in h function ([#8213](https://github.com/vuejs/core/issues/8213)) ([8f6b505](https://github.com/vuejs/core/commit/8f6b5050518441a5047d128138da44f798836002)), closes [#6913](https://github.com/vuejs/core/issues/6913)
* **runtime-core:** use separate emits caches for components and mixins ([#11661](https://github.com/vuejs/core/issues/11661)) ([15fc75f](https://github.com/vuejs/core/commit/15fc75f4031dea805c3bbb67a75e48a9dc307c11))
* **Suspence:** handle Suspense + KeepAlive HMR updating edge case ([#13076](https://github.com/vuejs/core/issues/13076)) ([5d75a17](https://github.com/vuejs/core/commit/5d75a170c8d23acd11ef2513173d4cbc4d0b54de)), closes [#13075](https://github.com/vuejs/core/issues/13075)
* **Teleport:** hydrate disabled Teleport with undefined target ([#11235](https://github.com/vuejs/core/issues/11235)) ([00978f7](https://github.com/vuejs/core/commit/00978f7d14e85b49d9d334ea92fa8c03733ce64c)), closes [#11230](https://github.com/vuejs/core/issues/11230)
* **templateRef:** prevent unnecessary set ref on dynamic ref change or component unmount ([#12642](https://github.com/vuejs/core/issues/12642)) ([93ba107](https://github.com/vuejs/core/commit/93ba10767230872fcdca974a1e19e8bd69b7eb6a)), closes [#12639](https://github.com/vuejs/core/issues/12639)
* **watch:** use maximum depth for duplicates ([#13434](https://github.com/vuejs/core/issues/13434)) ([f2699a5](https://github.com/vuejs/core/commit/f2699a5cb376ffa452a54feb171c14411c67287c))
### Performance Improvements
* improve regexp performance with non-capturing groups ([#13567](https://github.com/vuejs/core/issues/13567)) ([1e8b65a](https://github.com/vuejs/core/commit/1e8b65aa4934c94ef6142b4f49cdfb13ba5e6ce5))
## [3.5.20](https://github.com/vuejs/core/compare/v3.5.19...v3.5.20) (2025-08-25)
### Bug Fixes
* **runtime-dom:** add name to vShow for prop mismatch check ([#13806](https://github.com/vuejs/core/issues/13806)) ([1031e8d](https://github.com/vuejs/core/commit/1031e8de08b735059217b1ad0057f62565c99c4f)), closes [#13805](https://github.com/vuejs/core/issues/13805) re-fix [#13744](https://github.com/vuejs/core/issues/13744) revert [#13777](https://github.com/vuejs/core/issues/13777)
## [3.5.19](https://github.com/vuejs/core/compare/v3.5.18...v3.5.19) (2025-08-21)
### Bug Fixes
* **compiler-core:** adjacent v-else should cause a compiler error ([#13699](https://github.com/vuejs/core/issues/13699)) ([911e670](https://github.com/vuejs/core/commit/911e67045e2a63e0ecbd198ed4f567530f6d1c17)), closes [#13698](https://github.com/vuejs/core/issues/13698)
* **compiler-core:** prevent cached array children from retaining detached dom nodes ([#13691](https://github.com/vuejs/core/issues/13691)) ([7f60ef8](https://github.com/vuejs/core/commit/7f60ef83e735dbd29d323347acecf69f22b06d53)), closes [element-plus/element-plus#21408](https://github.com/element-plus/element-plus/issues/21408) [#13211](https://github.com/vuejs/core/issues/13211)
* **compiler-sfc:** improve type inference for generic type aliases types ([#12876](https://github.com/vuejs/core/issues/12876)) ([d9dd628](https://github.com/vuejs/core/commit/d9dd628800ae32e673bdfabfe79f1988037991d0)), closes [#12872](https://github.com/vuejs/core/issues/12872)
* **compiler-sfc:** throw mismatched script langs error before invoking babel ([#13194](https://github.com/vuejs/core/issues/13194)) ([0562548](https://github.com/vuejs/core/commit/0562548ab3a040073386021222225e0e9d43c632)), closes [#13193](https://github.com/vuejs/core/issues/13193)
* **compiler-ssr:** disable v-memo transform in ssr vdom fallback branch ([#13725](https://github.com/vuejs/core/issues/13725)) ([0a202d8](https://github.com/vuejs/core/commit/0a202d890ff2a564b1fab51e4ac621708640818e)), closes [#13724](https://github.com/vuejs/core/issues/13724)
* **devtools:** clear performance measures ([#13701](https://github.com/vuejs/core/issues/13701)) ([c875019](https://github.com/vuejs/core/commit/c875019d49b4c36a88d929ccadc31ad414747c7b)), closes [#13700](https://github.com/vuejs/core/issues/13700)
* **hmr:** prevent updating unmounting component during HMR rerender ([#13775](https://github.com/vuejs/core/issues/13775)) ([6e5143d](https://github.com/vuejs/core/commit/6e5143d9635dac3f20fb394a827109df30e232ae)), closes [#13771](https://github.com/vuejs/core/issues/13771) [#13772](https://github.com/vuejs/core/issues/13772)
* **hydration:** also set vShow name if `__FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__` flag is enabled ([#13777](https://github.com/vuejs/core/issues/13777)) ([439e1a5](https://github.com/vuejs/core/commit/439e1a543e62de4dbf7658d78d05c358c9677c86)), closes [#13744](https://github.com/vuejs/core/issues/13744)
* **reactivity:** warn on nested readonly ref update during unwrapping ([#12141](https://github.com/vuejs/core/issues/12141)) ([1498821](https://github.com/vuejs/core/commit/1498821ed9eeb22a0767e53ddc1f6a2840598a29))
* **runtime-core:** avoid setting direct ref of useTemplateRef in dev ([#13449](https://github.com/vuejs/core/issues/13449)) ([4a2953f](https://github.com/vuejs/core/commit/4a2953f57b90dfc24e34ff1a87cc1ebb0b97636d))
* **runtime-core:** improve consistency of `PublicInstanceProxyHandlers.has` ([#13507](https://github.com/vuejs/core/issues/13507)) ([d7283f3](https://github.com/vuejs/core/commit/d7283f3b7f0631c8b8a4a31a05983dac9f078c4f))
* **suspense:** don't immediately resolve suspense on last dep unmount ([#13456](https://github.com/vuejs/core/issues/13456)) ([a871315](https://github.com/vuejs/core/commit/a8713159ee24602c7c2b70c5fd52d2e5cd37dca5)), closes [#13453](https://github.com/vuejs/core/issues/13453)
* **transition:** handle KeepAlive + transition leaving edge case ([#13152](https://github.com/vuejs/core/issues/13152)) ([3190b17](https://github.com/vuejs/core/commit/3190b179b0545a3dc4549737793eec630cf9f0d1)), closes [#13153](https://github.com/vuejs/core/issues/13153)
## [3.5.18](https://github.com/vuejs/core/compare/v3.5.17...v3.5.18) (2025-07-23)
### Bug Fixes
* **compiler-core:** avoid cached text vnodes retaining detached DOM nodes ([#13662](https://github.com/vuejs/core/issues/13662)) ([00695a5](https://github.com/vuejs/core/commit/00695a5b41b2d032deaeada83831ff83aa6bfd4e)), closes [#13661](https://github.com/vuejs/core/issues/13661)
* **compiler-core:** avoid self updates of `v-pre` ([#12556](https://github.com/vuejs/core/issues/12556)) ([21b685a](https://github.com/vuejs/core/commit/21b685ad9d9d0e6060fc7d07b719bf35f2d9ae1f))
* **compiler-core:** identifiers in function parameters should not be inferred as references ([#13548](https://github.com/vuejs/core/issues/13548)) ([9b02923](https://github.com/vuejs/core/commit/9b029239edf88558465b941e1e4c085f92b1ebff))
* **compiler-core:** recognize empty string as non-identifier ([#12553](https://github.com/vuejs/core/issues/12553)) ([ce93339](https://github.com/vuejs/core/commit/ce933390ad1c72bed258f7ad959a78f0e8acdf57))
* **compiler-core:** transform empty `v-bind` dynamic argument content correctly ([#12554](https://github.com/vuejs/core/issues/12554)) ([d3af67e](https://github.com/vuejs/core/commit/d3af67e878790892f9d34cfea15d13625aabe733))
* **compiler-sfc:** transform empty srcset w/ includeAbsolute: true ([#13639](https://github.com/vuejs/core/issues/13639)) ([d8e40ef](https://github.com/vuejs/core/commit/d8e40ef7e1c20ee86b294e7cf78e2de60d12830e)), closes [vitejs/vite-plugin-vue#631](https://github.com/vitejs/vite-plugin-vue/issues/631)
* **css-vars:** nullish v-bind in style should not lead to unexpected inheritance ([#12461](https://github.com/vuejs/core/issues/12461)) ([c85f1b5](https://github.com/vuejs/core/commit/c85f1b5a132eb8ec25f71b250e25e65a5c20964f)), closes [#12434](https://github.com/vuejs/core/issues/12434) [#12439](https://github.com/vuejs/core/issues/12439) [#7474](https://github.com/vuejs/core/issues/7474) [#7475](https://github.com/vuejs/core/issues/7475)
* **custom-element:** ensure exposed methods are accessible from custom elements by making them enumerable ([#13634](https://github.com/vuejs/core/issues/13634)) ([90573b0](https://github.com/vuejs/core/commit/90573b06bf6fb6c14c6bbff6c4e34e0ab108953a)), closes [#13632](https://github.com/vuejs/core/issues/13632)
* **hydration:** prevent lazy hydration for updated components ([#13511](https://github.com/vuejs/core/issues/13511)) ([a9269c6](https://github.com/vuejs/core/commit/a9269c642bf944560bc29adb5dae471c11cd9ee8)), closes [#13510](https://github.com/vuejs/core/issues/13510)
* **runtime-core:** ensure correct anchor el for unresolved async components ([#13560](https://github.com/vuejs/core/issues/13560)) ([7f29943](https://github.com/vuejs/core/commit/7f2994393dcdb82cacbf62e02b5ba5565f32588b)), closes [#13559](https://github.com/vuejs/core/issues/13559)
* **slots:** refine internal key checking to support slot names starting with an underscore ([#13612](https://github.com/vuejs/core/issues/13612)) ([c5f7db1](https://github.com/vuejs/core/commit/c5f7db11542bb2246363aef78c88a8e6cef0ee93)), closes [#13611](https://github.com/vuejs/core/issues/13611)
* **ssr:** ensure empty slots render as a comment node in Transition ([#13396](https://github.com/vuejs/core/issues/13396)) ([8cfc10a](https://github.com/vuejs/core/commit/8cfc10a80b9cbf5d801ab149e49b8506d192e7e1)), closes [#13394](https://github.com/vuejs/core/issues/13394)
## [3.5.17](https://github.com/vuejs/core/compare/v3.5.16...v3.5.17) (2025-06-18)
### Bug Fixes
* **compat:** allow v-model built in modifiers on component ([#12654](https://github.com/vuejs/core/issues/12654)) ([cb14b86](https://github.com/vuejs/core/commit/cb14b860f150c4a83bcd52cd26096b7a5aa3a2bf)), closes [#12652](https://github.com/vuejs/core/issues/12652)
* **compile-sfc:** handle mapped types work with omit and pick ([#12648](https://github.com/vuejs/core/issues/12648)) ([4eb46e4](https://github.com/vuejs/core/commit/4eb46e443f1878199755cb73d481d318a9714392)), closes [#12647](https://github.com/vuejs/core/issues/12647)
* **compiler-core:** do not increase newlines in `InEntity` state ([#13362](https://github.com/vuejs/core/issues/13362)) ([f05a8d6](https://github.com/vuejs/core/commit/f05a8d613bd873b811cfdb9979ccac8382dba322))
* **compiler-core:** ignore whitespace when matching adjacent v-if ([#12321](https://github.com/vuejs/core/issues/12321)) ([10ebcef](https://github.com/vuejs/core/commit/10ebcef8c870dbc042b0ea49b1424b2e8f692145)), closes [#9173](https://github.com/vuejs/core/issues/9173)
* **compiler-core:** prevent comments from blocking static node hoisting ([#13345](https://github.com/vuejs/core/issues/13345)) ([55dad62](https://github.com/vuejs/core/commit/55dad625acd9e9ddd5a933d5e323ecfdec1a612f)), closes [#13344](https://github.com/vuejs/core/issues/13344)
* **compiler-sfc:** improved type resolution for function type aliases ([#13452](https://github.com/vuejs/core/issues/13452)) ([f3479aa](https://github.com/vuejs/core/commit/f3479aac9625f4459e650d1c0a70e73863147903)), closes [#13444](https://github.com/vuejs/core/issues/13444)
* **custom-element:** ensure configureApp is applied to async component ([#12607](https://github.com/vuejs/core/issues/12607)) ([5ba1afb](https://github.com/vuejs/core/commit/5ba1afba09c3ea56c1c17484f5d8aeae210ce52a)), closes [#12448](https://github.com/vuejs/core/issues/12448)
* **custom-element:** prevent injecting child styles if shadowRoot is false ([#12769](https://github.com/vuejs/core/issues/12769)) ([73055d8](https://github.com/vuejs/core/commit/73055d8d9578d485e3fe846726b50666e1aa56f5)), closes [#12630](https://github.com/vuejs/core/issues/12630)
* **reactivity:** add `__v_skip` flag to `Dep` to prevent reactive conversion ([#12804](https://github.com/vuejs/core/issues/12804)) ([e8d8f5f](https://github.com/vuejs/core/commit/e8d8f5f604e821acc46b4200d5b06979c05af1c2)), closes [#12803](https://github.com/vuejs/core/issues/12803)
* **runtime-core:** unset old ref during patching when new ref is absent ([#12900](https://github.com/vuejs/core/issues/12900)) ([47ddf98](https://github.com/vuejs/core/commit/47ddf986021dff8de68b0da72787e53a6c19de4c)), closes [#12898](https://github.com/vuejs/core/issues/12898)
* **slots:** make cache indexes marker non-enumerable ([#13469](https://github.com/vuejs/core/issues/13469)) ([919c447](https://github.com/vuejs/core/commit/919c44744bba1f0c661c87d2059c3b429611aa7e)), closes [#13468](https://github.com/vuejs/core/issues/13468)
* **ssr:** handle initial selected state for select with v-model + v-for/v-if option ([#13487](https://github.com/vuejs/core/issues/13487)) ([1552095](https://github.com/vuejs/core/commit/15520954f9f1c7f834175938a50dba5d4be0e6c4)), closes [#13486](https://github.com/vuejs/core/issues/13486)
* **types:** typo of `vOnce` and `vSlot` ([#13343](https://github.com/vuejs/core/issues/13343)) ([762fae4](https://github.com/vuejs/core/commit/762fae4b57ad60602e5c84465a3bff562785b314))
## [3.5.16](https://github.com/vuejs/core/compare/v3.5.15...v3.5.16) (2025-05-29)
### Reverts
* Revert "fix(compiler-sfc): add scoping tag to trailing universal selector" (#13406) ([19f23b1](https://github.com/vuejs/core/commit/19f23b180bb679e38db95d6a10a420abeedc8e1c)), closes [#13406](https://github.com/vuejs/core/issues/13406)
* Revert "fix(compiler-sfc): add error handling for defineModel() without variable" (#13390) ([42f879f](https://github.com/vuejs/core/commit/42f879fcab48e0e1011967a771b4ad9e8838d760)), closes [#13390](https://github.com/vuejs/core/issues/13390)
## [3.5.15](https://github.com/vuejs/core/compare/v3.5.14...v3.5.15) (2025-05-26)
### Bug Fixes
* **compat:** ensure false value on input retains value attribute ([#13216](https://github.com/vuejs/core/issues/13216)) ([1a66474](https://github.com/vuejs/core/commit/1a664749d4d65a345589a6d78106ede7574cb2e1)), closes [#13205](https://github.com/vuejs/core/issues/13205)
* **compat:** should not warn COMPILER_V_BIND_OBJECT_ORDER when using v-bind together with v-for ([#12993](https://github.com/vuejs/core/issues/12993)) ([93949e6](https://github.com/vuejs/core/commit/93949e6587ee019bccd5b8b9d76f0e1ed6ea16fc)), closes [#12992](https://github.com/vuejs/core/issues/12992)
* **compile-sfc:** handle inline template source map in prod build ([#12701](https://github.com/vuejs/core/issues/12701)) ([89edc6c](https://github.com/vuejs/core/commit/89edc6cdcbd34ea6394927ecbfaa61dc4f871de7)), closes [#12682](https://github.com/vuejs/core/issues/12682) [vitejs/vite-plugin-vue#500](https://github.com/vitejs/vite-plugin-vue/issues/500)
* **compiler-core:** ensure mapping is added only if node source is available ([#13285](https://github.com/vuejs/core/issues/13285)) ([d37a2ac](https://github.com/vuejs/core/commit/d37a2ac59d904ac0e3257ba552b6c04920a363f0)), closes [#13261](https://github.com/vuejs/core/issues/13261) [vitejs/vite-plugin-vue#368](https://github.com/vitejs/vite-plugin-vue/issues/368)
* **compiler-dom:** improve HTML nesting validation to allow any child element within template tag ([#13320](https://github.com/vuejs/core/issues/13320)) ([163b365](https://github.com/vuejs/core/commit/163b3651d174321911648a164052effa9249a2aa)), closes [#13318](https://github.com/vuejs/core/issues/13318)
* **compiler-sfc:** add error handling for defineModel() without variable assignment ([#13352](https://github.com/vuejs/core/issues/13352)) ([00734af](https://github.com/vuejs/core/commit/00734afef5f7bddbdaee52aa5359a6ef989f32d3)), closes [#13280](https://github.com/vuejs/core/issues/13280)
* **compiler-sfc:** add scoping tag to trailing universal selector ([#12918](https://github.com/vuejs/core/issues/12918)) ([949df80](https://github.com/vuejs/core/commit/949df808809fd7cccf7718797beab0654aa68302)), closes [#12906](https://github.com/vuejs/core/issues/12906)
* **compiler-sfc:** improve type inference for TSTypeAliasDeclaration with better runtime type detection ([#13245](https://github.com/vuejs/core/issues/13245)) ([cf5a5e0](https://github.com/vuejs/core/commit/cf5a5e0edf0efcab25c27aa2d13eba91f7372d39)), closes [#13240](https://github.com/vuejs/core/issues/13240)
* **compiler-sfc:** simulate `allowArbitraryExtensions` on resolving type ([#13301](https://github.com/vuejs/core/issues/13301)) ([f7ce5ae](https://github.com/vuejs/core/commit/f7ce5ae666129339c006b339437c2dff6bceffe0)), closes [#13295](https://github.com/vuejs/core/issues/13295)
* **custom-element:** allow injecting values from app context in nested elements ([#13219](https://github.com/vuejs/core/issues/13219)) ([b991075](https://github.com/vuejs/core/commit/b9910755a50c7d6c52b28c3aef20cf97810295c9)), closes [#13212](https://github.com/vuejs/core/issues/13212)
* **custom-element:** ensure proper remount and prevent redundant slot parsing with shadowRoot false ([#13201](https://github.com/vuejs/core/issues/13201)) ([1d41d4d](https://github.com/vuejs/core/commit/1d41d4de7f64a37160c8171d0137fd8d35c346c9)), closes [#13199](https://github.com/vuejs/core/issues/13199)
* **custom-element:** preserve appContext during update ([#12455](https://github.com/vuejs/core/issues/12455)) ([013749e](https://github.com/vuejs/core/commit/013749e75ef3b51762a86da379ea4ba4501b54ae)), closes [#12453](https://github.com/vuejs/core/issues/12453)
* **custom-element:** properly resolve props for sync component defs ([#12855](https://github.com/vuejs/core/issues/12855)) ([a683c80](https://github.com/vuejs/core/commit/a683c80cf44ecc482f8ac9c76bf2381443c1b0bb)), closes [#12854](https://github.com/vuejs/core/issues/12854)
* **hydration:** handle transition appear hydration edge case ([#13339](https://github.com/vuejs/core/issues/13339)) ([35aeae7](https://github.com/vuejs/core/commit/35aeae7fa3168adcf9ed95fd35495d17c8b93eeb)), closes [#13335](https://github.com/vuejs/core/issues/13335)
* **hydration:** skip lazy hydration for patched components ([#13283](https://github.com/vuejs/core/issues/13283)) ([80055fd](https://github.com/vuejs/core/commit/80055fddfb3ca1e2a44f19c7f0ffaeba00de5140)), closes [#13255](https://github.com/vuejs/core/issues/13255)
* **suspense:** handle edge case in patching list nodes within Suspense ([#13306](https://github.com/vuejs/core/issues/13306)) ([772b008](https://github.com/vuejs/core/commit/772b0087cb7be151c514a1d30365fb0f61a652ba)), closes [#13305](https://github.com/vuejs/core/issues/13305)
* **teleport:** handle deferred teleport updates before and after mount ([#13350](https://github.com/vuejs/core/issues/13350)) ([d15dce3](https://github.com/vuejs/core/commit/d15dce3142474f2ef9fffed38383acdadcb26c4c)), closes [#13349](https://github.com/vuejs/core/issues/13349)
* **types:** avoid merging component instance into `$props` in `ComponentInstance` ([#12870](https://github.com/vuejs/core/issues/12870)) ([f44feed](https://github.com/vuejs/core/commit/f44feed6fa461a9c4c724e9631c19e9e214c0a20)), closes [#12751](https://github.com/vuejs/core/issues/12751)
* **types:** exclude `undefined` from inferred prop types with default values ([#13007](https://github.com/vuejs/core/issues/13007)) ([5179d32](https://github.com/vuejs/core/commit/5179d328d950015e7fb2a74fe1a8518fd8d2c94e)), closes [#13006](https://github.com/vuejs/core/issues/13006)
* **watch:** update `oldValue` before running `cb` to prevent stale value ([#12296](https://github.com/vuejs/core/issues/12296)) ([c69c4bb](https://github.com/vuejs/core/commit/c69c4bb59c114f2b5e03733b55ef9ace3087b5c3)), closes [#12294](https://github.com/vuejs/core/issues/12294)
## [3.5.14](https://github.com/vuejs/core/compare/v3.5.13...v3.5.14) (2025-05-15)
### Bug Fixes
* **compat:** correct deprecation message for v-bind.sync usage ([#13137](https://github.com/vuejs/core/issues/13137)) ([466b30f](https://github.com/vuejs/core/commit/466b30f4049ec89fb282624ec17d1a93472ab93f)), closes [#13133](https://github.com/vuejs/core/issues/13133)
* **compiler-core:** remove slot cache from parent renderCache during unmounting ([#13215](https://github.com/vuejs/core/issues/13215)) ([5d166f3](https://github.com/vuejs/core/commit/5d166f3796a03a497435fc079c6a83a4e9c6cf52))
* **compiler-sfc:** fix scope handling for props destructure in function parameters and catch clauses ([8e34357](https://github.com/vuejs/core/commit/8e3435779a667de485cf9efd78667d0ca14c5f84)), closes [#12790](https://github.com/vuejs/core/issues/12790)
* **compiler-sfc:** treat the return value of `useTemplateRef` as a definite ref ([#13197](https://github.com/vuejs/core/issues/13197)) ([8ae1122](https://github.com/vuejs/core/commit/8ae11226e8ee938615e17c7b81dc38ae3f7cefb9))
* **compiler:** fix spelling error in domTagConfig ([#13043](https://github.com/vuejs/core/issues/13043)) ([388295b](https://github.com/vuejs/core/commit/388295b27f3cc69eba25d325bbe60a36a3df831a))
* **customFormatter:** properly accessing ref value during debugger ([#12948](https://github.com/vuejs/core/issues/12948)) ([fdbd026](https://github.com/vuejs/core/commit/fdbd02658301dd794fe0c84f0018d080a07fca9f))
* **hmr/teleport:** adjust static children traversal for HMR in dev mode ([#12819](https://github.com/vuejs/core/issues/12819)) ([5e37dd0](https://github.com/vuejs/core/commit/5e37dd009562bcd8080a200c32abde2d6e4f0305)), closes [#12816](https://github.com/vuejs/core/issues/12816)
* **hmr:** avoid hydration for hmr root reload ([#12450](https://github.com/vuejs/core/issues/12450)) ([1f98a9c](https://github.com/vuejs/core/commit/1f98a9c493d01c21befa90107f0593bc92a58932)), closes [vitejs/vite-plugin-vue#146](https://github.com/vitejs/vite-plugin-vue/issues/146) [vitejs/vite-plugin-vue#477](https://github.com/vitejs/vite-plugin-vue/issues/477)
* **hmr:** avoid hydration for hmr updating ([#12262](https://github.com/vuejs/core/issues/12262)) ([9c4dbbc](https://github.com/vuejs/core/commit/9c4dbbc5185125835ad3e49baba303bd54676111)), closes [#7706](https://github.com/vuejs/core/issues/7706) [#8170](https://github.com/vuejs/core/issues/8170)
* **reactivity:** ensure markRaw objects are not reactive ([#12824](https://github.com/vuejs/core/issues/12824)) ([295b5ec](https://github.com/vuejs/core/commit/295b5ec19b6a52c4a56652cc4d6e93a4ea7c14ed)), closes [#12807](https://github.com/vuejs/core/issues/12807)
* **reactivity:** ensure multiple effectScope on() and off() calls maintains correct active scope ([22dcbf3](https://github.com/vuejs/core/commit/22dcbf3e20eb84f69c8952f6f70d9990136a4a68)), closes [#12631](https://github.com/vuejs/core/issues/12631) [#12632](https://github.com/vuejs/core/issues/12632) [#12641](https://github.com/vuejs/core/issues/12641)
* **reactivity:** should not recompute if computed does not track reactive data ([#12341](https://github.com/vuejs/core/issues/12341)) ([0b23fd2](https://github.com/vuejs/core/commit/0b23fd23833cf085e7e112bf4435cfc9b360d072)), closes [#12337](https://github.com/vuejs/core/issues/12337)
* **runtime-core:** stop tracking deps in setRef during unmount ([#13210](https://github.com/vuejs/core/issues/13210)) ([016c472](https://github.com/vuejs/core/commit/016c472bd2e7604b21c69dee1da8545ce26e4d2f))
* **runtime-core:** update __vnode of static nodes when patching along the optimized path ([#13223](https://github.com/vuejs/core/issues/13223)) ([b3ecee3](https://github.com/vuejs/core/commit/b3ecee3da8ed5c55dea89ce6b4b376b2b722b018))
* **runtime-core:** inherit comment nodes during block patch in production build ([#10748](https://github.com/vuejs/core/issues/10748)) ([6264505](https://github.com/vuejs/core/commit/626450590d81f79117b34d2a73073b1dc8f551bd)), closes [#10747](https://github.com/vuejs/core/issues/10747) [#12650](https://github.com/vuejs/core/issues/12650)
* **runtime-core:** prevent unmounted vnode from being inserted during transition leave ([#12862](https://github.com/vuejs/core/issues/12862)) ([d6a6ec1](https://github.com/vuejs/core/commit/d6a6ec13ce521683bfb2a22932778ef7b51f8600)), closes [#12860](https://github.com/vuejs/core/issues/12860)
* **runtime-core:** respect immutability for readonly reactive arrays in `v-for` ([#13091](https://github.com/vuejs/core/issues/13091)) ([3f27c58](https://github.com/vuejs/core/commit/3f27c58ffbd4309df369bc89493fdc284dc540bb)), closes [#13087](https://github.com/vuejs/core/issues/13087)
* **runtime-dom:** always treat autocorrect as attribute ([#13001](https://github.com/vuejs/core/issues/13001)) ([1499135](https://github.com/vuejs/core/commit/1499135c227236e037bb746beeb777941b0b58ff)), closes [#5705](https://github.com/vuejs/core/issues/5705)
* **slots:** properly warn if slot invoked in setup ([#12195](https://github.com/vuejs/core/issues/12195)) ([9196222](https://github.com/vuejs/core/commit/9196222ae1d63b52b35ac5fbf5e71494587ccf05)), closes [#12194](https://github.com/vuejs/core/issues/12194)
* **ssr:** properly init slots during ssr rendering ([#12441](https://github.com/vuejs/core/issues/12441)) ([2206cd2](https://github.com/vuejs/core/commit/2206cd235a1627c540e795e378b7564a55b47313)), closes [#12438](https://github.com/vuejs/core/issues/12438)
* **transition:** fix KeepAlive with transition out-in mode behavior in production ([#12468](https://github.com/vuejs/core/issues/12468)) ([343c891](https://github.com/vuejs/core/commit/343c89122448719bd6ed6bd9de986dfb2721d6bf)), closes [#12465](https://github.com/vuejs/core/issues/12465)
* **TransitionGroup:** reset prevChildren to prevent memory leak ([#13183](https://github.com/vuejs/core/issues/13183)) ([8b848cb](https://github.com/vuejs/core/commit/8b848cbbd2af337d23e19e202f9ab433f8580855)), closes [#13181](https://github.com/vuejs/core/issues/13181)
* **types:** allow return any for Options API lifecycle hooks ([#5914](https://github.com/vuejs/core/issues/5914)) ([06310e8](https://github.com/vuejs/core/commit/06310e82f5bed62d1b9733dcb18cd8d6edc988de))
* **types:** the directive's modifiers should be optional ([#12605](https://github.com/vuejs/core/issues/12605)) ([10e54dc](https://github.com/vuejs/core/commit/10e54dcc86a7967f3196d96200bcbd1d3d42082f))
* **typos:** fix comments referencing transformElement.ts ([#12551](https://github.com/vuejs/core/issues/12551))[ci-skip] ([11c053a](https://github.com/vuejs/core/commit/11c053a5429ad0d27a0e2c78b6b026ea00ace116))
### Features
* **types:** add type TemplateRef ([#12645](https://github.com/vuejs/core/issues/12645)) ([636a861](https://github.com/vuejs/core/commit/636a8619f06c71dfd79f7f6412fd130c4f84226f))
## [3.5.13](https://github.com/vuejs/core/compare/v3.5.12...v3.5.13) (2024-11-15)
### Bug Fixes
* **compiler-core:** handle v-memo + v-for with functional key ([#12014](https://github.com/vuejs/core/issues/12014)) ([99009ee](https://github.com/vuejs/core/commit/99009eee0efc238392daba93792d478525b21afa)), closes [#12013](https://github.com/vuejs/core/issues/12013)
* **compiler-dom:** properly stringify template string style ([#12392](https://github.com/vuejs/core/issues/12392)) ([2d78539](https://github.com/vuejs/core/commit/2d78539da35322aea5f821b3cf9b02d006abac72)), closes [#12391](https://github.com/vuejs/core/issues/12391)
* **custom-element:** avoid triggering mutationObserver when relecting props ([352bc88](https://github.com/vuejs/core/commit/352bc88c1bd2fda09c61ab17ea1a5967ffcd7bc0)), closes [#12214](https://github.com/vuejs/core/issues/12214) [#12215](https://github.com/vuejs/core/issues/12215)
* **deps:** update dependency postcss to ^8.4.48 ([#12356](https://github.com/vuejs/core/issues/12356)) ([b5ff930](https://github.com/vuejs/core/commit/b5ff930089985a58c3553977ef999cec2a6708a4))
* **hydration:** the component vnode's el should be updated when a mismatch occurs. ([#12255](https://github.com/vuejs/core/issues/12255)) ([a20a4cb](https://github.com/vuejs/core/commit/a20a4cb36a3e717d1f8f259d0d59f133f508ff0a)), closes [#12253](https://github.com/vuejs/core/issues/12253)
* **reactivity:** avoid unnecessary watcher effect removal from inactive scope ([2193284](https://github.com/vuejs/core/commit/21932840eae72ffcd357a62ec596aaecc7ec224a)), closes [#5783](https://github.com/vuejs/core/issues/5783) [#5806](https://github.com/vuejs/core/issues/5806)
* **reactivity:** release nested effects/scopes on effect scope stop ([#12373](https://github.com/vuejs/core/issues/12373)) ([bee2f5e](https://github.com/vuejs/core/commit/bee2f5ee62dc0cd04123b737779550726374dd0a)), closes [#12370](https://github.com/vuejs/core/issues/12370)
* **runtime-dom:** set css vars before user onMounted hooks ([2d5c5e2](https://github.com/vuejs/core/commit/2d5c5e25e9b7a56e883674fb434135ac514429b5)), closes [#11533](https://github.com/vuejs/core/issues/11533)
* **runtime-dom:** set css vars on update to handle child forcing reflow in onMount ([#11561](https://github.com/vuejs/core/issues/11561)) ([c4312f9](https://github.com/vuejs/core/commit/c4312f9c715c131a09e552ba46e9beb4b36d55e6))
* **ssr:** avoid updating subtree of async component if it is resolved ([#12363](https://github.com/vuejs/core/issues/12363)) ([da7ad5e](https://github.com/vuejs/core/commit/da7ad5e3d24f3e108401188d909d27a4910da095)), closes [#12362](https://github.com/vuejs/core/issues/12362)
* **ssr:** ensure v-text updates correctly with custom directives in SSR output ([#12311](https://github.com/vuejs/core/issues/12311)) ([1f75d4e](https://github.com/vuejs/core/commit/1f75d4e6dfe18121ebe443cd3e8105d54f727893)), closes [#12309](https://github.com/vuejs/core/issues/12309)
* **ssr:** handle initial selected state for select with v-model + v-for option ([#12399](https://github.com/vuejs/core/issues/12399)) ([4f8d807](https://github.com/vuejs/core/commit/4f8d8078221ee52deed266677a227ad2a6d8dd22)), closes [#12395](https://github.com/vuejs/core/issues/12395)
* **teleport:** handle deferred teleport update before mounted ([#12168](https://github.com/vuejs/core/issues/12168)) ([8bff142](https://github.com/vuejs/core/commit/8bff142f99b646e9dd15897ec75368fbf34f1534)), closes [#12161](https://github.com/vuejs/core/issues/12161)
* **templateRef:** set ref on cached async component which wrapped in KeepAlive ([#12290](https://github.com/vuejs/core/issues/12290)) ([983eb50](https://github.com/vuejs/core/commit/983eb50a17eac76f1bba4394ad0316c62b72191d)), closes [#4999](https://github.com/vuejs/core/issues/4999) [#5004](https://github.com/vuejs/core/issues/5004)
* **test:** update snapshot ([#12169](https://github.com/vuejs/core/issues/12169)) ([828d4a4](https://github.com/vuejs/core/commit/828d4a443919fa2aa4e2e92fbd03a5f04b258eea))
* **Transition:** fix transition memory leak edge case ([#12182](https://github.com/vuejs/core/issues/12182)) ([660132d](https://github.com/vuejs/core/commit/660132df6c6a8c14bf75e593dc47d2fdada30322)), closes [#12181](https://github.com/vuejs/core/issues/12181)
* **transition:** reflow before leave-active class after leave-from ([#12288](https://github.com/vuejs/core/issues/12288)) ([4b479db](https://github.com/vuejs/core/commit/4b479db61d233b054561402ae94ef08550073ea1)), closes [#2593](https://github.com/vuejs/core/issues/2593)
* **types:** defineEmits w/ interface declaration ([#12343](https://github.com/vuejs/core/issues/12343)) ([1022eab](https://github.com/vuejs/core/commit/1022eabaa1aaf8436876f5ec5573cb1e4b3959a6)), closes [#8457](https://github.com/vuejs/core/issues/8457)
* **v-once:** setting hasOnce to current block only when in v-once ([#12374](https://github.com/vuejs/core/issues/12374)) ([37300fc](https://github.com/vuejs/core/commit/37300fc26190a7299efddbf98800ffd96d5cad96)), closes [#12371](https://github.com/vuejs/core/issues/12371)
### Performance Improvements
* **reactivity:** do not track inner key `__v_skip`` ([#11690](https://github.com/vuejs/core/issues/11690)) ([d637bd6](https://github.com/vuejs/core/commit/d637bd6c0164c2883e6eabd3c2f1f8c258dedfb1))
* **runtime-core:** use feature flag for call to resolveMergedOptions ([#12163](https://github.com/vuejs/core/issues/12163)) ([1755ac0](https://github.com/vuejs/core/commit/1755ac0a108ba3486bd8397e56d3bdcd69196594))
## [3.5.12](https://github.com/vuejs/core/compare/v3.5.11...v3.5.12) (2024-10-11)
### Bug Fixes
* **compiler-dom:** avoid stringify option with null value ([#12096](https://github.com/vuejs/core/issues/12096)) ([f6d9926](https://github.com/vuejs/core/commit/f6d99262364b7444ebab8742158599e8cdd79eaa)), closes [#12093](https://github.com/vuejs/core/issues/12093)
* **compiler-sfc:** do not skip TSInstantiationExpression when transforming props destructure ([#12064](https://github.com/vuejs/core/issues/12064)) ([d3ecde8](https://github.com/vuejs/core/commit/d3ecde8a696ff62c8d0ab067fd1d7ee0565b63c5))
* **compiler-sfc:** use sass modern api if available and avoid deprecation warning ([#11992](https://github.com/vuejs/core/issues/11992)) ([4474c11](https://github.com/vuejs/core/commit/4474c113d1fb1c26298dd6794275d5b5c7cc4d93))
* **compiler:** clone loc to `ifNode` ([#12131](https://github.com/vuejs/core/issues/12131)) ([cde2c06](https://github.com/vuejs/core/commit/cde2c0671b00d4f6111fcbd7aa76e45872f20b0c)), closes [vuejs/language-tools#4911](https://github.com/vuejs/language-tools/issues/4911)
* **custom-element:** properly remove hyphenated attribute ([#12143](https://github.com/vuejs/core/issues/12143)) ([e16e9a7](https://github.com/vuejs/core/commit/e16e9a7341e7cfb3c443da4e5e5b06e8158712c3)), closes [#12139](https://github.com/vuejs/core/issues/12139)
* **defineModel:** handle kebab-case model correctly ([#12063](https://github.com/vuejs/core/issues/12063)) ([c0418a3](https://github.com/vuejs/core/commit/c0418a3b8fa96a0b108ab71b7aab5d3388f90557)), closes [#12060](https://github.com/vuejs/core/issues/12060)
* **deps:** update dependency monaco-editor to ^0.52.0 ([#12119](https://github.com/vuejs/core/issues/12119)) ([f7cbea2](https://github.com/vuejs/core/commit/f7cbea2111c7770a180b640f36f6a5d4d6abc698))
* **hydration:** provide compat fallback for idle callback hydration strategy ([#11935](https://github.com/vuejs/core/issues/11935)) ([1ae545a](https://github.com/vuejs/core/commit/1ae545a3786abef983be1c969726489685569c92))
* **reactivity:** trigger reactivity for Map key `undefined` ([#12055](https://github.com/vuejs/core/issues/12055)) ([7ad289e](https://github.com/vuejs/core/commit/7ad289e1e7fea654524008ff91e43a8b8a55ef22)), closes [#12054](https://github.com/vuejs/core/issues/12054)
* **runtime-core:** allow symbol values for slot prop key ([#12069](https://github.com/vuejs/core/issues/12069)) ([d9d4d4e](https://github.com/vuejs/core/commit/d9d4d4e158cd51a9ddda249f29de8467f60b2792)), closes [#12068](https://github.com/vuejs/core/issues/12068)
* **runtime-core:** fix required prop check false positive for kebab-case edge cases ([#12034](https://github.com/vuejs/core/issues/12034)) ([9da1ac1](https://github.com/vuejs/core/commit/9da1ac156552ac449754e1373aac7e349841becb)), closes [#12011](https://github.com/vuejs/core/issues/12011)
* **runtime-dom:** prevent unnecessary updates in v-model checkbox when value is unchanged ([#12146](https://github.com/vuejs/core/issues/12146)) ([ea943af](https://github.com/vuejs/core/commit/ea943afe404c4ca4b729906c5e8daf7aa2ccde9b)), closes [#12144](https://github.com/vuejs/core/issues/12144)
* **teleport:** handle disabled teleport with updateCssVars ([#12113](https://github.com/vuejs/core/issues/12113)) ([76a8223](https://github.com/vuejs/core/commit/76a8223199c148b79a5c0ea19e235164809760cd)), closes [#12112](https://github.com/vuejs/core/issues/12112)
* **transition/ssr:** make transition appear work with Suspense in SSR ([#12047](https://github.com/vuejs/core/issues/12047)) ([f1a4f67](https://github.com/vuejs/core/commit/f1a4f67aedfe83e440c54222213f070774faa421)), closes [#12046](https://github.com/vuejs/core/issues/12046)
* **types:** ensure `this.$props` type does not include `string` ([#12123](https://github.com/vuejs/core/issues/12123)) ([704173e](https://github.com/vuejs/core/commit/704173e24276706de672cca6c9507e4dd9651197)), closes [#12122](https://github.com/vuejs/core/issues/12122)
* **types:** retain union type narrowing with defaults applied ([#12108](https://github.com/vuejs/core/issues/12108)) ([05685a9](https://github.com/vuejs/core/commit/05685a9d7c42d4cd37169b867833776b91154fed)), closes [#12106](https://github.com/vuejs/core/issues/12106)
* **useId:** ensure useId consistency when using serverPrefetch ([#12128](https://github.com/vuejs/core/issues/12128)) ([b4d3534](https://github.com/vuejs/core/commit/b4d35349d8bc39aa15bd3f1094d230e5928b177c)), closes [#12102](https://github.com/vuejs/core/issues/12102)
* **watch:** watchEffect clean-up with SSR ([#12097](https://github.com/vuejs/core/issues/12097)) ([b094c72](https://github.com/vuejs/core/commit/b094c72b3d40c52c7124f145a9db028509a11202)), closes [#11956](https://github.com/vuejs/core/issues/11956)
### Performance Improvements
* **reactivity:** avoid unnecessary recursion in removeSub ([#12135](https://github.com/vuejs/core/issues/12135)) ([ec917cf](https://github.com/vuejs/core/commit/ec917cfdb9d0169cd0835d3a0e28244242657dc9))
## [3.5.11](https://github.com/vuejs/core/compare/v3.5.10...v3.5.11) (2024-10-03)
### Bug Fixes
* **compiler-sfc:** do not skip `TSSatisfiesExpression` when transforming props destructure ([#12062](https://github.com/vuejs/core/issues/12062)) ([2328b05](https://github.com/vuejs/core/commit/2328b051f4efa1f1394b7d4e73b7c3f76e430e7c)), closes [#12061](https://github.com/vuejs/core/issues/12061)
* **reactivity:** prevent overwriting `next` property during batch processing ([#12075](https://github.com/vuejs/core/issues/12075)) ([d3f5e6e](https://github.com/vuejs/core/commit/d3f5e6e5319b4ffaa55ca9a2ea3d95d78e76fa58)), closes [#12072](https://github.com/vuejs/core/issues/12072)
* **scheduler:** job ordering when the post queue is flushing ([#12090](https://github.com/vuejs/core/issues/12090)) ([577edca](https://github.com/vuejs/core/commit/577edca8e7795436efd710d1c289ea8ea2642b0e))
* **types:** correctly infer `TypeProps` when it is `any` ([#12073](https://github.com/vuejs/core/issues/12073)) ([57315ab](https://github.com/vuejs/core/commit/57315ab9688c9741a271d1075bbd28cbe5f71e2f)), closes [#12058](https://github.com/vuejs/core/issues/12058)
* **types:** should not intersect `PublicProps` with `Props` ([#12077](https://github.com/vuejs/core/issues/12077)) ([6f85894](https://github.com/vuejs/core/commit/6f8589437635706f825ccec51800effba1d2bf5f))
* **types:** infer the first generic type of `Ref` correctly ([#12094](https://github.com/vuejs/core/issues/12094)) ([c97bb84](https://github.com/vuejs/core/commit/c97bb84d0b0a16b012f886b6498e924415ed63e5))
## [3.5.10](https://github.com/vuejs/core/compare/v3.5.9...v3.5.10) (2024-09-27)
### Bug Fixes
* **custom-element:** properly set kebab-case props on Vue custom elements ([ea3efa0](https://github.com/vuejs/core/commit/ea3efa09e008918c1d9ba7226833a8b1a7a57244)), closes [#12030](https://github.com/vuejs/core/issues/12030) [#12032](https://github.com/vuejs/core/issues/12032)
* **reactivity:** fix nested batch edge case ([93c95dd](https://github.com/vuejs/core/commit/93c95dd4cd416503f43a98a1455f62658d22b0b2))
* **reactivity:** only clear notified flags for computed in first batch iteration ([aa9ef23](https://github.com/vuejs/core/commit/aa9ef2386a0cd39a174e5a887ec2b1a3525034fc)), closes [#12045](https://github.com/vuejs/core/issues/12045)
* **types/ref:** handle nested refs in UnwrapRef ([#12049](https://github.com/vuejs/core/issues/12049)) ([e2c19c2](https://github.com/vuejs/core/commit/e2c19c20cfee9788519a80c0e53e216b78505994)), closes [#12044](https://github.com/vuejs/core/issues/12044)
## [3.5.9](https://github.com/vuejs/core/compare/v3.5.8...v3.5.9) (2024-09-26)
### Bug Fixes
* **reactivity:** fix property dep removal regression ([6001e5c](https://github.com/vuejs/core/commit/6001e5c81a05c894586f9287fbd991677bdd0455)), closes [#12020](https://github.com/vuejs/core/issues/12020) [#12021](https://github.com/vuejs/core/issues/12021)
* **reactivity:** fix recursive sync watcher on computed edge case ([10ff159](https://github.com/vuejs/core/commit/10ff15924053d9bd95ad706f78ce09e288213fcf)), closes [#12033](https://github.com/vuejs/core/issues/12033) [#12037](https://github.com/vuejs/core/issues/12037)
* **runtime-core:** avoid rendering plain object as VNode ([#12038](https://github.com/vuejs/core/issues/12038)) ([cb34b28](https://github.com/vuejs/core/commit/cb34b28a4a9bf868be4785b001c526163eda342e)), closes [#12035](https://github.com/vuejs/core/issues/12035) [vitejs/vite-plugin-vue#353](https://github.com/vitejs/vite-plugin-vue/issues/353)
* **runtime-core:** make useId() always return a string ([a177092](https://github.com/vuejs/core/commit/a177092754642af2f98c33a4feffe8f198c3c950))
* **types:** correct type inference of union event names ([#12022](https://github.com/vuejs/core/issues/12022)) ([4da6881](https://github.com/vuejs/core/commit/4da688141d9e7c15b622c289deaa81b11845b2c7))
* **vue:** properly cache runtime compilation ([#12019](https://github.com/vuejs/core/issues/12019)) ([fa0ba24](https://github.com/vuejs/core/commit/fa0ba24b3ace02d7ecab65e57c2bea89a2550dcb))
## [3.5.8](https://github.com/vuejs/core/compare/v3.5.7...v3.5.8) (2024-09-22)
### Bug Fixes
* **reactivity:** do not remove dep from depsMap when cleaning up deps of computed ([#11995](https://github.com/vuejs/core/issues/11995)) ([0267a58](https://github.com/vuejs/core/commit/0267a588017eee4951ac2a877fe1ccae84cad905))
## [3.5.7](https://github.com/vuejs/core/compare/v3.5.6...v3.5.7) (2024-09-20)
### Bug Fixes
* **compile-core:** fix v-model with newlines edge case ([#11960](https://github.com/vuejs/core/issues/11960)) ([6224288](https://github.com/vuejs/core/commit/62242886d705ece88dbcad45bb78072ecccad0ca)), closes [#8306](https://github.com/vuejs/core/issues/8306)
* **compiler-sfc:** initialize scope with null prototype object ([#11963](https://github.com/vuejs/core/issues/11963)) ([215e154](https://github.com/vuejs/core/commit/215e15407294bf667261360218f975b88c99c2e5))
* **hydration:** avoid observing non-Element node ([#11954](https://github.com/vuejs/core/issues/11954)) ([7257e6a](https://github.com/vuejs/core/commit/7257e6a34200409b3fc347d3bb807e11e2785974)), closes [#11952](https://github.com/vuejs/core/issues/11952)
* **reactivity:** do not remove dep from depsMap when unsubbed by computed ([960706e](https://github.com/vuejs/core/commit/960706eebf73f08ebc9d5dd853a05def05e2c153))
* **reactivity:** fix dev-only memory leak by updating dep.subsHead on sub removal ([5c8b76e](https://github.com/vuejs/core/commit/5c8b76ed6cfbbcee4cbaac0b72beab7291044e4f)), closes [#11956](https://github.com/vuejs/core/issues/11956)
* **reactivity:** fix memory leak from dep instances of garbage collected objects ([235ea47](https://github.com/vuejs/core/commit/235ea4772ed2972914cf142da8b7ac1fb04f7585)), closes [#11979](https://github.com/vuejs/core/issues/11979) [#11971](https://github.com/vuejs/core/issues/11971)
* **reactivity:** fix triggerRef call on ObjectRefImpl returned by toRef ([#11986](https://github.com/vuejs/core/issues/11986)) ([b030c8b](https://github.com/vuejs/core/commit/b030c8bc7327877efb98aa3d9a58eb287a6ff07a)), closes [#11982](https://github.com/vuejs/core/issues/11982)
* **scheduler:** ensure recursive jobs can't be queued twice ([#11955](https://github.com/vuejs/core/issues/11955)) ([d18d6aa](https://github.com/vuejs/core/commit/d18d6aa1b20dc57a8103c51ec4d61e8e53ed936d))
* **ssr:** don't render comments in TransitionGroup ([#11961](https://github.com/vuejs/core/issues/11961)) ([a2f6ede](https://github.com/vuejs/core/commit/a2f6edeb02faedbb673c4bc5c6a59d9a79a37d07)), closes [#11958](https://github.com/vuejs/core/issues/11958)
* **transition:** respect `duration` setting even when it is `0` ([#11967](https://github.com/vuejs/core/issues/11967)) ([f927a4a](https://github.com/vuejs/core/commit/f927a4ae6f7c453f70ba89498ee0c737dc9866fd))
* **types:** correct type inference of all-optional props ([#11644](https://github.com/vuejs/core/issues/11644)) ([9eca65e](https://github.com/vuejs/core/commit/9eca65ee9871d1ac878755afa9a3eb1b02030350)), closes [#11733](https://github.com/vuejs/core/issues/11733) [vuejs/language-tools#4704](https://github.com/vuejs/language-tools/issues/4704)
### Performance Improvements
* **hydration:** avoid observer if element is in viewport ([#11639](https://github.com/vuejs/core/issues/11639)) ([e075dfa](https://github.com/vuejs/core/commit/e075dfad5c7649c6045e3711687ec888e7aa1a39))
## [3.5.6](https://github.com/vuejs/core/compare/v3.5.5...v3.5.6) (2024-09-16)
### Bug Fixes
* **compile-dom:** should be able to stringify mathML ([#11891](https://github.com/vuejs/core/issues/11891)) ([85c138c](https://github.com/vuejs/core/commit/85c138ced108268f7656b568dfd3036a1e0aae34))
* **compiler-sfc:** preserve old behavior when using withDefaults with desutructure ([8492c3c](https://github.com/vuejs/core/commit/8492c3c49a922363d6c77ef192c133a8fbce6514)), closes [#11930](https://github.com/vuejs/core/issues/11930)
* **reactivity:** avoid exponential perf cost and reduce call stack depth for deeply chained computeds ([#11944](https://github.com/vuejs/core/issues/11944)) ([c74bb8c](https://github.com/vuejs/core/commit/c74bb8c2dd9e82aaabb0a2a2b368e900929b513b)), closes [#11928](https://github.com/vuejs/core/issues/11928)
* **reactivity:** rely on dirty check only when computed has deps ([#11931](https://github.com/vuejs/core/issues/11931)) ([aa5dafd](https://github.com/vuejs/core/commit/aa5dafd2b55d42d6a29316a3bc91aea85c676a0b)), closes [#11929](https://github.com/vuejs/core/issues/11929)
* **watch:** `once` option should be ignored by watchEffect ([#11884](https://github.com/vuejs/core/issues/11884)) ([49fa673](https://github.com/vuejs/core/commit/49fa673493d93b77ddba2165ab6545bae84fd1ae))
* **watch:** unwatch should be callable during SSR ([#11925](https://github.com/vuejs/core/issues/11925)) ([2d6adf7](https://github.com/vuejs/core/commit/2d6adf78a047eed091db277ffbd9df0822fb0bdd)), closes [#11924](https://github.com/vuejs/core/issues/11924)
## [3.5.5](https://github.com/vuejs/core/compare/v3.5.4...v3.5.5) (2024-09-13)
### Bug Fixes
* **compiler-core:** fix handling of delimiterOpen in VPre ([#11915](https://github.com/vuejs/core/issues/11915)) ([706d4ac](https://github.com/vuejs/core/commit/706d4ac1d0210b2d9134b3228280187fe02fc971)), closes [#11913](https://github.com/vuejs/core/issues/11913)
* **compiler-dom:** fix stringify static edge for partially eligible chunks in cached parent ([1d99d61](https://github.com/vuejs/core/commit/1d99d61c1bd77f9ea6743f6214a82add8346a121)), closes [#11879](https://github.com/vuejs/core/issues/11879) [#11890](https://github.com/vuejs/core/issues/11890)
* **compiler-dom:** should ignore leading newline in `<textarea>` per spec ([3c4bf76](https://github.com/vuejs/core/commit/3c4bf7627649ec1e3220f8c4e4163c20d2afb367))
* **compiler-sfc:** nested css supports atrule and comment ([#11899](https://github.com/vuejs/core/issues/11899)) ([0e7bc71](https://github.com/vuejs/core/commit/0e7bc717e6640644f062957ec5031506f0dab215)), closes [#11896](https://github.com/vuejs/core/issues/11896)
* **custom-element:** handle nested customElement mount w/ shadowRoot false ([#11861](https://github.com/vuejs/core/issues/11861)) ([f2d8019](https://github.com/vuejs/core/commit/f2d801918841e7673ff3f048d0d895592a2f7e23)), closes [#11851](https://github.com/vuejs/core/issues/11851) [#11871](https://github.com/vuejs/core/issues/11871)
* **hmr:** reload async child wrapped in Suspense + KeepAlive ([#11907](https://github.com/vuejs/core/issues/11907)) ([10a2c60](https://github.com/vuejs/core/commit/10a2c6053bd30d160d0214bb3566f540187e6874)), closes [#11868](https://github.com/vuejs/core/issues/11868)
* **hydration:** fix mismatch of leading newline in `<textarea>` and `<pre>` ([a5f3c2e](https://github.com/vuejs/core/commit/a5f3c2eb4d2e7fae93ff93ce865b269f01cc825e)), closes [#11873](https://github.com/vuejs/core/issues/11873) [#11874](https://github.com/vuejs/core/issues/11874)
* **reactivity:** properly clean up deps, fix memory leak ([8ea5d6d](https://github.com/vuejs/core/commit/8ea5d6d6981ab7febda0be43c3c92b18869c3a2a)), closes [#11901](https://github.com/vuejs/core/issues/11901)
* **runtime-core:** properly update async component nested in KeepAlive ([#11917](https://github.com/vuejs/core/issues/11917)) ([7fe6c79](https://github.com/vuejs/core/commit/7fe6c795a1fc7ddcea5ad91a56141561192373ac)), closes [#11916](https://github.com/vuejs/core/issues/11916)
* **TransitionGroup:** not warn unkeyed text children with whitespece preserve ([#11888](https://github.com/vuejs/core/issues/11888)) ([7571f20](https://github.com/vuejs/core/commit/7571f20bc3d1854377a146f41d211e05bb68cd47)), closes [#11885](https://github.com/vuejs/core/issues/11885)
## [3.5.4](https://github.com/vuejs/core/compare/v3.5.3...v3.5.4) (2024-09-10) ## [3.5.4](https://github.com/vuejs/core/compare/v3.5.3...v3.5.4) (2024-09-10)

View File

@ -34,7 +34,8 @@ Please make sure to respect issue requirements and use [the new issue helper](ht
## Stay In Touch ## Stay In Touch
- [Twitter](https://twitter.com/vuejs) - [X](https://x.com/vuejs)
- [Bluesky](https://bsky.app/profile/vuejs.org)
- [Blog](https://blog.vuejs.org/) - [Blog](https://blog.vuejs.org/)
- [Job Board](https://vuejobs.com/?ref=vuejs) - [Job Board](https://vuejobs.com/?ref=vuejs)
@ -44,7 +45,9 @@ Please make sure to read the [Contributing Guide](https://github.com/vuejs/core/
Thank you to all the people who already contributed to Vue! Thank you to all the people who already contributed to Vue!
<a href="https://github.com/vuejs/core/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890" /></a> <a href="https://github.com/vuejs/core/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890&limit=500" /></a>
<sub>_Note: Showing the first 500 contributors only due to GitHub image size limitations_</sub>
## License ## License

View File

@ -13,3 +13,4 @@ We would like to thank the following security researchers for responsibly disclo
- Jeet Pal - [@jeetpal2007](https://github.com/jeetpal2007) | [Email](mailto:jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290) - Jeet Pal - [@jeetpal2007](https://github.com/jeetpal2007) | [Email](mailto:jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290)
- Mix - [@mnixry](https://github.com/mnixry) - Mix - [@mnixry](https://github.com/mnixry)
- Aviv Keller - [@RedYetiDev](https://github.com/redyetidev) | [LinkedIn](https://www.linkedin.com/in/redyetidev) <redyetidev@gmail.com> - Aviv Keller - [@RedYetiDev](https://github.com/redyetidev) | [LinkedIn](https://www.linkedin.com/in/redyetidev) <redyetidev@gmail.com>
- Ben Zimmermann - [@bzzimmy](https://github.com/bzzimmy) | [Email](mailto:kernelrocks@proton.me)

View File

@ -56,13 +56,13 @@
- **hydration:** handle camel-case tag name when performing match assertion ([#3247](https://github.com/vuejs/core/issues/3247)) ([9036f88](https://github.com/vuejs/core/commit/9036f88d8304a3455265f1ecd86ec8f4a5ea4715)), closes [#3243](https://github.com/vuejs/core/issues/3243) - **hydration:** handle camel-case tag name when performing match assertion ([#3247](https://github.com/vuejs/core/issues/3247)) ([9036f88](https://github.com/vuejs/core/commit/9036f88d8304a3455265f1ecd86ec8f4a5ea4715)), closes [#3243](https://github.com/vuejs/core/issues/3243)
- **KeepAlive:** adapt keepalive for ssr ([#3259](https://github.com/vuejs/core/issues/3259)) ([e8e9b00](https://github.com/vuejs/core/commit/e8e9b00f81ed42434afd92f84101e7a14d70a23c)), closes [#3255](https://github.com/vuejs/core/issues/3255) - **KeepAlive:** adapt keepalive for ssr ([#3259](https://github.com/vuejs/core/issues/3259)) ([e8e9b00](https://github.com/vuejs/core/commit/e8e9b00f81ed42434afd92f84101e7a14d70a23c)), closes [#3255](https://github.com/vuejs/core/issues/3255)
- **reactivity:** ensure computed can be wrapped by readonly ([41e02f0](https://github.com/vuejs/core/commit/41e02f0fac069c93c94438741517e713f3c94215)), closes [#3376](https://github.com/vuejs/core/issues/3376) - **reactivity:** ensure computed can be wrapped by readonly ([41e02f0](https://github.com/vuejs/core/commit/41e02f0fac069c93c94438741517e713f3c94215)), closes [#3376](https://github.com/vuejs/core/issues/3376)
- **reactivity:** ensure that shallow and normal proxies are tracked seperately (close [#2843](https://github.com/vuejs/core/issues/2843)) ([#2851](https://github.com/vuejs/core/issues/2851)) ([22cc4a7](https://github.com/vuejs/core/commit/22cc4a76592cfe336e75e2fa0c05232ae1f0f149)) - **reactivity:** ensure that shallow and normal proxies are tracked separately (close [#2843](https://github.com/vuejs/core/issues/2843)) ([#2851](https://github.com/vuejs/core/issues/2851)) ([22cc4a7](https://github.com/vuejs/core/commit/22cc4a76592cfe336e75e2fa0c05232ae1f0f149))
- **reactivity:** fix shallow readonly behavior for collections ([#3003](https://github.com/vuejs/core/issues/3003)) ([68de9f4](https://github.com/vuejs/core/commit/68de9f408a2e61a5726a4a0d03b026cba451c5bd)), closes [#3007](https://github.com/vuejs/core/issues/3007) - **reactivity:** fix shallow readonly behavior for collections ([#3003](https://github.com/vuejs/core/issues/3003)) ([68de9f4](https://github.com/vuejs/core/commit/68de9f408a2e61a5726a4a0d03b026cba451c5bd)), closes [#3007](https://github.com/vuejs/core/issues/3007)
- **rumtime-core:** custom dom props should be cloned when cloning a hoisted DOM ([#3080](https://github.com/vuejs/core/issues/3080)) ([5dbe834](https://github.com/vuejs/core/commit/5dbe8348581dacd7a3594a9b0055ce350ce8e5bf)), closes [#3072](https://github.com/vuejs/core/issues/3072) - **rumtime-core:** custom dom props should be cloned when cloning a hoisted DOM ([#3080](https://github.com/vuejs/core/issues/3080)) ([5dbe834](https://github.com/vuejs/core/commit/5dbe8348581dacd7a3594a9b0055ce350ce8e5bf)), closes [#3072](https://github.com/vuejs/core/issues/3072)
- **runtime-core:** cache props default values to avoid unnecessary watcher trigger ([#3474](https://github.com/vuejs/core/issues/3474)) ([44166b4](https://github.com/vuejs/core/commit/44166b43d9be1062f79612880f71284049bcab0b)), closes [#3471](https://github.com/vuejs/core/issues/3471) - **runtime-core:** cache props default values to avoid unnecessary watcher trigger ([#3474](https://github.com/vuejs/core/issues/3474)) ([44166b4](https://github.com/vuejs/core/commit/44166b43d9be1062f79612880f71284049bcab0b)), closes [#3471](https://github.com/vuejs/core/issues/3471)
- **runtime-core:** ensure only skip unflushed job ([#3406](https://github.com/vuejs/core/issues/3406)) ([bf34e33](https://github.com/vuejs/core/commit/bf34e33c909da89681b9c5004cdf04ab198ec5a7)) - **runtime-core:** ensure only skip unflushed job ([#3406](https://github.com/vuejs/core/issues/3406)) ([bf34e33](https://github.com/vuejs/core/commit/bf34e33c909da89681b9c5004cdf04ab198ec5a7))
- **runtime-core:** fix async component ref handling ([#3191](https://github.com/vuejs/core/issues/3191)) ([7562e72](https://github.com/vuejs/core/commit/7562e72c2b58a5646bd4fbd9adea11eb884fe140)), closes [#3188](https://github.com/vuejs/core/issues/3188) - **runtime-core:** fix async component ref handling ([#3191](https://github.com/vuejs/core/issues/3191)) ([7562e72](https://github.com/vuejs/core/commit/7562e72c2b58a5646bd4fbd9adea11eb884fe140)), closes [#3188](https://github.com/vuejs/core/issues/3188)
- **runtime-core:** fix erraneous emits warnings w/ mixins ([60d777d](https://github.com/vuejs/core/commit/60d777d228414515cc32526ad72a53ef070501be)), closes [#2651](https://github.com/vuejs/core/issues/2651) - **runtime-core:** fix erroneous emits warnings w/ mixins ([60d777d](https://github.com/vuejs/core/commit/60d777d228414515cc32526ad72a53ef070501be)), closes [#2651](https://github.com/vuejs/core/issues/2651)
- **runtime-core:** fix warning for absent props ([#3363](https://github.com/vuejs/core/issues/3363)) ([86ceef4](https://github.com/vuejs/core/commit/86ceef43523bfbbb0a24731d3802ca6849cbefd6)), closes [#3362](https://github.com/vuejs/core/issues/3362) - **runtime-core:** fix warning for absent props ([#3363](https://github.com/vuejs/core/issues/3363)) ([86ceef4](https://github.com/vuejs/core/commit/86ceef43523bfbbb0a24731d3802ca6849cbefd6)), closes [#3362](https://github.com/vuejs/core/issues/3362)
- **runtime-core:** handle error in async setup ([#2881](https://github.com/vuejs/core/issues/2881)) ([d668d48](https://github.com/vuejs/core/commit/d668d48e9e5211a49ee53361ea5b4d67ba16e0a3)) - **runtime-core:** handle error in async setup ([#2881](https://github.com/vuejs/core/issues/2881)) ([d668d48](https://github.com/vuejs/core/commit/d668d48e9e5211a49ee53361ea5b4d67ba16e0a3))
- **runtime-core:** handle error in async watchEffect ([#3129](https://github.com/vuejs/core/issues/3129)) ([eb1fae6](https://github.com/vuejs/core/commit/eb1fae63f926435fb0eef890663d24e09d4c79e1)) - **runtime-core:** handle error in async watchEffect ([#3129](https://github.com/vuejs/core/issues/3129)) ([eb1fae6](https://github.com/vuejs/core/commit/eb1fae63f926435fb0eef890663d24e09d4c79e1))
@ -202,7 +202,7 @@ may cause build issues in projects still using TS 3.x.
- **script-setup:** ensure useContext() return valid context ([73cdb9d](https://github.com/vuejs/core/commit/73cdb9d4208f887fe08349657122e39175d7166c)) - **script-setup:** ensure useContext() return valid context ([73cdb9d](https://github.com/vuejs/core/commit/73cdb9d4208f887fe08349657122e39175d7166c))
- **slots:** dynamically named slots should be keyed by name ([2ab8c41](https://github.com/vuejs/core/commit/2ab8c41a1a43952fb229587a9da48d9a1214ab9e)), closes [#2535](https://github.com/vuejs/core/issues/2535) - **slots:** dynamically named slots should be keyed by name ([2ab8c41](https://github.com/vuejs/core/commit/2ab8c41a1a43952fb229587a9da48d9a1214ab9e)), closes [#2535](https://github.com/vuejs/core/issues/2535)
- **slots:** should render fallback content when slot content contains no valid nodes ([#2485](https://github.com/vuejs/core/issues/2485)) ([ce4915d](https://github.com/vuejs/core/commit/ce4915d8bed12f4cdb5fa8ca39bda98d0d3aabb7)), closes [#2347](https://github.com/vuejs/core/issues/2347) [#2461](https://github.com/vuejs/core/issues/2461) - **slots:** should render fallback content when slot content contains no valid nodes ([#2485](https://github.com/vuejs/core/issues/2485)) ([ce4915d](https://github.com/vuejs/core/commit/ce4915d8bed12f4cdb5fa8ca39bda98d0d3aabb7)), closes [#2347](https://github.com/vuejs/core/issues/2347) [#2461](https://github.com/vuejs/core/issues/2461)
- **suspense:** fix nested async child toggle inside already resovled suspense ([cf7f1db](https://github.com/vuejs/core/commit/cf7f1dbc9be8d50ad220e3630c38f5a9a217d693)), closes [#2215](https://github.com/vuejs/core/issues/2215) - **suspense:** fix nested async child toggle inside already resolved suspense ([cf7f1db](https://github.com/vuejs/core/commit/cf7f1dbc9be8d50ad220e3630c38f5a9a217d693)), closes [#2215](https://github.com/vuejs/core/issues/2215)
- **teleport:** Teleport into SVG elements ([#2648](https://github.com/vuejs/core/issues/2648)) ([cd92836](https://github.com/vuejs/core/commit/cd928362232747a51d1fd4790bb20adcdd59d187)), closes [#2652](https://github.com/vuejs/core/issues/2652) - **teleport:** Teleport into SVG elements ([#2648](https://github.com/vuejs/core/issues/2648)) ([cd92836](https://github.com/vuejs/core/commit/cd928362232747a51d1fd4790bb20adcdd59d187)), closes [#2652](https://github.com/vuejs/core/issues/2652)
- **transition:** avoid invoking stale transition end callbacks ([eaf8a67](https://github.com/vuejs/core/commit/eaf8a67c7219e1b79d6abca44a1d7f1b341b58b0)), closes [#2482](https://github.com/vuejs/core/issues/2482) - **transition:** avoid invoking stale transition end callbacks ([eaf8a67](https://github.com/vuejs/core/commit/eaf8a67c7219e1b79d6abca44a1d7f1b341b58b0)), closes [#2482](https://github.com/vuejs/core/issues/2482)
- **transition:** respect rules in \*-leave-from transition class ([#2597](https://github.com/vuejs/core/issues/2597)) ([e2618a6](https://github.com/vuejs/core/commit/e2618a632d4add2819ffb8b575af0da189dc3204)), closes [#2593](https://github.com/vuejs/core/issues/2593) - **transition:** respect rules in \*-leave-from transition class ([#2597](https://github.com/vuejs/core/issues/2597)) ([e2618a6](https://github.com/vuejs/core/commit/e2618a632d4add2819ffb8b575af0da189dc3204)), closes [#2593](https://github.com/vuejs/core/issues/2593)
@ -236,7 +236,7 @@ may cause build issues in projects still using TS 3.x.
- **compiler-sfc:** compileScript inline render function mode ([886ed76](https://github.com/vuejs/core/commit/886ed7681dd203c07ff3b504538328f43e14d9b0)) - **compiler-sfc:** compileScript inline render function mode ([886ed76](https://github.com/vuejs/core/commit/886ed7681dd203c07ff3b504538328f43e14d9b0))
- **compiler-sfc:** new script setup implementation ([556560f](https://github.com/vuejs/core/commit/556560fae31d9e406cfae656089657b6332686c1)) - **compiler-sfc:** new script setup implementation ([556560f](https://github.com/vuejs/core/commit/556560fae31d9e406cfae656089657b6332686c1))
- **compiler-sfc:** new SFC css varaible injection implementation ([41bb7fa](https://github.com/vuejs/core/commit/41bb7fa330e78c4a354a2e67742bd13bee2f4293)) - **compiler-sfc:** new SFC css variable injection implementation ([41bb7fa](https://github.com/vuejs/core/commit/41bb7fa330e78c4a354a2e67742bd13bee2f4293))
- **compiler-sfc:** support kebab-case components in `<script setup>` sfc template ([3f99e23](https://github.com/vuejs/core/commit/3f99e239e03a8861c462d4ee91feb82066ab3e28)) - **compiler-sfc:** support kebab-case components in `<script setup>` sfc template ([3f99e23](https://github.com/vuejs/core/commit/3f99e239e03a8861c462d4ee91feb82066ab3e28))
- **runtime-core:** explicit expose API ([0e59770](https://github.com/vuejs/core/commit/0e59770b9282992f6a5af4d8fef33dafb948fc8b)) - **runtime-core:** explicit expose API ([0e59770](https://github.com/vuejs/core/commit/0e59770b9282992f6a5af4d8fef33dafb948fc8b))
@ -282,7 +282,7 @@ may cause build issues in projects still using TS 3.x.
- **runtime-core:** fix directive merging on component root ([4d1ebb5](https://github.com/vuejs/core/commit/4d1ebb5deb4c1cb2a02e8482bf8f9cc87197b088)), closes [#2298](https://github.com/vuejs/core/issues/2298) - **runtime-core:** fix directive merging on component root ([4d1ebb5](https://github.com/vuejs/core/commit/4d1ebb5deb4c1cb2a02e8482bf8f9cc87197b088)), closes [#2298](https://github.com/vuejs/core/issues/2298)
- **runtime-core:** fix duplicated unmount traversal in optimized mode ([376883d](https://github.com/vuejs/core/commit/376883d1cfea6ed92807cce1f1209f943a04b625)), closes [#2169](https://github.com/vuejs/core/issues/2169) - **runtime-core:** fix duplicated unmount traversal in optimized mode ([376883d](https://github.com/vuejs/core/commit/376883d1cfea6ed92807cce1f1209f943a04b625)), closes [#2169](https://github.com/vuejs/core/issues/2169)
- **runtime-core:** fix provide function data access in extends/mixins ([f06518a](https://github.com/vuejs/core/commit/f06518a8c9201b4fa2a956595aa9d89a192fcd20)), closes [#2300](https://github.com/vuejs/core/issues/2300) - **runtime-core:** fix provide function data access in extends/mixins ([f06518a](https://github.com/vuejs/core/commit/f06518a8c9201b4fa2a956595aa9d89a192fcd20)), closes [#2300](https://github.com/vuejs/core/issues/2300)
- **runtime-core:** fix SSR memoery leak due to props normalization cache ([a66e53a](https://github.com/vuejs/core/commit/a66e53a24f445b688eef6812ecb872dc53cf2702)), closes [#2225](https://github.com/vuejs/core/issues/2225) - **runtime-core:** fix SSR memory leak due to props normalization cache ([a66e53a](https://github.com/vuejs/core/commit/a66e53a24f445b688eef6812ecb872dc53cf2702)), closes [#2225](https://github.com/vuejs/core/issues/2225)
- **runtime-core:** make errorCaptured return value handling consistent with Vue 2 ([#2289](https://github.com/vuejs/core/issues/2289)) ([4d20ac8](https://github.com/vuejs/core/commit/4d20ac8173f84c87288255dcc03c62a6ee862a23)), closes [#2267](https://github.com/vuejs/core/issues/2267) - **runtime-core:** make errorCaptured return value handling consistent with Vue 2 ([#2289](https://github.com/vuejs/core/issues/2289)) ([4d20ac8](https://github.com/vuejs/core/commit/4d20ac8173f84c87288255dcc03c62a6ee862a23)), closes [#2267](https://github.com/vuejs/core/issues/2267)
- **runtime-core:** use consistent camelCase event casing for render functions ([#2278](https://github.com/vuejs/core/issues/2278)) ([62f2617](https://github.com/vuejs/core/commit/62f26173ba715fd8bf2b131e19d94275106e830d)), closes [#2249](https://github.com/vuejs/core/issues/2249) - **runtime-core:** use consistent camelCase event casing for render functions ([#2278](https://github.com/vuejs/core/issues/2278)) ([62f2617](https://github.com/vuejs/core/commit/62f26173ba715fd8bf2b131e19d94275106e830d)), closes [#2249](https://github.com/vuejs/core/issues/2249)
- **runtime-core:** vnode.el is null in watcher after rerendering ([#2295](https://github.com/vuejs/core/issues/2295)) ([28d5fd7](https://github.com/vuejs/core/commit/28d5fd7a2871c10df3427dfbbe0e203c2a976cb4)), closes [#2170](https://github.com/vuejs/core/issues/2170) - **runtime-core:** vnode.el is null in watcher after rerendering ([#2295](https://github.com/vuejs/core/issues/2295)) ([28d5fd7](https://github.com/vuejs/core/commit/28d5fd7a2871c10df3427dfbbe0e203c2a976cb4)), closes [#2170](https://github.com/vuejs/core/issues/2170)
@ -450,7 +450,7 @@ may cause build issues in projects still using TS 3.x.
- **compiler-core:** should attach key to single element child of `<template v-for>` ([#1910](https://github.com/vuejs/core/issues/1910)) ([69cfed6](https://github.com/vuejs/core/commit/69cfed6b313821d1ae7ecb02b63b0aaccb5599c6)) - **compiler-core:** should attach key to single element child of `<template v-for>` ([#1910](https://github.com/vuejs/core/issues/1910)) ([69cfed6](https://github.com/vuejs/core/commit/69cfed6b313821d1ae7ecb02b63b0aaccb5599c6))
- **reactivity:** unwrap non-index accessed refs on reactive arrays ([#1859](https://github.com/vuejs/core/issues/1859)) ([3c05f8b](https://github.com/vuejs/core/commit/3c05f8bbd6cd0e01bbc5830730852f9a93d8de8a)), closes [#1846](https://github.com/vuejs/core/issues/1846) - **reactivity:** unwrap non-index accessed refs on reactive arrays ([#1859](https://github.com/vuejs/core/issues/1859)) ([3c05f8b](https://github.com/vuejs/core/commit/3c05f8bbd6cd0e01bbc5830730852f9a93d8de8a)), closes [#1846](https://github.com/vuejs/core/issues/1846)
- **runtime-core:** correctly track dynamic nodes in renderSlot ([#1911](https://github.com/vuejs/core/issues/1911)) ([7ffb79c](https://github.com/vuejs/core/commit/7ffb79c56318861075a47bd2357e34cde8a6dad9)) - **runtime-core:** correctly track dynamic nodes in renderSlot ([#1911](https://github.com/vuejs/core/issues/1911)) ([7ffb79c](https://github.com/vuejs/core/commit/7ffb79c56318861075a47bd2357e34cde8a6dad9))
- **runtime-core:** disable block tracking when calling compiled slot function in tempalte expressions ([f02e2f9](https://github.com/vuejs/core/commit/f02e2f99d9c2ca95f4fd984d7bd62178eceaa214)), closes [#1745](https://github.com/vuejs/core/issues/1745) [#1918](https://github.com/vuejs/core/issues/1918) - **runtime-core:** disable block tracking when calling compiled slot function in template expressions ([f02e2f9](https://github.com/vuejs/core/commit/f02e2f99d9c2ca95f4fd984d7bd62178eceaa214)), closes [#1745](https://github.com/vuejs/core/issues/1745) [#1918](https://github.com/vuejs/core/issues/1918)
- **teleport:** only inherit el for non-patched nodes ([d4cc7b2](https://github.com/vuejs/core/commit/d4cc7b2496f9ed21ef6cac426697eac058da76bb)), closes [#1903](https://github.com/vuejs/core/issues/1903) - **teleport:** only inherit el for non-patched nodes ([d4cc7b2](https://github.com/vuejs/core/commit/d4cc7b2496f9ed21ef6cac426697eac058da76bb)), closes [#1903](https://github.com/vuejs/core/issues/1903)
### Performance Improvements ### Performance Improvements
@ -631,7 +631,7 @@ may cause build issues in projects still using TS 3.x.
- **runtime-dom/v-on:** only block event handlers based on attach timestamp ([8b320cc](https://github.com/vuejs/core/commit/8b320cc12f74aafea9ec69f7ce70231d4f0d08fd)), closes [#1565](https://github.com/vuejs/core/issues/1565) - **runtime-dom/v-on:** only block event handlers based on attach timestamp ([8b320cc](https://github.com/vuejs/core/commit/8b320cc12f74aafea9ec69f7ce70231d4f0d08fd)), closes [#1565](https://github.com/vuejs/core/issues/1565)
- **slots:** differentiate dynamic/static compiled slots ([65beba9](https://github.com/vuejs/core/commit/65beba98fe5793133d3218945218b9e3f8d136eb)), closes [#1557](https://github.com/vuejs/core/issues/1557) - **slots:** differentiate dynamic/static compiled slots ([65beba9](https://github.com/vuejs/core/commit/65beba98fe5793133d3218945218b9e3f8d136eb)), closes [#1557](https://github.com/vuejs/core/issues/1557)
- **v-on:** capitalize dynamic event names ([9152a89](https://github.com/vuejs/core/commit/9152a8901653d7cef864a52a3c618afcc70d827d)) - **v-on:** capitalize dynamic event names ([9152a89](https://github.com/vuejs/core/commit/9152a8901653d7cef864a52a3c618afcc70d827d))
- **v-on:** refactor DOM event options modifer handling ([380c679](https://github.com/vuejs/core/commit/380c6792d8899f1a43a9e6400c5df483c63290b6)), closes [#1567](https://github.com/vuejs/core/issues/1567) - **v-on:** refactor DOM event options modifier handling ([380c679](https://github.com/vuejs/core/commit/380c6792d8899f1a43a9e6400c5df483c63290b6)), closes [#1567](https://github.com/vuejs/core/issues/1567)
### Features ### Features
@ -743,7 +743,7 @@ may cause build issues in projects still using TS 3.x.
- **compiler-core:** fix parsing for directive with dynamic argument containing dots ([0d26413](https://github.com/vuejs/core/commit/0d26413433d41389f5525a0ef2c2dd7cfbb454d4)) - **compiler-core:** fix parsing for directive with dynamic argument containing dots ([0d26413](https://github.com/vuejs/core/commit/0d26413433d41389f5525a0ef2c2dd7cfbb454d4))
- **compiler-core:** support static slot names containing dots for 2.x compat ([825ec15](https://github.com/vuejs/core/commit/825ec1500feda8b0c43245e7e92074af7f9dcca2)), closes [#1241](https://github.com/vuejs/core/issues/1241) - **compiler-core:** support static slot names containing dots for 2.x compat ([825ec15](https://github.com/vuejs/core/commit/825ec1500feda8b0c43245e7e92074af7f9dcca2)), closes [#1241](https://github.com/vuejs/core/issues/1241)
- **hmr:** force full update on nested child components ([#1312](https://github.com/vuejs/core/issues/1312)) ([8f2a748](https://github.com/vuejs/core/commit/8f2a7489b7c74f5cfc1844697c60287c37fc0eb8)) - **hmr:** force full update on nested child components ([#1312](https://github.com/vuejs/core/issues/1312)) ([8f2a748](https://github.com/vuejs/core/commit/8f2a7489b7c74f5cfc1844697c60287c37fc0eb8))
- **reactivity:** fix toRaw for objects prototype inherting reactive ([10bb34b](https://github.com/vuejs/core/commit/10bb34bb869a47c37d945f8c80abf723fac9fc1a)), closes [#1246](https://github.com/vuejs/core/issues/1246) - **reactivity:** fix toRaw for objects prototype inheriting reactive ([10bb34b](https://github.com/vuejs/core/commit/10bb34bb869a47c37d945f8c80abf723fac9fc1a)), closes [#1246](https://github.com/vuejs/core/issues/1246)
- **runtime-core:** should pass instance to patchProp on mount for event error handling ([#1337](https://github.com/vuejs/core/issues/1337)) ([aac9b03](https://github.com/vuejs/core/commit/aac9b03c11c9be0c67b924004364a42d04d78195)), closes [#1336](https://github.com/vuejs/core/issues/1336) - **runtime-core:** should pass instance to patchProp on mount for event error handling ([#1337](https://github.com/vuejs/core/issues/1337)) ([aac9b03](https://github.com/vuejs/core/commit/aac9b03c11c9be0c67b924004364a42d04d78195)), closes [#1336](https://github.com/vuejs/core/issues/1336)
- **runtime-core:** track access to $attrs ([6abac87](https://github.com/vuejs/core/commit/6abac87b3d1b7a22df80b7a70a10101a7f3d3732)), closes [#1346](https://github.com/vuejs/core/issues/1346) - **runtime-core:** track access to $attrs ([6abac87](https://github.com/vuejs/core/commit/6abac87b3d1b7a22df80b7a70a10101a7f3d3732)), closes [#1346](https://github.com/vuejs/core/issues/1346)
- always treat spellcheck and draggable as attributes ([4492b88](https://github.com/vuejs/core/commit/4492b88938922a7f1bcc36a608375ad99f16b22e)), closes [#1350](https://github.com/vuejs/core/issues/1350) - always treat spellcheck and draggable as attributes ([4492b88](https://github.com/vuejs/core/commit/4492b88938922a7f1bcc36a608375ad99f16b22e)), closes [#1350](https://github.com/vuejs/core/issues/1350)
@ -863,7 +863,7 @@ may cause build issues in projects still using TS 3.x.
### Bug Fixes ### Bug Fixes
- **compiler:** bail strigification on runtime constant expressions ([f9a3766](https://github.com/vuejs/core/commit/f9a3766fd68dc6996cdbda6475287c4005f55243)) - **compiler:** bail stringification on runtime constant expressions ([f9a3766](https://github.com/vuejs/core/commit/f9a3766fd68dc6996cdbda6475287c4005f55243))
- **transitionGroup:** fix transition children resolving condition ([f05aeea](https://github.com/vuejs/core/commit/f05aeea7aec2e6cd859f40edc6236afd0ce2ea7d)) - **transitionGroup:** fix transition children resolving condition ([f05aeea](https://github.com/vuejs/core/commit/f05aeea7aec2e6cd859f40edc6236afd0ce2ea7d))
### Features ### Features

View File

@ -28,7 +28,7 @@
- **build:** avoid using async/await syntax ([438754a](https://github.com/vuejs/core/commit/438754a0d1428d10e27d1a290beb4b81da5fdaeb)) - **build:** avoid using async/await syntax ([438754a](https://github.com/vuejs/core/commit/438754a0d1428d10e27d1a290beb4b81da5fdaeb))
- **build:** fix generated code containing unprocessed class field syntax ([2788154](https://github.com/vuejs/core/commit/2788154f7707928f1dd3e4d9bd144f758a8c0478)), closes [#4052](https://github.com/vuejs/core/issues/4052) [vuejs/vue-cli#6562](https://github.com/vuejs/vue-cli/issues/6562) - **build:** fix generated code containing unprocessed class field syntax ([2788154](https://github.com/vuejs/core/commit/2788154f7707928f1dd3e4d9bd144f758a8c0478)), closes [#4052](https://github.com/vuejs/core/issues/4052) [vuejs/vue-cli#6562](https://github.com/vuejs/vue-cli/issues/6562)
- **codegen:** ensure valid types in genreated code when using global directives ([a44d528](https://github.com/vuejs/core/commit/a44d528af1227c05dedf610b6ec45504d8e58276)), closes [#4054](https://github.com/vuejs/core/issues/4054) - **codegen:** ensure valid types in generated code when using global directives ([a44d528](https://github.com/vuejs/core/commit/a44d528af1227c05dedf610b6ec45504d8e58276)), closes [#4054](https://github.com/vuejs/core/issues/4054)
- **compiler-sfc:** fix parse-only mode when there is no script setup block ([253ca27](https://github.com/vuejs/core/commit/253ca2729d808fc051215876aa4af986e4caa43c)) - **compiler-sfc:** fix parse-only mode when there is no script setup block ([253ca27](https://github.com/vuejs/core/commit/253ca2729d808fc051215876aa4af986e4caa43c))
- **runtime-core:** add useAttrs and useSlots export ([#4053](https://github.com/vuejs/core/issues/4053)) ([735ada1](https://github.com/vuejs/core/commit/735ada1507623b8d36e80b30a4f67a8af4a45c99)) - **runtime-core:** add useAttrs and useSlots export ([#4053](https://github.com/vuejs/core/issues/4053)) ([735ada1](https://github.com/vuejs/core/commit/735ada1507623b8d36e80b30a4f67a8af4a45c99))
- **runtime-core:** fix instance accessed via $parent chain when using expose() ([#4048](https://github.com/vuejs/core/issues/4048)) ([12cf9f4](https://github.com/vuejs/core/commit/12cf9f4ea148a59fd9002ecf9ea9d365829ce37c)) - **runtime-core:** fix instance accessed via $parent chain when using expose() ([#4048](https://github.com/vuejs/core/issues/4048)) ([12cf9f4](https://github.com/vuejs/core/commit/12cf9f4ea148a59fd9002ecf9ea9d365829ce37c))
@ -114,7 +114,7 @@
### Performance Improvements ### Performance Improvements
- only trigger `$attrs` update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e)) - only trigger `$attrs` update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e))
- **compiler:** skip unncessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b)) - **compiler:** skip unnecessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b))
- avoid deopt for props/emits normalization when global mixins are used ([51d2be2](https://github.com/vuejs/core/commit/51d2be20386d4dc59006d31a1cc96676871027ce)) - avoid deopt for props/emits normalization when global mixins are used ([51d2be2](https://github.com/vuejs/core/commit/51d2be20386d4dc59006d31a1cc96676871027ce))
### Deprecations ### Deprecations
@ -181,7 +181,7 @@
* **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299)) * **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299))
* **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc)) * **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc))
* **compiler-core:** fix whitespace management for slots with whitespace: 'preserve' ([#3767](https://github.com/vuejs/core/issues/3767)) ([47da921](https://github.com/vuejs/core/commit/47da92146c9fb3fa6b1e250e064ca49b74d815e4)), closes [#3766](https://github.com/vuejs/core/issues/3766) * **compiler-core:** fix whitespace management for slots with whitespace: 'preserve' ([#3767](https://github.com/vuejs/core/issues/3767)) ([47da921](https://github.com/vuejs/core/commit/47da92146c9fb3fa6b1e250e064ca49b74d815e4)), closes [#3766](https://github.com/vuejs/core/issues/3766)
* **compiler-dom:** comments in the v-if branchs should be ignored when used in Transition ([#3622](https://github.com/vuejs/core/issues/3622)) ([7c74feb](https://github.com/vuejs/core/commit/7c74feb3dc6beae7ff3ad22193be3b5a0f4d8aac)), closes [#3619](https://github.com/vuejs/core/issues/3619) * **compiler-dom:** comments in the v-if branches should be ignored when used in Transition ([#3622](https://github.com/vuejs/core/issues/3622)) ([7c74feb](https://github.com/vuejs/core/commit/7c74feb3dc6beae7ff3ad22193be3b5a0f4d8aac)), closes [#3619](https://github.com/vuejs/core/issues/3619)
* **compiler-sfc:** support tsx in setup script ([#3825](https://github.com/vuejs/core/issues/3825)) ([01e8ba8](https://github.com/vuejs/core/commit/01e8ba8f873afe3857a23fb68b44fdc057e31781)), closes [#3808](https://github.com/vuejs/core/issues/3808) * **compiler-sfc:** support tsx in setup script ([#3825](https://github.com/vuejs/core/issues/3825)) ([01e8ba8](https://github.com/vuejs/core/commit/01e8ba8f873afe3857a23fb68b44fdc057e31781)), closes [#3808](https://github.com/vuejs/core/issues/3808)
* **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536) * **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536)
* **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50)) * **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50))
@ -265,7 +265,7 @@
- **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299)) - **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299))
- **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc)) - **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc))
- **compiler-core:** fix whitespace management for slots with whitespace: 'preserve' ([#3767](https://github.com/vuejs/core/issues/3767)) ([47da921](https://github.com/vuejs/core/commit/47da92146c9fb3fa6b1e250e064ca49b74d815e4)), closes [#3766](https://github.com/vuejs/core/issues/3766) - **compiler-core:** fix whitespace management for slots with whitespace: 'preserve' ([#3767](https://github.com/vuejs/core/issues/3767)) ([47da921](https://github.com/vuejs/core/commit/47da92146c9fb3fa6b1e250e064ca49b74d815e4)), closes [#3766](https://github.com/vuejs/core/issues/3766)
- **compiler-dom:** comments in the v-if branchs should be ignored when used in Transition ([#3622](https://github.com/vuejs/core/issues/3622)) ([7c74feb](https://github.com/vuejs/core/commit/7c74feb3dc6beae7ff3ad22193be3b5a0f4d8aac)), closes [#3619](https://github.com/vuejs/core/issues/3619) - **compiler-dom:** comments in the v-if branches should be ignored when used in Transition ([#3622](https://github.com/vuejs/core/issues/3622)) ([7c74feb](https://github.com/vuejs/core/commit/7c74feb3dc6beae7ff3ad22193be3b5a0f4d8aac)), closes [#3619](https://github.com/vuejs/core/issues/3619)
- **compiler-sfc:** support tsx in setup script ([#3825](https://github.com/vuejs/core/issues/3825)) ([01e8ba8](https://github.com/vuejs/core/commit/01e8ba8f873afe3857a23fb68b44fdc057e31781)), closes [#3808](https://github.com/vuejs/core/issues/3808) - **compiler-sfc:** support tsx in setup script ([#3825](https://github.com/vuejs/core/issues/3825)) ([01e8ba8](https://github.com/vuejs/core/commit/01e8ba8f873afe3857a23fb68b44fdc057e31781)), closes [#3808](https://github.com/vuejs/core/issues/3808)
- **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536) - **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536)
- **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50)) - **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50))
@ -317,4 +317,4 @@
### Performance Improvements ### Performance Improvements
- only trigger $attrs update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e)) - only trigger $attrs update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e))
- **compiler:** skip unncessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b)) - **compiler:** skip unnecessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b))

View File

@ -26,7 +26,7 @@
* **reactivity-transform:** fix $$ escape edge cases ([e06d3b6](https://github.com/vuejs/core/commit/e06d3b614ea518e9cdf83fca9200fc816eb4e5a1)), closes [#6312](https://github.com/vuejs/core/issues/6312) [#6944](https://github.com/vuejs/core/issues/6944) * **reactivity-transform:** fix $$ escape edge cases ([e06d3b6](https://github.com/vuejs/core/commit/e06d3b614ea518e9cdf83fca9200fc816eb4e5a1)), closes [#6312](https://github.com/vuejs/core/issues/6312) [#6944](https://github.com/vuejs/core/issues/6944)
* **reactivity-transform:** prohibit const assignment at compile time ([#6993](https://github.com/vuejs/core/issues/6993)) ([3427052](https://github.com/vuejs/core/commit/3427052229db3448252d938292a40e960a0f4b9c)), closes [#6992](https://github.com/vuejs/core/issues/6992) * **reactivity-transform:** prohibit const assignment at compile time ([#6993](https://github.com/vuejs/core/issues/6993)) ([3427052](https://github.com/vuejs/core/commit/3427052229db3448252d938292a40e960a0f4b9c)), closes [#6992](https://github.com/vuejs/core/issues/6992)
* **reactivity:** `triggerRef` working with `toRef` from reactive ([#7507](https://github.com/vuejs/core/issues/7507)) ([e64c9ae](https://github.com/vuejs/core/commit/e64c9ae957aa2606b55e8652bbde30a6ada59fb0)) * **reactivity:** `triggerRef` working with `toRef` from reactive ([#7507](https://github.com/vuejs/core/issues/7507)) ([e64c9ae](https://github.com/vuejs/core/commit/e64c9ae957aa2606b55e8652bbde30a6ada59fb0))
* **reactivity:** ensure watch(Effect) can run independent of unmounted instance if created in a detatched effectScope (fix [#7319](https://github.com/vuejs/core/issues/7319)) ([#7330](https://github.com/vuejs/core/issues/7330)) ([cd7c887](https://github.com/vuejs/core/commit/cd7c887b755810aedf83f3d458cb956d5b147f6f)) * **reactivity:** ensure watch(Effect) can run independent of unmounted instance if created in a detached effectScope (fix [#7319](https://github.com/vuejs/core/issues/7319)) ([#7330](https://github.com/vuejs/core/issues/7330)) ([cd7c887](https://github.com/vuejs/core/commit/cd7c887b755810aedf83f3d458cb956d5b147f6f))
* **reactivity:** track hasOwnProperty ([588bd44](https://github.com/vuejs/core/commit/588bd44f036b79d7dee5d23661aa7244f70e6beb)), closes [#2619](https://github.com/vuejs/core/issues/2619) [#2621](https://github.com/vuejs/core/issues/2621) * **reactivity:** track hasOwnProperty ([588bd44](https://github.com/vuejs/core/commit/588bd44f036b79d7dee5d23661aa7244f70e6beb)), closes [#2619](https://github.com/vuejs/core/issues/2619) [#2621](https://github.com/vuejs/core/issues/2621)
* **runtime-core:** ensure prop type validation warning shows custom class names ([#7198](https://github.com/vuejs/core/issues/7198)) ([620327d](https://github.com/vuejs/core/commit/620327d527593c6263a21500baddbae1ebc30db8)) * **runtime-core:** ensure prop type validation warning shows custom class names ([#7198](https://github.com/vuejs/core/issues/7198)) ([620327d](https://github.com/vuejs/core/commit/620327d527593c6263a21500baddbae1ebc30db8))
* **runtime-core:** fix keep-alive cache prune logic on vnodes with same type but different keys ([#7510](https://github.com/vuejs/core/issues/7510)) ([1fde49c](https://github.com/vuejs/core/commit/1fde49c0f57cc50fedf91366a274c9759d1d9a39)), closes [#7355](https://github.com/vuejs/core/issues/7355) * **runtime-core:** fix keep-alive cache prune logic on vnodes with same type but different keys ([#7510](https://github.com/vuejs/core/issues/7510)) ([1fde49c](https://github.com/vuejs/core/commit/1fde49c0f57cc50fedf91366a274c9759d1d9a39)), closes [#7355](https://github.com/vuejs/core/issues/7355)
@ -126,7 +126,7 @@
* **transition/keep-alive:** fix unmount bug for component with out-in transition ([#6839](https://github.com/vuejs/core/issues/6839)) ([64e6d92](https://github.com/vuejs/core/commit/64e6d9221d353598b5f61c158c978d80e3b4628c)), closes [#6835](https://github.com/vuejs/core/issues/6835) * **transition/keep-alive:** fix unmount bug for component with out-in transition ([#6839](https://github.com/vuejs/core/issues/6839)) ([64e6d92](https://github.com/vuejs/core/commit/64e6d9221d353598b5f61c158c978d80e3b4628c)), closes [#6835](https://github.com/vuejs/core/issues/6835)
* **types/reactivity-transform:** fix type when initial value is not used ([#6821](https://github.com/vuejs/core/issues/6821)) ([fdc5902](https://github.com/vuejs/core/commit/fdc5902cce0d077c722dfd422850ca69fd51be8e)), closes [#6820](https://github.com/vuejs/core/issues/6820) * **types/reactivity-transform:** fix type when initial value is not used ([#6821](https://github.com/vuejs/core/issues/6821)) ([fdc5902](https://github.com/vuejs/core/commit/fdc5902cce0d077c722dfd422850ca69fd51be8e)), closes [#6820](https://github.com/vuejs/core/issues/6820)
* **types:** `$watch` callback parameters type ([#6136](https://github.com/vuejs/core/issues/6136)) ([41d9c47](https://github.com/vuejs/core/commit/41d9c47300888fce9d4ff6a02f69d8a912cded8f)), closes [#6135](https://github.com/vuejs/core/issues/6135) * **types:** `$watch` callback parameters type ([#6136](https://github.com/vuejs/core/issues/6136)) ([41d9c47](https://github.com/vuejs/core/commit/41d9c47300888fce9d4ff6a02f69d8a912cded8f)), closes [#6135](https://github.com/vuejs/core/issues/6135)
* **types:** ensure createBlock() helper accepts Teleport and Supsense types (fix: [#2855](https://github.com/vuejs/core/issues/2855)) ([#5458](https://github.com/vuejs/core/issues/5458)) ([e5fc7dc](https://github.com/vuejs/core/commit/e5fc7dcc02f2dd3fa8172958259049031626375f)) * **types:** ensure createBlock() helper accepts Teleport and Suspense types (fix: [#2855](https://github.com/vuejs/core/issues/2855)) ([#5458](https://github.com/vuejs/core/issues/5458)) ([e5fc7dc](https://github.com/vuejs/core/commit/e5fc7dcc02f2dd3fa8172958259049031626375f))
* **types:** export `Raw` type ([#6380](https://github.com/vuejs/core/issues/6380)) ([e9172db](https://github.com/vuejs/core/commit/e9172db68b86fad2e0bb1de9e5d0dddbe3c2a25e)), closes [#7048](https://github.com/vuejs/core/issues/7048) * **types:** export `Raw` type ([#6380](https://github.com/vuejs/core/issues/6380)) ([e9172db](https://github.com/vuejs/core/commit/e9172db68b86fad2e0bb1de9e5d0dddbe3c2a25e)), closes [#7048](https://github.com/vuejs/core/issues/7048)
* **types:** should unwrap tuple correctly ([#3820](https://github.com/vuejs/core/issues/3820)) ([e816812](https://github.com/vuejs/core/commit/e816812f10b9e3a375eef8dffd617d7f08b23c00)), closes [#3819](https://github.com/vuejs/core/issues/3819) * **types:** should unwrap tuple correctly ([#3820](https://github.com/vuejs/core/issues/3820)) ([e816812](https://github.com/vuejs/core/commit/e816812f10b9e3a375eef8dffd617d7f08b23c00)), closes [#3819](https://github.com/vuejs/core/issues/3819)
* **types:** stricter type condition for `EventHandlers` ([#6855](https://github.com/vuejs/core/issues/6855)) ([bad3f3c](https://github.com/vuejs/core/commit/bad3f3ce46aad1f5fec47d1d02aee26af393bcff)), closes [#6899](https://github.com/vuejs/core/issues/6899) * **types:** stricter type condition for `EventHandlers` ([#6855](https://github.com/vuejs/core/issues/6855)) ([bad3f3c](https://github.com/vuejs/core/commit/bad3f3ce46aad1f5fec47d1d02aee26af393bcff)), closes [#6899](https://github.com/vuejs/core/issues/6899)
@ -714,7 +714,7 @@
* **compiler-core:** avoid runtime dependency on @babel/types ([1045590](https://github.com/vuejs/core/commit/1045590d4bbaf4a2b05311f11b22a0b3d22cf609)), closes [#4531](https://github.com/vuejs/core/issues/4531) * **compiler-core:** avoid runtime dependency on @babel/types ([1045590](https://github.com/vuejs/core/commit/1045590d4bbaf4a2b05311f11b22a0b3d22cf609)), closes [#4531](https://github.com/vuejs/core/issues/4531)
* **compiler-core:** pick last char when dynamic directive doesn't close ([#4507](https://github.com/vuejs/core/issues/4507)) ([5d262e0](https://github.com/vuejs/core/commit/5d262e08d5d5fb29f48ba5fa5b97a9a3e34b9d4b)) * **compiler-core:** pick last char when dynamic directive doesn't close ([#4507](https://github.com/vuejs/core/issues/4507)) ([5d262e0](https://github.com/vuejs/core/commit/5d262e08d5d5fb29f48ba5fa5b97a9a3e34b9d4b))
* **compiler:** condense whitespaces in static class attributes ([#4432](https://github.com/vuejs/core/issues/4432)) ([b8653d3](https://github.com/vuejs/core/commit/b8653d390a555e1ee3f92a1c49cfd8800c67e46a)), closes [#4251](https://github.com/vuejs/core/issues/4251) * **compiler:** condense whitespaces in static class attributes ([#4432](https://github.com/vuejs/core/issues/4432)) ([b8653d3](https://github.com/vuejs/core/commit/b8653d390a555e1ee3f92a1c49cfd8800c67e46a)), closes [#4251](https://github.com/vuejs/core/issues/4251)
* **runtime-dom:** style patching shoud always preserve v-show display property ([d534515](https://github.com/vuejs/core/commit/d53451583684c37bda7d30bff912216e1a58126f)), closes [#4424](https://github.com/vuejs/core/issues/4424) * **runtime-dom:** style patching should always preserve v-show display property ([d534515](https://github.com/vuejs/core/commit/d53451583684c37bda7d30bff912216e1a58126f)), closes [#4424](https://github.com/vuejs/core/issues/4424)
* **type:** fix prop type infer ([#4530](https://github.com/vuejs/core/issues/4530)) ([4178d5d](https://github.com/vuejs/core/commit/4178d5d7d9549a0a1d19663bc2f92c8ac6a731b2)), closes [#4525](https://github.com/vuejs/core/issues/4525) * **type:** fix prop type infer ([#4530](https://github.com/vuejs/core/issues/4530)) ([4178d5d](https://github.com/vuejs/core/commit/4178d5d7d9549a0a1d19663bc2f92c8ac6a731b2)), closes [#4525](https://github.com/vuejs/core/issues/4525)
@ -741,7 +741,7 @@
* **compiler-sfc:** ensure script setup generates type-valid ts output ([bacb201](https://github.com/vuejs/core/commit/bacb2012acb4045a2db6988ba4545a7655d6ca14)), closes [#4455](https://github.com/vuejs/core/issues/4455) * **compiler-sfc:** ensure script setup generates type-valid ts output ([bacb201](https://github.com/vuejs/core/commit/bacb2012acb4045a2db6988ba4545a7655d6ca14)), closes [#4455](https://github.com/vuejs/core/issues/4455)
* **compiler-sfc:** generate matching prop types when withDefaults is used ([#4466](https://github.com/vuejs/core/issues/4466)) ([8580796](https://github.com/vuejs/core/commit/85807967dc874e6ea6b20f341875beda938e3058)), closes [#4455](https://github.com/vuejs/core/issues/4455) * **compiler-sfc:** generate matching prop types when withDefaults is used ([#4466](https://github.com/vuejs/core/issues/4466)) ([8580796](https://github.com/vuejs/core/commit/85807967dc874e6ea6b20f341875beda938e3058)), closes [#4455](https://github.com/vuejs/core/issues/4455)
* **compiler:** generate function ref for script setup if inline is ture. ([#4492](https://github.com/vuejs/core/issues/4492)) ([4cd282b](https://github.com/vuejs/core/commit/4cd282b0a17589ef9ca2649e7beb0bdee4a73c57)) * **compiler:** generate function ref for script setup if inline is true. ([#4492](https://github.com/vuejs/core/issues/4492)) ([4cd282b](https://github.com/vuejs/core/commit/4cd282b0a17589ef9ca2649e7beb0bdee4a73c57))
* **compiler:** report invalid directive name error ([#4494](https://github.com/vuejs/core/issues/4494)) ([#4495](https://github.com/vuejs/core/issues/4495)) ([c00925e](https://github.com/vuejs/core/commit/c00925ed5c409b57a1540b79c595b7f8117e2d4c)) * **compiler:** report invalid directive name error ([#4494](https://github.com/vuejs/core/issues/4494)) ([#4495](https://github.com/vuejs/core/issues/4495)) ([c00925e](https://github.com/vuejs/core/commit/c00925ed5c409b57a1540b79c595b7f8117e2d4c))
* **types:** include ref-macros.d.ts in npm dist files ([d7f1b77](https://github.com/vuejs/core/commit/d7f1b771f80ab9014a4701913b50458fd251a117)), closes [#4433](https://github.com/vuejs/core/issues/4433) * **types:** include ref-macros.d.ts in npm dist files ([d7f1b77](https://github.com/vuejs/core/commit/d7f1b771f80ab9014a4701913b50458fd251a117)), closes [#4433](https://github.com/vuejs/core/issues/4433)
@ -798,7 +798,7 @@
### Bug Fixes ### Bug Fixes
* **compiler-sfc:** fix import usage check for lowercase imported components ([57f1081](https://github.com/vuejs/core/commit/57f10812cc7f1e9f6c92736c36aba577943996fd)), closes [#4358](https://github.com/vuejs/core/issues/4358) * **compiler-sfc:** fix import usage check for lowercase imported components ([57f1081](https://github.com/vuejs/core/commit/57f10812cc7f1e9f6c92736c36aba577943996fd)), closes [#4358](https://github.com/vuejs/core/issues/4358)
* **runtime-core:** ensure consistent arguments for tempalte and render funtion slot usage ([644971e](https://github.com/vuejs/core/commit/644971ec06642817cf7e720ad4980182d2140f53)), closes [#4367](https://github.com/vuejs/core/issues/4367) * **runtime-core:** ensure consistent arguments for template and render function slot usage ([644971e](https://github.com/vuejs/core/commit/644971ec06642817cf7e720ad4980182d2140f53)), closes [#4367](https://github.com/vuejs/core/issues/4367)
* **runtime-core:** fix child component double update on props change ([c1f564e](https://github.com/vuejs/core/commit/c1f564e1dc40eda9af657c30cd787a8d770dde0f)), closes [#4365](https://github.com/vuejs/core/issues/4365) * **runtime-core:** fix child component double update on props change ([c1f564e](https://github.com/vuejs/core/commit/c1f564e1dc40eda9af657c30cd787a8d770dde0f)), closes [#4365](https://github.com/vuejs/core/issues/4365)

View File

@ -259,7 +259,7 @@
* **sfc:** support imported types in SFC macros ([#8083](https://github.com/vuejs/core/pull/8083)) * **sfc:** support imported types in SFC macros ([#8083](https://github.com/vuejs/core/pull/8083))
* **types/slots:** support slot presence / props type checks via `defineSlots` macro and `slots` option ([#7982](https://github.com/vuejs/core/issues/7982)) ([5a2f5d5](https://github.com/vuejs/core/commit/5a2f5d59cffa36a99e6f2feab6b3ba7958b7362f)) * **types/slots:** support slot presence / props type checks via `defineSlots` macro and `slots` option ([#7982](https://github.com/vuejs/core/issues/7982)) ([5a2f5d5](https://github.com/vuejs/core/commit/5a2f5d59cffa36a99e6f2feab6b3ba7958b7362f))
* **sfc:** support more ergnomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94)) * **sfc:** support more ergonomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94))
* **sfc:** introduce `defineModel` macro and `useModel` helper ([#8018](https://github.com/vuejs/core/issues/8018)) ([14f3d74](https://github.com/vuejs/core/commit/14f3d747a34d45415b0036b274517d70a27ec0d3)) * **sfc:** introduce `defineModel` macro and `useModel` helper ([#8018](https://github.com/vuejs/core/issues/8018)) ([14f3d74](https://github.com/vuejs/core/commit/14f3d747a34d45415b0036b274517d70a27ec0d3))
* **reactivity:** improve support of getter usage in reactivity APIs ([#7997](https://github.com/vuejs/core/issues/7997)) ([59e8284](https://github.com/vuejs/core/commit/59e828448e7f37643cd0eaea924a764e9d314448)) * **reactivity:** improve support of getter usage in reactivity APIs ([#7997](https://github.com/vuejs/core/issues/7997)) ([59e8284](https://github.com/vuejs/core/commit/59e828448e7f37643cd0eaea924a764e9d314448))
* **compiler-sfc:** add defineOptions macro ([#5738](https://github.com/vuejs/core/issues/5738)) ([bcf5841](https://github.com/vuejs/core/commit/bcf5841ddecc64d0bdbd56ce1463eb8ebf01bb9d)) * **compiler-sfc:** add defineOptions macro ([#5738](https://github.com/vuejs/core/issues/5738)) ([bcf5841](https://github.com/vuejs/core/commit/bcf5841ddecc64d0bdbd56ce1463eb8ebf01bb9d))
@ -483,7 +483,7 @@
* **compiler-sfc:** support arbitrary expression as withDefaults argument ([fe61944](https://github.com/vuejs/core/commit/fe619443d2e99301975de120685dbae8d66c03a6)), closes [#6459](https://github.com/vuejs/core/issues/6459) * **compiler-sfc:** support arbitrary expression as withDefaults argument ([fe61944](https://github.com/vuejs/core/commit/fe619443d2e99301975de120685dbae8d66c03a6)), closes [#6459](https://github.com/vuejs/core/issues/6459)
* **reactivity:** improve support of getter usage in reactivity APIs ([#7997](https://github.com/vuejs/core/issues/7997)) ([59e8284](https://github.com/vuejs/core/commit/59e828448e7f37643cd0eaea924a764e9d314448)) * **reactivity:** improve support of getter usage in reactivity APIs ([#7997](https://github.com/vuejs/core/issues/7997)) ([59e8284](https://github.com/vuejs/core/commit/59e828448e7f37643cd0eaea924a764e9d314448))
* **sfc:** revert withDefaults() deprecation ([4af5d1b](https://github.com/vuejs/core/commit/4af5d1b0754035058436f9e4e5c12aedef199177)) * **sfc:** revert withDefaults() deprecation ([4af5d1b](https://github.com/vuejs/core/commit/4af5d1b0754035058436f9e4e5c12aedef199177))
* **sfc:** support more ergnomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94)) * **sfc:** support more ergonomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94))
* **types/slots:** support slot presence / props type checks via `defineSlots` macro and `slots` option ([#7982](https://github.com/vuejs/core/issues/7982)) ([5a2f5d5](https://github.com/vuejs/core/commit/5a2f5d59cffa36a99e6f2feab6b3ba7958b7362f)) * **types/slots:** support slot presence / props type checks via `defineSlots` macro and `slots` option ([#7982](https://github.com/vuejs/core/issues/7982)) ([5a2f5d5](https://github.com/vuejs/core/commit/5a2f5d59cffa36a99e6f2feab6b3ba7958b7362f))
@ -544,7 +544,7 @@
### Bug Fixes ### Bug Fixes
* **runtime-core:** support `getCurrentInstance` across mutiple builds of Vue ([8d2d5bf](https://github.com/vuejs/core/commit/8d2d5bf48a24dab44e5b03cb8fa0c5faa4b696e3)) * **runtime-core:** support `getCurrentInstance` across multiple builds of Vue ([8d2d5bf](https://github.com/vuejs/core/commit/8d2d5bf48a24dab44e5b03cb8fa0c5faa4b696e3))
* **types:** ensure defineProps with generics return correct types ([c288c7b](https://github.com/vuejs/core/commit/c288c7b0bd6077d690f42153c3fc49a45454a66a)) * **types:** ensure defineProps with generics return correct types ([c288c7b](https://github.com/vuejs/core/commit/c288c7b0bd6077d690f42153c3fc49a45454a66a))

View File

@ -167,7 +167,7 @@
### Bug Fixes ### Bug Fixes
* **compat:** correctly transform non-identifier expressions in legacy filter syntax ([#10896](https://github.com/vuejs/core/issues/10896)) ([07b3c4b](https://github.com/vuejs/core/commit/07b3c4b7860009e19446f3d78571556c5737d82a)), closes [#10852](https://github.com/vuejs/core/issues/10852) * **compat:** correctly transform non-identifier expressions in legacy filter syntax ([#10896](https://github.com/vuejs/core/issues/10896)) ([07b3c4b](https://github.com/vuejs/core/commit/07b3c4b7860009e19446f3d78571556c5737d82a)), closes [#10852](https://github.com/vuejs/core/issues/10852)
* **compat:** ensure proper handling of render fuction from SFC using Vue.extend ([#7781](https://github.com/vuejs/core/issues/7781)) ([c73847f](https://github.com/vuejs/core/commit/c73847f2becc20f03cb9c68748eea92455e688ee)), closes [#7766](https://github.com/vuejs/core/issues/7766) * **compat:** ensure proper handling of render function from SFC using Vue.extend ([#7781](https://github.com/vuejs/core/issues/7781)) ([c73847f](https://github.com/vuejs/core/commit/c73847f2becc20f03cb9c68748eea92455e688ee)), closes [#7766](https://github.com/vuejs/core/issues/7766)
* **compat:** only warn ATTR_FALSE_VALUE when enabled ([04729ba](https://github.com/vuejs/core/commit/04729ba2163d840f0ca7866bc964696eb5557804)), closes [#11126](https://github.com/vuejs/core/issues/11126) * **compat:** only warn ATTR_FALSE_VALUE when enabled ([04729ba](https://github.com/vuejs/core/commit/04729ba2163d840f0ca7866bc964696eb5557804)), closes [#11126](https://github.com/vuejs/core/issues/11126)
* **compile-sfc:** register props destructure rest id as setup bindings ([#10888](https://github.com/vuejs/core/issues/10888)) ([b2b5f57](https://github.com/vuejs/core/commit/b2b5f57c2c945edd0eebc1b545ec1b7568e51484)), closes [#10885](https://github.com/vuejs/core/issues/10885) * **compile-sfc:** register props destructure rest id as setup bindings ([#10888](https://github.com/vuejs/core/issues/10888)) ([b2b5f57](https://github.com/vuejs/core/commit/b2b5f57c2c945edd0eebc1b545ec1b7568e51484)), closes [#10885](https://github.com/vuejs/core/issues/10885)
* **compile-sfc:** Support project reference with folder, ([#10908](https://github.com/vuejs/core/issues/10908)) ([bdeac37](https://github.com/vuejs/core/commit/bdeac377c7b85888193b49ac187e927636cc40bc)), closes [#10907](https://github.com/vuejs/core/issues/10907) * **compile-sfc:** Support project reference with folder, ([#10908](https://github.com/vuejs/core/issues/10908)) ([bdeac37](https://github.com/vuejs/core/commit/bdeac377c7b85888193b49ac187e927636cc40bc)), closes [#10907](https://github.com/vuejs/core/issues/10907)
@ -218,7 +218,7 @@
### Bug Fixes ### Bug Fixes
* **compat:** include legacy scoped slots ([#10868](https://github.com/vuejs/core/issues/10868)) ([8366126](https://github.com/vuejs/core/commit/83661264a4ced3cb2ff6800904a86dd9e82bbfe2)), closes [#8869](https://github.com/vuejs/core/issues/8869) * **compat:** include legacy scoped slots ([#10868](https://github.com/vuejs/core/issues/10868)) ([8366126](https://github.com/vuejs/core/commit/83661264a4ced3cb2ff6800904a86dd9e82bbfe2)), closes [#8869](https://github.com/vuejs/core/issues/8869)
* **compiler-core:** add support for arrow aysnc function with unbracketed ([#5789](https://github.com/vuejs/core/issues/5789)) ([ca7d421](https://github.com/vuejs/core/commit/ca7d421e8775f6813f8943d32ab485e0c542f98b)), closes [#5788](https://github.com/vuejs/core/issues/5788) * **compiler-core:** add support for arrow async function with unbracketed ([#5789](https://github.com/vuejs/core/issues/5789)) ([ca7d421](https://github.com/vuejs/core/commit/ca7d421e8775f6813f8943d32ab485e0c542f98b)), closes [#5788](https://github.com/vuejs/core/issues/5788)
* **compiler-dom:** restrict createStaticVNode usage with option elements ([#10846](https://github.com/vuejs/core/issues/10846)) ([0e3d617](https://github.com/vuejs/core/commit/0e3d6178b02d0386d779720ae2cc4eac1d1ec990)), closes [#6568](https://github.com/vuejs/core/issues/6568) [#7434](https://github.com/vuejs/core/issues/7434) * **compiler-dom:** restrict createStaticVNode usage with option elements ([#10846](https://github.com/vuejs/core/issues/10846)) ([0e3d617](https://github.com/vuejs/core/commit/0e3d6178b02d0386d779720ae2cc4eac1d1ec990)), closes [#6568](https://github.com/vuejs/core/issues/6568) [#7434](https://github.com/vuejs/core/issues/7434)
* **compiler-sfc:** handle keyof operator ([#10874](https://github.com/vuejs/core/issues/10874)) ([10d34a5](https://github.com/vuejs/core/commit/10d34a5624775f20437ccad074a97270ef74c3fb)), closes [#10871](https://github.com/vuejs/core/issues/10871) * **compiler-sfc:** handle keyof operator ([#10874](https://github.com/vuejs/core/issues/10874)) ([10d34a5](https://github.com/vuejs/core/commit/10d34a5624775f20437ccad074a97270ef74c3fb)), closes [#10871](https://github.com/vuejs/core/issues/10871)
* **hydration:** handle edge case of style mismatch without style attribute ([f2c1412](https://github.com/vuejs/core/commit/f2c1412e46a8fad3e13403bfa78335c4f704f21c)), closes [#10786](https://github.com/vuejs/core/issues/10786) * **hydration:** handle edge case of style mismatch without style attribute ([f2c1412](https://github.com/vuejs/core/commit/f2c1412e46a8fad3e13403bfa78335c4f704f21c)), closes [#10786](https://github.com/vuejs/core/issues/10786)
@ -417,7 +417,7 @@
* **compiler-sfc:** fix type resolution for symlinked node_modules structure w/ pnpm ([75e866b](https://github.com/vuejs/core/commit/75e866bd4ef368b4e037a4933dbaf188920dc683)), closes [#10121](https://github.com/vuejs/core/issues/10121) * **compiler-sfc:** fix type resolution for symlinked node_modules structure w/ pnpm ([75e866b](https://github.com/vuejs/core/commit/75e866bd4ef368b4e037a4933dbaf188920dc683)), closes [#10121](https://github.com/vuejs/core/issues/10121)
* correct url for production error reference links ([c3087ff](https://github.com/vuejs/core/commit/c3087ff2cce7d96c60a870f8233441311ab4dfb4)) * correct url for production error reference links ([c3087ff](https://github.com/vuejs/core/commit/c3087ff2cce7d96c60a870f8233441311ab4dfb4))
* **hydration:** fix incorect mismatch warning for option with non-string value and inner text ([d16a213](https://github.com/vuejs/core/commit/d16a2138a33b106b9e1499bbb9e1c67790370c97)) * **hydration:** fix incorrect mismatch warning for option with non-string value and inner text ([d16a213](https://github.com/vuejs/core/commit/d16a2138a33b106b9e1499bbb9e1c67790370c97))
* **reactivity:** re-fix [#10114](https://github.com/vuejs/core/issues/10114) ([#10123](https://github.com/vuejs/core/issues/10123)) ([c2b274a](https://github.com/vuejs/core/commit/c2b274a887f61deb7e0185d1bef3b77d31e991cc)) * **reactivity:** re-fix [#10114](https://github.com/vuejs/core/issues/10114) ([#10123](https://github.com/vuejs/core/issues/10123)) ([c2b274a](https://github.com/vuejs/core/commit/c2b274a887f61deb7e0185d1bef3b77d31e991cc))
* **runtime-core:** should not warn out-of-render slot fn usage when mounting another app in setup ([#10125](https://github.com/vuejs/core/issues/10125)) ([6fa33e6](https://github.com/vuejs/core/commit/6fa33e67ec42af140a86fbdb86939032c3a1f345)), closes [#10124](https://github.com/vuejs/core/issues/10124) * **runtime-core:** should not warn out-of-render slot fn usage when mounting another app in setup ([#10125](https://github.com/vuejs/core/issues/10125)) ([6fa33e6](https://github.com/vuejs/core/commit/6fa33e67ec42af140a86fbdb86939032c3a1f345)), closes [#10124](https://github.com/vuejs/core/issues/10124)
@ -741,17 +741,6 @@ Note that this is a type-only breaking change in a minor release, which adheres
## [3.3.13](https://github.com/vuejs/core/compare/v3.3.12...v3.3.13) (2023-12-19)
### Bug Fixes
* **compiler-core:** fix v-on with modifiers on inline expression of undefined ([#9866](https://github.com/vuejs/core/issues/9866)) ([bae79dd](https://github.com/vuejs/core/commit/bae79ddf8564a2da4a5365cfeb8d811990f42335)), closes [#9865](https://github.com/vuejs/core/issues/9865)
* **runtime-dom:** cache event handlers by key/modifiers ([#9851](https://github.com/vuejs/core/issues/9851)) ([04d2c05](https://github.com/vuejs/core/commit/04d2c05054c26b02fbc1d84839b0ed5cd36455b6)), closes [#9849](https://github.com/vuejs/core/issues/9849)
* **types:** extract properties from extended collections ([#9854](https://github.com/vuejs/core/issues/9854)) ([24b1c1d](https://github.com/vuejs/core/commit/24b1c1dd57fd55d998aa231a147500e010b10219)), closes [#9852](https://github.com/vuejs/core/issues/9852)
# [3.4.0-beta.3](https://github.com/vuejs/core/compare/v3.3.12...v3.4.0-beta.3) (2023-12-16) # [3.4.0-beta.3](https://github.com/vuejs/core/compare/v3.3.12...v3.4.0-beta.3) (2023-12-16)
@ -764,19 +753,6 @@ Note that this is a type-only breaking change in a minor release, which adheres
## [3.3.12](https://github.com/vuejs/core/compare/v3.3.11...v3.3.12) (2023-12-16)
### Bug Fixes
* **hydration:** handle appear transition before patch props ([#9837](https://github.com/vuejs/core/issues/9837)) ([e70f4c4](https://github.com/vuejs/core/commit/e70f4c47c553b6e16d8fad70743271ca23802fe7)), closes [#9832](https://github.com/vuejs/core/issues/9832)
* **sfc/cssVars:** fix loss of CSS v-bind variables when setting inline style with string value ([#9824](https://github.com/vuejs/core/issues/9824)) ([0a387df](https://github.com/vuejs/core/commit/0a387dfb1d04afb6eae4296b6da76dfdaca77af4)), closes [#9821](https://github.com/vuejs/core/issues/9821)
* **ssr:** fix suspense hydration of fallback content ([#7188](https://github.com/vuejs/core/issues/7188)) ([60415b5](https://github.com/vuejs/core/commit/60415b5d67df55f1fd6b176615299c08640fa142))
* **types:** add `xmlns:xlink` to `SVGAttributes` ([#9300](https://github.com/vuejs/core/issues/9300)) ([0d61b42](https://github.com/vuejs/core/commit/0d61b429ecf63591d31e09702058fa4c7132e1a7)), closes [#9299](https://github.com/vuejs/core/issues/9299)
* **types:** fix `shallowRef` type error ([#9839](https://github.com/vuejs/core/issues/9839)) ([9a57158](https://github.com/vuejs/core/commit/9a571582b53220270e498d8712ea59312c0bef3a))
* **types:** support for generic keyof slots ([#8374](https://github.com/vuejs/core/issues/8374)) ([213eba4](https://github.com/vuejs/core/commit/213eba479ce080efc1053fe636f6be4a4c889b44))
# [3.4.0-beta.2](https://github.com/vuejs/core/compare/v3.4.0-beta.1...v3.4.0-beta.2) (2023-12-14) # [3.4.0-beta.2](https://github.com/vuejs/core/compare/v3.4.0-beta.1...v3.4.0-beta.2) (2023-12-14)
@ -836,22 +812,6 @@ default.
## [3.3.11](https://github.com/vuejs/core/compare/v3.3.10...v3.3.11) (2023-12-08)
### Bug Fixes
* **custom-element:** correctly handle number type props in prod ([#8989](https://github.com/vuejs/core/issues/8989)) ([d74d364](https://github.com/vuejs/core/commit/d74d364d62db8e48881af6b5a75ce4fb5f36cc35))
* **reactivity:** fix mutation on user proxy of reactive Array ([6ecbd5c](https://github.com/vuejs/core/commit/6ecbd5ce2a7f59314a8326a1d193874b87f4d8c8)), closes [#9742](https://github.com/vuejs/core/issues/9742) [#9751](https://github.com/vuejs/core/issues/9751) [#9750](https://github.com/vuejs/core/issues/9750)
* **runtime-dom:** fix width and height prop check condition ([5b00286](https://github.com/vuejs/core/commit/5b002869c533220706f9788b496b8ca8d8e98609)), closes [#9762](https://github.com/vuejs/core/issues/9762)
* **shared:** handle Map with symbol keys in toDisplayString ([#9731](https://github.com/vuejs/core/issues/9731)) ([364821d](https://github.com/vuejs/core/commit/364821d6bdb1775e2f55a69bcfb9f40f7acf1506)), closes [#9727](https://github.com/vuejs/core/issues/9727)
* **shared:** handle more Symbol cases in toDisplayString ([983d45d](https://github.com/vuejs/core/commit/983d45d4f8eb766b5a16b7ea93b86d3c51618fa6))
* **Suspense:** properly get anchor when mount fallback vnode ([#9770](https://github.com/vuejs/core/issues/9770)) ([b700328](https://github.com/vuejs/core/commit/b700328342e17dc16b19316c2e134a26107139d2)), closes [#9769](https://github.com/vuejs/core/issues/9769)
* **types:** ref() return type should not be any when initial value is any ([#9768](https://github.com/vuejs/core/issues/9768)) ([cdac121](https://github.com/vuejs/core/commit/cdac12161ec27b45ded48854c3d749664b6d4a6d))
* **watch:** should not fire pre watcher on child component unmount ([#7181](https://github.com/vuejs/core/issues/7181)) ([6784f0b](https://github.com/vuejs/core/commit/6784f0b1f8501746ea70d87d18ed63a62cf6b76d)), closes [#7030](https://github.com/vuejs/core/issues/7030)
# [3.4.0-alpha.4](https://github.com/vuejs/core/compare/v3.3.10...v3.4.0-alpha.4) (2023-12-04) # [3.4.0-alpha.4](https://github.com/vuejs/core/compare/v3.3.10...v3.4.0-alpha.4) (2023-12-04)
@ -873,37 +833,6 @@ default.
## [3.3.10](https://github.com/vuejs/core/compare/v3.3.9...v3.3.10) (2023-12-04)
### Bug Fixes
* **app:** prevent template from being cached between apps with different options ([#9724](https://github.com/vuejs/core/issues/9724)) ([ec71585](https://github.com/vuejs/core/commit/ec715854ca12520b2afc9e9b3981cbae05ae5206)), closes [#9618](https://github.com/vuejs/core/issues/9618)
* **compiler-sfc:** avoid passing forEach index to genMap ([f12db7f](https://github.com/vuejs/core/commit/f12db7fb564a534cef2e5805cc9f54afe5d72fbf))
* **compiler-sfc:** deindent pug/jade templates ([6345197](https://github.com/vuejs/core/commit/634519720a21fb5a6871454e1cadad7053a568b8)), closes [#3231](https://github.com/vuejs/core/issues/3231) [#3842](https://github.com/vuejs/core/issues/3842) [#7723](https://github.com/vuejs/core/issues/7723)
* **compiler-sfc:** fix :where and :is selector in scoped mode with multiple selectors ([#9735](https://github.com/vuejs/core/issues/9735)) ([c3e2c55](https://github.com/vuejs/core/commit/c3e2c556b532656b50b8ab5cd2d9eabc26622d63)), closes [#9707](https://github.com/vuejs/core/issues/9707)
* **compiler-sfc:** generate more treeshaking friendly code ([#9507](https://github.com/vuejs/core/issues/9507)) ([8d74ca0](https://github.com/vuejs/core/commit/8d74ca0e6fa2738ca6854b7e879ff59419f948c7)), closes [#9500](https://github.com/vuejs/core/issues/9500)
* **compiler-sfc:** support inferring generic types ([#8511](https://github.com/vuejs/core/issues/8511)) ([eb5e307](https://github.com/vuejs/core/commit/eb5e307c0be62002e62c4c800d0dfacb39b0d4ca)), closes [#8482](https://github.com/vuejs/core/issues/8482)
* **compiler-sfc:** support resolving components from props ([#8785](https://github.com/vuejs/core/issues/8785)) ([7cbcee3](https://github.com/vuejs/core/commit/7cbcee3d831241a8bd3588ae92d3f27e3641e25f))
* **compiler-sfc:** throw error when failing to load TS during type resolution ([#8883](https://github.com/vuejs/core/issues/8883)) ([4936d2e](https://github.com/vuejs/core/commit/4936d2e11a8d0ca3704bfe408548cb26bb3fd5e9))
* **cssVars:** cssVar names should be double-escaped when generating code for ssr ([#8824](https://github.com/vuejs/core/issues/8824)) ([5199a12](https://github.com/vuejs/core/commit/5199a12f8855cd06f24bf355708b5a2134f63176)), closes [#7823](https://github.com/vuejs/core/issues/7823)
* **deps:** update compiler to ^7.23.4 ([#9681](https://github.com/vuejs/core/issues/9681)) ([31f6ebc](https://github.com/vuejs/core/commit/31f6ebc4df84490ed29fb75e7bf4259200eb51f0))
* **runtime-core:** Suspense get anchor properly in Transition ([#9309](https://github.com/vuejs/core/issues/9309)) ([65f3fe2](https://github.com/vuejs/core/commit/65f3fe273127a8b68e1222fbb306d28d85f01757)), closes [#8105](https://github.com/vuejs/core/issues/8105)
* **runtime-dom:** set width/height with units as attribute ([#8781](https://github.com/vuejs/core/issues/8781)) ([bfc1838](https://github.com/vuejs/core/commit/bfc1838f31199de3f189198a3c234fa7bae91386))
* **ssr:** avoid computed being accidentally cached before server render ([#9688](https://github.com/vuejs/core/issues/9688)) ([30d5d93](https://github.com/vuejs/core/commit/30d5d93a92b2154406ec04f8aca6b217fa01177c)), closes [#5300](https://github.com/vuejs/core/issues/5300)
* **types:** expose emits as props in functional components ([#9234](https://github.com/vuejs/core/issues/9234)) ([887e54c](https://github.com/vuejs/core/commit/887e54c347ea9eac4c721b5e2288f054873d1d30))
* **types:** fix reactive collection types ([#8960](https://github.com/vuejs/core/issues/8960)) ([ad27473](https://github.com/vuejs/core/commit/ad274737015c36906d76f3189203093fa3a2e4e7)), closes [#8904](https://github.com/vuejs/core/issues/8904)
* **types:** improve return type withKeys and withModifiers ([#9734](https://github.com/vuejs/core/issues/9734)) ([43c3cfd](https://github.com/vuejs/core/commit/43c3cfdec5ae5d70fa2a21e857abc2d73f1a0d07))
### Performance Improvements
* optimize on* prop check ([38aaa8c](https://github.com/vuejs/core/commit/38aaa8c88648c54fe2616ad9c0961288092fcb44))
* **runtime-dom:** cache modifier wrapper functions ([da4a4fb](https://github.com/vuejs/core/commit/da4a4fb5e8eee3c6d31f24ebd79a9d0feca56cb2)), closes [#8882](https://github.com/vuejs/core/issues/8882)
* **v-on:** constant handlers with modifiers should not be treated as dynamic ([4d94ebf](https://github.com/vuejs/core/commit/4d94ebfe75174b340d2b794e699cad1add3600a9))
# [3.4.0-alpha.3](https://github.com/vuejs/core/compare/v3.4.0-alpha.2...v3.4.0-alpha.3) (2023-11-28) # [3.4.0-alpha.3](https://github.com/vuejs/core/compare/v3.4.0-alpha.2...v3.4.0-alpha.3) (2023-11-28)
@ -960,55 +889,6 @@ default.
## [3.3.9](https://github.com/vuejs/core/compare/v3.3.8...v3.3.9) (2023-11-25)
### Bug Fixes
* **compiler-core:** avoid rewriting scope variables in inline for loops ([#7245](https://github.com/vuejs/core/issues/7245)) ([a2d810e](https://github.com/vuejs/core/commit/a2d810eb40cef631f61991ca68b426ee9546aba0)), closes [#7238](https://github.com/vuejs/core/issues/7238)
* **compiler-core:** fix `resolveParserPlugins` decorators check ([#9566](https://github.com/vuejs/core/issues/9566)) ([9d0eba9](https://github.com/vuejs/core/commit/9d0eba916f3bf6fb5c03222400edae1a2db7444f)), closes [#9560](https://github.com/vuejs/core/issues/9560)
* **compiler-sfc:** consistently escape type-only prop names ([#8654](https://github.com/vuejs/core/issues/8654)) ([3e08d24](https://github.com/vuejs/core/commit/3e08d246dfd8523c54fb8e7a4a6fd5506ffb1bcc)), closes [#8635](https://github.com/vuejs/core/issues/8635) [#8910](https://github.com/vuejs/core/issues/8910) [vitejs/vite-plugin-vue#184](https://github.com/vitejs/vite-plugin-vue/issues/184)
* **compiler-sfc:** malformed filename on windows using path.posix.join() ([#9478](https://github.com/vuejs/core/issues/9478)) ([f18a174](https://github.com/vuejs/core/commit/f18a174979626b3429db93c5d5b7ae5448917c70)), closes [#8671](https://github.com/vuejs/core/issues/8671) [#9583](https://github.com/vuejs/core/issues/9583) [#9446](https://github.com/vuejs/core/issues/9446) [#9473](https://github.com/vuejs/core/issues/9473)
* **compiler-sfc:** support `:is` and `:where` selector in scoped css rewrite ([#8929](https://github.com/vuejs/core/issues/8929)) ([3227e50](https://github.com/vuejs/core/commit/3227e50b32105f8893f7dff2f29278c5b3a9f621))
* **compiler-sfc:** support resolve extends interface for defineEmits ([#8470](https://github.com/vuejs/core/issues/8470)) ([9e1b74b](https://github.com/vuejs/core/commit/9e1b74bcd5fa4151f5d1bc02c69fbbfa4762f577)), closes [#8465](https://github.com/vuejs/core/issues/8465)
* **hmr/transition:** fix kept-alive component inside transition disappearing after hmr ([#7126](https://github.com/vuejs/core/issues/7126)) ([d11e978](https://github.com/vuejs/core/commit/d11e978fc98dcc83526c167e603b8308f317f786)), closes [#7121](https://github.com/vuejs/core/issues/7121)
* **hydration:** force hydration for v-bind with .prop modifier ([364f319](https://github.com/vuejs/core/commit/364f319d214226770d97c98d8fcada80c9e8dde3)), closes [#7490](https://github.com/vuejs/core/issues/7490)
* **hydration:** properly hydrate indeterminate prop ([34b5a5d](https://github.com/vuejs/core/commit/34b5a5da4ae9c9faccac237acd7acc8e7e017571)), closes [#7476](https://github.com/vuejs/core/issues/7476)
* **reactivity:** clear method on readonly collections should return undefined ([#7316](https://github.com/vuejs/core/issues/7316)) ([657476d](https://github.com/vuejs/core/commit/657476dcdb964be4fbb1277c215c073f3275728e))
* **reactivity:** onCleanup also needs to be cleaned ([#8655](https://github.com/vuejs/core/issues/8655)) ([73fd810](https://github.com/vuejs/core/commit/73fd810eebdd383a2b4629f67736c4db1f428abd)), closes [#5151](https://github.com/vuejs/core/issues/5151) [#7695](https://github.com/vuejs/core/issues/7695)
* **ssr:** hydration `__vnode` missing for devtools ([#9328](https://github.com/vuejs/core/issues/9328)) ([5156ac5](https://github.com/vuejs/core/commit/5156ac5b38cfa80d3db26f2c9bf40cb22a7521cb))
* **types:** allow falsy value types in `StyleValue` ([#7954](https://github.com/vuejs/core/issues/7954)) ([17aa92b](https://github.com/vuejs/core/commit/17aa92b79b31d8bb8b5873ddc599420cb9806db8)), closes [#7955](https://github.com/vuejs/core/issues/7955)
* **types:** defineCustomElement using defineComponent return type with emits ([#7937](https://github.com/vuejs/core/issues/7937)) ([5d932a8](https://github.com/vuejs/core/commit/5d932a8e6d14343c9d7fc7c2ecb58ac618b2f938)), closes [#7782](https://github.com/vuejs/core/issues/7782)
* **types:** fix `unref` and `toValue` when input union type contains ComputedRef ([#8748](https://github.com/vuejs/core/issues/8748)) ([176d476](https://github.com/vuejs/core/commit/176d47671271b1abc21b1508e9a493c7efca6451)), closes [#8747](https://github.com/vuejs/core/issues/8747) [#8857](https://github.com/vuejs/core/issues/8857)
* **types:** fix instance type when props type is incompatible with setup returned type ([#7338](https://github.com/vuejs/core/issues/7338)) ([0e1e8f9](https://github.com/vuejs/core/commit/0e1e8f919e5a74cdaadf9c80ee135088b25e7fa3)), closes [#5885](https://github.com/vuejs/core/issues/5885)
* **types:** fix shallowRef return type with union value type ([#7853](https://github.com/vuejs/core/issues/7853)) ([7c44800](https://github.com/vuejs/core/commit/7c448000b0def910c2cfabfdf7ff20a3d6bc844f)), closes [#7852](https://github.com/vuejs/core/issues/7852)
* **types:** more precise types for class bindings ([#8012](https://github.com/vuejs/core/issues/8012)) ([46e3374](https://github.com/vuejs/core/commit/46e33744c890bd49482c5e5c5cdea44e00ec84d5))
* **types:** remove optional properties from defineProps return type ([#6421](https://github.com/vuejs/core/issues/6421)) ([94c049d](https://github.com/vuejs/core/commit/94c049d930d922069e38ea8700d7ff0970f71e61)), closes [#6420](https://github.com/vuejs/core/issues/6420)
* **types:** return type of withDefaults should be readonly ([#8601](https://github.com/vuejs/core/issues/8601)) ([f15debc](https://github.com/vuejs/core/commit/f15debc01acb22d23f5acee97e6f02db88cef11a))
* **types:** revert class type restrictions ([5d077c8](https://github.com/vuejs/core/commit/5d077c8754cc14f85d2d6d386df70cf8c0d93842)), closes [#8012](https://github.com/vuejs/core/issues/8012)
* **types:** update jsx type definitions ([#8607](https://github.com/vuejs/core/issues/8607)) ([58e2a94](https://github.com/vuejs/core/commit/58e2a94871ae06a909c5f8bad07fb401193e6a38))
* **types:** widen ClassValue type ([2424013](https://github.com/vuejs/core/commit/242401305944422d0c361b16101a4d18908927af))
* **v-model:** avoid overwriting number input with same value ([#7004](https://github.com/vuejs/core/issues/7004)) ([40f4b77](https://github.com/vuejs/core/commit/40f4b77bb570868cb6e47791078767797e465989)), closes [#7003](https://github.com/vuejs/core/issues/7003)
* **v-model:** unnecessary value binding error should apply to dynamic instead of static binding ([2859b65](https://github.com/vuejs/core/commit/2859b653c9a22460e60233cac10fe139e359b046)), closes [#3596](https://github.com/vuejs/core/issues/3596)
## [3.3.8](https://github.com/vuejs/core/compare/v3.3.7...v3.3.8) (2023-11-06)
### Bug Fixes
* **compile-sfc:** support `Error` type in `defineProps` ([#5955](https://github.com/vuejs/core/issues/5955)) ([a989345](https://github.com/vuejs/core/commit/a9893458ec519aae442e1b99e64e6d74685cd22c))
* **compiler-core:** known global should be shadowed by local variables in expression rewrite ([#9492](https://github.com/vuejs/core/issues/9492)) ([a75d1c5](https://github.com/vuejs/core/commit/a75d1c5c6242e91a73cc5ba01e6da620dea0b3d9)), closes [#9482](https://github.com/vuejs/core/issues/9482)
* **compiler-sfc:** fix dynamic directive arguments usage check for slots ([#9495](https://github.com/vuejs/core/issues/9495)) ([b39fa1f](https://github.com/vuejs/core/commit/b39fa1f8157647859331ce439c42ae016a49b415)), closes [#9493](https://github.com/vuejs/core/issues/9493)
* **deps:** update dependency @vue/repl to ^2.6.2 ([#9536](https://github.com/vuejs/core/issues/9536)) ([5cef325](https://github.com/vuejs/core/commit/5cef325f41e3b38657c72fa1a38dedeee1c7a60a))
* **deps:** update dependency @vue/repl to ^2.6.3 ([#9540](https://github.com/vuejs/core/issues/9540)) ([176d590](https://github.com/vuejs/core/commit/176d59058c9aecffe9da4d4311e98496684f06d4))
* **hydration:** fix tagName access error on comment/text node hydration mismatch ([dd8a0cf](https://github.com/vuejs/core/commit/dd8a0cf5dcde13d2cbd899262a0e07f16e14e489)), closes [#9531](https://github.com/vuejs/core/issues/9531)
* **types:** avoid exposing lru-cache types in generated dts ([462aeb3](https://github.com/vuejs/core/commit/462aeb3b600765e219ded2ee9a0ed1e74df61de0)), closes [#9521](https://github.com/vuejs/core/issues/9521)
* **warn:** avoid warning on empty children with Suspense ([#3962](https://github.com/vuejs/core/issues/3962)) ([405f345](https://github.com/vuejs/core/commit/405f34587a63a5f1e3d147b9848219ea98acc22d))
# [3.4.0-alpha.1](https://github.com/vuejs/core/compare/v3.3.7...v3.4.0-alpha.1) (2023-10-28) # [3.4.0-alpha.1](https://github.com/vuejs/core/compare/v3.3.7...v3.4.0-alpha.1) (2023-10-28)

View File

@ -1,6 +1,7 @@
import importX from 'eslint-plugin-import-x' import importX from 'eslint-plugin-import-x'
import tseslint from 'typescript-eslint' import tseslint from 'typescript-eslint'
import vitest from 'eslint-plugin-vitest' import { defineConfig } from 'eslint/config'
import vitest from '@vitest/eslint-plugin'
import { builtinModules } from 'node:module' import { builtinModules } from 'node:module'
const DOMGlobals = ['window', 'document'] const DOMGlobals = ['window', 'document']
@ -12,7 +13,7 @@ const banConstEnum = {
'Please use non-const enums. This project automatically inlines enums.', 'Please use non-const enums. This project automatically inlines enums.',
} }
export default tseslint.config( export default defineConfig(
{ {
files: ['**/*.js', '**/*.ts', '**/*.tsx'], files: ['**/*.js', '**/*.ts', '**/*.tsx'],
extends: [tseslint.configs.base], extends: [tseslint.configs.base],
@ -60,7 +61,10 @@ export default tseslint.config(
], ],
// This rule enforces the preference for using '@ts-expect-error' comments in TypeScript // This rule enforces the preference for using '@ts-expect-error' comments in TypeScript
// code to indicate intentional type errors, improving code clarity and maintainability. // code to indicate intentional type errors, improving code clarity and maintainability.
'@typescript-eslint/prefer-ts-expect-error': 'error', '@typescript-eslint/ban-ts-comment': [
'error',
{ minimumDescriptionLength: 0 },
],
// Enforce the use of 'import type' for importing types // Enforce the use of 'import type' for importing types
'@typescript-eslint/consistent-type-imports': [ '@typescript-eslint/consistent-type-imports': [
'error', 'error',

View File

@ -1,3 +1,3 @@
[build.environment] [build.environment]
NODE_VERSION = "18" NODE_VERSION = "22"
NPM_FLAGS = "--version" # prevent Netlify npm install NPM_FLAGS = "--version" # prevent Netlify npm install

View File

@ -1,14 +1,14 @@
{ {
"private": true, "private": true,
"version": "3.5.4", "version": "3.5.26",
"packageManager": "pnpm@9.10.0", "packageManager": "pnpm@10.25.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "node scripts/dev.js", "dev": "node scripts/dev.js",
"build": "node scripts/build.js", "build": "node scripts/build.js",
"build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js", "build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js",
"clean": "rimraf --glob packages/*/dist temp .eslintcache", "clean": "rimraf --glob packages/*/dist temp .eslintcache",
"size": "run-s \"size-*\" && tsx scripts/usage-size.ts", "size": "run-s \"size-*\" && node scripts/usage-size.js",
"size-global": "node scripts/build.js vue runtime-dom -f global -p --size", "size-global": "node scripts/build.js vue runtime-dom -f global -p --size",
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime", "size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler", "size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
@ -17,12 +17,15 @@
"format": "prettier --write --cache .", "format": "prettier --write --cache .",
"format-check": "prettier --check --cache .", "format-check": "prettier --check --cache .",
"test": "vitest", "test": "vitest",
"test-unit": "vitest -c vitest.unit.config.ts", "test-unit": "vitest --project unit*",
"test-e2e": "node scripts/build.js vue -f global -d && vitest -c vitest.e2e.config.ts", "test-e2e": "node scripts/build.js vue -f global -d && vitest --project e2e",
"test-dts": "run-s build-dts test-dts-only", "test-dts": "run-s build-dts test-dts-only",
"test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json", "test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json",
"test-coverage": "vitest run -c vitest.unit.config.ts --coverage", "test-coverage": "vitest run --project unit* --coverage",
"test-bench": "vitest bench", "prebench": "node scripts/build.js -pf esm-browser reactivity",
"prebench-compare": "node scripts/build.js -pf esm-browser reactivity",
"bench": "vitest bench --project=unit --outputJson=temp/bench.json",
"bench-compare": "vitest bench --project=unit --compare=temp/bench.json",
"release": "node scripts/release.js", "release": "node scripts/release.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"dev-esm": "node scripts/dev.js -if esm-bundler-runtime", "dev-esm": "node scripts/dev.js -if esm-bundler-runtime",
@ -61,64 +64,52 @@
"devDependencies": { "devDependencies": {
"@babel/parser": "catalog:", "@babel/parser": "catalog:",
"@babel/types": "catalog:", "@babel/types": "catalog:",
"@rollup/plugin-alias": "^5.1.0", "@rollup/plugin-alias": "^6.0.0",
"@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-commonjs": "^29.0.0",
"@rollup/plugin-json": "^6.1.0", "@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-replace": "5.0.4", "@rollup/plugin-replace": "5.0.4",
"@swc/core": "^1.7.24", "@swc/core": "^1.15.4",
"@types/hash-sum": "^1.0.2", "@types/hash-sum": "^1.0.2",
"@types/node": "^20.16.5", "@types/node": "^24.10.4",
"@types/semver": "^7.5.8", "@types/semver": "^7.7.1",
"@types/serve-handler": "^6.1.4", "@types/serve-handler": "^6.1.4",
"@vitest/coverage-v8": "^2.0.5", "@vitest/coverage-v8": "^3.2.4",
"@vitest/eslint-plugin": "^1.5.2",
"@vue/consolidate": "1.0.0", "@vue/consolidate": "1.0.0",
"conventional-changelog-cli": "^5.0.0", "conventional-changelog-cli": "^5.0.0",
"enquirer": "^2.4.1", "enquirer": "^2.4.1",
"esbuild": "^0.23.1", "esbuild": "^0.27.1",
"esbuild-plugin-polyfill-node": "^0.3.0", "esbuild-plugin-polyfill-node": "^0.3.0",
"eslint": "^9.9.1", "eslint": "^9.39.2",
"eslint-plugin-import-x": "^3.1.0", "eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-vitest": "^0.5.4",
"estree-walker": "catalog:", "estree-walker": "catalog:",
"jsdom": "^25.0.0", "jsdom": "^27.3.0",
"lint-staged": "^15.2.10", "lint-staged": "^16.2.7",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"magic-string": "^0.30.11", "magic-string": "^0.30.21",
"markdown-table": "^3.0.3", "markdown-table": "^3.0.4",
"marked": "13.0.3", "marked": "13.0.3",
"npm-run-all2": "^6.2.2", "npm-run-all2": "^8.0.4",
"picocolors": "^1.1.0", "picocolors": "^1.1.1",
"prettier": "^3.3.3", "prettier": "^3.7.4",
"pretty-bytes": "^6.1.1", "pretty-bytes": "^7.1.0",
"pug": "^3.0.3", "pug": "^3.0.3",
"puppeteer": "~23.3.0", "puppeteer": "~24.33.0",
"rimraf": "^6.0.1", "rimraf": "^6.1.2",
"rollup": "^4.21.2", "rollup": "^4.53.3",
"rollup-plugin-dts": "^6.1.1", "rollup-plugin-dts": "^6.3.0",
"rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-esbuild": "^6.2.1",
"rollup-plugin-polyfill-node": "^0.13.0", "rollup-plugin-polyfill-node": "^0.13.0",
"semver": "^7.6.3", "semver": "^7.7.3",
"serve": "^14.2.3", "serve": "^14.2.5",
"serve-handler": "^6.1.5", "serve-handler": "^6.1.6",
"simple-git-hooks": "^2.11.1", "simple-git-hooks": "^2.13.1",
"todomvc-app-css": "^2.4.3", "todomvc-app-css": "^2.4.3",
"tslib": "^2.7.0", "tslib": "^2.8.1",
"tsx": "^4.19.0",
"typescript": "~5.6.2", "typescript": "~5.6.2",
"typescript-eslint": "^8.4.0", "typescript-eslint": "^8.49.0",
"vite": "catalog:", "vite": "catalog:",
"vitest": "^2.0.5" "vitest": "^3.2.4"
},
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"typescript-eslint>eslint": "^9.0.0",
"@typescript-eslint/eslint-plugin>eslint": "^9.0.0",
"@typescript-eslint/parser>eslint": "^9.0.0",
"@typescript-eslint/type-utils>eslint": "^9.0.0",
"@typescript-eslint/utils>eslint": "^9.0.0"
}
}
} }
} }

View File

@ -3,12 +3,17 @@ import { expectType } from './utils'
const app = createApp({}) const app = createApp({})
app.directive<HTMLElement, string>('custom', { app.directive<HTMLElement, string, 'prevent' | 'stop', 'arg1' | 'arg2'>(
'custom',
{
mounted(el, binding) { mounted(el, binding) {
expectType<HTMLElement>(el) expectType<HTMLElement>(el)
expectType<string>(binding.value) expectType<string>(binding.value)
expectType<{ prevent?: boolean; stop?: boolean }>(binding.modifiers)
expectType<'arg1' | 'arg2'>(binding.arg!)
// @ts-expect-error not any // @ts-expect-error not any
expectType<number>(binding.value) expectType<number>(binding.value)
}, },
}) },
)

View File

@ -12,8 +12,11 @@ app.use(PluginWithoutType, 2)
app.use(PluginWithoutType, { anything: 'goes' }, true) app.use(PluginWithoutType, { anything: 'goes' }, true)
type PluginOptions = { type PluginOptions = {
/** option1 */
option1?: string option1?: string
/** option2 */
option2: number option2: number
/** option3 */
option3: boolean option3: boolean
} }
@ -25,6 +28,20 @@ const PluginWithObjectOptions = {
}, },
} }
const objectPluginOptional = {
install(app: App, options?: PluginOptions) {},
}
app.use(objectPluginOptional)
app.use(
objectPluginOptional,
// Test JSDoc and `go to definition` for options
{
option1: 'foo',
option2: 1,
option3: true,
},
)
for (const Plugin of [ for (const Plugin of [
PluginWithObjectOptions, PluginWithObjectOptions,
PluginWithObjectOptions.install, PluginWithObjectOptions.install,
@ -92,7 +109,27 @@ const PluginTyped: Plugin<PluginOptions> = (app, options) => {}
// @ts-expect-error: needs options // @ts-expect-error: needs options
app.use(PluginTyped) app.use(PluginTyped)
app.use(PluginTyped, { option2: 2, option3: true }) app.use(
PluginTyped,
// Test autocomplete for options
{
option1: '',
option2: 2,
option3: true,
},
)
const functionPluginOptional = (app: App, options?: PluginOptions) => {}
app.use(functionPluginOptional)
app.use(functionPluginOptional, { option2: 2, option3: true })
// type optional params
const functionPluginOptional2: Plugin<[options?: PluginOptions]> = (
app,
options,
) => {}
app.use(functionPluginOptional2)
app.use(functionPluginOptional2, { option2: 2, option3: true })
// vuetify usage // vuetify usage
const key: string = '' const key: string = ''

View File

@ -137,3 +137,18 @@ describe('Generic component', () => {
expectType<string | number>(comp.msg) expectType<string | number>(comp.msg)
expectType<Array<string | number>>(comp.list) expectType<Array<string | number>>(comp.list)
}) })
// #12751
{
const Comp = defineComponent({
__typeEmits: {} as {
'update:visible': [value?: boolean]
},
})
const comp: ComponentInstance<typeof Comp> = {} as any
expectType<((value?: boolean) => any) | undefined>(comp['onUpdate:visible'])
expectType<{ 'onUpdate:visible'?: (value?: boolean) => any }>(comp['$props'])
// @ts-expect-error
comp['$props']['$props']
}

View File

@ -20,6 +20,9 @@ import { type IsAny, type IsUnion, describe, expectType } from './utils'
describe('with object props', () => { describe('with object props', () => {
interface ExpectedProps { interface ExpectedProps {
a?: number | undefined a?: number | undefined
aa: number
aaa: number | null
aaaa: number | undefined
b: string b: string
e?: Function e?: Function
h: boolean h: boolean
@ -53,6 +56,19 @@ describe('with object props', () => {
const props = { const props = {
a: Number, a: Number,
aa: {
type: Number as PropType<number | undefined>,
default: 1,
},
aaa: {
type: Number as PropType<number | null>,
default: 1,
},
aaaa: {
type: Number as PropType<number | undefined>,
// `as const` prevents widening to `boolean` (keeps literal `true` type)
required: true as const,
},
// required should make property non-void // required should make property non-void
b: { b: {
type: String, type: String,
@ -146,6 +162,13 @@ describe('with object props', () => {
setup(props) { setup(props) {
// type assertion. See https://github.com/SamVerschueren/tsd // type assertion. See https://github.com/SamVerschueren/tsd
expectType<ExpectedProps['a']>(props.a) expectType<ExpectedProps['a']>(props.a)
expectType<ExpectedProps['aa']>(props.aa)
expectType<ExpectedProps['aaa']>(props.aaa)
// @ts-expect-error should included `undefined`
expectType<number>(props.aaaa)
expectType<ExpectedProps['aaaa']>(props.aaaa)
expectType<ExpectedProps['b']>(props.b) expectType<ExpectedProps['b']>(props.b)
expectType<ExpectedProps['e']>(props.e) expectType<ExpectedProps['e']>(props.e)
expectType<ExpectedProps['h']>(props.h) expectType<ExpectedProps['h']>(props.h)
@ -198,6 +221,8 @@ describe('with object props', () => {
render() { render() {
const props = this.$props const props = this.$props
expectType<ExpectedProps['a']>(props.a) expectType<ExpectedProps['a']>(props.a)
expectType<ExpectedProps['aa']>(props.aa)
expectType<ExpectedProps['aaa']>(props.aaa)
expectType<ExpectedProps['b']>(props.b) expectType<ExpectedProps['b']>(props.b)
expectType<ExpectedProps['e']>(props.e) expectType<ExpectedProps['e']>(props.e)
expectType<ExpectedProps['h']>(props.h) expectType<ExpectedProps['h']>(props.h)
@ -225,6 +250,8 @@ describe('with object props', () => {
// should also expose declared props on `this` // should also expose declared props on `this`
expectType<ExpectedProps['a']>(this.a) expectType<ExpectedProps['a']>(this.a)
expectType<ExpectedProps['aa']>(this.aa)
expectType<ExpectedProps['aaa']>(this.aaa)
expectType<ExpectedProps['b']>(this.b) expectType<ExpectedProps['b']>(this.b)
expectType<ExpectedProps['e']>(this.e) expectType<ExpectedProps['e']>(this.e)
expectType<ExpectedProps['h']>(this.h) expectType<ExpectedProps['h']>(this.h)
@ -269,6 +296,7 @@ describe('with object props', () => {
expectType<JSX.Element>( expectType<JSX.Element>(
<MyComponent <MyComponent
a={1} a={1}
aaaa={1}
b="b" b="b"
bb="bb" bb="bb"
e={() => {}} e={() => {}}
@ -295,6 +323,7 @@ describe('with object props', () => {
expectType<Component>( expectType<Component>(
<MyComponent <MyComponent
aaaa={1}
b="b" b="b"
dd={{ n: 1 }} dd={{ n: 1 }}
ddd={['ddd']} ddd={['ddd']}
@ -2068,3 +2097,48 @@ expectString(instance.actionText)
// public prop on $props should be optional // public prop on $props should be optional
// @ts-expect-error // @ts-expect-error
expectString(instance.$props.actionText) expectString(instance.$props.actionText)
// #12122
defineComponent({
props: { foo: String },
render() {
expectType<{ readonly foo?: string }>(this.$props)
// @ts-expect-error
expectType<string>(this.$props)
},
})
// #14117
defineComponent({
setup() {
const setup1 = ref('setup1')
const setup2 = ref('setup2')
return { setup1, setup2 }
},
data() {
return {
data1: 1,
}
},
props: {
props1: {
type: String,
},
},
methods: {
methods1() {
return `methods1`
},
},
computed: {
computed1() {
this.setup1
this.setup2
this.data1
this.props1
this.methods1()
return `computed1`
},
},
expose: ['setup1'],
})

View File

@ -13,7 +13,7 @@ type ExtractBinding<T> = T extends (
declare function testDirective< declare function testDirective<
Value, Value,
Modifiers extends string = string, Modifiers extends string = string,
Arg extends string = string, Arg = any,
>(): ExtractBinding<Directive<any, Value, Modifiers, Arg>> >(): ExtractBinding<Directive<any, Value, Modifiers, Arg>>
describe('vmodel', () => { describe('vmodel', () => {
@ -29,7 +29,7 @@ describe('custom', () => {
value: number value: number
oldValue: number | null oldValue: number | null
arg?: 'Arg' arg?: 'Arg'
modifiers: Record<'a' | 'b', boolean> modifiers: Partial<Record<'a' | 'b', boolean>>
}>(testDirective<number, 'a' | 'b', 'Arg'>()) }>(testDirective<number, 'a' | 'b', 'Arg'>())
expectType<{ expectType<{
@ -44,7 +44,7 @@ describe('custom', () => {
value: number value: number
oldValue: number | null oldValue: number | null
arg?: 'Arg' arg?: 'Arg'
modifiers: Record<'a' | 'b', boolean> modifiers: Partial<Record<'a' | 'b', boolean>>
// @ts-expect-error // @ts-expect-error
}>(testDirective<number, 'a' | 'b', 'Argx'>()) }>(testDirective<number, 'a' | 'b', 'Argx'>())
@ -52,7 +52,29 @@ describe('custom', () => {
value: number value: number
oldValue: number | null oldValue: number | null
arg?: 'Arg' arg?: 'Arg'
modifiers: Record<'a' | 'b', boolean> modifiers: Partial<Record<'a' | 'b', boolean>>
// @ts-expect-error // @ts-expect-error
}>(testDirective<string, 'a' | 'b', 'Arg'>()) }>(testDirective<string, 'a' | 'b', 'Arg'>())
expectType<{
value: number
oldValue: number | null
arg?: HTMLElement
modifiers: Partial<Record<'a' | 'b', boolean>>
}>(testDirective<number, 'a' | 'b', HTMLElement>())
expectType<{
value: number
oldValue: number | null
arg?: HTMLElement
modifiers: Partial<Record<'a' | 'b', boolean>>
// @ts-expect-error
}>(testDirective<number, 'a' | 'b', string>())
expectType<{
value: number
oldValue: number | null
arg?: HTMLElement
modifiers: Partial<Record<'a' | 'b', boolean>>
}>(testDirective<number, 'a' | 'b'>())
}) })

View File

@ -4,6 +4,7 @@ import {
type MaybeRefOrGetter, type MaybeRefOrGetter,
type Ref, type Ref,
type ShallowRef, type ShallowRef,
type TemplateRef,
type ToRefs, type ToRefs,
type WritableComputedRef, type WritableComputedRef,
computed, computed,
@ -189,6 +190,24 @@ describe('allow getter and setter types to be unrelated', <T>() => {
f.value = ref(1) f.value = ref(1)
}) })
describe('correctly unwraps nested refs', () => {
const obj = {
n: 24,
ref: ref(24),
nestedRef: ref({ n: ref(0) }),
}
const a = ref(obj)
expectType<number>(a.value.n)
expectType<number>(a.value.ref)
expectType<number>(a.value.nestedRef.n)
const b = reactive({ a })
expectType<number>(b.a.n)
expectType<number>(b.a.ref)
expectType<number>(b.a.nestedRef.n)
})
// computed // computed
describe('allow computed getter and setter types to be unrelated', () => { describe('allow computed getter and setter types to be unrelated', () => {
const obj = ref({ const obj = ref({
@ -517,7 +536,7 @@ expectType<string>(toValue(unref2))
// useTemplateRef // useTemplateRef
const tRef = useTemplateRef('foo') const tRef = useTemplateRef('foo')
expectType<Readonly<ShallowRef<unknown>>>(tRef) expectType<TemplateRef>(tRef)
const tRef2 = useTemplateRef<HTMLElement>('bar') const tRef2 = useTemplateRef<HTMLElement>('bar')
expectType<Readonly<ShallowRef<HTMLElement | null>>>(tRef2) expectType<TemplateRef<HTMLElement>>(tRef2)

View File

@ -0,0 +1,31 @@
import { nextTick } from 'vue'
import { describe, expectType } from './utils'
describe('nextTick', async () => {
expectType<Promise<void>>(nextTick())
expectType<Promise<string>>(nextTick(() => 'foo'))
expectType<Promise<string>>(nextTick(() => Promise.resolve('foo')))
expectType<Promise<string>>(
nextTick(() => Promise.resolve(Promise.resolve('foo'))),
)
expectType<void>(await nextTick())
expectType<string>(await nextTick(() => 'foo'))
expectType<string>(await nextTick(() => Promise.resolve('foo')))
expectType<string>(
await nextTick(() => Promise.resolve(Promise.resolve('foo'))),
)
nextTick().then(value => {
expectType<void>(value)
})
nextTick(() => 'foo').then(value => {
expectType<string>(value)
})
nextTick(() => Promise.resolve('foo')).then(value => {
expectType<string>(value)
})
nextTick(() => Promise.resolve(Promise.resolve('foo'))).then(value => {
expectType<string>(value)
})
})

View File

@ -33,6 +33,16 @@ describe('defineProps w/ type declaration', () => {
expectType<boolean>(props.boolAndUndefined) expectType<boolean>(props.boolAndUndefined)
}) })
describe('defineProps w/ never prop', () => {
const props = defineProps<{
foo?: never
bar: number
}>()
expectType<never | undefined>(props.foo)
expectType<number>(props.bar)
})
describe('defineProps w/ generics', () => { describe('defineProps w/ generics', () => {
function test<T extends boolean>() { function test<T extends boolean>() {
const props = defineProps<{ foo: T; bar: string; x?: boolean }>() const props = defineProps<{ foo: T; bar: string; x?: boolean }>()
@ -240,6 +250,23 @@ describe('withDefaults w/ defineProp type is different from the defaults type',
res1.value res1.value
}) })
describe('withDefaults w/ defineProp discriminate union type', () => {
const props = withDefaults(
defineProps<
{ type: 'button'; buttonType?: 'submit' } | { type: 'link'; href: string }
>(),
{
type: 'button',
},
)
if (props.type === 'button') {
expectType<'submit' | undefined>(props.buttonType)
}
if (props.type === 'link') {
expectType<string>(props.href)
}
})
describe('defineProps w/ runtime declaration', () => { describe('defineProps w/ runtime declaration', () => {
// runtime declaration // runtime declaration
const props = defineProps({ const props = defineProps({
@ -289,6 +316,14 @@ describe('defineEmits w/ type declaration', () => {
emit2('baz') emit2('baz')
}) })
describe('defineEmits w/ interface declaration', () => {
interface Emits {
foo: [value: string]
}
const emit = defineEmits<Emits>()
emit('foo', 'hi')
})
describe('defineEmits w/ alt type declaration', () => { describe('defineEmits w/ alt type declaration', () => {
const emit = defineEmits<{ const emit = defineEmits<{
foo: [id: string] foo: [id: string]

8
packages-private/global.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/// <reference types="vite/client" />
// Global compile-time constants
declare var __COMMIT__: string
declare module 'file-saver' {
export function saveAs(blob: any, name: any): void
}

View File

@ -13,7 +13,7 @@
"vite": "catalog:" "vite": "catalog:"
}, },
"dependencies": { "dependencies": {
"@vue/repl": "^4.3.1", "@vue/repl": "^4.7.1",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"vue": "workspace:*" "vue": "workspace:*"

View File

@ -2,7 +2,7 @@
import Header from './Header.vue' import Header from './Header.vue'
import { Repl, useStore, SFCOptions, useVueImportMap } from '@vue/repl' import { Repl, useStore, SFCOptions, useVueImportMap } from '@vue/repl'
import Monaco from '@vue/repl/monaco-editor' import Monaco from '@vue/repl/monaco-editor'
import { ref, watchEffect, onMounted, computed } from 'vue' import { ref, watchEffect, onMounted, computed, watch } from 'vue'
const replRef = ref<InstanceType<typeof Repl>>() const replRef = ref<InstanceType<typeof Repl>>()
@ -14,6 +14,12 @@ setVH()
const useSSRMode = ref(false) const useSSRMode = ref(false)
const AUTO_SAVE_STORAGE_KEY = 'vue-sfc-playground-auto-save'
const initAutoSave: boolean = JSON.parse(
localStorage.getItem(AUTO_SAVE_STORAGE_KEY) ?? 'true',
)
const autoSave = ref(initAutoSave)
const { productionMode, vueVersion, importMap } = useVueImportMap({ const { productionMode, vueVersion, importMap } = useVueImportMap({
runtimeDev: import.meta.env.PROD runtimeDev: import.meta.env.PROD
? `${location.origin}/vue.runtime.esm-browser.js` ? `${location.origin}/vue.runtime.esm-browser.js`
@ -89,6 +95,11 @@ function toggleSSR() {
useSSRMode.value = !useSSRMode.value useSSRMode.value = !useSSRMode.value
} }
function toggleAutoSave() {
autoSave.value = !autoSave.value
localStorage.setItem(AUTO_SAVE_STORAGE_KEY, String(autoSave.value))
}
function reloadPage() { function reloadPage() {
replRef.value?.reload() replRef.value?.reload()
} }
@ -104,6 +115,34 @@ onMounted(() => {
// @ts-expect-error process shim for old versions of @vue/compiler-sfc dependency // @ts-expect-error process shim for old versions of @vue/compiler-sfc dependency
window.process = { env: {} } window.process = { env: {} }
}) })
const isVaporSupported = ref(false)
watch(
() => store.vueVersion,
(version, oldVersion) => {
const [major, minor] = (version || store.compiler.version)
.split('.')
.map((v: string) => parseInt(v, 10))
isVaporSupported.value = major > 3 || (major === 3 && minor >= 6)
if (oldVersion) reloadPage()
},
{ immediate: true, flush: 'pre' },
)
const previewOptions = computed(() => ({
customCode: {
importCode: `import { initCustomFormatter${isVaporSupported.value ? ', vaporInteropPlugin' : ''} } from 'vue'`,
useCode: `
${isVaporSupported.value ? 'app.use(vaporInteropPlugin)' : ''}
if (window.devtoolsFormatters) {
const index = window.devtoolsFormatters.findIndex((v) => v.__vue_custom_formatter)
window.devtoolsFormatters.splice(index, 1)
initCustomFormatter()
} else {
initCustomFormatter()
}`,
},
}))
</script> </script>
<template> <template>
@ -111,9 +150,12 @@ onMounted(() => {
:store="store" :store="store"
:prod="productionMode" :prod="productionMode"
:ssr="useSSRMode" :ssr="useSSRMode"
:autoSave="autoSave"
:theme="theme"
@toggle-theme="toggleTheme" @toggle-theme="toggleTheme"
@toggle-prod="toggleProdMode" @toggle-prod="toggleProdMode"
@toggle-ssr="toggleSSR" @toggle-ssr="toggleSSR"
@toggle-autosave="toggleAutoSave"
@reload-page="reloadPage" @reload-page="reloadPage"
/> />
<Repl <Repl
@ -123,22 +165,15 @@ onMounted(() => {
@keydown.ctrl.s.prevent @keydown.ctrl.s.prevent
@keydown.meta.s.prevent @keydown.meta.s.prevent
:ssr="useSSRMode" :ssr="useSSRMode"
:model-value="autoSave"
:editorOptions="{ autoSaveText: false }"
:store="store" :store="store"
:showCompileOutput="true" :showCompileOutput="true"
:showSsrOutput="useSSRMode"
:showOpenSourceMap="true"
:autoResize="true" :autoResize="true"
:clearConsole="false" :clearConsole="false"
:preview-options="{ :preview-options="previewOptions"
customCode: {
importCode: `import { initCustomFormatter } from 'vue'`,
useCode: `if (window.devtoolsFormatters) {
const index = window.devtoolsFormatters.findIndex((v) => v.__vue_custom_formatter)
window.devtoolsFormatters.splice(index, 1)
initCustomFormatter()
} else {
initCustomFormatter()
}`,
},
}"
/> />
</template> </template>
@ -149,8 +184,9 @@ onMounted(() => {
body { body {
font-size: 13px; font-size: 13px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, font-family:
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
margin: 0; margin: 0;
--base: #444; --base: #444;
--nav-height: 50px; --nav-height: 50px;

View File

@ -14,11 +14,14 @@ const props = defineProps<{
store: ReplStore store: ReplStore
prod: boolean prod: boolean
ssr: boolean ssr: boolean
autoSave: boolean
theme: 'dark' | 'light'
}>() }>()
const emit = defineEmits([ const emit = defineEmits([
'toggle-theme', 'toggle-theme',
'toggle-ssr', 'toggle-ssr',
'toggle-prod', 'toggle-prod',
'toggle-autosave',
'reload-page', 'reload-page',
]) ])
@ -43,6 +46,7 @@ function resetVueVersion() {
async function copyLink(e: MouseEvent) { async function copyLink(e: MouseEvent) {
if (e.metaKey) { if (e.metaKey) {
resetVueVersion()
// hidden logic for going to local debug from play.vuejs.org // hidden logic for going to local debug from play.vuejs.org
window.location.href = 'http://localhost:5173/' + window.location.hash window.location.href = 'http://localhost:5173/' + window.location.hash
return return
@ -107,7 +111,19 @@ function toggleDark() {
> >
<span>{{ ssr ? 'SSR ON' : 'SSR OFF' }}</span> <span>{{ ssr ? 'SSR ON' : 'SSR OFF' }}</span>
</button> </button>
<button title="Toggle dark mode" class="toggle-dark" @click="toggleDark"> <button
title="Toggle editor auto save mode"
class="toggle-autosave"
:class="{ enabled: autoSave }"
@click="$emit('toggle-autosave')"
>
<span>{{ autoSave ? 'AutoSave ON' : 'AutoSave OFF' }}</span>
</button>
<button
:title="`Switch to ${theme === 'dark' ? 'light' : 'dark'} theme`"
class="toggle-dark"
@click="toggleDark"
>
<Sun class="light" /> <Sun class="light" />
<Moon class="dark" /> <Moon class="dark" />
</button> </button>
@ -199,7 +215,8 @@ h1 img {
} }
.toggle-prod span, .toggle-prod span,
.toggle-ssr span { .toggle-ssr span,
.toggle-autosave span {
font-size: 12px; font-size: 12px;
border-radius: 4px; border-radius: 4px;
padding: 4px 6px; padding: 4px 6px;
@ -214,11 +231,13 @@ h1 img {
background: var(--purple); background: var(--purple);
} }
.toggle-ssr span { .toggle-ssr span,
.toggle-autosave span {
background-color: var(--btn-bg); background-color: var(--btn-bg);
} }
.toggle-ssr.enabled span { .toggle-ssr.enabled span,
.toggle-autosave.enabled span {
color: #fff; color: #fff;
background-color: var(--green); background-color: var(--green);
} }

View File

@ -17,7 +17,10 @@ export async function downloadProject(store: ReplStore) {
// basic structure // basic structure
zip.file('index.html', index) zip.file('index.html', index)
zip.file('package.json', pkg) zip.file(
'package.json',
pkg.replace(`"vue": "latest"`, `"vue": "${store.vueVersion || 'latest'}"`),
)
zip.file('vite.config.js', config) zip.file('vite.config.js', config)
zip.file('README.md', readme) zip.file('README.md', readme)

View File

@ -8,10 +8,10 @@
"serve": "vite preview" "serve": "vite preview"
}, },
"dependencies": { "dependencies": {
"vue": "^3.4.0" "vue": "latest"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.1.3", "@vitejs/plugin-vue": "^6.0.3",
"vite": "^5.4.3" "vite": "^7.2.7"
} }
} }

View File

@ -11,7 +11,7 @@
"enableNonBrowserBranches": true "enableNonBrowserBranches": true
}, },
"dependencies": { "dependencies": {
"monaco-editor": "^0.51.0", "monaco-editor": "^0.55.1",
"source-map-js": "^1.2.0" "source-map-js": "^1.2.1"
} }
} }

View File

@ -1,8 +1,9 @@
body { body {
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, font-family:
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
--bg: #1d1f21; --bg: #1d1f21;
--border: #333; --border: #333;
} }

View File

@ -2019,6 +2019,21 @@ describe('compiler: parse', () => {
children: [{ type: NodeTypes.TEXT, content: `{{ number ` }], children: [{ type: NodeTypes.TEXT, content: `{{ number ` }],
}, },
]) ])
const ast3 = baseParse(`<div v-pre><textarea>{{ foo </textarea></div>`, {
parseMode: 'html',
})
expect((ast3.children[0] as ElementNode).children).toMatchObject([
{
type: NodeTypes.ELEMENT,
children: [
{
type: NodeTypes.TEXT,
content: `{{ foo `,
},
],
},
])
}) })
test('self-closing v-pre', () => { test('self-closing v-pre', () => {
@ -2256,6 +2271,11 @@ describe('compiler: parse', () => {
expect(span.loc.start.offset).toBe(0) expect(span.loc.start.offset).toBe(0)
expect(span.loc.end.offset).toBe(27) expect(span.loc.end.offset).toBe(27)
}) })
test('correct loc when a line in attribute value ends with &', () => {
const [span] = baseParse(`<span v-if="foo &&\nbar"></span>`).children
expect(span.loc.end.line).toBe(2)
})
}) })
describe('decodeEntities option', () => { describe('decodeEntities option', () => {
@ -2354,6 +2374,7 @@ describe('compiler: parse', () => {
test('should remove leading newline character immediately following the pre element start tag', () => { test('should remove leading newline character immediately following the pre element start tag', () => {
const ast = parse(`<pre>\n foo bar </pre>`, { const ast = parse(`<pre>\n foo bar </pre>`, {
isPreTag: tag => tag === 'pre', isPreTag: tag => tag === 'pre',
isIgnoreNewlineTag: tag => tag === 'pre',
}) })
expect(ast.children).toHaveLength(1) expect(ast.children).toHaveLength(1)
const preElement = ast.children[0] as ElementNode const preElement = ast.children[0] as ElementNode

View File

@ -7,9 +7,9 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("div", { key: "foo" }, null, -1 /* HOISTED */) _createElementVNode("div", { key: "foo" }, null, -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -21,16 +21,16 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("p", null, [ _createElementVNode("p", null, [
_createElementVNode("span"), _createElementVNode("span"),
_createElementVNode("span") _createElementVNode("span")
], -1 /* HOISTED */), ], -1 /* CACHED */),
_createElementVNode("p", null, [ _createElementVNode("p", null, [
_createElementVNode("span"), _createElementVNode("span"),
_createElementVNode("span") _createElementVNode("span")
], -1 /* HOISTED */) ], -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -42,11 +42,11 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("div", null, [ _createElementVNode("div", null, [
_createCommentVNode("comment") _createCommentVNode("comment")
], -1 /* HOISTED */) ], -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -58,11 +58,11 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { createElementVNode: _createElementVNode, createTextVNode: _createTextVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { createElementVNode: _createElementVNode, createTextVNode: _createTextVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", null, null, -1 /* HOISTED */), _createElementVNode("span", null, null, -1 /* CACHED */),
_createTextVNode("foo"), _createTextVNode("foo", -1 /* CACHED */),
_createElementVNode("div", null, null, -1 /* HOISTED */) _createElementVNode("div", null, null, -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -74,9 +74,9 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", { class: "inline" }, "hello", -1 /* HOISTED */) _createElementVNode("span", { class: "inline" }, "hello", -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -147,9 +147,9 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", null, "foo " + _toDisplayString(1) + " " + _toDisplayString(true), -1 /* HOISTED */) _createElementVNode("span", null, "foo " + _toDisplayString(1) + " " + _toDisplayString(true), -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -161,9 +161,9 @@ return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", { foo: 0 }, _toDisplayString(1), -1 /* HOISTED */) _createElementVNode("span", { foo: 0 }, _toDisplayString(1), -1 /* CACHED */)
]))) ]))]))
} }
}" }"
`; `;
@ -178,7 +178,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(1, (i) => { (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(1, (i) => {
return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", { class: "hi" }, null, -1 /* HOISTED */) _createElementVNode("span", { class: "hi" }, null, -1 /* CACHED */)
]))])) ]))]))
}), 256 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
])) ]))
@ -215,9 +215,9 @@ return function render(_ctx, _cache) {
const _directive_foo = _resolveDirective("foo") const _directive_foo = _resolveDirective("foo")
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
_withDirectives((_openBlock(), _createElementBlock("svg", null, _cache[0] || (_cache[0] = [ _withDirectives((_openBlock(), _createElementBlock("svg", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("path", { d: "M2,3H5.5L12" }, null, -1 /* HOISTED */) _createElementVNode("path", { d: "M2,3H5.5L12" }, null, -1 /* CACHED */)
]))), [ ]))])), [
[_directive_foo] [_directive_foo]
]) ])
])) ]))
@ -401,15 +401,41 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
ok ok
? (_openBlock(), _createElementBlock("div", _hoisted_1, _cache[0] || (_cache[0] = [ ? (_openBlock(), _createElementBlock("div", _hoisted_1, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", null, null, -1 /* HOISTED */) _createElementVNode("span", null, null, -1 /* CACHED */)
]))) ]))]))
: _createCommentVNode("v-if", true) : _createCommentVNode("v-if", true)
])) ]))
} }
}" }"
`; `;
exports[`compiler: cacheStatic transform > should hoist props for root with single element excluding comments 1`] = `
"const _Vue = Vue
const { createElementVNode: _createElementVNode, createCommentVNode: _createCommentVNode } = _Vue
const _hoisted_1 = { id: "a" }
return function render(_ctx, _cache) {
with (_ctx) {
const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createCommentVNode("comment"),
_createElementVNode("div", _hoisted_1, [...(_cache[0] || (_cache[0] = [
_createElementVNode("div", { id: "b" }, [
_createElementVNode("div", { id: "c" }, [
_createElementVNode("div", { id: "d" }, [
_createElementVNode("div", { id: "e" }, "hello")
])
])
], -1 /* CACHED */)
]))])
], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
}
}"
`;
exports[`compiler: cacheStatic transform > should hoist v-for children if static 1`] = ` exports[`compiler: cacheStatic transform > should hoist v-for children if static 1`] = `
"const _Vue = Vue "const _Vue = Vue
const { createElementVNode: _createElementVNode } = _Vue const { createElementVNode: _createElementVNode } = _Vue
@ -422,9 +448,9 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => { (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {
return (_openBlock(), _createElementBlock("div", _hoisted_1, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", _hoisted_1, [...(_cache[0] || (_cache[0] = [
_createElementVNode("span", null, null, -1 /* HOISTED */) _createElementVNode("span", null, null, -1 /* CACHED */)
]))) ]))]))
}), 256 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
])) ]))
} }

View File

@ -1,5 +1,23 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-memo transform > element v-for key expression prefixing + v-memo 1`] = `
"import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, isMemoSame as _isMemoSame, withMemo as _withMemo } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.tableData, (data, __, ___, _cached) => {
const _memo = (_ctx.getLetter(data))
if (_cached && _cached.key === _ctx.getId(data) && _isMemoSame(_cached, _memo)) return _cached
const _item = (_openBlock(), _createElementBlock("span", {
key: _ctx.getId(data)
}))
_item.memo = _memo
return _item
}, _cache, 0), 128 /* KEYED_FRAGMENT */))
]))
}"
`;
exports[`compiler: v-memo transform > on component 1`] = ` exports[`compiler: v-memo transform > on component 1`] = `
"import { resolveComponent as _resolveComponent, createVNode as _createVNode, withMemo as _withMemo, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue" "import { resolveComponent as _resolveComponent, createVNode as _createVNode, withMemo as _withMemo, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

View File

@ -8,7 +8,7 @@ return function render(_ctx, _cache) {
const { setBlockTracking: _setBlockTracking, createElementVNode: _createElementVNode } = _Vue const { setBlockTracking: _setBlockTracking, createElementVNode: _createElementVNode } = _Vue
return _cache[0] || ( return _cache[0] || (
_setBlockTracking(-1), _setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0, (_cache[0] = _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0,
_setBlockTracking(1), _setBlockTracking(1),
_cache[0] _cache[0]
@ -28,7 +28,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || ( _cache[0] || (
_setBlockTracking(-1), _setBlockTracking(-1, true),
(_cache[0] = _createVNode(_component_Comp, { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0, (_cache[0] = _createVNode(_component_Comp, { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0,
_setBlockTracking(1), _setBlockTracking(1),
_cache[0] _cache[0]
@ -47,7 +47,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || ( _cache[0] || (
_setBlockTracking(-1), _setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0, (_cache[0] = _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0,
_setBlockTracking(1), _setBlockTracking(1),
_cache[0] _cache[0]
@ -66,7 +66,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || ( _cache[0] || (
_setBlockTracking(-1), _setBlockTracking(-1, true),
(_cache[0] = _renderSlot($slots, "default")).cacheIndex = 0, (_cache[0] = _renderSlot($slots, "default")).cacheIndex = 0,
_setBlockTracking(1), _setBlockTracking(1),
_cache[0] _cache[0]
@ -85,7 +85,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [ return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || ( _cache[0] || (
_setBlockTracking(-1), _setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div")).cacheIndex = 0, (_cache[0] = _createElementVNode("div")).cacheIndex = 0,
_setBlockTracking(1), _setBlockTracking(1),
_cache[0] _cache[0]

View File

@ -139,6 +139,24 @@ return function render(_ctx, _cache) {
}" }"
`; `;
exports[`compiler: transform component slots > named slots w/ implicit default slot containing non-breaking space 1`] = `
"const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue
const _component_Comp = _resolveComponent("Comp")
return (_openBlock(), _createBlock(_component_Comp, null, {
one: _withCtx(() => ["foo"]),
default: _withCtx(() => ["   "]),
_: 1 /* STABLE */
}))
}
}"
`;
exports[`compiler: transform component slots > nested slots scoping 1`] = ` exports[`compiler: transform component slots > nested slots scoping 1`] = `
"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue "const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
@ -232,6 +250,20 @@ return function render(_ctx, _cache) {
}" }"
`; `;
exports[`compiler: transform component slots > with whitespace: 'preserve' > implicit default slot with non-breaking space 1`] = `
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent("Comp")
return (_openBlock(), _createBlock(_component_Comp, null, {
header: _withCtx(() => [" Header "]),
default: _withCtx(() => ["\\n  \\n "]),
_: 1 /* STABLE */
}))
}"
`;
exports[`compiler: transform component slots > with whitespace: 'preserve' > named default slot + implicit whitespace content 1`] = ` exports[`compiler: transform component slots > with whitespace: 'preserve' > named default slot + implicit whitespace content 1`] = `
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue "const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue
@ -246,6 +278,54 @@ return function render(_ctx, _cache) {
}" }"
`; `;
exports[`compiler: transform component slots > with whitespace: 'preserve' > named slot with v-if + v-else 1`] = `
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent("Comp")
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [
ok
? {
name: "one",
fn: _withCtx(() => ["foo"]),
key: "0"
}
: {
name: "two",
fn: _withCtx(() => ["baz"]),
key: "1"
}
]), 1024 /* DYNAMIC_SLOTS */))
}"
`;
exports[`compiler: transform component slots > with whitespace: 'preserve' > named slot with v-if + v-else and comments 1`] = `
"const { createTextVNode: _createTextVNode, createCommentVNode: _createCommentVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent("Comp")
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [
ok
? {
name: "one",
fn: _withCtx(() => [
_createTextVNode("foo")
]),
key: "0"
}
: {
name: "two",
fn: _withCtx(() => [
_createTextVNode("baz")
]),
key: "1"
}
]), 1024 /* DYNAMIC_SLOTS */))
}"
`;
exports[`compiler: transform component slots > with whitespace: 'preserve' > should not generate whitespace only default slot 1`] = ` exports[`compiler: transform component slots > with whitespace: 'preserve' > should not generate whitespace only default slot 1`] = `
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue "const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue

View File

@ -27,7 +27,7 @@ import { PatchFlags } from '@vue/shared'
const cachedChildrenArrayMatcher = ( const cachedChildrenArrayMatcher = (
tags: string[], tags: string[],
needArraySpread = false, needArraySpread = true,
) => ({ ) => ({
type: NodeTypes.JS_CACHE_EXPRESSION, type: NodeTypes.JS_CACHE_EXPRESSION,
needArraySpread, needArraySpread,
@ -533,6 +533,32 @@ describe('compiler: cacheStatic transform', () => {
expect(generate(root).code).toMatchSnapshot() expect(generate(root).code).toMatchSnapshot()
}) })
test('should hoist props for root with single element excluding comments', () => {
// deeply nested div to trigger stringification condition
const root = transformWithCache(
`<!--comment--><div id="a"><div id="b"><div id="c"><div id="d"><div id="e">hello</div></div></div></div></div>`,
)
expect(root.cached.length).toBe(1)
expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'a' })])
expect((root.codegenNode as VNodeCall).children).toMatchObject([
{
type: NodeTypes.COMMENT,
content: 'comment',
},
{
type: NodeTypes.ELEMENT,
codegenNode: {
type: NodeTypes.VNODE_CALL,
tag: `"div"`,
props: { content: `_hoisted_1` },
children: { type: NodeTypes.JS_CACHE_EXPRESSION },
},
},
])
expect(generate(root).code).toMatchSnapshot()
})
describe('prefixIdentifiers', () => { describe('prefixIdentifiers', () => {
test('cache nested static tree with static interpolation', () => { test('cache nested static tree with static interpolation', () => {
const root = transformWithCache( const root = transformWithCache(

View File

@ -716,4 +716,42 @@ describe('compiler: expression transform', () => {
}) })
}) })
}) })
describe('switch case variable declarations', () => {
test('should handle const declarations in switch case without braces', () => {
const { code } = compile(
`{{ (() => { switch (1) { case 1: const foo = "bar"; return \`\${foo}\`; } })() }}`,
)
expect(code).toMatch(`const foo = "bar";`)
expect(code).toMatch(`return \`\${foo}\`;`)
expect(code).not.toMatch(`_ctx.foo`)
})
test('should handle const declarations in switch case with braces (existing behavior)', () => {
const { code } = compile(
`{{ (() => {
switch (true) {
case true: {
const foo = "bar";
return \`\${foo}\`;
}
}
})() }}`,
)
expect(code).toMatch(`const foo = "bar";`)
expect(code).toMatch(`return \`\${foo}\`;`)
expect(code).not.toMatch(`_ctx.foo`)
})
test('should parse switch case test as local scoped variables', () => {
const { code } = compile(
`{{ (() => { switch (foo) { case bar: return \`\${bar}\`; } })() }}`,
)
expect(code).toMatch('_ctx.foo')
expect(code).toMatch(`_ctx.bar`)
})
})
}) })

View File

@ -4,6 +4,7 @@ import {
type ForNode, type ForNode,
NodeTypes, NodeTypes,
generate, generate,
isWhitespaceText,
baseParse as parse, baseParse as parse,
transform, transform,
} from '../../src' } from '../../src'
@ -109,6 +110,24 @@ describe('compiler: transform text', () => {
expect(generate(root).code).toMatchSnapshot() expect(generate(root).code).toMatchSnapshot()
}) })
test('whitespace text', () => {
const root = transformWithTextOpt(`<div/>hello<div/> <div/>`)
expect(root.children.length).toBe(5)
expect(root.children[0].type).toBe(NodeTypes.ELEMENT)
expect(root.children[1].type).toBe(NodeTypes.TEXT_CALL)
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
expect(root.children[3].type).toBe(NodeTypes.TEXT_CALL)
expect(root.children[4].type).toBe(NodeTypes.ELEMENT)
expect(root.children.map(isWhitespaceText)).toEqual([
false,
false,
false,
true,
false,
])
})
test('consecutive text mixed with elements', () => { test('consecutive text mixed with elements', () => {
const root = transformWithTextOpt( const root = transformWithTextOpt(
`<div/>{{ foo }} bar {{ baz }}<div/>hello<div/>`, `<div/>{{ foo }} bar {{ baz }}<div/>hello<div/>`,

View File

@ -17,6 +17,7 @@ import {
helperNameMap, helperNameMap,
} from '../../src/runtimeHelpers' } from '../../src/runtimeHelpers'
import { transformExpression } from '../../src/transforms/transformExpression' import { transformExpression } from '../../src/transforms/transformExpression'
import { transformVBindShorthand } from '../../src/transforms/transformVBindShorthand'
function parseWithVBind( function parseWithVBind(
template: string, template: string,
@ -25,6 +26,7 @@ function parseWithVBind(
const ast = parse(template) const ast = parse(template)
transform(ast, { transform(ast, {
nodeTransforms: [ nodeTransforms: [
transformVBindShorthand,
...(options.prefixIdentifiers ? [transformExpression] : []), ...(options.prefixIdentifiers ? [transformExpression] : []),
transformElement, transformElement,
], ],
@ -110,6 +112,27 @@ describe('compiler: transform v-bind', () => {
}) })
}) })
test('no expression (shorthand) in-DOM templates', () => {
try {
__BROWSER__ = true
// :id in in-DOM templates will be parsed into :id="" by browser
const node = parseWithVBind(`<div :id="" />`)
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
expect(props.properties[0]).toMatchObject({
key: {
content: `id`,
isStatic: true,
},
value: {
content: `id`,
isStatic: false,
},
})
} finally {
__BROWSER__ = false
}
})
test('dynamic arg', () => { test('dynamic arg', () => {
const node = parseWithVBind(`<div v-bind:[id]="id"/>`) const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
const props = (node.codegenNode as VNodeCall).props as CallExpression const props = (node.codegenNode as VNodeCall).props as CallExpression

View File

@ -21,6 +21,7 @@ import { type CompilerOptions, generate } from '../../src'
import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers' import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'
import { PatchFlags } from '@vue/shared' import { PatchFlags } from '@vue/shared'
import { createObjectMatcher } from '../testUtils' import { createObjectMatcher } from '../testUtils'
import { transformVBindShorthand } from '../../src/transforms/transformVBindShorthand'
export function parseWithForTransform( export function parseWithForTransform(
template: string, template: string,
@ -32,6 +33,7 @@ export function parseWithForTransform(
const ast = parse(template, options) const ast = parse(template, options)
transform(ast, { transform(ast, {
nodeTransforms: [ nodeTransforms: [
transformVBindShorthand,
transformIf, transformIf,
transformFor, transformFor,
...(options.prefixIdentifiers ? [transformExpression] : []), ...(options.prefixIdentifiers ? [transformExpression] : []),

View File

@ -17,7 +17,12 @@ import {
type VNodeCall, type VNodeCall,
} from '../../src/ast' } from '../../src/ast'
import { ErrorCodes } from '../../src/errors' import { ErrorCodes } from '../../src/errors'
import { type CompilerOptions, TO_HANDLERS, generate } from '../../src' import {
type CompilerOptions,
TO_HANDLERS,
generate,
transformVBindShorthand,
} from '../../src'
import { import {
CREATE_COMMENT, CREATE_COMMENT,
FRAGMENT, FRAGMENT,
@ -35,7 +40,12 @@ function parseWithIfTransform(
) { ) {
const ast = parse(template, options) const ast = parse(template, options)
transform(ast, { transform(ast, {
nodeTransforms: [transformIf, transformSlotOutlet, transformElement], nodeTransforms: [
transformVBindShorthand,
transformIf,
transformSlotOutlet,
transformElement,
],
...options, ...options,
}) })
if (!options.onError) { if (!options.onError) {
@ -209,6 +219,16 @@ describe('compiler: v-if', () => {
content: `_ctx.ok`, content: `_ctx.ok`,
}) })
}) })
//#11321
test('v-if + :key shorthand', () => {
const { node } = parseWithIfTransform(`<div v-if="ok" :key></div>`)
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches[0].userKey).toMatchObject({
arg: { content: 'key' },
exp: { content: 'key' },
})
})
}) })
describe('errors', () => { describe('errors', () => {
@ -246,6 +266,31 @@ describe('compiler: v-if', () => {
loc: node3.loc, loc: node3.loc,
}, },
]) ])
const { node: node4 } = parseWithIfTransform(
`<div v-if="bar"/>foo<div v-else/>`,
{ onError },
2,
)
expect(onError.mock.calls[3]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: node4.loc,
},
])
// Non-breaking space
const { node: node5 } = parseWithIfTransform(
`<div v-if="bar"/>\u00a0<div v-else/>`,
{ onError },
2,
)
expect(onError.mock.calls[4]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: node5.loc,
},
])
}) })
test('error on v-else-if missing adjacent v-if or v-else-if', () => { test('error on v-else-if missing adjacent v-if or v-else-if', () => {
@ -285,6 +330,31 @@ describe('compiler: v-if', () => {
}, },
]) ])
const { node: node4 } = parseWithIfTransform(
`<div v-if="bar"/>foo<div v-else-if="foo"/>`,
{ onError },
2,
)
expect(onError.mock.calls[3]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: node4.loc,
},
])
// Non-breaking space
const { node: node5 } = parseWithIfTransform(
`<div v-if="bar"/>\u00a0<div v-else-if="foo"/>`,
{ onError },
2,
)
expect(onError.mock.calls[4]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: node5.loc,
},
])
const { const {
node: { branches }, node: { branches },
} = parseWithIfTransform( } = parseWithIfTransform(
@ -293,7 +363,26 @@ describe('compiler: v-if', () => {
0, 0,
) )
expect(onError.mock.calls[3]).toMatchObject([ expect(onError.mock.calls[5]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: branches[branches.length - 1].loc,
},
])
})
test('error on adjacent v-else', () => {
const onError = vi.fn()
const {
node: { branches },
} = parseWithIfTransform(
`<div v-if="false"/><div v-else/><div v-else/>`,
{ onError },
0,
)
expect(onError.mock.calls[0]).toMatchObject([
{ {
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: branches[branches.length - 1].loc, loc: branches[branches.length - 1].loc,

View File

@ -53,4 +53,12 @@ describe('compiler: v-memo transform', () => {
), ),
).toMatchSnapshot() ).toMatchSnapshot()
}) })
test('element v-for key expression prefixing + v-memo', () => {
expect(
compile(
`<span v-for="data of tableData" :key="getId(data)" v-memo="getLetter(data)"></span>`,
),
).toMatchSnapshot()
})
}) })

View File

@ -582,5 +582,22 @@ describe('compiler: transform v-model', () => {
}), }),
) )
}) })
test('used on const binding', () => {
const onError = vi.fn()
parseWithVModel('<div v-model="c" />', {
onError,
bindingMetadata: {
c: BindingTypes.LITERAL_CONST,
},
})
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_V_MODEL_ON_CONST,
}),
)
})
}) })
}) })

View File

@ -28,8 +28,12 @@ import { createObjectMatcher } from '../testUtils'
import { PatchFlags } from '@vue/shared' import { PatchFlags } from '@vue/shared'
import { transformFor } from '../../src/transforms/vFor' import { transformFor } from '../../src/transforms/vFor'
import { transformIf } from '../../src/transforms/vIf' import { transformIf } from '../../src/transforms/vIf'
import { transformText } from '../../src/transforms/transformText'
function parseWithSlots(template: string, options: CompilerOptions = {}) { function parseWithSlots(
template: string,
options: CompilerOptions & { transformText?: boolean } = {},
) {
const ast = parse(template, { const ast = parse(template, {
whitespace: options.whitespace, whitespace: options.whitespace,
}) })
@ -43,6 +47,7 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
transformSlotOutlet, transformSlotOutlet,
transformElement, transformElement,
trackSlotScopes, trackSlotScopes,
...(options.transformText ? [transformText] : []),
], ],
directiveTransforms: { directiveTransforms: {
on: transformOn, on: transformOn,
@ -307,6 +312,40 @@ describe('compiler: transform component slots', () => {
expect(generate(root).code).toMatchSnapshot() expect(generate(root).code).toMatchSnapshot()
}) })
test('named slots w/ implicit default slot containing non-breaking space', () => {
const { root, slots } = parseWithSlots(
`<Comp>
\u00a0
<template #one>foo</template>
</Comp>`,
)
expect(slots).toMatchObject(
createSlotMatcher({
one: {
type: NodeTypes.JS_FUNCTION_EXPRESSION,
params: undefined,
returns: [
{
type: NodeTypes.TEXT,
content: `foo`,
},
],
},
default: {
type: NodeTypes.JS_FUNCTION_EXPRESSION,
params: undefined,
returns: [
{
type: NodeTypes.TEXT,
content: ` \u00a0 `,
},
],
},
}),
)
expect(generate(root).code).toMatchSnapshot()
})
test('dynamically named slots', () => { test('dynamically named slots', () => {
const { root, slots } = parseWithSlots( const { root, slots } = parseWithSlots(
`<Comp> `<Comp>
@ -478,7 +517,10 @@ describe('compiler: transform component slots', () => {
}) })
test('should only force dynamic slots when actually using scope vars w/ prefixIdentifiers: true', () => { test('should only force dynamic slots when actually using scope vars w/ prefixIdentifiers: true', () => {
function assertDynamicSlots(template: string, shouldForce: boolean) { function assertDynamicSlots(
template: string,
expectedPatchFlag?: PatchFlags,
) {
const { root } = parseWithSlots(template, { prefixIdentifiers: true }) const { root } = parseWithSlots(template, { prefixIdentifiers: true })
let flag: any let flag: any
if (root.children[0].type === NodeTypes.FOR) { if (root.children[0].type === NodeTypes.FOR) {
@ -491,8 +533,8 @@ describe('compiler: transform component slots', () => {
.children[0] as ComponentNode .children[0] as ComponentNode
flag = (innerComp.codegenNode as VNodeCall).patchFlag flag = (innerComp.codegenNode as VNodeCall).patchFlag
} }
if (shouldForce) { if (expectedPatchFlag) {
expect(flag).toBe(PatchFlags.DYNAMIC_SLOTS) expect(flag).toBe(expectedPatchFlag)
} else { } else {
expect(flag).toBeUndefined() expect(flag).toBeUndefined()
} }
@ -502,14 +544,13 @@ describe('compiler: transform component slots', () => {
`<div v-for="i in list"> `<div v-for="i in list">
<Comp v-slot="bar">foo</Comp> <Comp v-slot="bar">foo</Comp>
</div>`, </div>`,
false,
) )
assertDynamicSlots( assertDynamicSlots(
`<div v-for="i in list"> `<div v-for="i in list">
<Comp v-slot="bar">{{ i }}</Comp> <Comp v-slot="bar">{{ i }}</Comp>
</div>`, </div>`,
true, PatchFlags.DYNAMIC_SLOTS,
) )
// reference the component's own slot variable should not force dynamic slots // reference the component's own slot variable should not force dynamic slots
@ -517,14 +558,13 @@ describe('compiler: transform component slots', () => {
`<Comp v-slot="foo"> `<Comp v-slot="foo">
<Comp v-slot="bar">{{ bar }}</Comp> <Comp v-slot="bar">{{ bar }}</Comp>
</Comp>`, </Comp>`,
false,
) )
assertDynamicSlots( assertDynamicSlots(
`<Comp v-slot="foo"> `<Comp v-slot="foo">
<Comp v-slot="bar">{{ foo }}</Comp> <Comp v-slot="bar">{{ foo }}</Comp>
</Comp>`, </Comp>`,
true, PatchFlags.DYNAMIC_SLOTS,
) )
// #2564 // #2564
@ -532,14 +572,35 @@ describe('compiler: transform component slots', () => {
`<div v-for="i in list"> `<div v-for="i in list">
<Comp v-slot="bar"><button @click="fn(i)" /></Comp> <Comp v-slot="bar"><button @click="fn(i)" /></Comp>
</div>`, </div>`,
true, PatchFlags.DYNAMIC_SLOTS,
) )
assertDynamicSlots( assertDynamicSlots(
`<div v-for="i in list"> `<div v-for="i in list">
<Comp v-slot="bar"><button @click="fn()" /></Comp> <Comp v-slot="bar"><button @click="fn()" /></Comp>
</div>`, </div>`,
false, )
// #9380
assertDynamicSlots(
`<div v-for="i in list">
<Comp :i="i">foo</Comp>
</div>`,
PatchFlags.PROPS,
)
assertDynamicSlots(
`<div v-for="i in list">
<Comp v-slot="{ value = i }"><button @click="fn()" /></Comp>
</div>`,
PatchFlags.DYNAMIC_SLOTS,
)
assertDynamicSlots(
`<div v-for="i in list">
<Comp v-slot:[i]><button @click="fn()" /></Comp>
</div>`,
PatchFlags.DYNAMIC_SLOTS,
) )
}) })
@ -988,5 +1049,58 @@ describe('compiler: transform component slots', () => {
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot() expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
}) })
test('implicit default slot with non-breaking space', () => {
const source = `
<Comp>
&nbsp;
<template #header> Header </template>
</Comp>
`
const { root } = parseWithSlots(source, {
whitespace: 'preserve',
})
const slots = (root as any).children[0].codegenNode.children
.properties as ObjectExpression['properties']
expect(
slots.some(p => (p.key as SimpleExpressionNode).content === 'default'),
).toBe(true)
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
})
test('named slot with v-if + v-else', () => {
const source = `
<Comp>
<template #one v-if="ok">foo</template>
<template #two v-else>baz</template>
</Comp>
`
const { root } = parseWithSlots(source, {
whitespace: 'preserve',
})
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
})
test('named slot with v-if + v-else and comments', () => {
const source = `
<Comp>
<template #one v-if="ok">foo</template>
<!-- start -->
<!-- end -->
<template #two v-else>baz</template>
</Comp>
`
const { root } = parseWithSlots(source, {
transformText: true,
whitespace: 'preserve',
})
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
})
}) })
}) })

View File

@ -1,4 +1,9 @@
import type { ExpressionNode, TransformContext } from '../src' import { babelParse, walkIdentifiers } from '@vue/compiler-sfc'
import {
type ExpressionNode,
type TransformContext,
isReferencedIdentifier,
} from '../src'
import { type Position, createSimpleExpression } from '../src/ast' import { type Position, createSimpleExpression } from '../src/ast'
import { import {
advancePositionWithClone, advancePositionWithClone,
@ -115,3 +120,18 @@ test('toValidAssetId', () => {
'_component_test_2797935797_1', '_component_test_2797935797_1',
) )
}) })
describe('isReferencedIdentifier', () => {
test('identifiers in function parameters should not be inferred as references', () => {
expect.assertions(4)
const ast = babelParse(`(({ title }) => [])`)
walkIdentifiers(
ast.program.body[0],
(node, parent, parentStack, isReference) => {
expect(isReference).toBe(false)
expect(isReferencedIdentifier(node, parent, parentStack)).toBe(false)
},
true,
)
})
})

View File

@ -1,6 +1,6 @@
{ {
"name": "@vue/compiler-core", "name": "@vue/compiler-core",
"version": "3.5.4", "version": "3.5.26",
"description": "@vue/compiler-core", "description": "@vue/compiler-core",
"main": "index.js", "main": "index.js",
"module": "dist/compiler-core.esm-bundler.js", "module": "dist/compiler-core.esm-bundler.js",
@ -48,7 +48,7 @@
"dependencies": { "dependencies": {
"@babel/parser": "catalog:", "@babel/parser": "catalog:",
"@vue/shared": "workspace:*", "@vue/shared": "workspace:*",
"entities": "^4.5.0", "entities": "^7.0.0",
"estree-walker": "catalog:", "estree-walker": "catalog:",
"source-map-js": "catalog:" "source-map-js": "catalog:"
}, },

View File

@ -418,6 +418,7 @@ export interface CacheExpression extends Node {
index: number index: number
value: JSChildNode value: JSChildNode
needPauseTracking: boolean needPauseTracking: boolean
inVOnce: boolean
needArraySpread: boolean needArraySpread: boolean
} }
@ -774,12 +775,14 @@ export function createCacheExpression(
index: number, index: number,
value: JSChildNode, value: JSChildNode,
needPauseTracking: boolean = false, needPauseTracking: boolean = false,
inVOnce: boolean = false,
): CacheExpression { ): CacheExpression {
return { return {
type: NodeTypes.JS_CACHE_EXPRESSION, type: NodeTypes.JS_CACHE_EXPRESSION,
index, index,
value, value,
needPauseTracking: needPauseTracking, needPauseTracking: needPauseTracking,
inVOnce,
needArraySpread: false, needArraySpread: false,
loc: locStub, loc: locStub,
} }

View File

@ -10,6 +10,8 @@ import type {
Node, Node,
ObjectProperty, ObjectProperty,
Program, Program,
SwitchCase,
SwitchStatement,
} from '@babel/types' } from '@babel/types'
import { walk } from 'estree-walker' import { walk } from 'estree-walker'
@ -80,15 +82,32 @@ export function walkIdentifiers(
markScopeIdentifier(node, id, knownIds), markScopeIdentifier(node, id, knownIds),
) )
} }
} else if (node.type === 'SwitchStatement') {
if (node.scopeIds) {
node.scopeIds.forEach(id => markKnownIds(id, knownIds))
} else {
// record switch case block-level local variables
walkSwitchStatement(node, false, id =>
markScopeIdentifier(node, id, knownIds),
)
}
} else if (node.type === 'CatchClause' && node.param) { } else if (node.type === 'CatchClause' && node.param) {
if (node.scopeIds) {
node.scopeIds.forEach(id => markKnownIds(id, knownIds))
} else {
for (const id of extractIdentifiers(node.param)) { for (const id of extractIdentifiers(node.param)) {
markScopeIdentifier(node, id, knownIds) markScopeIdentifier(node, id, knownIds)
} }
}
} else if (isForStatement(node)) { } else if (isForStatement(node)) {
if (node.scopeIds) {
node.scopeIds.forEach(id => markKnownIds(id, knownIds))
} else {
walkForStatement(node, false, id => walkForStatement(node, false, id =>
markScopeIdentifier(node, id, knownIds), markScopeIdentifier(node, id, knownIds),
) )
} }
}
}, },
leave(node: Node & { scopeIds?: Set<string> }, parent: Node | null) { leave(node: Node & { scopeIds?: Set<string> }, parent: Node | null) {
parent && parentStack.pop() parent && parentStack.pop()
@ -122,7 +141,7 @@ export function isReferencedIdentifier(
return false return false
} }
if (isReferenced(id, parent)) { if (isReferenced(id, parent, parentStack[parentStack.length - 2])) {
return true return true
} }
@ -132,7 +151,8 @@ export function isReferencedIdentifier(
case 'AssignmentExpression': case 'AssignmentExpression':
case 'AssignmentPattern': case 'AssignmentPattern':
return true return true
case 'ObjectPattern': case 'ObjectProperty':
return parent.key !== id && isInDestructureAssignment(parent, parentStack)
case 'ArrayPattern': case 'ArrayPattern':
return isInDestructureAssignment(parent, parentStack) return isInDestructureAssignment(parent, parentStack)
} }
@ -186,10 +206,11 @@ export function walkFunctionParams(
} }
export function walkBlockDeclarations( export function walkBlockDeclarations(
block: BlockStatement | Program, block: BlockStatement | SwitchCase | Program,
onIdent: (node: Identifier) => void, onIdent: (node: Identifier) => void,
): void { ): void {
for (const stmt of block.body) { const body = block.type === 'SwitchCase' ? block.consequent : block.body
for (const stmt of body) {
if (stmt.type === 'VariableDeclaration') { if (stmt.type === 'VariableDeclaration') {
if (stmt.declare) continue if (stmt.declare) continue
for (const decl of stmt.declarations) { for (const decl of stmt.declarations) {
@ -205,6 +226,8 @@ export function walkBlockDeclarations(
onIdent(stmt.id) onIdent(stmt.id)
} else if (isForStatement(stmt)) { } else if (isForStatement(stmt)) {
walkForStatement(stmt, true, onIdent) walkForStatement(stmt, true, onIdent)
} else if (stmt.type === 'SwitchStatement') {
walkSwitchStatement(stmt, true, onIdent)
} }
} }
} }
@ -238,6 +261,28 @@ function walkForStatement(
} }
} }
function walkSwitchStatement(
stmt: SwitchStatement,
isVar: boolean,
onIdent: (id: Identifier) => void,
) {
for (const cs of stmt.cases) {
for (const stmt of cs.consequent) {
if (
stmt.type === 'VariableDeclaration' &&
(stmt.kind === 'var' ? isVar : !isVar)
) {
for (const decl of stmt.declarations) {
for (const id of extractIdentifiers(decl.id)) {
onIdent(id)
}
}
}
}
walkBlockDeclarations(cs, onIdent)
}
}
export function extractIdentifiers( export function extractIdentifiers(
param: Node, param: Node,
nodes: Identifier[] = [], nodes: Identifier[] = [],

View File

@ -119,8 +119,10 @@ enum NewlineType {
Unknown = -3, Unknown = -3,
} }
export interface CodegenContext export interface CodegenContext extends Omit<
extends Omit<Required<CodegenOptions>, 'bindingMetadata' | 'inline'> { Required<CodegenOptions>,
'bindingMetadata' | 'inline'
> {
source: string source: string
code: string code: string
line: number line: number
@ -188,8 +190,10 @@ function createCodegenContext(
name = content name = content
} }
} }
if (node.loc.source) {
addMapping(node.loc.start, name) addMapping(node.loc.start, name)
} }
}
if (newlineIndex === NewlineType.Unknown) { if (newlineIndex === NewlineType.Unknown) {
// multiple newlines, full iteration // multiple newlines, full iteration
advancePositionWithMutation(context, code) advancePositionWithMutation(context, code)
@ -225,7 +229,7 @@ function createCodegenContext(
context.column = code.length - newlineIndex context.column = code.length - newlineIndex
} }
} }
if (node && node.loc !== locStub) { if (node && node.loc !== locStub && node.loc.source) {
addMapping(node.loc.end) addMapping(node.loc.end)
} }
} }
@ -1017,7 +1021,9 @@ function genCacheExpression(node: CacheExpression, context: CodegenContext) {
push(`_cache[${node.index}] || (`) push(`_cache[${node.index}] || (`)
if (needPauseTracking) { if (needPauseTracking) {
indent() indent()
push(`${helper(SET_BLOCK_TRACKING)}(-1),`) push(`${helper(SET_BLOCK_TRACKING)}(-1`)
if (node.inVOnce) push(`, true`)
push(`),`)
newline() newline()
push(`(`) push(`(`)
} }

View File

@ -22,6 +22,7 @@ import { transformModel } from './transforms/vModel'
import { transformFilter } from './compat/transformFilter' import { transformFilter } from './compat/transformFilter'
import { ErrorCodes, createCompilerError, defaultOnError } from './errors' import { ErrorCodes, createCompilerError, defaultOnError } from './errors'
import { transformMemo } from './transforms/vMemo' import { transformMemo } from './transforms/vMemo'
import { transformVBindShorthand } from './transforms/transformVBindShorthand'
export type TransformPreset = [ export type TransformPreset = [
NodeTransform[], NodeTransform[],
@ -33,6 +34,7 @@ export function getBaseTransformPreset(
): TransformPreset { ): TransformPreset {
return [ return [
[ [
transformVBindShorthand,
transformOnce, transformOnce,
transformIf, transformIf,
transformMemo, transformMemo,

View File

@ -88,6 +88,7 @@ export enum ErrorCodes {
X_V_MODEL_MALFORMED_EXPRESSION, X_V_MODEL_MALFORMED_EXPRESSION,
X_V_MODEL_ON_SCOPE_VARIABLE, X_V_MODEL_ON_SCOPE_VARIABLE,
X_V_MODEL_ON_PROPS, X_V_MODEL_ON_PROPS,
X_V_MODEL_ON_CONST,
X_INVALID_EXPRESSION, X_INVALID_EXPRESSION,
X_KEEP_ALIVE_INVALID_CHILDREN, X_KEEP_ALIVE_INVALID_CHILDREN,
@ -176,6 +177,7 @@ export const errorMessages: Record<ErrorCodes, string> = {
[ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`, [ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`,
[ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`, [ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`,
[ErrorCodes.X_V_MODEL_ON_PROPS]: `v-model cannot be used on a prop, because local prop bindings are not writable.\nUse a v-bind binding combined with a v-on listener that emits update:x event instead.`, [ErrorCodes.X_V_MODEL_ON_PROPS]: `v-model cannot be used on a prop, because local prop bindings are not writable.\nUse a v-bind binding combined with a v-on listener that emits update:x event instead.`,
[ErrorCodes.X_V_MODEL_ON_CONST]: `v-model cannot be used on a const binding because it is not writable.`,
[ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `, [ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `,
[ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`, [ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`,
[ErrorCodes.X_VNODE_HOOKS]: `@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.`, [ErrorCodes.X_VNODE_HOOKS]: `@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.`,

View File

@ -66,6 +66,7 @@ export {
buildDirectiveArgs, buildDirectiveArgs,
type PropsExpression, type PropsExpression,
} from './transforms/transformElement' } from './transforms/transformElement'
export { transformVBindShorthand } from './transforms/transformVBindShorthand'
export { processSlotOutlet } from './transforms/transformSlotOutlet' export { processSlotOutlet } from './transforms/transformSlotOutlet'
export { getConstantType } from './transforms/cacheStatic' export { getConstantType } from './transforms/cacheStatic'
export { generateCodeFrame } from '@vue/shared' export { generateCodeFrame } from '@vue/shared'

View File

@ -20,8 +20,7 @@ export interface ErrorHandlingOptions {
} }
export interface ParserOptions export interface ParserOptions
extends ErrorHandlingOptions, extends ErrorHandlingOptions, CompilerCompatOptions {
CompilerCompatOptions {
/** /**
* Base mode is platform agnostic and only parses HTML-like template syntax, * Base mode is platform agnostic and only parses HTML-like template syntax,
* treating all tags the same way. Specific tag parsing behavior can be * treating all tags the same way. Specific tag parsing behavior can be
@ -52,6 +51,11 @@ export interface ParserOptions
* e.g. elements that should preserve whitespace inside, e.g. `<pre>` * e.g. elements that should preserve whitespace inside, e.g. `<pre>`
*/ */
isPreTag?: (tag: string) => boolean isPreTag?: (tag: string) => boolean
/**
* Elements that should ignore the first newline token per parinsg spec
* e.g. `<textarea>` and `<pre>`
*/
isIgnoreNewlineTag?: (tag: string) => boolean
/** /**
* Platform-specific built-in components e.g. `<Transition>` * Platform-specific built-in components e.g. `<Transition>`
*/ */
@ -212,7 +216,8 @@ interface SharedTransformCodegenOptions {
} }
export interface TransformOptions export interface TransformOptions
extends SharedTransformCodegenOptions, extends
SharedTransformCodegenOptions,
ErrorHandlingOptions, ErrorHandlingOptions,
CompilerCompatOptions { CompilerCompatOptions {
/** /**

View File

@ -40,11 +40,13 @@ import {
} from './errors' } from './errors'
import { import {
forAliasRE, forAliasRE,
isAllWhitespace,
isCoreComponent, isCoreComponent,
isSimpleIdentifier, isSimpleIdentifier,
isStaticArgOf, isStaticArgOf,
isVPre,
} from './utils' } from './utils'
import { decodeHTML } from 'entities/lib/decode.js' import { decodeHTML } from 'entities/decode'
import { import {
type ParserOptions as BabelOptions, type ParserOptions as BabelOptions,
parse, parse,
@ -72,6 +74,7 @@ export const defaultParserOptions: MergedParserOptions = {
getNamespace: () => Namespaces.HTML, getNamespace: () => Namespaces.HTML,
isVoidTag: NO, isVoidTag: NO,
isPreTag: NO, isPreTag: NO,
isIgnoreNewlineTag: NO,
isCustomElement: NO, isCustomElement: NO,
onError: defaultOnError, onError: defaultOnError,
onWarn: defaultOnWarn, onWarn: defaultOnWarn,
@ -245,7 +248,7 @@ const tokenizer = new Tokenizer(stack, {
ondirarg(start, end) { ondirarg(start, end) {
if (start === end) return if (start === end) return
const arg = getSlice(start, end) const arg = getSlice(start, end)
if (inVPre) { if (inVPre && !isVPre(currentProp!)) {
;(currentProp as AttributeNode).name += arg ;(currentProp as AttributeNode).name += arg
setLocEnd((currentProp as AttributeNode).nameLoc, end) setLocEnd((currentProp as AttributeNode).nameLoc, end)
} else { } else {
@ -261,7 +264,7 @@ const tokenizer = new Tokenizer(stack, {
ondirmodifier(start, end) { ondirmodifier(start, end) {
const mod = getSlice(start, end) const mod = getSlice(start, end)
if (inVPre) { if (inVPre && !isVPre(currentProp!)) {
;(currentProp as AttributeNode).name += '.' + mod ;(currentProp as AttributeNode).name += '.' + mod
setLocEnd((currentProp as AttributeNode).nameLoc, end) setLocEnd((currentProp as AttributeNode).nameLoc, end)
} else if ((currentProp as DirectiveNode).name === 'slot') { } else if ((currentProp as DirectiveNode).name === 'slot') {
@ -387,7 +390,7 @@ const tokenizer = new Tokenizer(stack, {
CompilerDeprecationTypes.COMPILER_V_BIND_SYNC, CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,
currentOptions, currentOptions,
currentProp.loc, currentProp.loc,
currentProp.rawName, currentProp.arg!.loc.source,
) )
) { ) {
currentProp.name = 'model' currentProp.name = 'model'
@ -633,7 +636,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
} }
// refine element type // refine element type
const { tag, ns } = el const { tag, ns, children } = el
if (!inVPre) { if (!inVPre) {
if (tag === 'slot') { if (tag === 'slot') {
el.tagType = ElementTypes.SLOT el.tagType = ElementTypes.SLOT
@ -646,8 +649,18 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
// whitespace management // whitespace management
if (!tokenizer.inRCDATA) { if (!tokenizer.inRCDATA) {
el.children = condenseWhitespace(el.children, el.tag) el.children = condenseWhitespace(children)
} }
if (ns === Namespaces.HTML && currentOptions.isIgnoreNewlineTag(tag)) {
// remove leading newline for <textarea> and <pre> per html spec
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody
const first = children[0]
if (first && first.type === NodeTypes.TEXT) {
first.content = first.content.replace(/^\r?\n/, '')
}
}
if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) { if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) {
inPre-- inPre--
} }
@ -821,10 +834,7 @@ function isUpperCase(c: number) {
} }
const windowsNewlineRE = /\r\n/g const windowsNewlineRE = /\r\n/g
function condenseWhitespace( function condenseWhitespace(nodes: TemplateChildNode[]): TemplateChildNode[] {
nodes: TemplateChildNode[],
tag?: string,
): TemplateChildNode[] {
const shouldCondense = currentOptions.whitespace !== 'preserve' const shouldCondense = currentOptions.whitespace !== 'preserve'
let removedWhitespace = false let removedWhitespace = false
for (let i = 0; i < nodes.length; i++) { for (let i = 0; i < nodes.length; i++) {
@ -869,26 +879,9 @@ function condenseWhitespace(
} }
} }
} }
if (inPre && tag && currentOptions.isPreTag(tag)) {
// remove leading newline per html spec
// https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element
const first = nodes[0]
if (first && first.type === NodeTypes.TEXT) {
first.content = first.content.replace(/^\r?\n/, '')
}
}
return removedWhitespace ? nodes.filter(Boolean) : nodes return removedWhitespace ? nodes.filter(Boolean) : nodes
} }
function isAllWhitespace(str: string) {
for (let i = 0; i < str.length; i++) {
if (!isWhitespace(str.charCodeAt(i))) {
return false
}
}
return true
}
function hasNewlineChar(str: string) { function hasNewlineChar(str: string) {
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i) const c = str.charCodeAt(i)
@ -930,6 +923,10 @@ function getLoc(start: number, end?: number): SourceLocation {
} }
} }
export function cloneLoc(loc: SourceLocation): SourceLocation {
return getLoc(loc.start.offset, loc.end.offset)
}
function setLocEnd(loc: SourceLocation, end: number) { function setLocEnd(loc: SourceLocation, end: number) {
loc.end = tokenizer.getPos(end) loc.end = tokenizer.getPos(end)
loc.source = getSlice(loc.start.offset, end) loc.source = getSlice(loc.start.offset, end)
@ -1049,7 +1046,7 @@ export function baseParse(input: string, options?: ParserOptions): RootNode {
`[@vue/compiler-core] decodeEntities option is passed but will be ` + `[@vue/compiler-core] decodeEntities option is passed but will be ` +
`ignored in non-browser builds.`, `ignored in non-browser builds.`,
) )
} else if (__BROWSER__ && !currentOptions.decodeEntities) { } else if (__BROWSER__ && !__TEST__ && !currentOptions.decodeEntities) {
throw new Error( throw new Error(
`[@vue/compiler-core] decodeEntities option is required in browser builds.`, `[@vue/compiler-core] decodeEntities option is required in browser builds.`,
) )

View File

@ -36,7 +36,7 @@ import {
EntityDecoder, EntityDecoder,
fromCodePoint, fromCodePoint,
htmlDecodeTree, htmlDecodeTree,
} from 'entities/lib/decode.js' } from 'entities/decode'
export enum ParseMode { export enum ParseMode {
BASE, BASE,
@ -296,14 +296,30 @@ export default class Tokenizer {
public getPos(index: number): Position { public getPos(index: number): Position {
let line = 1 let line = 1
let column = index + 1 let column = index + 1
for (let i = this.newlines.length - 1; i >= 0; i--) { const length = this.newlines.length
const newlineIndex = this.newlines[i] let j = -1
if (index > newlineIndex) { if (length > 100) {
line = i + 2 let l = -1
column = index - newlineIndex let r = length
while (l + 1 < r) {
const m = (l + r) >>> 1
this.newlines[m] < index ? (l = m) : (r = m)
}
j = l
} else {
for (let i = length - 1; i >= 0; i--) {
if (index > this.newlines[i]) {
j = i
break break
} }
} }
}
if (j >= 0) {
line = j + 2
column = index - this.newlines[j]
}
return { return {
column, column,
line, line,
@ -438,7 +454,7 @@ export default class Tokenizer {
// We have to parse entities in <title> and <textarea> tags. // We have to parse entities in <title> and <textarea> tags.
if (!__BROWSER__ && c === CharCodes.Amp) { if (!__BROWSER__ && c === CharCodes.Amp) {
this.startEntity() this.startEntity()
} else if (c === this.delimiterOpen[0]) { } else if (!this.inVPre && c === this.delimiterOpen[0]) {
// We also need to handle interpolation // We also need to handle interpolation
this.state = State.InterpolationOpen this.state = State.InterpolationOpen
this.delimiterIndex = 0 this.delimiterIndex = 0
@ -929,7 +945,7 @@ export default class Tokenizer {
this.buffer = input this.buffer = input
while (this.index < this.buffer.length) { while (this.index < this.buffer.length) {
const c = this.buffer.charCodeAt(this.index) const c = this.buffer.charCodeAt(this.index)
if (c === CharCodes.NewLine) { if (c === CharCodes.NewLine && this.state !== State.InEntity) {
this.newlines.push(this.index) this.newlines.push(this.index)
} }
switch (this.state) { switch (this.state) {

View File

@ -37,7 +37,7 @@ import {
helperNameMap, helperNameMap,
} from './runtimeHelpers' } from './runtimeHelpers'
import { isVSlot } from './utils' import { isVSlot } from './utils'
import { cacheStatic, isSingleElementRoot } from './transforms/cacheStatic' import { cacheStatic, getSingleElementRoot } from './transforms/cacheStatic'
import type { CompilerCompatOptions } from './compat/compatConfig' import type { CompilerCompatOptions } from './compat/compatConfig'
// There are two types of transforms: // There are two types of transforms:
@ -82,7 +82,8 @@ export interface ImportItem {
} }
export interface TransformContext export interface TransformContext
extends Required<Omit<TransformOptions, keyof CompilerCompatOptions>>, extends
Required<Omit<TransformOptions, keyof CompilerCompatOptions>>,
CompilerCompatOptions { CompilerCompatOptions {
selfName: string | null selfName: string | null
root: RootNode root: RootNode
@ -116,7 +117,7 @@ export interface TransformContext
addIdentifiers(exp: ExpressionNode | string): void addIdentifiers(exp: ExpressionNode | string): void
removeIdentifiers(exp: ExpressionNode | string): void removeIdentifiers(exp: ExpressionNode | string): void
hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode
cache(exp: JSChildNode, isVNode?: boolean): CacheExpression cache(exp: JSChildNode, isVNode?: boolean, inVOnce?: boolean): CacheExpression
constantCache: WeakMap<TemplateChildNode, ConstantTypes> constantCache: WeakMap<TemplateChildNode, ConstantTypes>
// 2.x Compat only // 2.x Compat only
@ -297,11 +298,12 @@ export function createTransformContext(
identifier.hoisted = exp identifier.hoisted = exp
return identifier return identifier
}, },
cache(exp, isVNode = false) { cache(exp, isVNode = false, inVOnce = false) {
const cacheExp = createCacheExpression( const cacheExp = createCacheExpression(
context.cached.length, context.cached.length,
exp, exp,
isVNode, isVNode,
inVOnce,
) )
context.cached.push(cacheExp) context.cached.push(cacheExp)
return cacheExp return cacheExp
@ -355,12 +357,12 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
const { helper } = context const { helper } = context
const { children } = root const { children } = root
if (children.length === 1) { if (children.length === 1) {
const child = children[0] const singleElementRootChild = getSingleElementRoot(root)
// if the single child is an element, turn it into a block. // if the single child is an element, turn it into a block.
if (isSingleElementRoot(root, child) && child.codegenNode) { if (singleElementRootChild && singleElementRootChild.codegenNode) {
// single element root is never hoisted so codegenNode will never be // single element root is never hoisted so codegenNode will never be
// SimpleExpressionNode // SimpleExpressionNode
const codegenNode = child.codegenNode const codegenNode = singleElementRootChild.codegenNode
if (codegenNode.type === NodeTypes.VNODE_CALL) { if (codegenNode.type === NodeTypes.VNODE_CALL) {
convertToBlock(codegenNode, context) convertToBlock(codegenNode, context)
} }
@ -369,7 +371,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
// - single <slot/>, IfNode, ForNode: already blocks. // - single <slot/>, IfNode, ForNode: already blocks.
// - single text node: always patched. // - single text node: always patched.
// root codegen falls through via genNode() // root codegen falls through via genNode()
root.codegenNode = child root.codegenNode = children[0]
} }
} else if (children.length > 1) { } else if (children.length > 1) {
// root has multiple nodes - return a fragment block. // root has multiple nodes - return a fragment block.

View File

@ -21,7 +21,13 @@ import {
getVNodeHelper, getVNodeHelper,
} from '../ast' } from '../ast'
import type { TransformContext } from '../transform' import type { TransformContext } from '../transform'
import { PatchFlags, isArray, isString, isSymbol } from '@vue/shared' import {
PatchFlagNames,
PatchFlags,
isArray,
isString,
isSymbol,
} from '@vue/shared'
import { findDir, isSlotOutlet } from '../utils' import { findDir, isSlotOutlet } from '../utils'
import { import {
GUARD_REACTIVE_PROPS, GUARD_REACTIVE_PROPS,
@ -38,20 +44,19 @@ export function cacheStatic(root: RootNode, context: TransformContext): void {
context, context,
// Root node is unfortunately non-hoistable due to potential parent // Root node is unfortunately non-hoistable due to potential parent
// fallthrough attributes. // fallthrough attributes.
isSingleElementRoot(root, root.children[0]), !!getSingleElementRoot(root),
) )
} }
export function isSingleElementRoot( export function getSingleElementRoot(
root: RootNode, root: RootNode,
child: TemplateChildNode, ): PlainElementNode | ComponentNode | TemplateNode | null {
): child is PlainElementNode | ComponentNode | TemplateNode { const children = root.children.filter(x => x.type !== NodeTypes.COMMENT)
const { children } = root return children.length === 1 &&
return ( children[0].type === NodeTypes.ELEMENT &&
children.length === 1 && !isSlotOutlet(children[0])
child.type === NodeTypes.ELEMENT && ? children[0]
!isSlotOutlet(child) : null
)
} }
function walk( function walk(
@ -107,6 +112,15 @@ function walk(
? ConstantTypes.NOT_CONSTANT ? ConstantTypes.NOT_CONSTANT
: getConstantType(child, context) : getConstantType(child, context)
if (constantType >= ConstantTypes.CAN_CACHE) { if (constantType >= ConstantTypes.CAN_CACHE) {
if (
child.codegenNode.type === NodeTypes.JS_CALL_EXPRESSION &&
child.codegenNode.arguments.length > 0
) {
child.codegenNode.arguments.push(
PatchFlags.CACHED +
(__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.CACHED]} */` : ``),
)
}
toCache.push(child) toCache.push(child)
continue continue
} }
@ -205,9 +219,13 @@ function walk(
// #6978, #7138, #7114 // #6978, #7138, #7114
// a cached children array inside v-for can caused HMR errors since // a cached children array inside v-for can caused HMR errors since
// it might be mutated when mounting the first item // it might be mutated when mounting the first item
if (inFor && context.hmr) { // #13221
// fix memory leak in cached array:
// cached vnodes get replaced by cloned ones during mountChildren,
// which bind DOM elements. These DOM references persist after unmount,
// preventing garbage collection. Array spread avoids mutating cached
// array, preventing memory leaks.
exp.needArraySpread = true exp.needArraySpread = true
}
return exp return exp
} }

View File

@ -594,11 +594,9 @@ export function buildProps(
hasDynamicKeys = true hasDynamicKeys = true
if (exp) { if (exp) {
if (isVBind) { if (isVBind) {
// #10696 in case a v-bind object contains ref if (__COMPAT__) {
pushRefVForMarker()
// have to merge early for compat build check // have to merge early for compat build check
pushMergeArg() pushMergeArg()
if (__COMPAT__) {
// 2.x v-bind object order compat // 2.x v-bind object order compat
if (__DEV__) { if (__DEV__) {
const hasOverridableKeys = mergeArgs.some(arg => { const hasOverridableKeys = mergeArgs.some(arg => {
@ -641,6 +639,9 @@ export function buildProps(
} }
} }
// #10696 in case a v-bind object contains ref
pushRefVForMarker()
pushMergeArg()
mergeArgs.push(exp) mergeArgs.push(exp)
} else { } else {
// v-on="obj" -> toHandlers(obj) // v-on="obj" -> toHandlers(obj)

View File

@ -24,7 +24,7 @@ import {
isStaticPropertyKey, isStaticPropertyKey,
walkIdentifiers, walkIdentifiers,
} from '../babelUtils' } from '../babelUtils'
import { advancePositionWithClone, isSimpleIdentifier } from '../utils' import { advancePositionWithClone, findDir, isSimpleIdentifier } from '../utils'
import { import {
genPropsAccessExp, genPropsAccessExp,
hasOwn, hasOwn,
@ -54,6 +54,7 @@ export const transformExpression: NodeTransform = (node, context) => {
) )
} else if (node.type === NodeTypes.ELEMENT) { } else if (node.type === NodeTypes.ELEMENT) {
// handle directives on element // handle directives on element
const memo = findDir(node, 'memo')
for (let i = 0; i < node.props.length; i++) { for (let i = 0; i < node.props.length; i++) {
const dir = node.props[i] const dir = node.props[i]
// do not process for v-on & v-for since they are special handled // do not process for v-on & v-for since they are special handled
@ -65,7 +66,14 @@ export const transformExpression: NodeTransform = (node, context) => {
if ( if (
exp && exp &&
exp.type === NodeTypes.SIMPLE_EXPRESSION && exp.type === NodeTypes.SIMPLE_EXPRESSION &&
!(dir.name === 'on' && arg) !(dir.name === 'on' && arg) &&
// key has been processed in transformFor(vMemo + vFor)
!(
memo &&
arg &&
arg.type === NodeTypes.SIMPLE_EXPRESSION &&
arg.content === 'key'
)
) { ) {
dir.exp = processExpression( dir.exp = processExpression(
exp, exp,

View File

@ -0,0 +1,48 @@
import { camelize } from '@vue/shared'
import {
NodeTypes,
type SimpleExpressionNode,
createSimpleExpression,
} from '../ast'
import type { NodeTransform } from '../transform'
import { ErrorCodes, createCompilerError } from '../errors'
import { validFirstIdentCharRE } from '../utils'
export const transformVBindShorthand: NodeTransform = (node, context) => {
if (node.type === NodeTypes.ELEMENT) {
for (const prop of node.props) {
// same-name shorthand - :arg is expanded to :arg="arg"
if (
prop.type === NodeTypes.DIRECTIVE &&
prop.name === 'bind' &&
(!prop.exp ||
// #13930 :foo in in-DOM templates will be parsed into :foo="" by browser
(__BROWSER__ &&
prop.exp.type === NodeTypes.SIMPLE_EXPRESSION &&
!prop.exp.content.trim())) &&
prop.arg
) {
const arg = prop.arg
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION || !arg.isStatic) {
// only simple expression is allowed for same-name shorthand
context.onError(
createCompilerError(
ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
arg.loc,
),
)
prop.exp = createSimpleExpression('', true, arg.loc)
} else {
const propName = camelize((arg as SimpleExpressionNode).content)
if (
validFirstIdentCharRE.test(propName[0]) ||
// allow hyphen first char for https://github.com/vuejs/language-tools/pull/3424
propName[0] === '-'
) {
prop.exp = createSimpleExpression(propName, false, arg.loc)
}
}
}
}
}
}

View File

@ -1,18 +1,15 @@
import type { DirectiveTransform, TransformContext } from '../transform' import type { DirectiveTransform } from '../transform'
import { import {
type DirectiveNode,
type ExpressionNode, type ExpressionNode,
NodeTypes, NodeTypes,
type SimpleExpressionNode,
createObjectProperty, createObjectProperty,
createSimpleExpression, createSimpleExpression,
} from '../ast' } from '../ast'
import { ErrorCodes, createCompilerError } from '../errors' import { ErrorCodes, createCompilerError } from '../errors'
import { camelize } from '@vue/shared' import { camelize } from '@vue/shared'
import { CAMELIZE } from '../runtimeHelpers' import { CAMELIZE } from '../runtimeHelpers'
import { processExpression } from './transformExpression'
// v-bind without arg is handled directly in ./transformElements.ts due to it affecting // v-bind without arg is handled directly in ./transformElement.ts due to its affecting
// codegen for the entire props object. This transform here is only for v-bind // codegen for the entire props object. This transform here is only for v-bind
// *with* args. // *with* args.
export const transformBind: DirectiveTransform = (dir, _node, context) => { export const transformBind: DirectiveTransform = (dir, _node, context) => {
@ -40,32 +37,11 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
} }
} }
// same-name shorthand - :arg is expanded to :arg="arg"
if (!exp) {
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION || !arg.isStatic) {
// only simple expression is allowed for same-name shorthand
context.onError(
createCompilerError(
ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
arg.loc,
),
)
return {
props: [
createObjectProperty(arg, createSimpleExpression('', true, loc)),
],
}
}
transformBindShorthand(dir, context)
exp = dir.exp!
}
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) { if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) {
arg.children.unshift(`(`) arg.children.unshift(`(`)
arg.children.push(`) || ""`) arg.children.push(`) || ""`)
} else if (!arg.isStatic) { } else if (!arg.isStatic) {
arg.content = `${arg.content} || ""` arg.content = arg.content ? `${arg.content} || ""` : `""`
} }
// .sync is replaced by v-model:arg // .sync is replaced by v-model:arg
@ -92,20 +68,7 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
} }
return { return {
props: [createObjectProperty(arg, exp)], props: [createObjectProperty(arg, exp!)],
}
}
export const transformBindShorthand = (
dir: DirectiveNode,
context: TransformContext,
): void => {
const arg = dir.arg!
const propName = camelize((arg as SimpleExpressionNode).content)
dir.exp = createSimpleExpression(propName, false, arg.loc)
if (!__BROWSER__) {
dir.exp = processExpression(dir.exp, context)
} }
} }

View File

@ -48,7 +48,6 @@ import {
import { processExpression } from './transformExpression' import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression' import { validateBrowserExpression } from '../validateExpression'
import { PatchFlags } from '@vue/shared' import { PatchFlags } from '@vue/shared'
import { transformBindShorthand } from './vBind'
export const transformFor: NodeTransform = createStructuralDirectiveTransform( export const transformFor: NodeTransform = createStructuralDirectiveTransform(
'for', 'for',
@ -63,17 +62,23 @@ export const transformFor: NodeTransform = createStructuralDirectiveTransform(
const isTemplate = isTemplateNode(node) const isTemplate = isTemplateNode(node)
const memo = findDir(node, 'memo') const memo = findDir(node, 'memo')
const keyProp = findProp(node, `key`, false, true) const keyProp = findProp(node, `key`, false, true)
if (keyProp && keyProp.type === NodeTypes.DIRECTIVE && !keyProp.exp) { const isDirKey = keyProp && keyProp.type === NodeTypes.DIRECTIVE
// resolve :key shorthand #10882 let keyExp =
transformBindShorthand(keyProp, context)
}
const keyExp =
keyProp && keyProp &&
(keyProp.type === NodeTypes.ATTRIBUTE (keyProp.type === NodeTypes.ATTRIBUTE
? keyProp.value ? keyProp.value
? createSimpleExpression(keyProp.value.content, true) ? createSimpleExpression(keyProp.value.content, true)
: undefined : undefined
: keyProp.exp) : keyProp.exp)
if (memo && keyExp && isDirKey) {
if (!__BROWSER__) {
keyProp.exp = keyExp = processExpression(
keyExp as SimpleExpressionNode,
context,
)
}
}
const keyProperty = const keyProperty =
keyProp && keyExp ? createObjectProperty(`key`, keyExp) : null keyProp && keyExp ? createObjectProperty(`key`, keyExp) : null
@ -253,7 +258,7 @@ export function processFor(
dir: DirectiveNode, dir: DirectiveNode,
context: TransformContext, context: TransformContext,
processCodegen?: (forNode: ForNode) => (() => void) | undefined, processCodegen?: (forNode: ForNode) => (() => void) | undefined,
) { ): (() => void) | undefined {
if (!dir.exp) { if (!dir.exp) {
context.onError( context.onError(
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc), createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc),

View File

@ -30,12 +30,19 @@ import {
import { ErrorCodes, createCompilerError } from '../errors' import { ErrorCodes, createCompilerError } from '../errors'
import { processExpression } from './transformExpression' import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression' import { validateBrowserExpression } from '../validateExpression'
import { cloneLoc } from '../parser'
import { CREATE_COMMENT, FRAGMENT } from '../runtimeHelpers' import { CREATE_COMMENT, FRAGMENT } from '../runtimeHelpers'
import { findDir, findProp, getMemoedVNodeCall, injectProp } from '../utils' import {
findDir,
findProp,
getMemoedVNodeCall,
injectProp,
isCommentOrWhitespace,
} from '../utils'
import { PatchFlags } from '@vue/shared' import { PatchFlags } from '@vue/shared'
export const transformIf: NodeTransform = createStructuralDirectiveTransform( export const transformIf: NodeTransform = createStructuralDirectiveTransform(
/^(if|else|else-if)$/, /^(?:if|else|else-if)$/,
(node, dir, context) => { (node, dir, context) => {
return processIf(node, dir, context, (ifNode, branch, isRoot) => { return processIf(node, dir, context, (ifNode, branch, isRoot) => {
// #1587: We need to dynamically increment the key based on the current // #1587: We need to dynamically increment the key based on the current
@ -110,7 +117,7 @@ export function processIf(
const branch = createIfBranch(node, dir) const branch = createIfBranch(node, dir)
const ifNode: IfNode = { const ifNode: IfNode = {
type: NodeTypes.IF, type: NodeTypes.IF,
loc: node.loc, loc: cloneLoc(node.loc),
branches: [branch], branches: [branch],
} }
context.replaceNode(ifNode) context.replaceNode(ifNode)
@ -124,25 +131,18 @@ export function processIf(
let i = siblings.indexOf(node) let i = siblings.indexOf(node)
while (i-- >= -1) { while (i-- >= -1) {
const sibling = siblings[i] const sibling = siblings[i]
if (sibling && sibling.type === NodeTypes.COMMENT) { if (sibling && isCommentOrWhitespace(sibling)) {
context.removeNode(sibling) context.removeNode(sibling)
__DEV__ && comments.unshift(sibling) if (__DEV__ && sibling.type === NodeTypes.COMMENT) {
continue comments.unshift(sibling)
} }
if (
sibling &&
sibling.type === NodeTypes.TEXT &&
!sibling.content.trim().length
) {
context.removeNode(sibling)
continue continue
} }
if (sibling && sibling.type === NodeTypes.IF) { if (sibling && sibling.type === NodeTypes.IF) {
// Check if v-else was followed by v-else-if // Check if v-else was followed by v-else-if or there are two adjacent v-else
if ( if (
dir.name === 'else-if' && (dir.name === 'else-if' || dir.name === 'else') &&
sibling.branches[sibling.branches.length - 1].condition === undefined sibling.branches[sibling.branches.length - 1].condition === undefined
) { ) {
context.onError( context.onError(

View File

@ -16,7 +16,7 @@ const seen = new WeakSet()
export const transformMemo: NodeTransform = (node, context) => { export const transformMemo: NodeTransform = (node, context) => {
if (node.type === NodeTypes.ELEMENT) { if (node.type === NodeTypes.ELEMENT) {
const dir = findDir(node, 'memo') const dir = findDir(node, 'memo')
if (!dir || seen.has(node)) { if (!dir || seen.has(node) || context.inSSR) {
return return
} }
seen.add(node) seen.add(node)

View File

@ -31,7 +31,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
// we assume v-model directives are always parsed // we assume v-model directives are always parsed
// (not artificially created by a transform) // (not artificially created by a transform)
const rawExp = exp.loc.source const rawExp = exp.loc.source.trim()
const expString = const expString =
exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp
@ -48,6 +48,15 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
return createTransformProps() return createTransformProps()
} }
// const bindings are not writable.
if (
bindingType === BindingTypes.LITERAL_CONST ||
bindingType === BindingTypes.SETUP_CONST
) {
context.onError(createCompilerError(ErrorCodes.X_V_MODEL_ON_CONST, exp.loc))
return createTransformProps()
}
const maybeRef = const maybeRef =
!__BROWSER__ && !__BROWSER__ &&
context.inline && context.inline &&

View File

@ -17,7 +17,7 @@ import { hasScopeRef, isFnExpression, isMemberExpression } from '../utils'
import { TO_HANDLER_KEY } from '../runtimeHelpers' import { TO_HANDLER_KEY } from '../runtimeHelpers'
export interface VOnDirectiveNode extends DirectiveNode { export interface VOnDirectiveNode extends DirectiveNode {
// v-on without arg is handled directly in ./transformElements.ts due to it affecting // v-on without arg is handled directly in ./transformElement.ts due to its affecting
// codegen for the entire props object. This transform here is only for v-on // codegen for the entire props object. This transform here is only for v-on
// *with* args. // *with* args.
arg: ExpressionNode arg: ExpressionNode

View File

@ -17,7 +17,11 @@ export const transformOnce: NodeTransform = (node, context) => {
context.inVOnce = false context.inVOnce = false
const cur = context.currentNode as ElementNode | IfNode | ForNode const cur = context.currentNode as ElementNode | IfNode | ForNode
if (cur.codegenNode) { if (cur.codegenNode) {
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */) cur.codegenNode = context.cache(
cur.codegenNode,
true /* isVNode */,
true /* inVOnce */,
)
} }
} }
} }

View File

@ -26,9 +26,11 @@ import {
assert, assert,
findDir, findDir,
hasScopeRef, hasScopeRef,
isCommentOrWhitespace,
isStaticExp, isStaticExp,
isTemplateNode, isTemplateNode,
isVSlot, isVSlot,
isWhitespaceText,
} from '../utils' } from '../utils'
import { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers' import { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers'
import { createForLoopParams, finalizeForParseResult } from './vFor' import { createForLoopParams, finalizeForParseResult } from './vFor'
@ -131,9 +133,17 @@ export function buildSlots(
// since it likely uses a scope variable. // since it likely uses a scope variable.
let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0
// with `prefixIdentifiers: true`, this can be further optimized to make // with `prefixIdentifiers: true`, this can be further optimized to make
// it dynamic only when the slot actually uses the scope variables. // it dynamic when
// 1. the slot arg or exp uses the scope variables.
// 2. the slot children use the scope variables.
if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) { if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) {
hasDynamicSlots = hasScopeRef(node, context.identifiers) hasDynamicSlots =
node.props.some(
prop =>
isVSlot(prop) &&
(hasScopeRef(prop.arg, context.identifiers) ||
hasScopeRef(prop.exp, context.identifiers)),
) || children.some(child => hasScopeRef(child, context.identifiers))
} }
// 1. Check for slot with slotProps on component itself. // 1. Check for slot with slotProps on component itself.
@ -215,18 +225,18 @@ export function buildSlots(
), ),
) )
} else if ( } else if (
(vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */)) (vElse = findDir(slotElement, /^else(?:-if)?$/, true /* allowEmpty */))
) { ) {
// find adjacent v-if // find adjacent v-if
let j = i let j = i
let prev let prev
while (j--) { while (j--) {
prev = children[j] prev = children[j]
if (prev.type !== NodeTypes.COMMENT) { if (!isCommentOrWhitespace(prev)) {
break break
} }
} }
if (prev && isTemplateNode(prev) && findDir(prev, /^(else-)?if$/)) { if (prev && isTemplateNode(prev) && findDir(prev, /^(?:else-)?if$/)) {
__TEST__ && assert(dynamicSlots.length > 0) __TEST__ && assert(dynamicSlots.length > 0)
// attach this slot to previous conditional // attach this slot to previous conditional
let conditional = dynamicSlots[ let conditional = dynamicSlots[
@ -319,7 +329,7 @@ export function buildSlots(
// #3766 // #3766
// with whitespace: 'preserve', whitespaces between slots will end up in // with whitespace: 'preserve', whitespaces between slots will end up in
// implicitDefaultChildren. Ignore if all implicit children are whitespaces. // implicitDefaultChildren. Ignore if all implicit children are whitespaces.
implicitDefaultChildren.some(node => isNonWhitespaceContent(node)) !implicitDefaultChildren.every(isWhitespaceText)
) { ) {
// implicit default slot (mixed with named slots) // implicit default slot (mixed with named slots)
if (hasNamedDefaultSlot) { if (hasNamedDefaultSlot) {
@ -342,7 +352,6 @@ export function buildSlots(
: hasForwardedSlots(node.children) : hasForwardedSlots(node.children)
? SlotFlags.FORWARDED ? SlotFlags.FORWARDED
: SlotFlags.STABLE : SlotFlags.STABLE
let slots = createObjectExpression( let slots = createObjectExpression(
slotsProperties.concat( slotsProperties.concat(
createObjectProperty( createObjectProperty(
@ -412,11 +421,3 @@ function hasForwardedSlots(children: TemplateChildNode[]): boolean {
} }
return false return false
} }
function isNonWhitespaceContent(node: TemplateChildNode): boolean {
if (node.type !== NodeTypes.TEXT && node.type !== NodeTypes.TEXT_CALL)
return true
return node.type === NodeTypes.TEXT
? !!node.content.trim()
: isNonWhitespaceContent(node.content)
}

View File

@ -42,6 +42,7 @@ import type { PropsExpression } from './transforms/transformElement'
import { parseExpression } from '@babel/parser' import { parseExpression } from '@babel/parser'
import type { Expression, Node } from '@babel/types' import type { Expression, Node } from '@babel/types'
import { unwrapTSNode } from './babelUtils' import { unwrapTSNode } from './babelUtils'
import { isWhitespace } from './tokenizer'
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode => export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic
@ -63,7 +64,7 @@ export function isCoreComponent(tag: string): symbol | void {
} }
} }
const nonIdentifierRE = /^\d|[^\$\w\xA0-\uFFFF]/ const nonIdentifierRE = /^$|^\d|[^\$\w\xA0-\uFFFF]/
export const isSimpleIdentifier = (name: string): boolean => export const isSimpleIdentifier = (name: string): boolean =>
!nonIdentifierRE.test(name) !nonIdentifierRE.test(name)
@ -74,7 +75,7 @@ enum MemberExpLexState {
inString, inString,
} }
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/ export const validFirstIdentCharRE: RegExp = /[A-Za-z_$\xA0-\uFFFF]/
const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/ const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/
const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g
@ -189,7 +190,7 @@ export const isMemberExpression: (
) => boolean = __BROWSER__ ? isMemberExpressionBrowser : isMemberExpressionNode ) => boolean = __BROWSER__ ? isMemberExpressionBrowser : isMemberExpressionNode
const fnExpRE = const fnExpRE =
/^\s*(async\s*)?(\([^)]*?\)|[\w$_]+)\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/ /^\s*(?:async\s*)?(?:\([^)]*?\)|[\w$_]+)\s*(?::[^=]+)?=>|^\s*(?:async\s+)?function(?:\s+[\w$]+)?\s*\(/
export const isFnExpressionBrowser: (exp: ExpressionNode) => boolean = exp => export const isFnExpressionBrowser: (exp: ExpressionNode) => boolean = exp =>
fnExpRE.test(getExpSource(exp)) fnExpRE.test(getExpSource(exp))
@ -343,6 +344,10 @@ export function isText(
return node.type === NodeTypes.INTERPOLATION || node.type === NodeTypes.TEXT return node.type === NodeTypes.INTERPOLATION || node.type === NodeTypes.TEXT
} }
export function isVPre(p: ElementNode['props'][0]): p is DirectiveNode {
return p.type === NodeTypes.DIRECTIVE && p.name === 'pre'
}
export function isVSlot(p: ElementNode['props'][0]): p is DirectiveNode { export function isVSlot(p: ElementNode['props'][0]): p is DirectiveNode {
return p.type === NodeTypes.DIRECTIVE && p.name === 'slot' return p.type === NodeTypes.DIRECTIVE && p.name === 'slot'
} }
@ -564,3 +569,23 @@ export function getMemoedVNodeCall(
} }
export const forAliasRE: RegExp = /([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/ export const forAliasRE: RegExp = /([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/
export function isAllWhitespace(str: string): boolean {
for (let i = 0; i < str.length; i++) {
if (!isWhitespace(str.charCodeAt(i))) {
return false
}
}
return true
}
export function isWhitespaceText(node: TemplateChildNode): boolean {
return (
(node.type === NodeTypes.TEXT && isAllWhitespace(node.content)) ||
(node.type === NodeTypes.TEXT_CALL && isWhitespaceText(node.content))
)
}
export function isCommentOrWhitespace(node: TemplateChildNode): boolean {
return node.type === NodeTypes.COMMENT || isWhitespaceText(node)
}

View File

@ -32,6 +32,22 @@ describe('DOM parser', () => {
}) })
}) })
test('<textarea> should remove leading newline', () => {
const ast = parse('<textarea>\nhello</textarea>', parserOptions)
const element = ast.children[0] as ElementNode
const text = element.children[0] as TextNode
expect(element.children.length).toBe(1)
expect(text).toStrictEqual({
type: NodeTypes.TEXT,
content: 'hello',
loc: {
start: { offset: 10, line: 1, column: 11 },
end: { offset: 16, line: 2, column: 6 },
source: '\nhello',
},
})
})
test('should not treat Uppercase component as special tag', () => { test('should not treat Uppercase component as special tag', () => {
const ast = parse( const ast = parse(
'<TextArea>some<div>text</div>and<!--comment--></TextArea>', '<TextArea>some<div>text</div>and<!--comment--></TextArea>',

View File

@ -135,6 +135,18 @@ describe('Transition multi children warnings', () => {
false, false,
) )
}) })
test('non-breaking spaces are treated as normal text', () => {
checkWarning(
`
<transition>
\u00a0
<div>foo</div>
</transition>
`,
true,
)
})
}) })
test('inject persisted when child has v-show', () => { test('inject persisted when child has v-show', () => {
@ -164,3 +176,19 @@ test('the v-if/else-if/else branches in Transition should ignore comments', () =
`).code, `).code,
).toMatchSnapshot() ).toMatchSnapshot()
}) })
test('comments and preserved whitespace are ignored', () => {
expect(
compile(
`
<transition>
<!-- foo --> <!-- bar -->
<div>foo bar</div>
</transition>
`,
{
whitespace: 'preserve',
},
).code,
).toMatchSnapshot()
})

View File

@ -1,5 +1,22 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`comments and preserved whitespace are ignored 1`] = `
"const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, Transition: _Transition, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue
return (_openBlock(), _createBlock(_Transition, null, {
default: _withCtx(() => [
_createElementVNode("div", null, "foo bar")
]),
_: 1 /* STABLE */
}))
}
}"
`;
exports[`inject persisted when child has v-show 1`] = ` exports[`inject persisted when child has v-show 1`] = `
"const _Vue = Vue "const _Vue = Vue

View File

@ -1,12 +1,42 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`stringify static html > eligible content (elements > 20) + non-eligible content 1`] = `
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>", 20),
_createElementVNode("div", { key: "1" }, "1", -1 /* CACHED */),
_createStaticVNode("<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>", 20)
]))]))
}"
`;
exports[`stringify static html > eligible content + v-once node 1`] = `
"const { setBlockTracking: _setBlockTracking, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || (
_setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div", null, [
_createTextVNode(_toDisplayString(_ctx.msg), 1 /* TEXT */)
])).cacheIndex = 0,
_setBlockTracking(1),
_cache[0]
),
_cache[1] || (_cache[1] = _createStaticVNode("<span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span>", 5))
]))
}"
`;
exports[`stringify static html > escape 1`] = ` exports[`stringify static html > escape 1`] = `
"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<div><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span></div>", 1) _createStaticVNode("<div><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span><span class=\\"foo&gt;ar\\">1 + &lt;</span><span>&amp;</span></div>", 1)
]))) ]))]))
}" }"
`; `;
@ -14,9 +44,36 @@ exports[`stringify static html > serializing constant bindings 1`] = `
"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<div style=\\"color:red;\\"><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span></div>", 1) _createStaticVNode("<div style=\\"color:red;\\"><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span></div>", 1)
]))) ]))]))
}"
`;
exports[`stringify static html > serializing template string style 1`] = `
"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<div style=\\"color:red;\\"><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span></div>", 1)
]))]))
}"
`;
exports[`stringify static html > should bail for <option> elements with null values 1`] = `
"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("select", null, [
_createElementVNode("option", { value: null }),
_createElementVNode("option", { value: "1" }),
_createElementVNode("option", { value: "1" }),
_createElementVNode("option", { value: "1" }),
_createElementVNode("option", { value: "1" }),
_createElementVNode("option", { value: "1" })
], -1 /* CACHED */)
]))]))
}" }"
`; `;
@ -24,15 +81,31 @@ exports[`stringify static html > should bail for <option> elements with number v
"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("select", null, [ _createElementVNode("select", null, [
_createElementVNode("option", { value: 1 }), _createElementVNode("option", { value: 1 }),
_createElementVNode("option", { value: 1 }), _createElementVNode("option", { value: 1 }),
_createElementVNode("option", { value: 1 }), _createElementVNode("option", { value: 1 }),
_createElementVNode("option", { value: 1 }), _createElementVNode("option", { value: 1 }),
_createElementVNode("option", { value: 1 }) _createElementVNode("option", { value: 1 })
], -1 /* HOISTED */) ], -1 /* CACHED */)
]))) ]))]))
}"
`;
exports[`stringify static html > should bail for comments 1`] = `
"const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
const _hoisted_1 = { class: "a" }
return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createCommentVNode(" Comment 1 "),
_createElementVNode("div", _hoisted_1, [
_createCommentVNode(" Comment 2 "),
_cache[0] || (_cache[0] = _createStaticVNode("<span class=\\"b\\"></span><span class=\\"b\\"></span><span class=\\"b\\"></span><span class=\\"b\\"></span><span class=\\"b\\"></span>", 5))
])
], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
}" }"
`; `;
@ -40,7 +113,7 @@ exports[`stringify static html > should bail on bindings that are cached but not
"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createElementVNode("div", null, [ _createElementVNode("div", null, [
_createElementVNode("span", { class: "foo" }, "foo"), _createElementVNode("span", { class: "foo" }, "foo"),
_createElementVNode("span", { class: "foo" }, "foo"), _createElementVNode("span", { class: "foo" }, "foo"),
@ -48,8 +121,8 @@ return function render(_ctx, _cache) {
_createElementVNode("span", { class: "foo" }, "foo"), _createElementVNode("span", { class: "foo" }, "foo"),
_createElementVNode("span", { class: "foo" }, "foo"), _createElementVNode("span", { class: "foo" }, "foo"),
_createElementVNode("img", { src: _imports_0_ }) _createElementVNode("img", { src: _imports_0_ })
], -1 /* HOISTED */) ], -1 /* CACHED */)
]))) ]))]))
}" }"
`; `;
@ -57,9 +130,9 @@ exports[`stringify static html > should work for <option> elements with string v
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<select><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option></select>", 1) _createStaticVNode("<select><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option></select>", 1)
]))) ]))]))
}" }"
`; `;
@ -67,9 +140,9 @@ exports[`stringify static html > should work for multiple adjacent nodes 1`] = `
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span>", 5) _createStaticVNode("<span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span>", 5)
]))) ]))]))
}" }"
`; `;
@ -77,9 +150,9 @@ exports[`stringify static html > should work on eligible content (elements > 20)
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>", 1) _createStaticVNode("<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>", 1)
]))) ]))]))
}" }"
`; `;
@ -87,9 +160,9 @@ exports[`stringify static html > should work on eligible content (elements with
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<div><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span></div>", 1) _createStaticVNode("<div><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span><span class=\\"foo\\"></span></div>", 1)
]))) ]))]))
}" }"
`; `;
@ -97,9 +170,9 @@ exports[`stringify static html > should work with bindings that are non-static b
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue "const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<div><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><img src=\\"" + _imports_0_ + "\\"></div>", 1) _createStaticVNode("<div><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><span class=\\"foo\\">foo</span><img src=\\"" + _imports_0_ + "\\"></div>", 1)
]))) ]))]))
}" }"
`; `;

View File

@ -48,6 +48,22 @@ return function render(_ctx, _cache) {
}" }"
`; `;
exports[`compiler: transform v-model > input with v-bind shorthand type after v-model should use dynamic model 1`] = `
"const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { vModelDynamic: _vModelDynamic, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return _withDirectives((_openBlock(), _createElementBlock("input", {
"onUpdate:modelValue": $event => ((model) = $event)
}, null, 8 /* PROPS */, ["onUpdate:modelValue"])), [
[_vModelDynamic, model]
])
}
}"
`;
exports[`compiler: transform v-model > modifiers > .lazy 1`] = ` exports[`compiler: transform v-model > modifiers > .lazy 1`] = `
"const _Vue = Vue "const _Vue = Vue

View File

@ -162,6 +162,27 @@ describe('stringify static html', () => {
expect(code).toMatchSnapshot() expect(code).toMatchSnapshot()
}) })
// #12391
test('serializing template string style', () => {
const { ast, code } = compileWithStringify(
`<div><div :style="\`color:red;\`">${repeat(
`<span :class="[{ foo: true }, { bar: true }]">{{ 1 }} + {{ false }}</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
)}</div></div>`,
)
// should be optimized now
expect(ast.cached).toMatchObject([
cachedArrayStaticNodeMatcher(
`<div style="color:red;">${repeat(
`<span class="foo bar">1 + false</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
)}</div>`,
1,
),
])
expect(code).toMatchSnapshot()
})
test('escape', () => { test('escape', () => {
const { ast, code } = compileWithStringify( const { ast, code } = compileWithStringify(
`<div><div>${repeat( `<div><div>${repeat(
@ -389,6 +410,24 @@ describe('stringify static html', () => {
]) ])
}) })
test('should stringify mathML', () => {
const math = `<math xmlns="http://www.w3.org/1998/Math/MathML">`
const repeated = `<ms>1</ms>`
const { ast } = compileWithStringify(
`<div>${math}${repeat(
repeated,
StringifyThresholds.NODE_COUNT,
)}</math></div>`,
)
expect(ast.cached).toMatchObject([
cachedArrayStaticNodeMatcher(
`${math}${repeat(repeated, StringifyThresholds.NODE_COUNT)}</math>`,
1,
),
])
})
// #5439 // #5439
test('stringify v-html', () => { test('stringify v-html', () => {
const { code } = compileWithStringify(` const { code } = compileWithStringify(`
@ -451,4 +490,49 @@ describe('stringify static html', () => {
expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()]) expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])
expect(code).toMatchSnapshot() expect(code).toMatchSnapshot()
}) })
test('should bail for comments', () => {
const { code } = compileWithStringify(
`<!-- Comment 1 --><div class="a"><!-- Comment 2 -->${repeat(
`<span class="b"/>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
)}</div>`,
)
expect(code).toMatchSnapshot()
})
test('should bail for <option> elements with null values', () => {
const { ast, code } = compileWithStringify(
`<div><select><option :value="null" />${repeat(
`<option value="1" />`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
)}</select></div>`,
)
expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])
expect(code).toMatchSnapshot()
})
test('eligible content (elements > 20) + non-eligible content', () => {
const { code } = compileWithStringify(
`<div>${repeat(
`<span/>`,
StringifyThresholds.NODE_COUNT,
)}<div key="1">1</div>${repeat(
`<span/>`,
StringifyThresholds.NODE_COUNT,
)}</div>`,
)
expect(code).toMatchSnapshot()
})
test('eligible content + v-once node', () => {
const { code } = compileWithStringify(
`<div>
<div v-once>{{ msg }}</div>
${repeat(`<span class="foo">foo</span>`, StringifyThresholds.ELEMENT_WITH_BINDING_COUNT)}
</div>`,
)
expect(code).toMatchSnapshot()
})
}) })

View File

@ -3,6 +3,7 @@ import {
generate, generate,
baseParse as parse, baseParse as parse,
transform, transform,
transformVBindShorthand,
} from '@vue/compiler-core' } from '@vue/compiler-core'
import { transformModel } from '../../src/transforms/vModel' import { transformModel } from '../../src/transforms/vModel'
import { transformElement } from '../../../compiler-core/src/transforms/transformElement' import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
@ -18,7 +19,7 @@ import {
function transformWithModel(template: string, options: CompilerOptions = {}) { function transformWithModel(template: string, options: CompilerOptions = {}) {
const ast = parse(template) const ast = parse(template)
transform(ast, { transform(ast, {
nodeTransforms: [transformElement], nodeTransforms: [transformVBindShorthand, transformElement],
directiveTransforms: { directiveTransforms: {
model: transformModel, model: transformModel,
}, },
@ -63,6 +64,14 @@ describe('compiler: transform v-model', () => {
expect(generate(root).code).toMatchSnapshot() expect(generate(root).code).toMatchSnapshot()
}) })
// #13169
test('input with v-bind shorthand type after v-model should use dynamic model', () => {
const root = transformWithModel('<input v-model="model" :type/>')
expect(root.helpers).toContain(V_MODEL_DYNAMIC)
expect(generate(root).code).toMatchSnapshot()
})
test('input w/ dynamic v-bind', () => { test('input w/ dynamic v-bind', () => {
const root = transformWithModel('<input v-bind="obj" v-model="model" />') const root = transformWithModel('<input v-bind="obj" v-model="model" />')

View File

@ -1,4 +1,5 @@
import { type CompilerError, compile } from '../../src' import { type CompilerError, compile } from '../../src'
import { isValidHTMLNesting } from '../../src/htmlNesting'
describe('validate html nesting', () => { describe('validate html nesting', () => {
it('should warn with p > div', () => { it('should warn with p > div', () => {
@ -17,4 +18,185 @@ describe('validate html nesting', () => {
}) })
expect(err).toBeUndefined() expect(err).toBeUndefined()
}) })
// #13318
it('should not warn when parent tag is template', () => {
let err: CompilerError | undefined
compile(`<template><tr/></template>`, {
onWarn: e => (err = e),
})
expect(err).toBeUndefined()
})
})
/**
* Copied from https://github.com/MananTank/validate-html-nesting
* with ISC license
*/
describe('isValidHTMLNesting', () => {
test('form', () => {
// invalid
expect(isValidHTMLNesting('form', 'form')).toBe(false)
// valid
expect(isValidHTMLNesting('form', 'div')).toBe(true)
expect(isValidHTMLNesting('form', 'input')).toBe(true)
expect(isValidHTMLNesting('form', 'select')).toBe(true)
expect(isValidHTMLNesting('form', 'button')).toBe(true)
expect(isValidHTMLNesting('form', 'label')).toBe(true)
expect(isValidHTMLNesting('form', 'h1')).toBe(true)
})
test('p', () => {
// invalid
expect(isValidHTMLNesting('p', 'p')).toBe(false)
expect(isValidHTMLNesting('p', 'div')).toBe(false)
expect(isValidHTMLNesting('p', 'hr')).toBe(false)
expect(isValidHTMLNesting('p', 'blockquote')).toBe(false)
expect(isValidHTMLNesting('p', 'pre')).toBe(false)
// valid
expect(isValidHTMLNesting('p', 'a')).toBe(true)
expect(isValidHTMLNesting('p', 'span')).toBe(true)
expect(isValidHTMLNesting('p', 'abbr')).toBe(true)
expect(isValidHTMLNesting('p', 'button')).toBe(true)
expect(isValidHTMLNesting('p', 'b')).toBe(true)
expect(isValidHTMLNesting('p', 'i')).toBe(true)
expect(isValidHTMLNesting('p', 'input')).toBe(true)
expect(isValidHTMLNesting('p', 'label')).toBe(true)
})
test('a', () => {
// invalid
expect(isValidHTMLNesting('a', 'a')).toBe(false)
// valid
expect(isValidHTMLNesting('a', 'div')).toBe(true)
expect(isValidHTMLNesting('a', 'span')).toBe(true)
})
test('button', () => {
// invalid
expect(isValidHTMLNesting('button', 'button')).toBe(false)
// valid
expect(isValidHTMLNesting('button', 'div')).toBe(true)
expect(isValidHTMLNesting('button', 'span')).toBe(true)
})
test('table', () => {
// invalid
expect(isValidHTMLNesting('table', 'tr')).toBe(false)
expect(isValidHTMLNesting('table', 'table')).toBe(false)
expect(isValidHTMLNesting('table', 'td')).toBe(false)
// valid
expect(isValidHTMLNesting('table', 'thead')).toBe(true)
expect(isValidHTMLNesting('table', 'tbody')).toBe(true)
expect(isValidHTMLNesting('table', 'tfoot')).toBe(true)
expect(isValidHTMLNesting('table', 'caption')).toBe(true)
expect(isValidHTMLNesting('table', 'colgroup')).toBe(true)
})
test('td', () => {
// valid
expect(isValidHTMLNesting('td', 'span')).toBe(true)
expect(isValidHTMLNesting('tr', 'td')).toBe(true)
// invalid
expect(isValidHTMLNesting('td', 'td')).toBe(false)
expect(isValidHTMLNesting('div', 'td')).toBe(false)
})
test('tbody', () => {
// invalid
expect(isValidHTMLNesting('tbody', 'td')).toBe(false)
// valid
expect(isValidHTMLNesting('tbody', 'tr')).toBe(true)
})
test('tr', () => {
// invalid
expect(isValidHTMLNesting('tr', 'tr')).toBe(false)
expect(isValidHTMLNesting('table', 'tr')).toBe(false)
// valid
expect(isValidHTMLNesting('tbody', 'tr')).toBe(true)
expect(isValidHTMLNesting('thead', 'tr')).toBe(true)
expect(isValidHTMLNesting('tfoot', 'tr')).toBe(true)
expect(isValidHTMLNesting('tr', 'td')).toBe(true)
expect(isValidHTMLNesting('tr', 'th')).toBe(true)
})
test('li', () => {
// invalid
expect(isValidHTMLNesting('li', 'li')).toBe(false)
// valid
expect(isValidHTMLNesting('li', 'div')).toBe(true)
expect(isValidHTMLNesting('li', 'ul')).toBe(true)
})
test('headings', () => {
// invalid
expect(isValidHTMLNesting('h1', 'h1')).toBe(false)
expect(isValidHTMLNesting('h2', 'h1')).toBe(false)
expect(isValidHTMLNesting('h3', 'h1')).toBe(false)
expect(isValidHTMLNesting('h1', 'h6')).toBe(false)
// valid
expect(isValidHTMLNesting('h1', 'div')).toBe(true)
})
describe('SVG', () => {
test('svg', () => {
// invalid non-svg tags as children
expect(isValidHTMLNesting('svg', 'div')).toBe(false)
expect(isValidHTMLNesting('svg', 'img')).toBe(false)
expect(isValidHTMLNesting('svg', 'p')).toBe(false)
expect(isValidHTMLNesting('svg', 'h2')).toBe(false)
expect(isValidHTMLNesting('svg', 'span')).toBe(false)
// valid non-svg tags as children
expect(isValidHTMLNesting('svg', 'a')).toBe(true)
expect(isValidHTMLNesting('svg', 'textarea')).toBe(true)
expect(isValidHTMLNesting('svg', 'input')).toBe(true)
expect(isValidHTMLNesting('svg', 'select')).toBe(true)
// valid svg tags as children
expect(isValidHTMLNesting('svg', 'g')).toBe(true)
expect(isValidHTMLNesting('svg', 'ellipse')).toBe(true)
expect(isValidHTMLNesting('svg', 'feOffset')).toBe(true)
})
test('foreignObject', () => {
// valid
expect(isValidHTMLNesting('foreignObject', 'g')).toBe(true)
expect(isValidHTMLNesting('foreignObject', 'div')).toBe(true)
expect(isValidHTMLNesting('foreignObject', 'a')).toBe(true)
expect(isValidHTMLNesting('foreignObject', 'textarea')).toBe(true)
})
test('g', () => {
// valid
expect(isValidHTMLNesting('g', 'div')).toBe(true)
expect(isValidHTMLNesting('g', 'p')).toBe(true)
expect(isValidHTMLNesting('g', 'a')).toBe(true)
expect(isValidHTMLNesting('g', 'textarea')).toBe(true)
expect(isValidHTMLNesting('g', 'g')).toBe(true)
})
test('dl', () => {
// valid
expect(isValidHTMLNesting('dl', 'dt')).toBe(true)
expect(isValidHTMLNesting('dl', 'dd')).toBe(true)
expect(isValidHTMLNesting('dl', 'div')).toBe(true)
expect(isValidHTMLNesting('div', 'dt')).toBe(true)
expect(isValidHTMLNesting('div', 'dd')).toBe(true)
// invalid
expect(isValidHTMLNesting('span', 'dt')).toBe(false)
expect(isValidHTMLNesting('span', 'dd')).toBe(false)
})
})
}) })

View File

@ -1,6 +1,6 @@
{ {
"name": "@vue/compiler-dom", "name": "@vue/compiler-dom",
"version": "3.5.4", "version": "3.5.26",
"description": "@vue/compiler-dom", "description": "@vue/compiler-dom",
"main": "index.js", "main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js", "module": "dist/compiler-dom.esm-bundler.js",

View File

@ -21,7 +21,7 @@ export function createDOMCompilerError(
} }
export enum DOMErrorCodes { export enum DOMErrorCodes {
X_V_HTML_NO_EXPRESSION = 53 /* ErrorCodes.__EXTEND_POINT__ */, X_V_HTML_NO_EXPRESSION = 54 /* ErrorCodes.__EXTEND_POINT__ */,
X_V_HTML_WITH_CHILDREN, X_V_HTML_WITH_CHILDREN,
X_V_TEXT_NO_EXPRESSION, X_V_TEXT_NO_EXPRESSION,
X_V_TEXT_WITH_CHILDREN, X_V_TEXT_WITH_CHILDREN,
@ -42,7 +42,7 @@ if (__TEST__) {
if (DOMErrorCodes.X_V_HTML_NO_EXPRESSION < ErrorCodes.__EXTEND_POINT__) { if (DOMErrorCodes.X_V_HTML_NO_EXPRESSION < ErrorCodes.__EXTEND_POINT__) {
throw new Error( throw new Error(
`DOMErrorCodes need to be updated to ${ `DOMErrorCodes need to be updated to ${
ErrorCodes.__EXTEND_POINT__ + 1 ErrorCodes.__EXTEND_POINT__
} to match extension point from core ErrorCodes.`, } to match extension point from core ErrorCodes.`,
) )
} }

View File

@ -11,6 +11,11 @@
* returns true if given parent-child nesting is valid HTML * returns true if given parent-child nesting is valid HTML
*/ */
export function isValidHTMLNesting(parent: string, child: string): boolean { export function isValidHTMLNesting(parent: string, child: string): boolean {
// if the parent is a template, it can have any child
if (parent === 'template') {
return true
}
// if we know the list of children that are the only valid children for the given parent // if we know the list of children that are the only valid children for the given parent
if (parent in onlyValidChildren) { if (parent in onlyValidChildren) {
return onlyValidChildren[parent].has(child) return onlyValidChildren[parent].has(child)

View File

@ -8,6 +8,7 @@ export const parserOptions: ParserOptions = {
isVoidTag, isVoidTag,
isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag) || isMathMLTag(tag), isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag) || isMathMLTag(tag),
isPreTag: tag => tag === 'pre', isPreTag: tag => tag === 'pre',
isIgnoreNewlineTag: tag => tag === 'pre' || tag === 'textarea',
decodeEntities: __BROWSER__ ? decodeHtmlBrowser : undefined, decodeEntities: __BROWSER__ ? decodeHtmlBrowser : undefined,
isBuiltInComponent: tag => { isBuiltInComponent: tag => {

View File

@ -4,6 +4,7 @@ import {
type IfBranchNode, type IfBranchNode,
type NodeTransform, type NodeTransform,
NodeTypes, NodeTypes,
isCommentOrWhitespace,
} from '@vue/compiler-core' } from '@vue/compiler-core'
import { TRANSITION } from '../runtimeHelpers' import { TRANSITION } from '../runtimeHelpers'
import { DOMErrorCodes, createDOMCompilerError } from '../errors' import { DOMErrorCodes, createDOMCompilerError } from '../errors'
@ -56,11 +57,9 @@ export const transformTransition: NodeTransform = (node, context) => {
} }
function hasMultipleChildren(node: ComponentNode | IfBranchNode): boolean { function hasMultipleChildren(node: ComponentNode | IfBranchNode): boolean {
// #1352 filter out potential comment nodes. // filter out potential comment nodes (#1352) and whitespace (#4637)
const children = (node.children = node.children.filter( const children = (node.children = node.children.filter(
c => c => !isCommentOrWhitespace(c),
c.type !== NodeTypes.COMMENT &&
!(c.type === NodeTypes.TEXT && !c.content.trim()),
)) ))
const child = children[0] const child = children[0]
return ( return (

View File

@ -16,9 +16,8 @@ import {
type TemplateChildNode, type TemplateChildNode,
type TextCallNode, type TextCallNode,
type TransformContext, type TransformContext,
type VNodeCall,
createArrayExpression,
createCallExpression, createCallExpression,
findDir,
isStaticArgOf, isStaticArgOf,
} from '@vue/compiler-core' } from '@vue/compiler-core'
import { import {
@ -26,6 +25,7 @@ import {
isArray, isArray,
isBooleanAttr, isBooleanAttr,
isKnownHtmlAttr, isKnownHtmlAttr,
isKnownMathMLAttr,
isKnownSvgAttr, isKnownSvgAttr,
isString, isString,
isSymbol, isSymbol,
@ -106,15 +106,23 @@ export const stringifyStatic: HoistTransform = (children, context, parent) => {
String(currentChunk.length), String(currentChunk.length),
]) ])
const deleteCount = currentChunk.length - 1
if (isParentCached) { if (isParentCached) {
;((parent.codegenNode as VNodeCall).children as CacheExpression).value = // if the parent is cached, then `children` is also the value of the
createArrayExpression([staticCall]) // CacheExpression. Just replace the corresponding range in the cached
// list with staticCall.
children.splice(
currentIndex - currentChunk.length,
currentChunk.length,
// @ts-expect-error
staticCall,
)
} else { } else {
// replace the first node's hoisted expression with the static vnode call // replace the first node's hoisted expression with the static vnode call
;(currentChunk[0].codegenNode as CacheExpression).value = staticCall ;(currentChunk[0].codegenNode as CacheExpression).value = staticCall
if (currentChunk.length > 1) { if (currentChunk.length > 1) {
// remove merged nodes from children // remove merged nodes from children
const deleteCount = currentChunk.length - 1
children.splice(currentIndex - currentChunk.length + 1, deleteCount) children.splice(currentIndex - currentChunk.length + 1, deleteCount)
// also adjust index for the remaining cache items // also adjust index for the remaining cache items
const cacheIndex = context.cached.indexOf( const cacheIndex = context.cached.indexOf(
@ -128,10 +136,10 @@ export const stringifyStatic: HoistTransform = (children, context, parent) => {
} }
context.cached.splice(cacheIndex - deleteCount + 1, deleteCount) context.cached.splice(cacheIndex - deleteCount + 1, deleteCount)
} }
}
}
return deleteCount return deleteCount
} }
}
}
return 0 return 0
} }
@ -177,13 +185,15 @@ const getCachedNode = (
} }
} }
const dataAriaRE = /^(data|aria)-/ const dataAriaRE = /^(?:data|aria)-/
const isStringifiableAttr = (name: string, ns: Namespaces) => { const isStringifiableAttr = (name: string, ns: Namespaces) => {
return ( return (
(ns === Namespaces.HTML (ns === Namespaces.HTML
? isKnownHtmlAttr(name) ? isKnownHtmlAttr(name)
: ns === Namespaces.SVG : ns === Namespaces.SVG
? isKnownSvgAttr(name) ? isKnownSvgAttr(name)
: ns === Namespaces.MATH_ML
? isKnownMathMLAttr(name)
: false) || dataAriaRE.test(name) : false) || dataAriaRE.test(name)
) )
} }
@ -204,6 +214,11 @@ function analyzeNode(node: StringifiableNode): [number, number] | false {
return false return false
} }
// v-once nodes should not be stringified
if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {
return false
}
if (node.type === NodeTypes.TEXT_CALL) { if (node.type === NodeTypes.TEXT_CALL) {
return [1, 0] return [1, 0]
} }
@ -252,8 +267,7 @@ function analyzeNode(node: StringifiableNode): [number, number] | false {
isOptionTag && isOptionTag &&
isStaticArgOf(p.arg, 'value') && isStaticArgOf(p.arg, 'value') &&
p.exp && p.exp &&
p.exp.ast && !p.exp.isStatic
p.exp.ast.type !== 'StringLiteral'
) { ) {
return bail() return bail()
} }

View File

@ -11,7 +11,6 @@ This package contains lower level utilities that you can use if you are writing
The API is intentionally low-level due to the various considerations when integrating Vue SFCs in a build system: The API is intentionally low-level due to the various considerations when integrating Vue SFCs in a build system:
- Separate hot-module replacement (HMR) for script, template and styles - Separate hot-module replacement (HMR) for script, template and styles
- template updates should not reset component state - template updates should not reset component state
- style updates should be performed without component re-render - style updates should be performed without component re-render

View File

@ -639,6 +639,44 @@ return { foo, bar, baz, y, z }
}" }"
`; `;
exports[`SFC compile <script setup> > demote const reactive binding to let when used in v-model (inlineTemplate) 1`] = `
"import { unref as _unref, resolveComponent as _resolveComponent, isRef as _isRef, openBlock as _openBlock, createBlock as _createBlock } from "vue"
import { reactive } from 'vue'
export default {
setup(__props) {
let name = reactive({ first: 'john', last: 'doe' })
return (_ctx, _cache) => {
const _component_MyComponent = _resolveComponent("MyComponent")
return (_openBlock(), _createBlock(_component_MyComponent, {
modelValue: _unref(name),
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (_isRef(name) ? (name).value = $event : name = $event))
}, null, 8 /* PROPS */, ["modelValue"]))
}
}
}"
`;
exports[`SFC compile <script setup> > demote const reactive binding to let when used in v-model 1`] = `
"import { reactive } from 'vue'
export default {
setup(__props, { expose: __expose }) {
__expose();
let name = reactive({ first: 'john', last: 'doe' })
return { get name() { return name }, set name(v) { name = v }, reactive }
}
}"
`;
exports[`SFC compile <script setup> > errors > should allow defineProps/Emit() referencing imported binding 1`] = ` exports[`SFC compile <script setup> > errors > should allow defineProps/Emit() referencing imported binding 1`] = `
"import { bar } from './bar' "import { bar } from './bar'
@ -861,7 +899,7 @@ export default {
return (_ctx, _cache) => { return (_ctx, _cache) => {
return (_openBlock(), _createElementBlock(_Fragment, null, [ return (_openBlock(), _createElementBlock(_Fragment, null, [
_createElementVNode("div", null, _toDisplayString(count.value), 1 /* TEXT */), _createElementVNode("div", null, _toDisplayString(count.value), 1 /* TEXT */),
_cache[0] || (_cache[0] = _createElementVNode("div", null, "static", -1 /* HOISTED */)) _cache[0] || (_cache[0] = _createElementVNode("div", null, "static", -1 /* CACHED */))
], 64 /* STABLE_FRAGMENT */)) ], 64 /* STABLE_FRAGMENT */))
} }
} }
@ -884,9 +922,9 @@ export default {
return (_ctx, _push, _parent, _attrs) => { return (_ctx, _push, _parent, _attrs) => {
const _cssVars = { style: { const _cssVars = { style: {
"--xxxxxxxx-count": (count.value), ":--xxxxxxxx-count": (count.value),
"--xxxxxxxx-style\\\\.color": (style.color), ":--xxxxxxxx-style\\\\.color": (style.color),
"--xxxxxxxx-height\\\\ \\\\+\\\\ \\\\\\"px\\\\\\"": (height.value + "px") ":--xxxxxxxx-height\\\\ \\\\+\\\\ \\\\\\"px\\\\\\"": (height.value + "px")
}} }}
_push(\`<!--[--><div\${ _push(\`<!--[--><div\${
_ssrRenderAttrs(_cssVars) _ssrRenderAttrs(_cssVars)
@ -1084,6 +1122,29 @@ return (_ctx, _cache) => {
}" }"
`; `;
exports[`SFC compile <script setup> > inlineTemplate mode > v-model w/ newlines codegen 1`] = `
"import { unref as _unref, isRef as _isRef, vModelText as _vModelText, withDirectives as _withDirectives, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export default {
setup(__props) {
const count = ref(0)
return (_ctx, _cache) => {
return _withDirectives((_openBlock(), _createElementBlock("input", {
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (_isRef(count) ? (count).value = $event : null))
}, null, 512 /* NEED_PATCH */)), [
[_vModelText,
_unref(count)
]
])
}
}
}"
`;
exports[`SFC compile <script setup> > inlineTemplate mode > with defineExpose() 1`] = ` exports[`SFC compile <script setup> > inlineTemplate mode > with defineExpose() 1`] = `
" "
export default { export default {

View File

@ -12,6 +12,27 @@ export function render(_ctx, _cache) {
}" }"
`; `;
exports[`prefixing props edge case in inline mode 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { unref as _unref, openBlock as _openBlock, createBlock as _createBlock } from "vue"
export default /*@__PURE__*/_defineComponent({
props: {
Foo: { type: Object, required: true }
},
setup(__props: any) {
return (_ctx: any,_cache: any) => {
return (_openBlock(), _createBlock(_unref(__props["Foo"]).Bar))
}
}
})"
`;
exports[`should not hoist srcset URLs in SSR mode 1`] = ` exports[`should not hoist srcset URLs in SSR mode 1`] = `
"import { resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode } from "vue" "import { resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode } from "vue"
import { ssrRenderAttr as _ssrRenderAttr, ssrRenderComponent as _ssrRenderComponent } from "vue/server-renderer" import { ssrRenderAttr as _ssrRenderAttr, ssrRenderComponent as _ssrRenderComponent } from "vue/server-renderer"

View File

@ -41,8 +41,8 @@ const _hoisted_1 = _imports_0 + '#fragment'
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(_Fragment, null, [ return (_openBlock(), _createElementBlock(_Fragment, null, [
_cache[0] || (_cache[0] = _createElementVNode("use", { href: _hoisted_1 }, null, -1 /* HOISTED */)), _cache[0] || (_cache[0] = _createElementVNode("use", { href: _hoisted_1 }, null, -1 /* CACHED */)),
_cache[1] || (_cache[1] = _createElementVNode("use", { href: _hoisted_1 }, null, -1 /* HOISTED */)) _cache[1] || (_cache[1] = _createElementVNode("use", { href: _hoisted_1 }, null, -1 /* CACHED */))
], 64 /* STABLE_FRAGMENT */)) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;
@ -81,9 +81,9 @@ import _imports_1 from '/bar.png'
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<img src=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_1 + "\\"><img src=\\"https://foo.bar/baz.png\\"><img src=\\"//foo.bar/baz.png\\"><img src=\\"" + _imports_0 + "\\">", 5) _createStaticVNode("<img src=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_1 + "\\"><img src=\\"https://foo.bar/baz.png\\"><img src=\\"//foo.bar/baz.png\\"><img src=\\"" + _imports_0 + "\\">", 5)
]))) ]))]))
}" }"
`; `;

View File

@ -10,12 +10,22 @@ const _hoisted_2 = _imports_0 + ' 1x, ' + "/foo/logo.png" + ' 2x'
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(_Fragment, null, [ return (_openBlock(), _createElementBlock(_Fragment, null, [
_cache[0] || (_cache[0] = _createElementVNode("img", { srcset: _hoisted_1 }, null, -1 /* HOISTED */)), _cache[0] || (_cache[0] = _createElementVNode("img", { srcset: _hoisted_1 }, null, -1 /* CACHED */)),
_cache[1] || (_cache[1] = _createElementVNode("img", { srcset: _hoisted_2 }, null, -1 /* HOISTED */)) _cache[1] || (_cache[1] = _createElementVNode("img", { srcset: _hoisted_2 }, null, -1 /* CACHED */))
], 64 /* STABLE_FRAGMENT */)) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;
exports[`compiler sfc: transform srcset > transform empty srcset w/ includeAbsolute: true 1`] = `
"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
const _hoisted_1 = { srcset: " " }
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("img", _hoisted_1))
}"
`;
exports[`compiler sfc: transform srcset > transform srcset 1`] = ` exports[`compiler sfc: transform srcset > transform srcset 1`] = `
"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue" "import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
import _imports_0 from './logo.png' import _imports_0 from './logo.png'
@ -35,51 +45,51 @@ export function render(_ctx, _cache) {
_cache[0] || (_cache[0] = _createElementVNode("img", { _cache[0] || (_cache[0] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "" srcset: ""
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[1] || (_cache[1] = _createElementVNode("img", { _cache[1] || (_cache[1] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_1 srcset: _hoisted_1
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[2] || (_cache[2] = _createElementVNode("img", { _cache[2] || (_cache[2] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_2 srcset: _hoisted_2
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[3] || (_cache[3] = _createElementVNode("img", { _cache[3] || (_cache[3] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_3 srcset: _hoisted_3
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[4] || (_cache[4] = _createElementVNode("img", { _cache[4] || (_cache[4] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_4 srcset: _hoisted_4
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[5] || (_cache[5] = _createElementVNode("img", { _cache[5] || (_cache[5] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_5 srcset: _hoisted_5
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[6] || (_cache[6] = _createElementVNode("img", { _cache[6] || (_cache[6] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_6 srcset: _hoisted_6
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[7] || (_cache[7] = _createElementVNode("img", { _cache[7] || (_cache[7] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_7 srcset: _hoisted_7
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[8] || (_cache[8] = _createElementVNode("img", { _cache[8] || (_cache[8] = _createElementVNode("img", {
src: "/logo.png", src: "/logo.png",
srcset: "/logo.png, /logo.png 2x" srcset: "/logo.png, /logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[9] || (_cache[9] = _createElementVNode("img", { _cache[9] || (_cache[9] = _createElementVNode("img", {
src: "https://example.com/logo.png", src: "https://example.com/logo.png",
srcset: "https://example.com/logo.png, https://example.com/logo.png 2x" srcset: "https://example.com/logo.png, https://example.com/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[10] || (_cache[10] = _createElementVNode("img", { _cache[10] || (_cache[10] = _createElementVNode("img", {
src: "/logo.png", src: "/logo.png",
srcset: _hoisted_8 srcset: _hoisted_8
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[11] || (_cache[11] = _createElementVNode("img", { _cache[11] || (_cache[11] = _createElementVNode("img", {
src: "data:image/png;base64,i", src: "data:image/png;base64,i",
srcset: "data:image/png;base64,i 1x, data:image/png;base64,i 2x" srcset: "data:image/png;base64,i 1x, data:image/png;base64,i 2x"
}, null, -1 /* HOISTED */)) }, null, -1 /* CACHED */))
], 64 /* STABLE_FRAGMENT */)) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;
@ -92,51 +102,51 @@ export function render(_ctx, _cache) {
_cache[0] || (_cache[0] = _createElementVNode("img", { _cache[0] || (_cache[0] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "" srcset: ""
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[1] || (_cache[1] = _createElementVNode("img", { _cache[1] || (_cache[1] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png" srcset: "/foo/logo.png"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[2] || (_cache[2] = _createElementVNode("img", { _cache[2] || (_cache[2] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png 2x" srcset: "/foo/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[3] || (_cache[3] = _createElementVNode("img", { _cache[3] || (_cache[3] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png 2x" srcset: "/foo/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[4] || (_cache[4] = _createElementVNode("img", { _cache[4] || (_cache[4] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png, /foo/logo.png 2x" srcset: "/foo/logo.png, /foo/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[5] || (_cache[5] = _createElementVNode("img", { _cache[5] || (_cache[5] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png 2x, /foo/logo.png" srcset: "/foo/logo.png 2x, /foo/logo.png"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[6] || (_cache[6] = _createElementVNode("img", { _cache[6] || (_cache[6] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png 2x, /foo/logo.png 3x" srcset: "/foo/logo.png 2x, /foo/logo.png 3x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[7] || (_cache[7] = _createElementVNode("img", { _cache[7] || (_cache[7] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "/foo/logo.png, /foo/logo.png 2x, /foo/logo.png 3x" srcset: "/foo/logo.png, /foo/logo.png 2x, /foo/logo.png 3x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[8] || (_cache[8] = _createElementVNode("img", { _cache[8] || (_cache[8] = _createElementVNode("img", {
src: "/logo.png", src: "/logo.png",
srcset: "/logo.png, /logo.png 2x" srcset: "/logo.png, /logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[9] || (_cache[9] = _createElementVNode("img", { _cache[9] || (_cache[9] = _createElementVNode("img", {
src: "https://example.com/logo.png", src: "https://example.com/logo.png",
srcset: "https://example.com/logo.png, https://example.com/logo.png 2x" srcset: "https://example.com/logo.png, https://example.com/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[10] || (_cache[10] = _createElementVNode("img", { _cache[10] || (_cache[10] = _createElementVNode("img", {
src: "/logo.png", src: "/logo.png",
srcset: "/logo.png, /foo/logo.png 2x" srcset: "/logo.png, /foo/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[11] || (_cache[11] = _createElementVNode("img", { _cache[11] || (_cache[11] = _createElementVNode("img", {
src: "data:image/png;base64,i", src: "data:image/png;base64,i",
srcset: "data:image/png;base64,i 1x, data:image/png;base64,i 2x" srcset: "data:image/png;base64,i 1x, data:image/png;base64,i 2x"
}, null, -1 /* HOISTED */)) }, null, -1 /* CACHED */))
], 64 /* STABLE_FRAGMENT */)) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;
@ -162,51 +172,51 @@ export function render(_ctx, _cache) {
_cache[0] || (_cache[0] = _createElementVNode("img", { _cache[0] || (_cache[0] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: "" srcset: ""
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[1] || (_cache[1] = _createElementVNode("img", { _cache[1] || (_cache[1] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_1 srcset: _hoisted_1
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[2] || (_cache[2] = _createElementVNode("img", { _cache[2] || (_cache[2] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_2 srcset: _hoisted_2
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[3] || (_cache[3] = _createElementVNode("img", { _cache[3] || (_cache[3] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_3 srcset: _hoisted_3
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[4] || (_cache[4] = _createElementVNode("img", { _cache[4] || (_cache[4] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_4 srcset: _hoisted_4
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[5] || (_cache[5] = _createElementVNode("img", { _cache[5] || (_cache[5] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_5 srcset: _hoisted_5
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[6] || (_cache[6] = _createElementVNode("img", { _cache[6] || (_cache[6] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_6 srcset: _hoisted_6
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[7] || (_cache[7] = _createElementVNode("img", { _cache[7] || (_cache[7] = _createElementVNode("img", {
src: "./logo.png", src: "./logo.png",
srcset: _hoisted_7 srcset: _hoisted_7
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[8] || (_cache[8] = _createElementVNode("img", { _cache[8] || (_cache[8] = _createElementVNode("img", {
src: "/logo.png", src: "/logo.png",
srcset: _hoisted_8 srcset: _hoisted_8
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[9] || (_cache[9] = _createElementVNode("img", { _cache[9] || (_cache[9] = _createElementVNode("img", {
src: "https://example.com/logo.png", src: "https://example.com/logo.png",
srcset: "https://example.com/logo.png, https://example.com/logo.png 2x" srcset: "https://example.com/logo.png, https://example.com/logo.png 2x"
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[10] || (_cache[10] = _createElementVNode("img", { _cache[10] || (_cache[10] = _createElementVNode("img", {
src: "/logo.png", src: "/logo.png",
srcset: _hoisted_9 srcset: _hoisted_9
}, null, -1 /* HOISTED */)), }, null, -1 /* CACHED */)),
_cache[11] || (_cache[11] = _createElementVNode("img", { _cache[11] || (_cache[11] = _createElementVNode("img", {
src: "data:image/png;base64,i", src: "data:image/png;base64,i",
srcset: "data:image/png;base64,i 1x, data:image/png;base64,i 2x" srcset: "data:image/png;base64,i 1x, data:image/png;base64,i 2x"
}, null, -1 /* HOISTED */)) }, null, -1 /* CACHED */))
], 64 /* STABLE_FRAGMENT */)) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;
@ -228,8 +238,8 @@ const _hoisted_8 = _imports_1 + ', ' + _imports_1 + ' 2x'
const _hoisted_9 = _imports_1 + ', ' + _imports_0 + ' 2x' const _hoisted_9 = _imports_1 + ', ' + _imports_0 + ' 2x'
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [ return (_openBlock(), _createElementBlock("div", null, [...(_cache[0] || (_cache[0] = [
_createStaticVNode("<img src=\\"./logo.png\\" srcset=\\"\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_1 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_2 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_3 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_4 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_5 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_6 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_7 + "\\"><img src=\\"/logo.png\\" srcset=\\"" + _hoisted_8 + "\\"><img src=\\"https://example.com/logo.png\\" srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\"><img src=\\"/logo.png\\" srcset=\\"" + _hoisted_9 + "\\"><img src=\\"data:image/png;base64,i\\" srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">", 12) _createStaticVNode("<img src=\\"./logo.png\\" srcset=\\"\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_1 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_2 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_3 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_4 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_5 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_6 + "\\"><img src=\\"./logo.png\\" srcset=\\"" + _hoisted_7 + "\\"><img src=\\"/logo.png\\" srcset=\\"" + _hoisted_8 + "\\"><img src=\\"https://example.com/logo.png\\" srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\"><img src=\\"/logo.png\\" srcset=\\"" + _hoisted_9 + "\\"><img src=\\"data:image/png;base64,i\\" srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">", 12)
]))) ]))]))
}" }"
`; `;

Some files were not shown because too many files have changed in this diff Show More