Repository navigation
Description
Problem
Void's Vue Pages adapter overwrites a page component's existing props declaration with the keys of the props received from the server.
This discards Vue's prop types, default values, required flags, and custom validators.
Additionally, the component's props declaration becomes fixed based on the first received props object, potentially affecting subsequent navigations.
Steps to Reproduce
- Create the following page component:
<script setup lang="ts">
defineProps({
title: {
type: String,
default: 'DEFAULT',
},
count: {
type: Number,
required: true,
validator: (value: number) => value > 0,
},
});
</script>
<template>
<p>title: {{ title }}</p>
<p>count: {{ count }}</p>
</template>- Render the page with
titleomitted andcount: -1:
{
component: 'Example',
props: { count: -1 },
url: '/example',
params: {},
shared: {},
errors: null,
}- Check the rendered output and Vue's validation warnings.
Actual Behavior
Both the generated SSR and client code contain the following implementation:
function patchProps(comp, props) {
if (comp.__voidPatched) return;
comp.props = Object.keys(props);
comp.__voidPatched = true;
}This replaces the original props declaration with:
comp.props = ['count'];Consequently:
- The
titledefault value (DEFAULT) is lost. - The type, required flag, and custom validator for
countare removed. __voidPatchedprevents the declaration from adapting to subsequent props objects.- Other usages of the same component definition may also be affected.
Root Cause
The Vue Pages adapter strips type arguments from defineProps<T>() and dynamically registers props based on the received page data.
However, patchProps() also runs on components with existing runtime props declarations.
Instead of supplementing missing declarations, it replaces the entire comp.props definition.
The __voidPatched flag then prevents subsequent updates to the registered prop names.
Expected Behavior
- Preserve the component's original Vue props declaration.
- Apply
DEFAULTwhentitleis omitted. - Emit a validation warning for
count: -1in development mode. - Preserve the same props contract across page navigations.
Acceptance Criteria
- Preserve prop types, default values, required flags, and custom validators.
- Do not derive a permanent props declaration from the first received props object.
- Preserve props behavior across subsequent navigations.
- Avoid mutating the original component definition.
- Ensure consistent behavior in both SSR and client rendering.
- Maintain compatibility with existing type-based
defineProps<T>()declarations.
Relevant Code
packages/vue/src/plugin-pages.ts
https://github.com/voidzero-dev/void/blob/main/packages/vue/src/plugin-pages.ts
The affected patchProps() implementation is generated by both generateRendererModule() and generateClientEntry().
The problematic code path has been verified through source inspection. The reproduction above has not yet been executed as a runtime test.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
fix(vue): preserve runtime props declarations in pages patchProps
fix(vue): preserve runtime props declarations in pages patchProps
0froq commentedon Oct 26, 2026
Fix on the way
fix(vue): preserve runtime props declarations in pages patchProps (vo…