@mpxjs/webpack-plugin 2.7.52 → 2.8.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config.js +24 -24
- package/lib/dependencies/CommonJsVariableDependency.js +1 -1
- package/lib/dependencies/DynamicEntryDependency.js +18 -11
- package/lib/extractor.js +1 -1
- package/lib/helpers.js +3 -1
- package/lib/index.js +24 -21
- package/lib/json-compiler/helper.js +1 -1
- package/lib/json-compiler/index.js +17 -17
- package/lib/json-compiler/plugin.js +3 -2
- package/lib/json-compiler/theme.js +1 -1
- package/lib/loader.js +3 -3
- package/lib/native-loader.js +1 -1
- package/lib/platform/json/normalize-test.js +3 -1
- package/lib/platform/run-rules.js +2 -2
- package/lib/platform/template/wx/component-config/camera.js +3 -3
- package/lib/platform/template/wx/component-config/canvas.js +5 -5
- package/lib/platform/template/wx/component-config/map.js +5 -5
- package/lib/platform/template/wx/component-config/navigator.js +7 -7
- package/lib/platform/template/wx/component-config/progress.js +4 -4
- package/lib/platform/template/wx/component-config/scroll-view.js +3 -3
- package/lib/platform/template/wx/component-config/slider.js +6 -6
- package/lib/platform/template/wx/component-config/swiper.js +2 -2
- package/lib/platform/template/wx/component-config/video.js +4 -4
- package/lib/platform/template/wx/component-config/view.js +4 -4
- package/lib/platform/template/wx/index.js +45 -13
- package/lib/resolver/PackageEntryPlugin.js +1 -1
- package/lib/runtime/components/web/filterTag.js +6 -6
- package/lib/runtime/components/web/getInnerListeners.js +1 -1
- package/lib/runtime/components/web/mpx-button.vue +0 -1
- package/lib/runtime/components/web/mpx-icon.vue +1 -1
- package/lib/runtime/components/web/mpx-keep-alive.vue +2 -2
- package/lib/runtime/components/web/mpx-picker.vue +1 -1
- package/lib/runtime/components/web/mpx-progress.vue +1 -1
- package/lib/runtime/components/web/mpx-scroll-view.vue +1 -1
- package/lib/runtime/env.js +1 -0
- package/lib/runtime/i18n.wxs +44 -81
- package/lib/runtime/optionProcessor.d.ts +0 -4
- package/lib/runtime/optionProcessor.js +15 -13
- package/lib/runtime/stringify.wxs +3 -3
- package/lib/runtime/swanHelper.wxs +2 -2
- package/lib/runtime/{components/web/util.js → utils.js} +8 -5
- package/lib/script-setup-compiler/index.js +1163 -0
- package/lib/style-compiler/index.js +1 -1
- package/lib/style-compiler/plugins/rpx.js +1 -1
- package/lib/style-compiler/plugins/vw.js +6 -4
- package/lib/template-compiler/bind-this.js +5 -5
- package/lib/template-compiler/compiler.js +122 -179
- package/lib/template-compiler/index.js +3 -3
- package/lib/utils/add-query.js +2 -1
- package/lib/utils/gen-component-tag.js +1 -1
- package/lib/utils/has-own.js +5 -0
- package/lib/utils/is-empty-object.js +2 -1
- package/lib/utils/parse-request.js +3 -3
- package/lib/utils/{index.js → process-defs.js} +3 -10
- package/lib/utils/stringify-query.js +23 -21
- package/lib/web/processJSON.js +5 -5
- package/lib/web/processScript.js +16 -19
- package/lib/web/processTemplate.js +1 -1
- package/lib/wxml/loader.js +3 -3
- package/lib/wxs/i18n-loader.js +4 -11
- package/lib/wxs/pre-loader.js +51 -44
- package/lib/wxss/compile-exports.js +4 -4
- package/lib/wxss/createResolver.js +3 -3
- package/lib/wxss/css-base.js +13 -13
- package/lib/wxss/getLocalIdent.js +5 -4
- package/lib/wxss/loader.js +1 -1
- package/lib/wxss/localsLoader.js +14 -14
- package/lib/wxss/processCss.js +10 -7
- package/package.json +4 -3
- package/lib/utils/env.js +0 -4
- package/lib/utils/parse-asset.js +0 -195
|
@@ -0,0 +1,1163 @@
|
|
|
1
|
+
const babylon = require('@babel/parser')
|
|
2
|
+
const MagicString = require('magic-string')
|
|
3
|
+
const traverse = require('@babel/traverse').default
|
|
4
|
+
const t = require('@babel/types')
|
|
5
|
+
const formatCodeFrame = require('@babel/code-frame')
|
|
6
|
+
const parseRequest = require('../utils/parse-request')
|
|
7
|
+
|
|
8
|
+
// Special compiler macros
|
|
9
|
+
const DEFINE_PROPS = 'defineProps'
|
|
10
|
+
const DEFINE_OPTIONS = 'defineOptions'
|
|
11
|
+
const DEFINE_EXPOSE = 'defineExpose'
|
|
12
|
+
const WITH_DEFAULTS = 'withDefaults'
|
|
13
|
+
|
|
14
|
+
const MPX_CORE = '@mpxjs/core'
|
|
15
|
+
|
|
16
|
+
const BindingTypes = {
|
|
17
|
+
/**
|
|
18
|
+
* declared as a prop
|
|
19
|
+
*/
|
|
20
|
+
PROPS: 'props',
|
|
21
|
+
/**
|
|
22
|
+
* a local alias of a `<script setup>` destructured prop.
|
|
23
|
+
* the original is stored in __propsAliases of the bindingMetadata object.
|
|
24
|
+
*/
|
|
25
|
+
PROPS_ALIASED: 'props-aliased',
|
|
26
|
+
/**
|
|
27
|
+
* a let binding (may or may not be a ref)
|
|
28
|
+
*/
|
|
29
|
+
SETUP_LET: 'setup-let',
|
|
30
|
+
/**
|
|
31
|
+
* a const binding that can never be a ref.
|
|
32
|
+
* these bindings don't need `unref()` calls when processed in inlined
|
|
33
|
+
* template expressions.
|
|
34
|
+
*/
|
|
35
|
+
SETUP_CONST: 'setup-const',
|
|
36
|
+
/**
|
|
37
|
+
* a const binding that does not need `unref()`, but may be mutated.
|
|
38
|
+
*/
|
|
39
|
+
SETUP_REACTIVE_CONST: 'setup-reactive-const',
|
|
40
|
+
/**
|
|
41
|
+
* a const binding that may be a ref.
|
|
42
|
+
*/
|
|
43
|
+
SETUP_MAYBE_REF: 'setup-maybe-ref',
|
|
44
|
+
/**
|
|
45
|
+
* bindings that are guaranteed to be refs
|
|
46
|
+
*/
|
|
47
|
+
SETUP_REF: 'setup-ref',
|
|
48
|
+
/**
|
|
49
|
+
* declared by other options, e.g. computed, inject
|
|
50
|
+
*/
|
|
51
|
+
OPTIONS: 'options'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function compileScriptSetup (
|
|
55
|
+
scriptSetup,
|
|
56
|
+
ctorType,
|
|
57
|
+
filePath
|
|
58
|
+
) {
|
|
59
|
+
const content = scriptSetup.content
|
|
60
|
+
const _s = new MagicString(content)
|
|
61
|
+
const scriptBindings = Object.create(null)
|
|
62
|
+
const setupBindings = Object.create(null)
|
|
63
|
+
const userImportAlias = Object.create(null)
|
|
64
|
+
const userImports = Object.create(null)
|
|
65
|
+
// const genSourceMap = false
|
|
66
|
+
|
|
67
|
+
let startOffset = 0
|
|
68
|
+
let endOffset = 0
|
|
69
|
+
let hasDefinePropsCall = false
|
|
70
|
+
let hasDefineOptionsCall = false
|
|
71
|
+
let hasDefineExposeCall = false
|
|
72
|
+
|
|
73
|
+
let propsRuntimeDecl
|
|
74
|
+
let propsRuntimeDefaults
|
|
75
|
+
let propsTypeDeclRaw
|
|
76
|
+
let propsTypeDecl
|
|
77
|
+
let propsIdentifier
|
|
78
|
+
let optionsRuntimeDecl
|
|
79
|
+
let exposeRuntimeDecl
|
|
80
|
+
|
|
81
|
+
const scriptSetupLang = scriptSetup && scriptSetup.lang
|
|
82
|
+
const isTS =
|
|
83
|
+
scriptSetupLang === 'ts' ||
|
|
84
|
+
scriptSetupLang === 'tsx'
|
|
85
|
+
const plugins = []
|
|
86
|
+
|
|
87
|
+
if (isTS) plugins.push('typescript', 'decorators-legacy')
|
|
88
|
+
|
|
89
|
+
// props/emits declared via types
|
|
90
|
+
const typeDeclaredProps = {}
|
|
91
|
+
const declaredTypes = {}
|
|
92
|
+
|
|
93
|
+
function error (
|
|
94
|
+
msg,
|
|
95
|
+
node,
|
|
96
|
+
end
|
|
97
|
+
) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`[@mpxjs/webpack-plugin script-setup-compiler] ${msg}\n\n${filePath}\n${formatCodeFrame(
|
|
100
|
+
content,
|
|
101
|
+
node.start + startOffset,
|
|
102
|
+
end
|
|
103
|
+
)}`
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function registerUserImport (
|
|
108
|
+
source,
|
|
109
|
+
local,
|
|
110
|
+
imported = false,
|
|
111
|
+
isType,
|
|
112
|
+
isFromSetup = true,
|
|
113
|
+
needTemplateUsageCheck
|
|
114
|
+
) {
|
|
115
|
+
if (source === MPX_CORE && imported) {
|
|
116
|
+
userImportAlias[imported] = local
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
userImports[local] = {
|
|
120
|
+
isType,
|
|
121
|
+
imported: imported || 'default',
|
|
122
|
+
source,
|
|
123
|
+
isFromSetup
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function processDefineExpose (node, declId) {
|
|
128
|
+
if (!isCallOf(node, DEFINE_EXPOSE)) {
|
|
129
|
+
return false
|
|
130
|
+
}
|
|
131
|
+
if (hasDefineExposeCall) {
|
|
132
|
+
error(`duplicate ${DEFINE_EXPOSE}() call`, node)
|
|
133
|
+
}
|
|
134
|
+
hasDefineExposeCall = true
|
|
135
|
+
exposeRuntimeDecl = node.arguments[0]
|
|
136
|
+
|
|
137
|
+
if (node.typeParameters) {
|
|
138
|
+
error(`${DEFINE_EXPOSE} is not support type parameters`, node)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (declId) {
|
|
142
|
+
console.warn(`${DEFINE_OPTIONS} no return value, please check it`, declId)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return true
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function processDefineOptions (node, declId) {
|
|
149
|
+
if (!isCallOf(node, DEFINE_OPTIONS)) {
|
|
150
|
+
return false
|
|
151
|
+
}
|
|
152
|
+
if (hasDefineOptionsCall) {
|
|
153
|
+
error(`duplicate ${DEFINE_OPTIONS}() call`, node)
|
|
154
|
+
}
|
|
155
|
+
hasDefineOptionsCall = true
|
|
156
|
+
const arg0 = node.arguments[0]
|
|
157
|
+
if (arg0.type === 'ObjectExpression') {
|
|
158
|
+
optionsRuntimeDecl = arg0.properties
|
|
159
|
+
} else {
|
|
160
|
+
error(`${DEFINE_OPTIONS} input parameter must be an object`)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (node.typeParameters) {
|
|
164
|
+
error(`${DEFINE_OPTIONS} is not support type parameters`, node)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (declId) {
|
|
168
|
+
console.warn(`${DEFINE_OPTIONS} no return value, please check it`, declId)
|
|
169
|
+
}
|
|
170
|
+
return true
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function processDefineProps (node, declId) {
|
|
174
|
+
if (!isCallOf(node, DEFINE_PROPS)) {
|
|
175
|
+
return false
|
|
176
|
+
}
|
|
177
|
+
if (hasDefinePropsCall) {
|
|
178
|
+
error(`duplicate ${DEFINE_PROPS}() call`, node)
|
|
179
|
+
}
|
|
180
|
+
hasDefinePropsCall = true
|
|
181
|
+
propsRuntimeDecl = node.arguments[0]
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* defineProps<{
|
|
185
|
+
* foo: string
|
|
186
|
+
* bar?: number
|
|
187
|
+
* }>()
|
|
188
|
+
*/
|
|
189
|
+
if (node.typeParameters) {
|
|
190
|
+
if (propsRuntimeDecl) {
|
|
191
|
+
error(
|
|
192
|
+
`${DEFINE_PROPS}() cannot accept both type and non-type arguments ` +
|
|
193
|
+
'at the same time. Use one or the other.',
|
|
194
|
+
node
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
propsTypeDeclRaw = node.typeParameters.params[0]
|
|
199
|
+
propsTypeDecl = resolveQualifiedType(
|
|
200
|
+
propsTypeDeclRaw,
|
|
201
|
+
node => node.type === 'TSFunctionType' || node.type === 'TSTypeLiteral'
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
if (!propsTypeDecl) {
|
|
205
|
+
error(
|
|
206
|
+
`type argument passed to ${DEFINE_PROPS}() must be a literal type, ` +
|
|
207
|
+
'or a reference to an interface or literal type.',
|
|
208
|
+
propsTypeDeclRaw
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 处理 VariableDeclaration declarations id
|
|
214
|
+
if (declId) {
|
|
215
|
+
propsIdentifier = content.slice(declId.start, declId.end)
|
|
216
|
+
}
|
|
217
|
+
return true
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function processWithDefaults (node, declId) {
|
|
221
|
+
if (!isCallOf(node, WITH_DEFAULTS)) {
|
|
222
|
+
return false
|
|
223
|
+
}
|
|
224
|
+
if (processDefineProps(node.arguments[0], declId)) {
|
|
225
|
+
if (propsRuntimeDecl) {
|
|
226
|
+
error(
|
|
227
|
+
`${WITH_DEFAULTS} can only be used with type-based ` +
|
|
228
|
+
`${DEFINE_PROPS} declaration.`,
|
|
229
|
+
node
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
propsRuntimeDefaults = node.arguments[1]
|
|
233
|
+
if (
|
|
234
|
+
!propsRuntimeDefaults ||
|
|
235
|
+
propsRuntimeDefaults.type !== 'ObjectExpression'
|
|
236
|
+
) {
|
|
237
|
+
error(
|
|
238
|
+
`The 2nd argument of ${WITH_DEFAULTS} must be an object literal.`,
|
|
239
|
+
propsRuntimeDefaults || node
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
error(
|
|
244
|
+
`${WITH_DEFAULTS}' first argument must be a ${DEFINE_PROPS} call.`,
|
|
245
|
+
node.arguments[0] || node
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
return true
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function resolveQualifiedType (node, qualifier) {
|
|
252
|
+
if (qualifier(node)) {
|
|
253
|
+
return node
|
|
254
|
+
}
|
|
255
|
+
// TSTypeReference defineProps<Props>()
|
|
256
|
+
if (node.type === 'TSTypeReference' && node.typeName.type === 'Identifier') {
|
|
257
|
+
const refName = node.typeName.name
|
|
258
|
+
const isQualifiedType = (node) => {
|
|
259
|
+
// interface Props TSInterfaceDeclaration
|
|
260
|
+
if (node.type === 'TSInterfaceDeclaration' && node.id.name === refName) {
|
|
261
|
+
return node.body
|
|
262
|
+
}
|
|
263
|
+
// type Props TSTypeAliasDeclaration
|
|
264
|
+
if (node.type === 'TSTypeAliasDeclaration' && node.id.name === refName && qualifier(node.typeAnnotation)) {
|
|
265
|
+
return node.typeAnnotation
|
|
266
|
+
}
|
|
267
|
+
// export type Props
|
|
268
|
+
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
|
|
269
|
+
return isQualifiedType(node.declaration)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const body = scriptSetupAst.program.body
|
|
273
|
+
for (const node of body) {
|
|
274
|
+
const qualified = isQualifiedType(node)
|
|
275
|
+
if (qualified) {
|
|
276
|
+
return qualified
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function hasStaticWithDefaults () {
|
|
283
|
+
return (
|
|
284
|
+
propsRuntimeDefaults &&
|
|
285
|
+
propsRuntimeDefaults.type === 'ObjectExpression' &&
|
|
286
|
+
propsRuntimeDefaults.properties.every(
|
|
287
|
+
node =>
|
|
288
|
+
(node.type === 'ObjectProperty' && !node.computed) ||
|
|
289
|
+
node.type === 'ObjectMethod'
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function genRuntimeProps (props) {
|
|
295
|
+
const keys = Object.keys(props)
|
|
296
|
+
if (!keys.length) {
|
|
297
|
+
return ''
|
|
298
|
+
}
|
|
299
|
+
const hasStaticDefaults = hasStaticWithDefaults()
|
|
300
|
+
const scriptSetupSource = content
|
|
301
|
+
const propsDecls = `{
|
|
302
|
+
${keys.map(key => {
|
|
303
|
+
let defaultString
|
|
304
|
+
if (hasStaticDefaults) {
|
|
305
|
+
const prop = propsRuntimeDefaults.properties.find(
|
|
306
|
+
node => node.key.name === key
|
|
307
|
+
)
|
|
308
|
+
if (prop) {
|
|
309
|
+
if (prop.type === 'ObjectProperty') {
|
|
310
|
+
defaultString = `value: ${scriptSetupSource.slice(
|
|
311
|
+
prop.value.start,
|
|
312
|
+
prop.value.end
|
|
313
|
+
)}`
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const { type } = props[key]
|
|
318
|
+
const propRuntimeTypes = toRuntimeTypeString(type)
|
|
319
|
+
if (propRuntimeTypes.optionalTypes) {
|
|
320
|
+
return `${key}: { type: ${propRuntimeTypes.type}, optionalTypes: ${propRuntimeTypes.optionalTypes}${
|
|
321
|
+
defaultString ? `, ${defaultString}` : ''
|
|
322
|
+
} }`
|
|
323
|
+
} else {
|
|
324
|
+
return `${key}: { type: ${propRuntimeTypes.type}${
|
|
325
|
+
defaultString ? `, ${defaultString}` : null
|
|
326
|
+
} }`
|
|
327
|
+
}
|
|
328
|
+
}).join(',\n ')}
|
|
329
|
+
}`
|
|
330
|
+
|
|
331
|
+
return `\n properties: ${propsDecls},`
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function checkInvalidScopeReference (node, method) {
|
|
335
|
+
if (!node) return
|
|
336
|
+
walkIdentifiers(node, id => {
|
|
337
|
+
if (setupBindings[id.name]) {
|
|
338
|
+
error(
|
|
339
|
+
`\`${method}()\` in <script setup> cannot reference locally ` +
|
|
340
|
+
'declared variables because it will be hoisted outside of the ' +
|
|
341
|
+
'setup() function.',
|
|
342
|
+
id
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
})
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// 1. parse <script setup> and walk over top level statements
|
|
349
|
+
const scriptSetupAst = babylon.parse(content, {
|
|
350
|
+
plugins: [
|
|
351
|
+
...plugins,
|
|
352
|
+
'topLevelAwait'
|
|
353
|
+
],
|
|
354
|
+
sourceType: 'module'
|
|
355
|
+
})
|
|
356
|
+
for (const node of scriptSetupAst.program.body) {
|
|
357
|
+
const start = node.start + startOffset
|
|
358
|
+
let end = node.end + startOffset
|
|
359
|
+
|
|
360
|
+
// 定位comment,例如 var a= 1; // a为属性
|
|
361
|
+
if (node.trailingComments && node.trailingComments.length > 0) {
|
|
362
|
+
const lastCommentNode =
|
|
363
|
+
node.trailingComments[node.trailingComments.length - 1]
|
|
364
|
+
end = lastCommentNode.end + startOffset
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// locate the end of whitespace between this statement and the next
|
|
368
|
+
while (end <= content.length) {
|
|
369
|
+
if (!/\s/.test(content.charAt(end))) {
|
|
370
|
+
break
|
|
371
|
+
}
|
|
372
|
+
end++
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (node.type === 'ImportDeclaration') {
|
|
376
|
+
// import declarations are moved to top
|
|
377
|
+
_s.move(start, end, 0)
|
|
378
|
+
// dedupe imports
|
|
379
|
+
let removed = 0
|
|
380
|
+
const removeSpecifier = (i) => {
|
|
381
|
+
const removeLeft = i > removed
|
|
382
|
+
removed++
|
|
383
|
+
const current = node.specifiers[i]
|
|
384
|
+
const next = node.specifiers[i + 1]
|
|
385
|
+
_s.remove(
|
|
386
|
+
removeLeft ? node.specifiers[i - 1].end + startOffset : current.start + startOffset,
|
|
387
|
+
next && !removeLeft ? next.start + startOffset : current.end + startOffset
|
|
388
|
+
)
|
|
389
|
+
}
|
|
390
|
+
// 判断defineProps等是否有被引入
|
|
391
|
+
// record imports for dedupe
|
|
392
|
+
for (let i = 0; i < node.specifiers.length; i++) {
|
|
393
|
+
const specifier = node.specifiers[i]
|
|
394
|
+
let imported = specifier.type === 'ImportSpecifier' && specifier.imported.type === 'Identifier' && specifier.imported.name
|
|
395
|
+
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
396
|
+
imported = '*'
|
|
397
|
+
}
|
|
398
|
+
const local = specifier.local.name
|
|
399
|
+
const source = node.source.value
|
|
400
|
+
const existing = userImports[local]
|
|
401
|
+
if (source === MPX_CORE && isCompilerMacro(imported)) {
|
|
402
|
+
console.warn(`${imported} is a compiler macro and no longer needs to be imported.`)
|
|
403
|
+
// 不需要经过
|
|
404
|
+
removeSpecifier(i)
|
|
405
|
+
} else if (existing) {
|
|
406
|
+
if (existing.source === source && existing.imported === imported) {
|
|
407
|
+
// already imported in <script setup>, dedupe
|
|
408
|
+
removeSpecifier(i)
|
|
409
|
+
} else {
|
|
410
|
+
error('different imports aliased to same local name.', specifier)
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
registerUserImport(
|
|
414
|
+
node.source.value,
|
|
415
|
+
specifier.local.name,
|
|
416
|
+
imported,
|
|
417
|
+
node.importKind === 'type' ||
|
|
418
|
+
(specifier.type === 'ImportSpecifier' &&
|
|
419
|
+
specifier.importKind === 'type'),
|
|
420
|
+
true
|
|
421
|
+
)
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (node.specifiers.length && removed === node.specifiers.length) {
|
|
425
|
+
_s.remove(node.start, node.end)
|
|
426
|
+
}
|
|
427
|
+
startOffset = node.loc.end.index
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// process defineProps defineOptions 等编译宏
|
|
431
|
+
if (node.type === 'ExpressionStatement') {
|
|
432
|
+
if (
|
|
433
|
+
processDefineProps(node.expression) ||
|
|
434
|
+
processDefineOptions(node.expression) ||
|
|
435
|
+
processDefineExpose(node.expression) ||
|
|
436
|
+
processWithDefaults(node.expression)
|
|
437
|
+
) {
|
|
438
|
+
_s.remove(node.start, node.end)
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (node.type === 'VariableDeclaration' && !node.declare) {
|
|
443
|
+
const total = node.declarations.length
|
|
444
|
+
let left = total
|
|
445
|
+
for (let i = 0; i < total; i++) {
|
|
446
|
+
const decl = node.declarations[i]
|
|
447
|
+
if (decl.init) {
|
|
448
|
+
const isDefineProps = processDefineProps(decl.init, decl.id) || processWithDefaults(decl.init, decl.id)
|
|
449
|
+
const isDefineOptions = processDefineOptions(decl.init, decl.id)
|
|
450
|
+
if (isDefineProps || isDefineOptions) {
|
|
451
|
+
if (left === 1) {
|
|
452
|
+
_s.remove(node.start, node.end)
|
|
453
|
+
} else {
|
|
454
|
+
// let a,b = defineProps({})
|
|
455
|
+
let start = decl.start
|
|
456
|
+
let end = decl.end
|
|
457
|
+
if (i < total - 1) {
|
|
458
|
+
// not the last one, locate the start of the next
|
|
459
|
+
end = node.declarations[i + 1].start
|
|
460
|
+
} else {
|
|
461
|
+
// last one, locate the end of the prev
|
|
462
|
+
start = node.declarations[i - 1].end
|
|
463
|
+
}
|
|
464
|
+
_s.remove(start, end)
|
|
465
|
+
left--
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// walk declarations to record declared bindings
|
|
473
|
+
if (
|
|
474
|
+
(node.type === 'VariableDeclaration' ||
|
|
475
|
+
node.type === 'FunctionDeclaration' ||
|
|
476
|
+
node.type === 'ClassDeclaration') &&
|
|
477
|
+
!node.declare
|
|
478
|
+
) {
|
|
479
|
+
walkDeclaration(node, setupBindings, userImportAlias)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// walk statements & named exports / variable declarations for top level
|
|
483
|
+
// await,when find await will throw error
|
|
484
|
+
// { await someFunc ()}
|
|
485
|
+
if (
|
|
486
|
+
(node.type === 'VariableDeclaration' && !node.declare) ||
|
|
487
|
+
node.type.endsWith('Statement')
|
|
488
|
+
) {
|
|
489
|
+
const scope = [scriptSetupAst.body]
|
|
490
|
+
traverse(node, {
|
|
491
|
+
enter (path) {
|
|
492
|
+
if (isFunctionType(path.node)) {
|
|
493
|
+
path.skip()
|
|
494
|
+
}
|
|
495
|
+
if (t.isBlockStatement(path.node)) {
|
|
496
|
+
scope.push(path.node.body)
|
|
497
|
+
}
|
|
498
|
+
if (t.isAwaitExpression(path.node)) {
|
|
499
|
+
// error
|
|
500
|
+
error('if the await expression is an expression statement and is in the root scope or is not the first statement in a nested block scope, this is not support in miniprogram')
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
exit (path) {
|
|
504
|
+
if (t.isBlockStatement(path.node)) scope.pop()
|
|
505
|
+
},
|
|
506
|
+
noScope: true
|
|
507
|
+
})
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (
|
|
511
|
+
(node.type === 'ExportNamedDeclaration' && node.exportKind !== 'type') ||
|
|
512
|
+
node.type === 'ExportAllDeclaration' ||
|
|
513
|
+
node.type === 'ExportDefaultDeclaration'
|
|
514
|
+
) {
|
|
515
|
+
error(
|
|
516
|
+
'<script setup> cannot contain ES module exports. ',
|
|
517
|
+
node
|
|
518
|
+
)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// working with TS code
|
|
522
|
+
if (isTS) {
|
|
523
|
+
if (
|
|
524
|
+
node.type.startsWith('TS') ||
|
|
525
|
+
(node.type === 'ExportNamedDeclaration' &&
|
|
526
|
+
node.exportKind === 'type') ||
|
|
527
|
+
(node.type === 'VariableDeclaration' && node.declare)
|
|
528
|
+
) {
|
|
529
|
+
recordType(node, declaredTypes)
|
|
530
|
+
_s.move(node.start, node.end, 0)
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
endOffset = node.loc.end.index
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// 2. extract runtime props code from setup context type
|
|
538
|
+
if (propsTypeDecl) {
|
|
539
|
+
// TS defineProps 提取Props
|
|
540
|
+
extractRuntimeProps(propsTypeDecl, typeDeclaredProps, declaredTypes)
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// 3. check useOptions args to make sure it doesn't reference setup scope
|
|
544
|
+
checkInvalidScopeReference(propsRuntimeDecl, DEFINE_PROPS)
|
|
545
|
+
checkInvalidScopeReference(optionsRuntimeDecl, DEFINE_OPTIONS)
|
|
546
|
+
|
|
547
|
+
// 4. finalize setup() argument signature
|
|
548
|
+
let args = '__props'
|
|
549
|
+
if (propsTypeDecl) {
|
|
550
|
+
args += ': any'
|
|
551
|
+
}
|
|
552
|
+
// inject user assignment of props
|
|
553
|
+
if (propsIdentifier) {
|
|
554
|
+
_s.prependLeft(
|
|
555
|
+
startOffset,
|
|
556
|
+
`\nconst ${propsIdentifier} = __props${
|
|
557
|
+
propsTypeDecl ? ' as any' : ''
|
|
558
|
+
}\n`)
|
|
559
|
+
}
|
|
560
|
+
// args 添加 __context
|
|
561
|
+
args += `, __context${isTS ? ': any' : ''}`
|
|
562
|
+
|
|
563
|
+
// 5. generate return statement
|
|
564
|
+
let returned
|
|
565
|
+
if (hasDefineExposeCall && exposeRuntimeDecl) {
|
|
566
|
+
const declCode = content.slice(exposeRuntimeDecl.start, exposeRuntimeDecl.end).trim()
|
|
567
|
+
returned = `${declCode}`
|
|
568
|
+
} else {
|
|
569
|
+
const allBindings = {
|
|
570
|
+
...scriptBindings,
|
|
571
|
+
...setupBindings
|
|
572
|
+
}
|
|
573
|
+
for (const key in userImports) {
|
|
574
|
+
// import 进的的变量或方法,非mpxjs/core中的,暂时都进行return
|
|
575
|
+
if (!userImports[key].isType && !userImportAlias[key]) {
|
|
576
|
+
allBindings[key] = true
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
returned = `{ ${Object.keys(allBindings).join(', ')} }`
|
|
580
|
+
}
|
|
581
|
+
_s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)
|
|
582
|
+
|
|
583
|
+
// 6. finalize default export
|
|
584
|
+
let runtimeOptions = ''
|
|
585
|
+
if (propsRuntimeDecl) {
|
|
586
|
+
const declCode = content.slice(propsRuntimeDecl.start, propsRuntimeDecl.end).trim()
|
|
587
|
+
runtimeOptions += `\n properties: ${declCode},`
|
|
588
|
+
} else if (propsTypeDecl) {
|
|
589
|
+
runtimeOptions += genRuntimeProps(typeDeclaredProps)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (optionsRuntimeDecl) {
|
|
593
|
+
for (const node of optionsRuntimeDecl) {
|
|
594
|
+
if (node.key.name === 'properties' && hasDefinePropsCall) {
|
|
595
|
+
console.warn(`${DEFINE_PROPS} has been called, ${DEFINE_OPTIONS} set properties will be ignored`)
|
|
596
|
+
} else {
|
|
597
|
+
const declCode = content.slice(node.value.start, node.value.end).trim()
|
|
598
|
+
runtimeOptions += `\n ${node.key.name}: ${declCode},`
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// import {createComponent} from '@mpxjs/core' 添加是否已有import判断
|
|
604
|
+
const ctor = getCtor(ctorType)
|
|
605
|
+
_s.prependLeft(
|
|
606
|
+
startOffset,
|
|
607
|
+
`\nimport {${ctor}} from '${MPX_CORE}'\n${getCtor(ctorType)} ({${runtimeOptions}\n ` +
|
|
608
|
+
`setup(${args}) {\n const useContext = () => { return __context }`
|
|
609
|
+
)
|
|
610
|
+
_s.appendRight(endOffset, '})')
|
|
611
|
+
|
|
612
|
+
return {
|
|
613
|
+
content: _s.toString()
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
function isCallOf (
|
|
618
|
+
node,
|
|
619
|
+
test
|
|
620
|
+
) {
|
|
621
|
+
return !!(
|
|
622
|
+
node &&
|
|
623
|
+
node.type === 'CallExpression' &&
|
|
624
|
+
node.callee.type === 'Identifier' &&
|
|
625
|
+
(typeof test === 'string'
|
|
626
|
+
? node.callee.name === test
|
|
627
|
+
: test(node.callee.name))
|
|
628
|
+
)
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function canNeverBeRef (
|
|
632
|
+
node,
|
|
633
|
+
userReactiveImport
|
|
634
|
+
) {
|
|
635
|
+
if (isCallOf(node, userReactiveImport)) {
|
|
636
|
+
return true
|
|
637
|
+
}
|
|
638
|
+
switch (node.type) {
|
|
639
|
+
case 'UnaryExpression':
|
|
640
|
+
case 'BinaryExpression':
|
|
641
|
+
case 'ArrayExpression':
|
|
642
|
+
case 'ObjectExpression':
|
|
643
|
+
case 'FunctionExpression':
|
|
644
|
+
case 'ArrowFunctionExpression':
|
|
645
|
+
case 'UpdateExpression':
|
|
646
|
+
case 'ClassExpression':
|
|
647
|
+
case 'TaggedTemplateExpression':
|
|
648
|
+
return true
|
|
649
|
+
case 'SequenceExpression':
|
|
650
|
+
return canNeverBeRef(
|
|
651
|
+
node.expressions[node.expressions.length - 1],
|
|
652
|
+
userReactiveImport
|
|
653
|
+
)
|
|
654
|
+
default:
|
|
655
|
+
if (node.type.endsWith('Literal')) {
|
|
656
|
+
return true
|
|
657
|
+
}
|
|
658
|
+
return false
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function isCompilerMacro (c) {
|
|
663
|
+
return c === DEFINE_PROPS || c === DEFINE_OPTIONS || c === DEFINE_EXPOSE
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function registerBinding (
|
|
667
|
+
bindings,
|
|
668
|
+
node,
|
|
669
|
+
type
|
|
670
|
+
) {
|
|
671
|
+
bindings[node.name] = type
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
function walkDeclaration (
|
|
675
|
+
node,
|
|
676
|
+
bindings,
|
|
677
|
+
userImportAlias
|
|
678
|
+
) {
|
|
679
|
+
if (node.type === 'VariableDeclaration') {
|
|
680
|
+
const isConst = node.kind === 'const'
|
|
681
|
+
for (const { id, init } of node.declarations) {
|
|
682
|
+
const isDefineCall = !!(
|
|
683
|
+
isConst &&
|
|
684
|
+
isCallOf(
|
|
685
|
+
init,
|
|
686
|
+
isCompilerMacro
|
|
687
|
+
)
|
|
688
|
+
)
|
|
689
|
+
if (id.type === 'Identifier') {
|
|
690
|
+
let bindingType
|
|
691
|
+
const userReactiveBinding = userImportAlias.reactive || 'reactive'
|
|
692
|
+
// 是否是 reactive init
|
|
693
|
+
if (isCallOf(init, userReactiveBinding)) {
|
|
694
|
+
bindingType = isConst
|
|
695
|
+
? BindingTypes.SETUP_REACTIVE_CONST
|
|
696
|
+
: BindingTypes.SETUP_LET
|
|
697
|
+
} else if (
|
|
698
|
+
isDefineCall ||
|
|
699
|
+
(isConst && canNeverBeRef(init, userReactiveBinding))
|
|
700
|
+
) {
|
|
701
|
+
bindingType = isCallOf(init, DEFINE_PROPS)
|
|
702
|
+
? BindingTypes.SETUP_REACTIVE_CONST
|
|
703
|
+
: BindingTypes.SETUP_CONST
|
|
704
|
+
} else if (isConst) {
|
|
705
|
+
if (isCallOf(init, userImportAlias.ref || 'ref')) {
|
|
706
|
+
bindingType = BindingTypes.SETUP_REF
|
|
707
|
+
} else {
|
|
708
|
+
bindingType = BindingTypes.SETUP_MAYBE_REF
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
bindingType = BindingTypes.SETUP_LET
|
|
712
|
+
}
|
|
713
|
+
registerBinding(bindings, id, bindingType)
|
|
714
|
+
} else {
|
|
715
|
+
if (isCallOf(init, DEFINE_PROPS)) {
|
|
716
|
+
// skip walking props destructure
|
|
717
|
+
return
|
|
718
|
+
}
|
|
719
|
+
if (id.type === 'ObjectPattern') {
|
|
720
|
+
walkObjectPattern(id, bindings, isConst, isDefineCall)
|
|
721
|
+
} else if (id.type === 'ArrayPattern') {
|
|
722
|
+
walkArrayPattern(id, bindings, isConst, isDefineCall)
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
} else if (
|
|
727
|
+
node.type === 'TSEnumDeclaration' ||
|
|
728
|
+
node.type === 'FunctionDeclaration' ||
|
|
729
|
+
node.type === 'ClassDeclaration'
|
|
730
|
+
) {
|
|
731
|
+
bindings[node.id.name] = BindingTypes.SETUP_CONST
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function walkObjectPattern (
|
|
736
|
+
node,
|
|
737
|
+
bindings,
|
|
738
|
+
isConst,
|
|
739
|
+
isDefineCall = false
|
|
740
|
+
) {
|
|
741
|
+
for (const p of node.properties) {
|
|
742
|
+
if (p.type === 'ObjectProperty') {
|
|
743
|
+
if (p.key.type === 'Identifier' && p.key === p.value) {
|
|
744
|
+
// shorthand: const { x } = ...
|
|
745
|
+
const type = isDefineCall ? BindingTypes.SETUP_CONST : isConst ? BindingTypes.SETUP_MAYBE_REF : BindingTypes.SETUP_LET
|
|
746
|
+
registerBinding(bindings, p.key, type)
|
|
747
|
+
} else {
|
|
748
|
+
walkPattern(p.value, bindings, isConst, isDefineCall)
|
|
749
|
+
}
|
|
750
|
+
} else {
|
|
751
|
+
// ...rest
|
|
752
|
+
const type = isConst ? BindingTypes.SETUP_CONST : BindingTypes.SETUP_LET
|
|
753
|
+
registerBinding(bindings, p.argument, type)
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function walkArrayPattern (
|
|
759
|
+
node,
|
|
760
|
+
bindings,
|
|
761
|
+
isConst,
|
|
762
|
+
isDefineCall = false
|
|
763
|
+
) {
|
|
764
|
+
for (const e of node.elements) {
|
|
765
|
+
e && walkPattern(e, bindings, isConst, isDefineCall)
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function walkPattern (
|
|
770
|
+
node,
|
|
771
|
+
bindings,
|
|
772
|
+
isConst,
|
|
773
|
+
isDefineCall = false
|
|
774
|
+
) {
|
|
775
|
+
if (node.type === 'Identifier') {
|
|
776
|
+
const type = isDefineCall
|
|
777
|
+
? BindingTypes.SETUP_CONST
|
|
778
|
+
: isConst
|
|
779
|
+
? BindingTypes.SETUP_MAYBE_REF
|
|
780
|
+
: BindingTypes.SETUP_LET
|
|
781
|
+
registerBinding(bindings, node, type)
|
|
782
|
+
} else if (node.type === 'RestElement') {
|
|
783
|
+
const type = isConst ? BindingTypes.SETUP_CONST : BindingTypes.SETUP_LET
|
|
784
|
+
registerBinding(bindings, node.argument, type)
|
|
785
|
+
} else if (node.type === 'ObjectPattern') {
|
|
786
|
+
walkObjectPattern(node, bindings, isConst)
|
|
787
|
+
} else if (node.type === 'ArrayPattern') {
|
|
788
|
+
walkArrayPattern(node, bindings, isConst)
|
|
789
|
+
} else if (node.type === 'AssignmentPattern') {
|
|
790
|
+
// const {propsA:c=2} = defineProps
|
|
791
|
+
if (node.left.type === 'Identifier') {
|
|
792
|
+
const type = isDefineCall
|
|
793
|
+
? BindingTypes.SETUP_CONST
|
|
794
|
+
: isConst
|
|
795
|
+
? BindingTypes.SETUP_MAYBE_REF
|
|
796
|
+
: BindingTypes.SETUP_LET
|
|
797
|
+
registerBinding(bindings, node.left, type)
|
|
798
|
+
} else {
|
|
799
|
+
walkPattern(node.left, bindings, isConst)
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function recordType (node, declaredTypes) {
|
|
805
|
+
if (node.type === 'TSInterfaceDeclaration') {
|
|
806
|
+
declaredTypes[node.id.name] = ['Object']
|
|
807
|
+
} else if (node.type === 'TSTypeAliasDeclaration') {
|
|
808
|
+
declaredTypes[node.id.name] = inferRuntimeType(
|
|
809
|
+
node.typeAnnotation,
|
|
810
|
+
declaredTypes
|
|
811
|
+
)
|
|
812
|
+
} else if (node.type === 'ExportNamedDeclaration' && node.declaration) {
|
|
813
|
+
recordType(node.declaration, declaredTypes)
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
function toRuntimeTypeString (types) {
|
|
818
|
+
return {
|
|
819
|
+
type: types[0],
|
|
820
|
+
optionalTypes: types.length > 1 ? `[${types.slice(1).join(', ')}]` : undefined
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// extract runtime props from ts types
|
|
825
|
+
function extractRuntimeProps (
|
|
826
|
+
node,
|
|
827
|
+
props,
|
|
828
|
+
declaredTypes
|
|
829
|
+
) {
|
|
830
|
+
const members = node.type === 'TSTypeLiteral' ? node.members : node.body
|
|
831
|
+
for (const m of members) {
|
|
832
|
+
if (
|
|
833
|
+
(m.type === 'TSPropertySignature' || m.type === 'TSMethodSignature') &&
|
|
834
|
+
m.key.type === 'Identifier'
|
|
835
|
+
) {
|
|
836
|
+
let type
|
|
837
|
+
if (m.type === 'TSMethodSignature') {
|
|
838
|
+
type = ['Function']
|
|
839
|
+
} else if (m.typeAnnotation) {
|
|
840
|
+
type = inferRuntimeType(m.typeAnnotation.typeAnnotation, declaredTypes)
|
|
841
|
+
}
|
|
842
|
+
props[m.key.name] = {
|
|
843
|
+
key: m.key.name,
|
|
844
|
+
required: !m.optional,
|
|
845
|
+
type: type || ['null']
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function inferRuntimeType (
|
|
852
|
+
node,
|
|
853
|
+
declaredTypes
|
|
854
|
+
) {
|
|
855
|
+
switch (node.type) {
|
|
856
|
+
case 'TSStringKeyword':
|
|
857
|
+
return ['String']
|
|
858
|
+
case 'TSNumberKeyword':
|
|
859
|
+
return ['Number']
|
|
860
|
+
case 'TSBooleanKeyword':
|
|
861
|
+
return ['Boolean']
|
|
862
|
+
case 'TSObjectKeyword':
|
|
863
|
+
return ['Object']
|
|
864
|
+
case 'TSFunctionType':
|
|
865
|
+
return ['Function']
|
|
866
|
+
case 'TSArrayType':
|
|
867
|
+
case 'TSTupleType':
|
|
868
|
+
return ['Array']
|
|
869
|
+
case 'TSLiteralType':
|
|
870
|
+
switch (node.literal.type) {
|
|
871
|
+
case 'StringLiteral':
|
|
872
|
+
return ['String']
|
|
873
|
+
case 'BooleanLiteral':
|
|
874
|
+
return ['Boolean']
|
|
875
|
+
case 'NumericLiteral':
|
|
876
|
+
case 'BigIntLiteral':
|
|
877
|
+
return ['Number']
|
|
878
|
+
default:
|
|
879
|
+
return ['null']
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
case 'TSTypeReference':
|
|
883
|
+
if (node.typeName.type === 'Identifier') {
|
|
884
|
+
if (declaredTypes[node.typeName.name]) {
|
|
885
|
+
return declaredTypes[node.typeName.name]
|
|
886
|
+
}
|
|
887
|
+
switch (node.typeName.name) {
|
|
888
|
+
case 'Array':
|
|
889
|
+
case 'Function':
|
|
890
|
+
case 'Object':
|
|
891
|
+
case 'Set':
|
|
892
|
+
case 'Map':
|
|
893
|
+
case 'WeakSet':
|
|
894
|
+
case 'WeakMap':
|
|
895
|
+
case 'Date':
|
|
896
|
+
case 'Promise':
|
|
897
|
+
return [node.typeName.name]
|
|
898
|
+
case 'Record':
|
|
899
|
+
case 'Partial':
|
|
900
|
+
case 'Readonly':
|
|
901
|
+
case 'Pick':
|
|
902
|
+
case 'Omit':
|
|
903
|
+
case 'Exclude':
|
|
904
|
+
case 'Extract':
|
|
905
|
+
case 'Required':
|
|
906
|
+
case 'InstanceType':
|
|
907
|
+
return ['Object']
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return ['null']
|
|
911
|
+
|
|
912
|
+
case 'TSParenthesizedType':
|
|
913
|
+
return inferRuntimeType(node.typeAnnotation, declaredTypes)
|
|
914
|
+
|
|
915
|
+
case 'TSUnionType':
|
|
916
|
+
return [
|
|
917
|
+
...new Set(
|
|
918
|
+
[].concat(
|
|
919
|
+
...(node.types.map(t => inferRuntimeType(t, declaredTypes)))
|
|
920
|
+
)
|
|
921
|
+
)
|
|
922
|
+
]
|
|
923
|
+
case 'TSIntersectionType':
|
|
924
|
+
return ['Object']
|
|
925
|
+
|
|
926
|
+
default:
|
|
927
|
+
return ['null']
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function walkIdentifiers (
|
|
932
|
+
root,
|
|
933
|
+
onIdentifier,
|
|
934
|
+
parentStack = [],
|
|
935
|
+
knownIds = Object.create(null)
|
|
936
|
+
) {
|
|
937
|
+
const rootExp =
|
|
938
|
+
root.type === 'Program' &&
|
|
939
|
+
root.body[0].type === 'ExpressionStatement' &&
|
|
940
|
+
root.body[0].expression
|
|
941
|
+
traverse(root, {
|
|
942
|
+
enter (path) {
|
|
943
|
+
const { node, parent } = path
|
|
944
|
+
if (
|
|
945
|
+
parent &&
|
|
946
|
+
parent.type.startsWith('TS') &&
|
|
947
|
+
parent.type !== 'TSAsExpression' &&
|
|
948
|
+
parent.type !== 'TSNonNullExpression' &&
|
|
949
|
+
parent.type !== 'TSTypeAssertion'
|
|
950
|
+
) {
|
|
951
|
+
return path.skip()
|
|
952
|
+
}
|
|
953
|
+
if (node.type === 'Identifier') {
|
|
954
|
+
const isLocal = knownIds[node.name]
|
|
955
|
+
const isRefed = isReferencedIdentifier(node, parent, parentStack)
|
|
956
|
+
if (isRefed && !isLocal) {
|
|
957
|
+
onIdentifier(node, parent, parentStack, isRefed, isLocal)
|
|
958
|
+
}
|
|
959
|
+
} else if (
|
|
960
|
+
node.type === 'ObjectProperty' &&
|
|
961
|
+
parent.type === 'ObjectPattern'
|
|
962
|
+
) {
|
|
963
|
+
node.inPattern = true
|
|
964
|
+
} else if (isFunctionType(node)) {
|
|
965
|
+
walkFunctionParams(node, id => markScopeIdentifier(node, id, knownIds))
|
|
966
|
+
} else if (node.type === 'BlockStatement') {
|
|
967
|
+
walkBlockDeclarations(node, id =>
|
|
968
|
+
markScopeIdentifier(node, id, knownIds)
|
|
969
|
+
)
|
|
970
|
+
}
|
|
971
|
+
},
|
|
972
|
+
exit (path) {
|
|
973
|
+
const { node, parent } = path
|
|
974
|
+
parent && parentStack.pop()
|
|
975
|
+
if (node !== rootExp && node.scopeIds) {
|
|
976
|
+
for (const id of node.scopeIds) {
|
|
977
|
+
knownIds[id]--
|
|
978
|
+
if (knownIds[id] === 0) {
|
|
979
|
+
delete knownIds[id]
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
noScope: true
|
|
985
|
+
})
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function markScopeIdentifier (
|
|
989
|
+
node,
|
|
990
|
+
child,
|
|
991
|
+
knownIds
|
|
992
|
+
) {
|
|
993
|
+
const { name } = child
|
|
994
|
+
if (node.scopeIds && node.scopeIds.has(name)) {
|
|
995
|
+
return
|
|
996
|
+
}
|
|
997
|
+
if (name in knownIds) {
|
|
998
|
+
knownIds[name]++
|
|
999
|
+
} else {
|
|
1000
|
+
knownIds[name] = 1
|
|
1001
|
+
}
|
|
1002
|
+
(node.scopeIds || (node.scopeIds = new Set())).add(name)
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function walkFunctionParams (
|
|
1006
|
+
node,
|
|
1007
|
+
onIdent
|
|
1008
|
+
) {
|
|
1009
|
+
for (const p of node.params) {
|
|
1010
|
+
for (const id of extractIdentifiers(p)) {
|
|
1011
|
+
onIdent(id)
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
function walkBlockDeclarations (
|
|
1017
|
+
block,
|
|
1018
|
+
onIndent
|
|
1019
|
+
) {
|
|
1020
|
+
for (const stmt of block.body) {
|
|
1021
|
+
if (stmt.type === 'VariableDeclaration') {
|
|
1022
|
+
if (stmt.declare) continue
|
|
1023
|
+
for (const decl of stmt.declarations) {
|
|
1024
|
+
for (const id of extractIdentifiers(decl.id)) {
|
|
1025
|
+
onIndent(id)
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
} else if (
|
|
1029
|
+
stmt.type === 'FunctionDeclaration' ||
|
|
1030
|
+
stmt.type === 'ClassDeclaration'
|
|
1031
|
+
) {
|
|
1032
|
+
if (stmt.declare || !stmt.id) continue
|
|
1033
|
+
onIndent(stmt.id)
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function isReferencedIdentifier (
|
|
1039
|
+
id,
|
|
1040
|
+
parent,
|
|
1041
|
+
parentStack
|
|
1042
|
+
) {
|
|
1043
|
+
if (!parent) {
|
|
1044
|
+
return true
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// is a special keyword but parsed as identifier
|
|
1048
|
+
if (id.name === 'arguments') {
|
|
1049
|
+
return false
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
if (t.isReferenced(id, parent)) {
|
|
1053
|
+
return true
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// babel's isReferenced check returns false for ids being assigned to, so we
|
|
1057
|
+
// need to cover those cases here
|
|
1058
|
+
switch (parent.type) {
|
|
1059
|
+
case 'AssignmentExpression':
|
|
1060
|
+
case 'AssignmentPattern':
|
|
1061
|
+
return true
|
|
1062
|
+
case 'ObjectPattern':
|
|
1063
|
+
case 'ArrayPattern':
|
|
1064
|
+
return isInDestructureAssignment(parent, parentStack)
|
|
1065
|
+
}
|
|
1066
|
+
return false
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
function extractIdentifiers (
|
|
1070
|
+
param,
|
|
1071
|
+
nodes
|
|
1072
|
+
) {
|
|
1073
|
+
switch (param.type) {
|
|
1074
|
+
case 'Identifier':
|
|
1075
|
+
nodes.push(param)
|
|
1076
|
+
break
|
|
1077
|
+
|
|
1078
|
+
case 'MemberExpression': {
|
|
1079
|
+
let object = param
|
|
1080
|
+
while (object.type === 'MemberExpression') {
|
|
1081
|
+
object = object.object
|
|
1082
|
+
}
|
|
1083
|
+
nodes.push(object)
|
|
1084
|
+
break
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
case 'ObjectPattern':
|
|
1088
|
+
for (const prop of param.properties) {
|
|
1089
|
+
if (prop.type === 'RestElement') {
|
|
1090
|
+
extractIdentifiers(prop.argument, nodes)
|
|
1091
|
+
} else {
|
|
1092
|
+
extractIdentifiers(prop.value, nodes)
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
break
|
|
1096
|
+
|
|
1097
|
+
case 'ArrayPattern':
|
|
1098
|
+
param.elements.forEach(element => {
|
|
1099
|
+
if (element) extractIdentifiers(element, nodes)
|
|
1100
|
+
})
|
|
1101
|
+
break
|
|
1102
|
+
|
|
1103
|
+
case 'RestElement':
|
|
1104
|
+
extractIdentifiers(param.argument, nodes)
|
|
1105
|
+
break
|
|
1106
|
+
|
|
1107
|
+
case 'AssignmentPattern':
|
|
1108
|
+
extractIdentifiers(param.left, nodes)
|
|
1109
|
+
break
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
return nodes
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
function isInDestructureAssignment (
|
|
1116
|
+
parent,
|
|
1117
|
+
parentStack
|
|
1118
|
+
) {
|
|
1119
|
+
if (
|
|
1120
|
+
parent &&
|
|
1121
|
+
(parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')
|
|
1122
|
+
) {
|
|
1123
|
+
let i = parentStack.length
|
|
1124
|
+
while (i--) {
|
|
1125
|
+
const p = parentStack[i]
|
|
1126
|
+
if (p.type === 'AssignmentExpression') {
|
|
1127
|
+
return true
|
|
1128
|
+
} else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {
|
|
1129
|
+
break
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return false
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
function isFunctionType (node) {
|
|
1137
|
+
return /Function(?:Expression|Declaration)$|Method$/.test(node.type)
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
function getCtor (ctorType) {
|
|
1141
|
+
let ctor = 'createComponent'
|
|
1142
|
+
switch (ctorType) {
|
|
1143
|
+
case 'app':
|
|
1144
|
+
ctor = 'createApp'
|
|
1145
|
+
break
|
|
1146
|
+
case 'page':
|
|
1147
|
+
ctor = 'createPage'
|
|
1148
|
+
break
|
|
1149
|
+
}
|
|
1150
|
+
return ctor
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
module.exports = function (content) {
|
|
1154
|
+
const { queryObj } = parseRequest(this.resource)
|
|
1155
|
+
const { ctorType, lang } = queryObj
|
|
1156
|
+
const filePath = this.resourcePath
|
|
1157
|
+
const { content: callbackContent } = compileScriptSetup({
|
|
1158
|
+
content,
|
|
1159
|
+
lang
|
|
1160
|
+
}, ctorType, filePath)
|
|
1161
|
+
|
|
1162
|
+
this.callback(null, callbackContent)
|
|
1163
|
+
}
|