Skip to content

Commit d74d364

Browse files
fix(custom-element): correctly handle number type props in prod (#8989)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent af5df91 commit d74d364

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap

+60
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,66 @@ return { props, bar }
1818
}"
1919
`;
2020

21+
exports[`defineProps > custom element retains the props type & default value & production mode 1`] = `
22+
"import { defineComponent as _defineComponent } from 'vue'
23+
interface Props {
24+
foo?: number;
25+
}
26+
27+
export default /*#__PURE__*/_defineComponent({
28+
__name: 'app.ce',
29+
props: {
30+
foo: { default: 5.5, type: Number }
31+
},
32+
setup(__props: any, { expose: __expose }) {
33+
__expose();
34+
35+
const props = __props;
36+
37+
return { props }
38+
}
39+
40+
})"
41+
`;
42+
43+
exports[`defineProps > custom element retains the props type & production mode 1`] = `
44+
"import { defineComponent as _defineComponent } from 'vue'
45+
46+
export default /*#__PURE__*/_defineComponent({
47+
__name: 'app.ce',
48+
props: {
49+
foo: {type: Number}
50+
},
51+
setup(__props: any, { expose: __expose }) {
52+
__expose();
53+
54+
const props = __props
55+
56+
return { props }
57+
}
58+
59+
})"
60+
`;
61+
62+
exports[`defineProps > custom element retains the props type w/ production mode 1`] = `
63+
"import { defineComponent as _defineComponent } from 'vue'
64+
65+
export default /*#__PURE__*/_defineComponent({
66+
__name: 'app.ce',
67+
props: {
68+
foo: {type: Number}
69+
},
70+
setup(__props: any, { expose: __expose }) {
71+
__expose();
72+
73+
const props = __props
74+
75+
return { props }
76+
}
77+
78+
})"
79+
`;
80+
2181
exports[`defineProps > defineProps w/ runtime options 1`] = `
2282
"import { defineComponent as _defineComponent } from 'vue'
2383

packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts

+31
Original file line numberDiff line numberDiff line change
@@ -710,4 +710,35 @@ const props = defineProps({ foo: String })
710710
'da-sh': BindingTypes.PROPS
711711
})
712712
})
713+
714+
// #8989
715+
test('custom element retains the props type & production mode', () => {
716+
const { content } = compile(
717+
`<script setup lang="ts">
718+
const props = defineProps<{ foo: number}>()
719+
</script>`,
720+
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
721+
{ filename: 'app.ce.vue' }
722+
)
723+
724+
expect(content).toMatch(`foo: {type: Number}`)
725+
assertCode(content)
726+
})
727+
728+
test('custom element retains the props type & default value & production mode', () => {
729+
const { content } = compile(
730+
`<script setup lang="ts">
731+
interface Props {
732+
foo?: number;
733+
}
734+
const props = withDefaults(defineProps<Props>(), {
735+
foo: 5.5,
736+
});
737+
</script>`,
738+
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
739+
{ filename: 'app.ce.vue' }
740+
)
741+
expect(content).toMatch(`foo: { default: 5.5, type: Number }`)
742+
assertCode(content)
743+
})
713744
})

packages/compiler-sfc/src/compileScript.ts

+4
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ export interface SFCScriptCompileOptions {
130130
* using it, disable this and switch to the [Vue Macros implementation](https://vue-macros.sxzz.moe/features/reactivity-transform.html).
131131
*/
132132
reactivityTransform?: boolean
133+
/**
134+
* Transform Vue SFCs into custom elements.
135+
*/
136+
customElement?: boolean | ((filename: string) => boolean)
133137
}
134138

135139
export interface ImportBinding {

packages/compiler-sfc/src/script/context.ts

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { TypeScope } from './resolveType'
1212
export class ScriptCompileContext {
1313
isJS: boolean
1414
isTS: boolean
15+
isCE = false
1516

1617
scriptAst: Program | null
1718
scriptSetupAst: Program | null
@@ -95,6 +96,14 @@ export class ScriptCompileContext {
9596
scriptSetupLang === 'ts' ||
9697
scriptSetupLang === 'tsx'
9798

99+
const customElement = options.customElement
100+
const filename = this.descriptor.filename
101+
if (customElement) {
102+
this.isCE =
103+
typeof customElement === 'boolean'
104+
? customElement
105+
: customElement(filename)
106+
}
98107
// resolve parser plugins
99108
const plugins: ParserPlugin[] = resolveParserPlugins(
100109
(scriptLang || scriptSetupLang)!,

packages/compiler-sfc/src/script/defineProps.ts

+11
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,17 @@ function genRuntimePropFromType(
276276
defaultString
277277
])} }`
278278
} else {
279+
// #8989 for custom element, should keep the type
280+
if (ctx.isCE) {
281+
if (defaultString) {
282+
return `${finalKey}: ${`{ ${defaultString}, type: ${toRuntimeTypeString(
283+
type
284+
)} }`}`
285+
} else {
286+
return `${finalKey}: {type: ${toRuntimeTypeString(type)}}`
287+
}
288+
}
289+
279290
// production: checks are useless
280291
return `${finalKey}: ${defaultString ? `{ ${defaultString} }` : `{}`}`
281292
}

0 commit comments

Comments
 (0)