Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(language-core): do not spread exposed object #5526

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 24 additions & 34 deletions packages/language-core/lib/codegen/script/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc } from '../../types';
import { codeFeatures } from '../codeFeatures';
import { endOfLine, generateSfcBlockSection, newLine } from '../utils';
import { generateIntersectMerge, generateSpreadMerge } from '../utils/merge';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';

Expand Down Expand Up @@ -29,15 +30,23 @@ export function* generateComponent(
}

yield `setup() {${newLine}`;
yield `return {${newLine}`;
const returns: Code[] = [];
if (ctx.bypassDefineComponent) {
yield* `const __VLS_returns = {${newLine}`;
yield* generateComponentSetupReturns(scriptSetupRanges);
yield `}${endOfLine}`;
returns.push(`typeof __VLS_returns`);
}
if (scriptSetupRanges.defineExpose) {
yield `...__VLS_exposed,${newLine}`;
returns.push(`typeof __VLS_exposed`);
}
if (returns.length) {
yield `return {} as `;
yield* generateIntersectMerge(returns);
yield endOfLine;
}
yield `}${endOfLine}`;
yield `},${newLine}`;

if (!ctx.bypassDefineComponent) {
const emitOptionCodes = [...generateEmitsOption(options, scriptSetupRanges)];
yield* emitOptionCodes;
Expand Down Expand Up @@ -100,10 +109,14 @@ export function* generateEmitsOption(
}

if (options.vueCompilerOptions.target >= 3.5 && typeOptionCodes.length) {
yield* generateIntersectMerge('__typeEmits', typeOptionCodes);
yield `__typeEmits: {} as `;
yield* generateIntersectMerge(typeOptionCodes);
yield `,${newLine}`;
}
else if (optionCodes.length) {
yield* generateSpreadMerge('emits', optionCodes);
yield `emits: `;
yield* generateSpreadMerge(optionCodes);
yield `,${newLine}`;
}
}

Expand Down Expand Up @@ -159,36 +172,13 @@ export function* generatePropsOption(
) {
yield `__defaults: __VLS_withDefaultsArg,${newLine}`;
}
yield* generateSpreadMerge('__typeProps', typeOptionCodes);
yield `__typeProps: `;
yield* generateSpreadMerge(typeOptionCodes);
yield `,${newLine}`;
}
if (useOption) {
yield* generateSpreadMerge('props', getOptionCodes.map(fn => fn()));
}
}

function* generateIntersectMerge(key: string, codes: Code[]): Generator<Code> {
yield `${key}: {} as `;
yield codes[0];
for (let i = 1; i < codes.length; i++) {
yield ` & `;
yield codes[i];
}
yield `,${newLine}`;
}

function* generateSpreadMerge(key: string, codes: Code[]): Generator<Code> {
yield `${key}: `;
if (codes.length === 1) {
yield codes[0];
}
else {
yield `{${newLine}`;
for (const code of codes) {
yield `...`;
yield code;
yield `,${newLine}`;
}
yield `}`;
yield `props: `;
yield* generateSpreadMerge(getOptionCodes.map(fn => fn()));
yield `,${newLine}`;
}
yield `,${newLine}`;
}
26 changes: 5 additions & 21 deletions packages/language-core/lib/codegen/script/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createTemplateCodegenContext, type TemplateCodegenContext } from '../te
import { generateInterpolation } from '../template/interpolation';
import { generateStyleScopedClassReferences } from '../template/styleScopedClasses';
import { endOfLine, newLine } from '../utils';
import { generateIntersectMerge, generateSpreadMerge } from '../utils/merge';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';

Expand Down Expand Up @@ -40,19 +41,8 @@ function* generateTemplateCtx(options: ScriptCodegenOptions): Generator<Code> {
}

yield `const __VLS_ctx = `;
if (exps.length === 1) {
yield exps[0];
yield `${endOfLine}`;
}
else {
yield `{${newLine}`;
for (const exp of exps) {
yield `...`;
yield exp;
yield `,${newLine}`;
}
yield `}${endOfLine}`;
}
yield* generateSpreadMerge(exps);
yield endOfLine;
}

function* generateTemplateElements(): Generator<Code> {
Expand All @@ -76,10 +66,7 @@ function* generateTemplateComponents(options: ScriptCodegenOptions): Generator<C
}

yield `type __VLS_LocalComponents =`;
for (const type of types) {
yield ` & `;
yield type;
}
yield* generateIntersectMerge(types);
yield endOfLine;

yield `let __VLS_components!: __VLS_LocalComponents & __VLS_GlobalComponents${endOfLine}`;
Expand All @@ -102,10 +89,7 @@ export function* generateTemplateDirectives(options: ScriptCodegenOptions): Gene
}

yield `type __VLS_LocalDirectives =`;
for (const type of types) {
yield ` & `;
yield type;
}
yield* generateIntersectMerge(types);
yield endOfLine;

yield `let __VLS_directives!: __VLS_LocalDirectives & __VLS_GlobalDirectives${endOfLine}`;
Expand Down
25 changes: 25 additions & 0 deletions packages/language-core/lib/codegen/utils/merge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Code } from '../../types';
import { newLine } from './index';

export function* generateIntersectMerge(codes: Code[]): Generator<Code> {
yield codes[0];
for (let i = 1; i < codes.length; i++) {
yield ` & `;
yield codes[i];
}
}

