Skip to content

Commit b9ae179

Browse files
authored
fix(language-core): hoist the variables that may cause TS4081 (#5192)
1 parent 50d3a8e commit b9ae179

File tree

5 files changed

+48
-37
lines changed

5 files changed

+48
-37
lines changed

Diff for: packages/language-core/lib/codegen/template/context.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
4343
return features;
4444
}
4545

46+
const hoistVars = new Map<string, string>();
4647
const localVars = new Map<string, number>();
4748
const specialVars = new Set<string>();
4849
const accessExternalVariables = new Map<string, Set<number>>();
@@ -67,7 +68,10 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
6768
const inlayHints: InlayHintInfo[] = [];
6869
const bindingAttrLocs: CompilerDOM.SourceLocation[] = [];
6970
const inheritedAttrVars = new Set<string>();
70-
const templateRefs = new Map<string, [varName: string, offset: number]>();
71+
const templateRefs = new Map<string, {
72+
varName: string;
73+
offset: number;
74+
}>();
7175

7276
return {
7377
codeFeatures: new Proxy(codeFeatures, {
@@ -116,6 +120,19 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
116120
getInternalVariable: () => {
117121
return `__VLS_${variableId++}`;
118122
},
123+
getHoistVariable: (originalVar: string) => {
124+
let name = hoistVars.get(originalVar);
125+
if (name === undefined) {
126+
hoistVars.set(originalVar, name = `__VLS_${variableId++}`);
127+
}
128+
return name;
129+
},
130+
generateHoistVariables: function* () {
131+
// trick to avoid TS 4081 (#5186)
132+
for (const [originalVar, hoistVar] of hoistVars) {
133+
yield `var ${hoistVar} = ${originalVar}${endOfLine}`;
134+
}
135+
},
119136
ignoreError: function* (): Generator<Code> {
120137
if (!ignoredError) {
121138
ignoredError = true;

Diff for: packages/language-core/lib/codegen/template/element.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ export function* generateComponent(
272272
yield `${endOfLine}`;
273273

274274
if (refName) {
275-
ctx.templateRefs.set(refName, [varName, offset!]);
275+
ctx.templateRefs.set(refName, {
276+
varName: ctx.getHoistVariable(varName),
277+
offset: offset!
278+
});
276279
}
277280
if (isRootNode) {
278281
ctx.singleRootElType = `NonNullable<typeof ${varName}>['$el']`;
@@ -358,11 +361,14 @@ export function* generateElement(
358361

359362
const [refName, offset] = yield* generateVScope(options, ctx, node, node.props);
360363
if (refName) {
361-
let refValue = `__VLS_nativeElements['${node.tag}']`;
364+
let element = `__VLS_nativeElements['${node.tag}']`;
362365
if (isVForChild) {
363-
refValue = `[${refValue}]`;
366+
element = `[${element}]`;
364367
}
365-
ctx.templateRefs.set(refName, [refValue, offset!]);
368+
ctx.templateRefs.set(refName, {
369+
varName: element,
370+
offset: offset!
371+
});
366372
}
367373
if (ctx.singleRootNode === node) {
368374
ctx.singleRootElType = `typeof __VLS_nativeElements['${node.tag}']`;

Diff for: packages/language-core/lib/codegen/template/index.ts

+4-16
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator<Co
4545
}
4646

4747
yield* generateStyleScopedClassReferences(ctx);
48+
yield* ctx.generateAutoImportCompletion();
49+
yield* ctx.generateHoistVariables();
50+
4851
const speicalTypes = [
4952
[slotsPropertyName, yield* generateSlots(options, ctx)],
5053
['$attrs', yield* generateInheritedAttrs(options, ctx)],
@@ -58,7 +61,6 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator<Co
5861
}
5962
yield `} & { [K in keyof import('${options.vueCompilerOptions.lib}').ComponentPublicInstance]: unknown }${endOfLine}`;
6063

61-
yield* ctx.generateAutoImportCompletion();
6264
return ctx;
6365
}
6466

@@ -67,20 +69,6 @@ function* generateSlots(
6769
ctx: TemplateCodegenContext
6870
): Generator<Code> {
6971
if (!options.hasDefineSlots) {
70-
const hoistVars = new Map<string, string>();
71-
72-
// trick to avoid TS 4081 (#5186)
73-
for (const slot of ctx.dynamicSlots) {
74-
hoistVars.set(slot.expVar, slot.expVar = ctx.getInternalVariable());
75-
hoistVars.set(slot.propsVar, slot.propsVar = ctx.getInternalVariable());
76-
}
77-
for (const slot of ctx.slots) {
78-
hoistVars.set(slot.propsVar, slot.propsVar = ctx.getInternalVariable());
79-
}
80-
for (const [originalVar, hoistVar] of hoistVars) {
81-
yield `var ${hoistVar} = ${originalVar}${endOfLine}`;
82-
}
83-
8472
const name = getSlotsPropertyName(options.vueCompilerOptions.target);
8573
yield `type __VLS_Slots = __VLS_PrettifyGlobal<__VLS_OmitStringIndex<typeof __VLS_ctx.${name}>`;
8674
for (const { expVar, propsVar } of ctx.dynamicSlots) {
@@ -145,7 +133,7 @@ function* generateTemplateRefs(
145133
ctx: TemplateCodegenContext
146134
): Generator<Code> {
147135
yield `type __VLS_TemplateRefs = {${newLine}`;
148-
for (const [name, [varName, offset]] of ctx.templateRefs) {
136+
for (const [name, { varName, offset }] of ctx.templateRefs) {
149137
yield* generateObjectProperty(
150138
options,
151139
ctx,

Diff for: packages/language-core/lib/codegen/template/slotOutlet.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export function* generateSlotOutlet(
131131
offset: nameProp.loc.start.offset + nameProp.loc.source.indexOf(nameProp.value.content, nameProp.name.length),
132132
tagRange: [startTagOffset, startTagOffset + node.tag.length],
133133
nodeLoc: node.loc,
134-
propsVar,
134+
propsVar: ctx.getHoistVariable(propsVar),
135135
});
136136
}
137137
else if (
@@ -155,16 +155,16 @@ export function* generateSlotOutlet(
155155
);
156156
yield `)${endOfLine}`;
157157
ctx.dynamicSlots.push({
158-
expVar,
159-
propsVar,
158+
expVar: ctx.getHoistVariable(expVar),
159+
propsVar: ctx.getHoistVariable(propsVar),
160160
});
161161
}
162162
else {
163163
ctx.slots.push({
164164
name: 'default',
165165
tagRange: [startTagOffset, startTagEndOffset],
166166
nodeLoc: node.loc,
167-
propsVar,
167+
propsVar: ctx.getHoistVariable(propsVar),
168168
});
169169
}
170170
}

Diff for: packages/tsc/tests/__snapshots__/dts.spec.ts.snap

+12-12
Original file line numberDiff line numberDiff line change
@@ -587,23 +587,23 @@ export {};
587587
588588
exports[`vue-tsc-dts > Input: template-slots/component.vue, Output: template-slots/component.vue.d.ts 1`] = `
589589
"declare const __VLS_ctx: InstanceType<__VLS_PickNotAny<typeof __VLS_self, new () => {}>>;
590-
declare var __VLS_4: {};
591-
declare var __VLS_5: {
590+
declare var __VLS_1: {};
591+
declare var __VLS_3: {
592592
num: number;
593593
};
594-
declare var __VLS_6: {
594+
declare var __VLS_5: {
595595
str: string;
596596
};
597597
declare var __VLS_7: {
598598
num: number;
599599
str: string;
600600
};
601601
type __VLS_Slots = __VLS_PrettifyGlobal<__VLS_OmitStringIndex<typeof __VLS_ctx.$slots> & {
602-
'no-bind'?: (props: typeof __VLS_4) => any;
602+
'no-bind'?: (props: typeof __VLS_1) => any;
603603
} & {
604-
default?: (props: typeof __VLS_5) => any;
604+
default?: (props: typeof __VLS_3) => any;
605605
} & {
606-
'named-slot'?: (props: typeof __VLS_6) => any;
606+
'named-slot'?: (props: typeof __VLS_5) => any;
607607
} & {
608608
vbind?: (props: typeof __VLS_7) => any;
609609
}>;
@@ -664,23 +664,23 @@ type __VLS_WithSlots<T, S> = T & {
664664
665665
exports[`vue-tsc-dts > Input: template-slots/component-no-script.vue, Output: template-slots/component-no-script.vue.d.ts 1`] = `
666666
"declare const __VLS_ctx: InstanceType<__VLS_PickNotAny<typeof __VLS_self, new () => {}>>;
667-
declare var __VLS_4: {};
668-
declare var __VLS_5: {
667+
declare var __VLS_1: {};
668+
declare var __VLS_3: {
669669
num: number;
670670
};
671-
declare var __VLS_6: {
671+
declare var __VLS_5: {
672672
str: string;
673673
};
674674
declare var __VLS_7: {
675675
num: number;
676676
str: string;
677677
};
678678
type __VLS_Slots = __VLS_PrettifyGlobal<__VLS_OmitStringIndex<typeof __VLS_ctx.$slots> & {
679-
'no-bind'?: (props: typeof __VLS_4) => any;
679+
'no-bind'?: (props: typeof __VLS_1) => any;
680680
} & {
681-
default?: (props: typeof __VLS_5) => any;
681+
default?: (props: typeof __VLS_3) => any;
682682
} & {
683-
'named-slot'?: (props: typeof __VLS_6) => any;
683+
'named-slot'?: (props: typeof __VLS_5) => any;
684684
} & {
685685
vbind?: (props: typeof __VLS_7) => any;
686686
}>;

0 commit comments

Comments
 (0)