7
7
import {
8
8
Cache ,
9
9
createCache ,
10
+ first ,
11
+ invariant ,
10
12
rebaseSourceMap ,
11
13
SourceTransformer ,
12
14
} from '@vuedx/shared'
@@ -15,6 +17,7 @@ import type {
15
17
TransformOptionsResolved ,
16
18
} from '../types/TransformOptions'
17
19
import { transformCustomBlock } from './blocks/transformCustomBlock'
20
+ import { createProgram } from '@vuedx/transforms'
18
21
19
22
import type { RootNode } from '@vue/compiler-core'
20
23
import type { RawSourceMap } from 'source-map'
@@ -219,64 +222,61 @@ export function compileWithDecodedSourceMap(
219
222
} )
220
223
221
224
const exported = [
222
- scriptSetup . exportIdentifier ,
223
- scriptSetup . propsIdentifier ,
224
- scriptSetup . emitsIdentifier ,
225
- scriptSetup . exposeIdentifier ,
226
- template . attrsIdentifier ,
227
- template . slotsIdentifier ,
228
- resolvedOptions . contextIdentifier ,
225
+ ...( descriptor . scriptSetup == null
226
+ ? [ template . attrsIdentifier , template . slotsIdentifier , contextIdentifier ]
227
+ : [ scriptSetup . componentIdentifier ] ) ,
229
228
...Object . values ( scriptSetup . exports ) ,
230
229
] . join ( ', ' )
231
230
232
- builder . append ( `return {${ exported } };}) ;` )
231
+ builder . append ( `return {${ exported } };};` )
233
232
builder . nextLine ( )
234
- builder . append ( `const {${ exported } } = ${ scriptSetup . scopeIdentifier } ;\n` )
233
+ builder . append ( `const {${ exported } } = ${ scriptSetup . scopeIdentifier } () ;\n` )
235
234
Object . entries ( scriptSetup . exports ) . forEach ( ( [ name , identifier ] ) => {
236
235
builder . append ( `export type ${ name } = typeof ${ identifier } ;\n` )
237
236
} )
238
237
239
238
region ( 'public component definition' , ( ) => {
240
- const props = `${ resolvedOptions . contextIdentifier } .$props`
241
-
242
- const parentClassIfAny = ` extends ${ name } Public`
243
- const type = `new () => typeof ${ scriptSetup . exposeIdentifier } `
244
- if ( resolvedOptions . isTypeScript ) {
245
- builder . append ( `const ${ name } Public = null as unknown as ${ type } ;` )
246
- builder . nextLine ( )
239
+ if ( descriptor . scriptSetup == null ) {
240
+ const props = `${ resolvedOptions . contextIdentifier } .$props`
241
+ const inheritAttrs =
242
+ descriptor . template ?. content . includes ( '@vue-attrs-target' ) === true ||
243
+ script . inheritAttrs
244
+ const propsType = `typeof ${ props } `
245
+ const attrsType = `typeof ${ template . attrsIdentifier } `
246
+ const slotsType = `${ resolvedOptions . typeIdentifier } .internal.Slots<ReturnType<typeof ${ template . slotsIdentifier } >>`
247
+ builder . append (
248
+ [
249
+ `export default class ${ name } {` ,
250
+ defineProperty (
251
+ '$props' ,
252
+ inheritAttrs
253
+ ? `${ resolvedOptions . typeIdentifier } .internal.MergeAttrs<${ propsType } , ${ attrsType } > & {$slots: ${ slotsType } }`
254
+ : `${ propsType } & {$slots: ${ slotsType } }` ,
255
+ ) ,
256
+ `}` ,
257
+ ] . join ( '\n' ) ,
258
+ )
247
259
} else {
260
+ const generic =
261
+ typeof descriptor . scriptSetup . attrs [ 'generic' ] === 'string'
262
+ ? descriptor . scriptSetup . attrs [ 'generic' ]
263
+ : ''
264
+ const typeArgs = parseGenericArgNames ( generic )
265
+
266
+ const component =
267
+ typeArgs . length > 0
268
+ ? `(new (${ scriptSetup . scopeIdentifier } <${ typeArgs . join ( ', ' ) } >().${
269
+ scriptSetup . componentIdentifier
270
+ } <${ typeArgs . join ( ', ' ) } >))`
271
+ : `(new (${ scriptSetup . scopeIdentifier } ().${ scriptSetup . componentIdentifier } ))`
272
+
273
+ const genericExp = typeArgs . length > 0 ? `<${ generic } >` : ''
274
+ builder . append ( `export default class ${ name } ${ genericExp } {\n` )
248
275
builder . append (
249
- `const ${ name } Public = /** @type { ${ type } } */ (/** @type {unknown} */ (null)); ` ,
276
+ ` $props = {... ${ component } .$props, $slots: ${ component } .$slots };\n ` ,
250
277
)
251
- builder . nextLine ( )
278
+ builder . append ( `}` )
252
279
}
253
-
254
- const inheritAttrs =
255
- descriptor . template ?. content . includes ( '@vue-attrs-target' ) === true ||
256
- script . inheritAttrs
257
-
258
- const propsType =
259
- descriptor . scriptSetup != null
260
- ? `typeof ${ props } & ${ resolvedOptions . typeIdentifier } .internal.EmitsToProps<typeof ${ scriptSetup . emitsIdentifier } >`
261
- : `typeof ${ props } `
262
- const attrsType = `typeof ${ template . attrsIdentifier } `
263
-
264
- builder . append (
265
- [
266
- `export default class ${ name } ${ parentClassIfAny } {` ,
267
- defineProperty (
268
- '$props' ,
269
- inheritAttrs
270
- ? `${ resolvedOptions . typeIdentifier } .internal.MergeAttrs<${ propsType } , ${ attrsType } >`
271
- : propsType ,
272
- ) ,
273
- defineProperty (
274
- '$slots' ,
275
- `${ resolvedOptions . typeIdentifier } .internal.Slots<ReturnType<typeof ${ template . slotsIdentifier } >>` ,
276
- ) ,
277
- `}` ,
278
- ] . join ( '\n' ) ,
279
- )
280
280
builder . nextLine ( )
281
281
} )
282
282
@@ -303,6 +303,17 @@ export function compileWithDecodedSourceMap(
303
303
? ` ${ name } = null as unknown as ${ type } ;`
304
304
: ` ${ name } = /** @type {${ type } } */ (/** @type {unknown} */ (null));`
305
305
}
306
+
307
+ function parseGenericArgNames ( code : string ) : string [ ] {
308
+ const ts = options . typescript
309
+ const program = createProgram ( ts , `function _<${ code } >() {}` )
310
+ const sourceFile = program . getSourceFile ( 'input.ts' )
311
+ invariant ( sourceFile != null , 'sourceFile should not be null' )
312
+ const decl = first ( sourceFile . statements )
313
+ invariant ( ts . isFunctionDeclaration ( decl ) )
314
+ invariant ( decl . typeParameters != null )
315
+ return decl . typeParameters . map ( ( p ) => p . name . getText ( ) )
316
+ }
306
317
}
307
318
308
319
function runIfNeeded < R > (
0 commit comments