-
-
Notifications
You must be signed in to change notification settings - Fork 102
/
index.ts
107 lines (88 loc) · 2.69 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import {
DEFINE_OPTIONS,
MagicString,
addNormalScript,
checkInvalidScopeReference,
getTransformResult,
importHelperFn,
parseSFC,
} from '@vue-macros/common'
import { walkAST } from 'ast-walker-scope'
import {
type ExportDefaultDeclaration,
type Program,
type Statement,
} from '@babel/types'
import { filterMacro, hasPropsOrEmits as hasDisallowedProp } from './utils'
export * from './utils'
export function transformDefineOptions(code: string, id: string) {
if (!code.includes(DEFINE_OPTIONS)) return
const sfc = parseSFC(code, id)
if (!sfc.scriptSetup) return
const { scriptSetup, getSetupAst, getScriptAst } = sfc
const setupOffset = scriptSetup.loc.start.offset
const setupAst = getSetupAst()!
const nodes = filterMacro(setupAst!.body)
if (nodes.length === 0) {
return
} else if (nodes.length > 1)
throw new SyntaxError(`duplicate ${DEFINE_OPTIONS}() call`)
const scriptAst = getScriptAst()!
if (scriptAst) checkDefaultExport(scriptAst.body)
const setupBindings = getRootScopeIds(setupAst)
const s = new MagicString(code)
const [node] = nodes
const [arg] = node.arguments
if (arg) {
const normalScript = addNormalScript(sfc, s)
const scriptOffset = normalScript.start()
s.appendLeft(
scriptOffset,
`\nexport default /*#__PURE__*/ ${importHelperFn(
s,
scriptOffset,
'defineComponent'
)}(`
)
if (arg.type === 'ObjectExpression' && hasDisallowedProp(arg))
throw new SyntaxError(
`${DEFINE_OPTIONS}() please use defineProps, defineEmits, defineExpose, or defineSlots instead.`
)
checkInvalidScopeReference(arg, DEFINE_OPTIONS, setupBindings)
s.moveNode(arg, scriptOffset, { offset: setupOffset })
// removes defineOptions()
s.remove(setupOffset + node.start!, setupOffset + arg.start!)
s.remove(setupOffset + arg.end!, setupOffset + node.end!)
s.appendRight(scriptOffset, ');')
normalScript.end()
} else {
// removes defineOptions()
s.removeNode(node, { offset: setupOffset })
}
return getTransformResult(s, id)
}
function checkDefaultExport(stmts: Statement[]) {
const hasDefaultExport = stmts.some(
(node): node is ExportDefaultDeclaration =>
node.type === 'ExportDefaultDeclaration'
)
if (hasDefaultExport)
throw new SyntaxError(
`${DEFINE_OPTIONS} cannot be used with default export within <script>.`
)
}
function getRootScopeIds(program: Program) {
let ids: string[] = []
walkAST(program, {
enter(node) {
if (node.type === 'BlockStatement') {
this.skip()
}
},
leave(node) {
if (node.type !== 'Program') return
ids = Object.keys(this.scope)
},
})
return ids
}