export function* generateSpreadMerge(codes: Code[]): Generator<Code> {
if (codes.length === 1) {
yield codes[0];
}
else {
yield `{${newLine}`;
for (const code of codes) {
yield `...`;
yield code;
yield `,${newLine}`;
}
yield `}`;
}
}
22 changes: 11 additions & 11 deletions packages/tsc/tests/__snapshots__/dts.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type __VLS_PrettifyLocal<T> = {

exports[`vue-tsc-dts > Input: empty-component/component.vue, Output: empty-component/component.vue.d.ts 1`] = `
"declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand All @@ -55,7 +55,7 @@ export default _default;

exports[`vue-tsc-dts > Input: empty-component/custom-extension-component.cext, Output: empty-component/custom-extension-component.cext.d.ts 1`] = `
"declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -141,7 +141,7 @@ type __VLS_PrettifyLocal<T> = {

exports[`vue-tsc-dts > Input: generic/main.vue, Output: generic/main.vue.d.ts 1`] = `
"declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -243,7 +243,7 @@ export default _default;
exports[`vue-tsc-dts > Input: reference-type-events/component.vue, Output: reference-type-events/component.vue.d.ts 1`] = `
"import type { MyEvents } from './my-events';
declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -339,7 +339,7 @@ type __VLS_ModelEmit = {
'update:bar': [value: string | undefined];
};
declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand All @@ -366,7 +366,7 @@ export default _default;
exports[`vue-tsc-dts > Input: reference-type-props/component.vue, Output: reference-type-props/component.vue.d.ts 1`] = `
"import { MyProps } from './my-props';
declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -398,7 +398,7 @@ exports[`vue-tsc-dts > Input: reference-type-props/component-destructure.vue, Ou
text: string;
};
declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -473,7 +473,7 @@ export default _default;

exports[`vue-tsc-dts > Input: reference-type-props/component-js-setup.vue, Output: reference-type-props/component-js-setup.vue.d.ts 1`] = `
"declare const _default: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {
foo: {
Expand Down Expand Up @@ -667,7 +667,7 @@ type __VLS_Slots = {} & {
vbind?: (props: typeof __VLS_7) => any;
};
declare const __VLS_component: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -713,7 +713,7 @@ type __VLS_Slots = {
'no-bind': () => VNode[];
};
declare const __VLS_component: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down Expand Up @@ -762,7 +762,7 @@ type __VLS_Slots = {} & {
vbind?: (props: typeof __VLS_7) => any;
};
declare const __VLS_component: import("vue").DefineComponent2<{
setup(): {};
setup(): void;
data(): {};
props: {};
computed: {};
Expand Down
12 changes: 3 additions & 9 deletions test-workspace/tsc/passedFixtures/vue3.4/components/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ const ScriptSetupExact = defineComponent({
change(..._payload: any[]) { },
delete(..._payload: any[]) { },
},
setup() {
return {};
},
setup() {},
});
// https://vuejs.org/api/sfc-script-setup.html#defineexpose
const ScriptSetupExposeExact = defineComponent({
Expand All @@ -44,9 +42,7 @@ const ScriptSetupTypeOnlyExact = defineComponent({
change(_id: number) { },
update(_value: string) { },
},
setup() {
return {};
},
setup() {},
});
// https://vuejs.org/api/sfc-script-setup.html#default-props-values-when-using-type-declaration
const ScriptSetupDefaultPropsExact = defineComponent({
Expand All @@ -60,9 +56,7 @@ const ScriptSetupDefaultPropsExact = defineComponent({
default: () => ['one', 'two']
},
},
setup() {
return {};
},
setup() {},
});
// vue 3.3 generic
declare const ScriptSetupGenericExact: <T, >(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ const ScriptSetupExact = defineComponent({
"update:f": (_: string) => void
"update:g": (_: string | undefined) => void
},
setup() {
return {};
},
setup() {},
});
exactType(ScriptSetup, ScriptSetupExact);
Expand Down
12 changes: 3 additions & 9 deletions test-workspace/tsc/passedFixtures/vue3/components/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ const ScriptSetupExact = defineComponent({
change(..._payload: any[]) { },
delete(..._payload: any[]) { },
},
setup() {
return {};
},
setup() {},
});
// https://vuejs.org/api/sfc-script-setup.html#defineexpose
const ScriptSetupExposeExact = defineComponent({
Expand All @@ -41,9 +39,7 @@ const ScriptSetupTypeOnlyExact = defineComponent({
(e: 'change', id: number): void;
(e: 'update', value: string): void;
},
setup() {
return {};
},
setup() {},
});
// https://vuejs.org/api/sfc-script-setup.html#default-props-values-when-using-type-declaration
const ScriptSetupDefaultPropsExact = defineComponent({
Expand All @@ -55,9 +51,7 @@ const ScriptSetupDefaultPropsExact = defineComponent({
msg: 'hello',
labels: () => ['one', 'two']
},
setup() {
return {};
},
setup() {},
});
// vue 3.3 generic
declare const ScriptSetupGenericExact: <T, >(
Expand Down
4 changes: 1 addition & 3 deletions test-workspace/tsc/passedFixtures/vue3/defineModel/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ const ScriptSetupExact = defineComponent({
'update:f': [f: string | undefined];
'update:gG': [g: string | undefined];
},
setup() {
return {};
},
setup() {},
});
exactType(ScriptSetup, ScriptSetupExact);
Expand Down
Loading