Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
uni-app
提交
fe038fa6
U
uni-app
项目概览
DCloud
/
uni-app
3 天 前同步成功
通知
815
Star
38709
Fork
3642
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
8
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
8
Issue
8
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
fe038fa6
编写于
12月 15, 2023
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(uvue): setup
上级
eea2bb42
变更
33
展开全部
隐藏空白更改
内联
并排
Showing
33 changed file
with
5557 addition
and
27 deletion
+5557
-27
packages/shims-node.d.ts
packages/shims-node.d.ts
+12
-0
packages/uni-app-uts/package.json
packages/uni-app-uts/package.json
+2
-0
packages/uni-app-uts/src/plugins/android/uvue/code/style.ts
packages/uni-app-uts/src/plugins/android/uvue/code/style.ts
+1
-1
packages/uni-app-uts/src/plugins/android/uvue/code/template.ts
...ges/uni-app-uts/src/plugins/android/uvue/code/template.ts
+2
-0
packages/uni-app-uts/src/plugins/android/uvue/descriptorCache.ts
...s/uni-app-uts/src/plugins/android/uvue/descriptorCache.ts
+9
-18
packages/uni-app-uts/src/plugins/android/uvue/index.ts
packages/uni-app-uts/src/plugins/android/uvue/index.ts
+7
-3
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/compileScript.ts
...ts/src/plugins/android/uvue/sfc/compiler/compileScript.ts
+1263
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/rewriteDefault.ts
...s/src/plugins/android/uvue/sfc/compiler/rewriteDefault.ts
+123
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/analyzeScriptBindings.ts
...android/uvue/sfc/compiler/script/analyzeScriptBindings.ts
+131
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/context.ts
...s/src/plugins/android/uvue/sfc/compiler/script/context.ts
+151
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineEmits.ts
...c/plugins/android/uvue/sfc/compiler/script/defineEmits.ts
+124
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineExpose.ts
.../plugins/android/uvue/sfc/compiler/script/defineExpose.ts
+19
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineModel.ts
...c/plugins/android/uvue/sfc/compiler/script/defineModel.ts
+153
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineOptions.ts
...plugins/android/uvue/sfc/compiler/script/defineOptions.ts
+73
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineProps.ts
...c/plugins/android/uvue/sfc/compiler/script/defineProps.ts
+366
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/definePropsDestructure.ts
...ndroid/uvue/sfc/compiler/script/definePropsDestructure.ts
+306
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineSlots.ts
...c/plugins/android/uvue/sfc/compiler/script/defineSlots.ts
+33
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/normalScript.ts
.../plugins/android/uvue/sfc/compiler/script/normalScript.ts
+47
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/resolveType.ts
...c/plugins/android/uvue/sfc/compiler/script/resolveType.ts
+1610
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/topLevelAwait.ts
...plugins/android/uvue/sfc/compiler/script/topLevelAwait.ts
+69
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/utils.ts
...uts/src/plugins/android/uvue/sfc/compiler/script/utils.ts
+128
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/shims.d.ts
...-app-uts/src/plugins/android/uvue/sfc/compiler/shims.d.ts
+3
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/template/templateUtils.ts
...ugins/android/uvue/sfc/compiler/template/templateUtils.ts
+39
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/template/transformAssetUrl.ts
...s/android/uvue/sfc/compiler/template/transformAssetUrl.ts
+216
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/template/transformSrcset.ts
...ins/android/uvue/sfc/compiler/template/transformSrcset.ts
+171
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/warn.ts
...uni-app-uts/src/plugins/android/uvue/sfc/compiler/warn.ts
+16
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/index.ts
packages/uni-app-uts/src/plugins/android/uvue/sfc/index.ts
+64
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/main.ts
packages/uni-app-uts/src/plugins/android/uvue/sfc/main.ts
+265
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/script.ts
packages/uni-app-uts/src/plugins/android/uvue/sfc/script.ts
+58
-0
packages/uni-app-uts/src/plugins/android/uvue/sfc/template.ts
...ages/uni-app-uts/src/plugins/android/uvue/sfc/template.ts
+85
-0
packages/uni-cli-shared/src/vite/plugins/inject.ts
packages/uni-cli-shared/src/vite/plugins/inject.ts
+1
-1
packages/uni-mp-compiler/src/transforms/utils.ts
packages/uni-mp-compiler/src/transforms/utils.ts
+3
-3
pnpm-lock.yaml
pnpm-lock.yaml
+7
-1
未找到文件。
packages/shims-node.d.ts
浏览文件 @
fe038fa6
...
@@ -58,5 +58,17 @@ declare namespace NodeJS {
...
@@ -58,5 +58,17 @@ declare namespace NodeJS {
UNI_APP_X_PAGE_COUNT
:
string
UNI_APP_X_PAGE_COUNT
:
string
UNI_APP_X_TSC
?:
string
UNI_APP_X_TSC
?:
string
UNI_APP_X_SINGLE_THREAD
?:
string
UNI_APP_X_SINGLE_THREAD
?:
string
UNI_APP_X_SETUP
?:
string
}
}
}
}
declare
module
'
estree-walker
'
{
export
function
walk
<
T
>
(
root
:
T
,
options
:
{
enter
?:
(
node
:
T
,
parent
:
T
|
undefined
)
=>
any
leave
?:
(
node
:
T
,
parent
:
T
|
undefined
)
=>
any
exit
?:
(
node
:
T
)
=>
any
}
&
ThisType
<
{
skip
:
()
=>
void
}
>
)
}
packages/uni-app-uts/package.json
浏览文件 @
fe038fa6
...
@@ -28,12 +28,14 @@
...
@@ -28,12 +28,14 @@
"@jridgewell/trace-mapping"
:
"^0.3.19"
,
"@jridgewell/trace-mapping"
:
"^0.3.19"
,
"@rollup/pluginutils"
:
"^4.2.0"
,
"@rollup/pluginutils"
:
"^4.2.0"
,
"@vue/compiler-core"
:
"3.3.11"
,
"@vue/compiler-core"
:
"3.3.11"
,
"@vue/compiler-dom"
:
"3.3.11"
,
"@vue/compiler-sfc"
:
"3.3.11"
,
"@vue/compiler-sfc"
:
"3.3.11"
,
"@vue/shared"
:
"3.3.11"
,
"@vue/shared"
:
"3.3.11"
,
"debug"
:
"^4.3.3"
,
"debug"
:
"^4.3.3"
,
"es-module-lexer"
:
"^1.2.1"
,
"es-module-lexer"
:
"^1.2.1"
,
"estree-walker"
:
"^2.0.2"
,
"estree-walker"
:
"^2.0.2"
,
"fs-extra"
:
"^10.0.0"
,
"fs-extra"
:
"^10.0.0"
,
"magic-string"
:
"^0.30.0"
,
"picocolors"
:
"^1.0.0"
,
"picocolors"
:
"^1.0.0"
,
"source-map-js"
:
"^1.0.2"
,
"source-map-js"
:
"^1.0.2"
,
"unplugin-auto-import"
:
"^0.16.7"
"unplugin-auto-import"
:
"^0.16.7"
...
...
packages/uni-app-uts/src/plugins/android/uvue/code/style.ts
浏览文件 @
fe038fa6
...
@@ -4,7 +4,7 @@ import { ResolvedOptions, setSrcDescriptor } from '../descriptorCache'
...
@@ -4,7 +4,7 @@ import { ResolvedOptions, setSrcDescriptor } from '../descriptorCache'
export
function
genStyle
(
export
function
genStyle
(
_
:
SFCDescriptor
,
_
:
SFCDescriptor
,
{
className
}:
{
className
:
string
;
filename
:
string
}
{
className
}:
{
className
:
string
}
)
{
)
{
return
`/*
${
className
}
Styles*/`
return
`/*
${
className
}
Styles*/`
}
}
...
...
packages/uni-app-uts/src/plugins/android/uvue/code/template.ts
浏览文件 @
fe038fa6
...
@@ -19,3 +19,5 @@ export function genTemplate(
...
@@ -19,3 +19,5 @@ export function genTemplate(
}
}
return
compile
(
template
.
content
,
options
)
return
compile
(
template
.
content
,
options
)
}
}
export
const
genTemplateCode
=
genTemplate
packages/uni-app-uts/src/plugins/android/uvue/descriptorCache.ts
浏览文件 @
fe038fa6
...
@@ -19,8 +19,7 @@ export interface SFCParseResult {
...
@@ -19,8 +19,7 @@ export interface SFCParseResult {
errors
:
Array
<
CompilerError
|
SyntaxError
>
errors
:
Array
<
CompilerError
|
SyntaxError
>
}
}
const
cache
=
new
Map
<
string
,
SFCDescriptor
>
()
export
const
cache
=
new
Map
<
string
,
SFCDescriptor
>
()
const
prevCache
=
new
Map
<
string
,
SFCDescriptor
|
undefined
>
()
declare
module
'
@vue/compiler-sfc
'
{
declare
module
'
@vue/compiler-sfc
'
{
interface
SFCDescriptor
{
interface
SFCDescriptor
{
...
@@ -33,33 +32,25 @@ export function createDescriptor(
...
@@ -33,33 +32,25 @@ export function createDescriptor(
source
:
string
,
source
:
string
,
{
root
,
sourceMap
,
compiler
}:
ResolvedOptions
{
root
,
sourceMap
,
compiler
}:
ResolvedOptions
):
SFCParseResult
{
):
SFCParseResult
{
const
{
descriptor
,
errors
}
=
compiler
.
parse
(
source
,
{
filename
,
sourceMap
,
})
// ensure the path is normalized in a way that is consistent inside
// ensure the path is normalized in a way that is consistent inside
// project (relative to root) and on different systems.
// project (relative to root) and on different systems.
const
normalizedPath
=
normalizePath
(
const
normalizedPath
=
normalizePath
(
path
.
normalize
(
path
.
relative
(
root
,
filename
))
path
.
normalize
(
path
.
relative
(
root
,
filename
))
)
)
// 传入normalizedPath是为了让sourcemap记录的是相对路径
const
{
descriptor
,
errors
}
=
compiler
.
parse
(
source
,
{
filename
:
normalizedPath
,
sourceMap
,
})
// 重置为绝对路径
descriptor
.
filename
=
filename
descriptor
.
id
=
getHash
(
normalizedPath
)
descriptor
.
id
=
getHash
(
normalizedPath
)
cache
.
set
(
filename
,
descriptor
)
cache
.
set
(
filename
,
descriptor
)
return
{
descriptor
,
errors
}
return
{
descriptor
,
errors
}
}
}
export
function
getPrevDescriptor
(
filename
:
string
):
SFCDescriptor
|
undefined
{
return
prevCache
.
get
(
filename
)
}
export
function
setPrevDescriptor
(
filename
:
string
,
entry
:
SFCDescriptor
):
void
{
prevCache
.
set
(
filename
,
entry
)
}
export
function
getDescriptor
(
export
function
getDescriptor
(
filename
:
string
,
filename
:
string
,
options
:
ResolvedOptions
,
options
:
ResolvedOptions
,
...
...
packages/uni-app-uts/src/plugins/android/uvue/index.ts
浏览文件 @
fe038fa6
...
@@ -58,13 +58,14 @@ import { genTemplate } from './code/template'
...
@@ -58,13 +58,14 @@ import { genTemplate } from './code/template'
import
{
genJsStylesCode
,
genStyle
,
transformStyle
}
from
'
./code/style
'
import
{
genJsStylesCode
,
genStyle
,
transformStyle
}
from
'
./code/style
'
import
{
genComponentPublicInstanceImported
}
from
'
./compiler/utils
'
import
{
genComponentPublicInstanceImported
}
from
'
./compiler/utils
'
import
{
ImportItem
}
from
'
./compiler/transform
'
import
{
ImportItem
}
from
'
./compiler/transform
'
import
{
transformMain
}
from
'
./sfc/main
'
export
function
uniAppUVuePlugin
(
opts
:
{
export
function
uniAppUVuePlugin
(
opts
:
{
autoImportOptions
?:
AutoImportOptions
autoImportOptions
?:
AutoImportOptions
}):
Plugin
{
}):
Plugin
{
const
options
:
ResolvedOptions
=
{
const
options
:
ResolvedOptions
=
{
root
:
process
.
env
.
UNI_INPUT_DIR
,
root
:
process
.
env
.
UNI_INPUT_DIR
,
sourceMap
:
false
,
sourceMap
:
process
.
env
.
NODE_ENV
===
'
development
'
,
// eslint-disable-next-line no-restricted-globals
// eslint-disable-next-line no-restricted-globals
compiler
:
require
(
'
@vue/compiler-sfc
'
),
compiler
:
require
(
'
@vue/compiler-sfc
'
),
targetLanguage
:
process
.
env
.
UNI_UTS_TARGET_LANGUAGE
,
targetLanguage
:
process
.
env
.
UNI_UTS_TARGET_LANGUAGE
,
...
@@ -118,6 +119,9 @@ export function uniAppUVuePlugin(opts: {
...
@@ -118,6 +119,9 @@ export function uniAppUVuePlugin(opts: {
}
}
if
(
!
query
.
vue
)
{
if
(
!
query
.
vue
)
{
// main request
// main request
if
(
process
.
env
.
UNI_APP_X_SETUP
===
'
true
'
)
{
return
transformMain
(
code
,
filename
,
options
,
this
)
}
const
{
errors
,
uts
,
js
,
sourceMap
}
=
await
transformVue
(
const
{
errors
,
uts
,
js
,
sourceMap
}
=
await
transformVue
(
code
,
code
,
filename
,
filename
,
...
@@ -147,7 +151,7 @@ export function uniAppUVuePlugin(opts: {
...
@@ -147,7 +151,7 @@ export function uniAppUVuePlugin(opts: {
if
(
sourceMap
)
{
if
(
sourceMap
)
{
this
.
emitFile
({
this
.
emitFile
({
type
:
'
asset
'
,
type
:
'
asset
'
,
fileName
:
removeExt
(
fileName
)
+
'
.
template.
map
'
,
fileName
:
removeExt
(
fileName
)
+
'
.map
'
,
source
:
JSON
.
stringify
(
sourceMap
),
source
:
JSON
.
stringify
(
sourceMap
),
})
})
}
}
...
@@ -364,7 +368,7 @@ export async function transformVue(
...
@@ -364,7 +368,7 @@ export async function transformVue(
genScript
(
descriptor
,
{
filename
:
className
})
+
genScript
(
descriptor
,
{
filename
:
className
})
+
templateCode
+
templateCode
+
'
\n
'
+
'
\n
'
+
genStyle
(
descriptor
,
{
filename
:
relativeFileName
,
className
})
+
genStyle
(
descriptor
,
{
className
})
+
'
\n
'
'
\n
'
let
jsCodes
=
[
let
jsCodes
=
[
...
...
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/compileScript.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/rewriteDefault.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
parse
}
from
'
@babel/parser
'
import
MagicString
from
'
magic-string
'
import
type
{
ParserPlugin
}
from
'
@babel/parser
'
import
type
{
Identifier
,
Statement
}
from
'
@babel/types
'
export
function
rewriteDefault
(
input
:
string
,
as
:
string
,
parserPlugins
?:
ParserPlugin
[]
):
string
{
const
ast
=
parse
(
input
,
{
sourceType
:
'
module
'
,
plugins
:
parserPlugins
,
}).
program
.
body
const
s
=
new
MagicString
(
input
)
rewriteDefaultAST
(
ast
,
s
,
as
)
return
s
.
toString
()
}
/**
* Utility for rewriting `export default` in a script block into a variable
* declaration so that we can inject things into it
*/
export
function
rewriteDefaultAST
(
ast
:
Statement
[],
s
:
MagicString
,
as
:
string
):
void
{
if
(
!
hasDefaultExport
(
ast
))
{
s
.
append
(
`\nconst
${
as
}
= {}`
)
return
}
// if the script somehow still contains `default export`, it probably has
// multi-line comments or template strings. fallback to a full parse.
ast
.
forEach
((
node
)
=>
{
if
(
node
.
type
===
'
ExportDefaultDeclaration
'
)
{
if
(
node
.
declaration
.
type
===
'
ClassDeclaration
'
&&
node
.
declaration
.
id
)
{
let
start
:
number
=
node
.
declaration
.
decorators
&&
node
.
declaration
.
decorators
.
length
>
0
?
node
.
declaration
.
decorators
[
node
.
declaration
.
decorators
.
length
-
1
].
end
!
:
node
.
start
!
s
.
overwrite
(
start
,
node
.
declaration
.
id
.
start
!
,
` class `
)
s
.
append
(
`\nconst
${
as
}
=
${
node
.
declaration
.
id
.
name
}
`
)
}
else
{
s
.
overwrite
(
node
.
start
!
,
node
.
declaration
.
start
!
,
`const
${
as
}
= `
)
}
}
else
if
(
node
.
type
===
'
ExportNamedDeclaration
'
)
{
for
(
const
specifier
of
node
.
specifiers
)
{
if
(
specifier
.
type
===
'
ExportSpecifier
'
&&
specifier
.
exported
.
type
===
'
Identifier
'
&&
specifier
.
exported
.
name
===
'
default
'
)
{
if
(
node
.
source
)
{
if
(
specifier
.
local
.
name
===
'
default
'
)
{
s
.
prepend
(
`import { default as __VUE_DEFAULT__ } from '
${
node
.
source
.
value
}
'\n`
)
const
end
=
specifierEnd
(
s
,
specifier
.
local
.
end
!
,
node
.
end
!
)
s
.
remove
(
specifier
.
start
!
,
end
)
s
.
append
(
`\nconst
${
as
}
= __VUE_DEFAULT__`
)
continue
}
else
{
s
.
prepend
(
`import {
${
s
.
slice
(
specifier
.
local
.
start
!
,
specifier
.
local
.
end
!
)}
as __VUE_DEFAULT__ } from '
${
node
.
source
.
value
}
'\n`
)
const
end
=
specifierEnd
(
s
,
specifier
.
exported
.
end
!
,
node
.
end
!
)
s
.
remove
(
specifier
.
start
!
,
end
)
s
.
append
(
`\nconst
${
as
}
= __VUE_DEFAULT__`
)
continue
}
}
const
end
=
specifierEnd
(
s
,
specifier
.
end
!
,
node
.
end
!
)
s
.
remove
(
specifier
.
start
!
,
end
)
s
.
append
(
`\nconst
${
as
}
=
${
specifier
.
local
.
name
}
`
)
}
}
}
})
}
export
function
hasDefaultExport
(
ast
:
Statement
[]):
boolean
{
for
(
const
stmt
of
ast
)
{
if
(
stmt
.
type
===
'
ExportDefaultDeclaration
'
)
{
return
true
}
else
if
(
stmt
.
type
===
'
ExportNamedDeclaration
'
&&
stmt
.
specifiers
.
some
(
(
spec
)
=>
(
spec
.
exported
as
Identifier
).
name
===
'
default
'
)
)
{
return
true
}
}
return
false
}
function
specifierEnd
(
s
:
MagicString
,
end
:
number
,
nodeEnd
:
number
|
null
)
{
// export { default , foo } ...
let
hasCommas
=
false
let
oldEnd
=
end
while
(
end
<
nodeEnd
!
)
{
if
(
/
\s
/
.
test
(
s
.
slice
(
end
,
end
+
1
)))
{
end
++
}
else
if
(
s
.
slice
(
end
,
end
+
1
)
===
'
,
'
)
{
end
++
hasCommas
=
true
break
}
else
if
(
s
.
slice
(
end
,
end
+
1
)
===
'
}
'
)
{
break
}
}
return
hasCommas
?
end
:
oldEnd
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/analyzeScriptBindings.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
ArrayExpression
,
Node
,
ObjectExpression
,
Statement
,
}
from
'
@babel/types
'
import
{
BindingMetadata
,
BindingTypes
}
from
'
@vue/compiler-dom
'
import
{
resolveObjectKey
}
from
'
./utils
'
/**
* Analyze bindings in normal `<script>`
* Note that `compileScriptSetup` already analyzes bindings as part of its
* compilation process so this should only be used on single `<script>` SFCs.
*/
export
function
analyzeScriptBindings
(
ast
:
Statement
[]):
BindingMetadata
{
for
(
const
node
of
ast
)
{
if
(
node
.
type
===
'
ExportDefaultDeclaration
'
&&
node
.
declaration
.
type
===
'
ObjectExpression
'
)
{
return
analyzeBindingsFromOptions
(
node
.
declaration
)
}
}
return
{}
}
function
analyzeBindingsFromOptions
(
node
:
ObjectExpression
):
BindingMetadata
{
const
bindings
:
BindingMetadata
=
{}
// #3270, #3275
// mark non-script-setup so we don't resolve components/directives from these
Object
.
defineProperty
(
bindings
,
'
__isScriptSetup
'
,
{
enumerable
:
false
,
value
:
false
,
})
for
(
const
property
of
node
.
properties
)
{
if
(
property
.
type
===
'
ObjectProperty
'
&&
!
property
.
computed
&&
property
.
key
.
type
===
'
Identifier
'
)
{
// props
if
(
property
.
key
.
name
===
'
props
'
)
{
// props: ['foo']
// props: { foo: ... }
for
(
const
key
of
getObjectOrArrayExpressionKeys
(
property
.
value
))
{
bindings
[
key
]
=
BindingTypes
.
PROPS
}
}
// inject
else
if
(
property
.
key
.
name
===
'
inject
'
)
{
// inject: ['foo']
// inject: { foo: {} }
for
(
const
key
of
getObjectOrArrayExpressionKeys
(
property
.
value
))
{
bindings
[
key
]
=
BindingTypes
.
OPTIONS
}
}
// computed & methods
else
if
(
property
.
value
.
type
===
'
ObjectExpression
'
&&
(
property
.
key
.
name
===
'
computed
'
||
property
.
key
.
name
===
'
methods
'
)
)
{
// methods: { foo() {} }
// computed: { foo() {} }
for
(
const
key
of
getObjectExpressionKeys
(
property
.
value
))
{
bindings
[
key
]
=
BindingTypes
.
OPTIONS
}
}
}
// setup & data
else
if
(
property
.
type
===
'
ObjectMethod
'
&&
property
.
key
.
type
===
'
Identifier
'
&&
(
property
.
key
.
name
===
'
setup
'
||
property
.
key
.
name
===
'
data
'
)
)
{
for
(
const
bodyItem
of
property
.
body
.
body
)
{
// setup() {
// return {
// foo: null
// }
// }
if
(
bodyItem
.
type
===
'
ReturnStatement
'
&&
bodyItem
.
argument
&&
bodyItem
.
argument
.
type
===
'
ObjectExpression
'
)
{
for
(
const
key
of
getObjectExpressionKeys
(
bodyItem
.
argument
))
{
bindings
[
key
]
=
property
.
key
.
name
===
'
setup
'
?
BindingTypes
.
SETUP_MAYBE_REF
:
BindingTypes
.
DATA
}
}
}
}
}
return
bindings
}
function
getObjectExpressionKeys
(
node
:
ObjectExpression
):
string
[]
{
const
keys
=
[]
for
(
const
prop
of
node
.
properties
)
{
if
(
prop
.
type
===
'
SpreadElement
'
)
continue
const
key
=
resolveObjectKey
(
prop
.
key
,
prop
.
computed
)
if
(
key
)
keys
.
push
(
String
(
key
))
}
return
keys
}
function
getArrayExpressionKeys
(
node
:
ArrayExpression
):
string
[]
{
const
keys
=
[]
for
(
const
element
of
node
.
elements
)
{
if
(
element
&&
element
.
type
===
'
StringLiteral
'
)
{
keys
.
push
(
element
.
value
)
}
}
return
keys
}
export
function
getObjectOrArrayExpressionKeys
(
value
:
Node
):
string
[]
{
if
(
value
.
type
===
'
ArrayExpression
'
)
{
return
getArrayExpressionKeys
(
value
)
}
if
(
value
.
type
===
'
ObjectExpression
'
)
{
return
getObjectExpressionKeys
(
value
)
}
return
[]
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/context.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
CallExpression
,
Node
,
ObjectPattern
,
Program
}
from
'
@babel/types
'
import
{
SFCDescriptor
}
from
'
@vue/compiler-sfc
'
import
{
generateCodeFrame
}
from
'
@vue/shared
'
import
{
parse
as
babelParse
,
ParserPlugin
}
from
'
@babel/parser
'
import
{
ImportBinding
,
SFCScriptCompileOptions
}
from
'
../compileScript
'
import
{
PropsDestructureBindings
}
from
'
./defineProps
'
import
{
ModelDecl
}
from
'
./defineModel
'
import
type
{
BindingMetadata
}
from
'
@vue/compiler-core
'
import
MagicString
from
'
magic-string
'
import
{
TypeScope
}
from
'
./resolveType
'
export
class
ScriptCompileContext
{
scriptAst
:
Program
|
null
scriptSetupAst
:
Program
|
null
source
=
this
.
descriptor
.
source
filename
=
this
.
descriptor
.
filename
s
=
new
MagicString
(
this
.
source
)
startOffset
=
this
.
descriptor
.
scriptSetup
?.
loc
.
start
.
offset
endOffset
=
this
.
descriptor
.
scriptSetup
?.
loc
.
end
.
offset
// import / type analysis
scope
?:
TypeScope
globalScopes
?:
TypeScope
[]
userImports
:
Record
<
string
,
ImportBinding
>
=
Object
.
create
(
null
)
// macros presence check
hasDefinePropsCall
=
false
hasDefineEmitCall
=
false
hasDefineExposeCall
=
false
hasDefaultExportName
=
false
hasDefaultExportRender
=
false
hasDefineOptionsCall
=
false
hasDefineSlotsCall
=
false
hasDefineModelCall
=
false
// defineProps
propsCall
:
CallExpression
|
undefined
propsDecl
:
Node
|
undefined
propsRuntimeDecl
:
Node
|
undefined
propsTypeDecl
:
Node
|
undefined
propsDestructureDecl
:
ObjectPattern
|
undefined
propsDestructuredBindings
:
PropsDestructureBindings
=
Object
.
create
(
null
)
propsDestructureRestId
:
string
|
undefined
propsRuntimeDefaults
:
Node
|
undefined
// defineEmits
emitsRuntimeDecl
:
Node
|
undefined
emitsTypeDecl
:
Node
|
undefined
emitDecl
:
Node
|
undefined
// defineModel
modelDecls
:
Record
<
string
,
ModelDecl
>
=
Object
.
create
(
null
)
// defineOptions
optionsRuntimeDecl
:
Node
|
undefined
// codegen
bindingMetadata
:
BindingMetadata
=
{}
helperImports
:
Set
<
string
>
=
new
Set
()
helper
(
key
:
string
):
string
{
this
.
helperImports
.
add
(
key
)
return
`_
${
key
}
`
}
/**
* to be exposed on compiled script block for HMR cache busting
*/
deps
?:
Set
<
string
>
/**
* cache for resolved fs
*/
fs
?:
NonNullable
<
SFCScriptCompileOptions
[
'
fs
'
]
>
constructor
(
public
descriptor
:
SFCDescriptor
,
public
options
:
Partial
<
SFCScriptCompileOptions
>
)
{
// resolve parser plugins
const
plugins
:
ParserPlugin
[]
=
resolveParserPlugins
(
options
.
babelParserPlugins
)
function
parse
(
input
:
string
,
offset
:
number
):
Program
{
try
{
return
babelParse
(
input
,
{
plugins
,
sourceType
:
'
module
'
,
}).
program
}
catch
(
e
:
any
)
{
e
.
message
=
`[vue/compiler-sfc]
${
e
.
message
}
\n\n
${
descriptor
.
filename
}
\n
${
generateCodeFrame
(
descriptor
.
source
,
e
.
pos
+
offset
,
e
.
pos
+
offset
+
1
)}
`
throw
e
}
}
this
.
scriptAst
=
descriptor
.
script
&&
parse
(
descriptor
.
script
.
content
,
descriptor
.
script
.
loc
.
start
.
offset
)
this
.
scriptSetupAst
=
descriptor
.
scriptSetup
&&
parse
(
descriptor
.
scriptSetup
!
.
content
,
this
.
startOffset
!
)
}
getString
(
node
:
Node
,
scriptSetup
=
true
):
string
{
const
block
=
scriptSetup
?
this
.
descriptor
.
scriptSetup
!
:
this
.
descriptor
.
script
!
return
block
.
content
.
slice
(
node
.
start
!
,
node
.
end
!
)
}
error
(
msg
:
string
,
node
:
Node
,
scope
?:
TypeScope
):
never
{
const
offset
=
scope
?
scope
.
offset
:
this
.
startOffset
!
throw
new
Error
(
`[@vue/compiler-sfc]
${
msg
}
\n\n
${
(
scope
||
this
.
descriptor
).
filename
}
\n
${
generateCodeFrame
(
(
scope
||
this
.
descriptor
).
source
,
node
.
start
!
+
offset
,
node
.
end
!
+
offset
)}
`
)
}
}
export
function
resolveParserPlugins
(
userPlugins
?:
ParserPlugin
[],
dts
=
false
)
{
const
plugins
:
ParserPlugin
[]
=
[]
if
(
userPlugins
)
{
// If don't match the case of adding jsx
// should remove the jsx from user options
userPlugins
=
userPlugins
.
filter
((
p
)
=>
p
!==
'
jsx
'
)
}
plugins
.
push
([
'
typescript
'
,
{
dts
}])
if
(
!
userPlugins
||
!
userPlugins
.
includes
(
'
decorators
'
))
{
plugins
.
push
(
'
decorators-legacy
'
)
}
if
(
userPlugins
)
{
plugins
.
push
(...
userPlugins
)
}
return
plugins
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineEmits.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
ArrayPattern
,
Identifier
,
LVal
,
Node
,
ObjectPattern
,
RestElement
,
}
from
'
@babel/types
'
import
{
isCallOf
}
from
'
./utils
'
import
{
ScriptCompileContext
}
from
'
./context
'
import
{
resolveTypeElements
,
resolveUnionType
}
from
'
./resolveType
'
export
const
DEFINE_EMITS
=
'
defineEmits
'
export
function
processDefineEmits
(
ctx
:
ScriptCompileContext
,
node
:
Node
,
declId
?:
LVal
):
boolean
{
if
(
!
isCallOf
(
node
,
DEFINE_EMITS
))
{
return
false
}
if
(
ctx
.
hasDefineEmitCall
)
{
ctx
.
error
(
`duplicate
${
DEFINE_EMITS
}
() call`
,
node
)
}
ctx
.
hasDefineEmitCall
=
true
ctx
.
emitsRuntimeDecl
=
node
.
arguments
[
0
]
if
(
node
.
typeParameters
)
{
if
(
ctx
.
emitsRuntimeDecl
)
{
ctx
.
error
(
`
${
DEFINE_EMITS
}
() cannot accept both type and non-type arguments `
+
`at the same time. Use one or the other.`
,
node
)
}
ctx
.
emitsTypeDecl
=
node
.
typeParameters
.
params
[
0
]
}
ctx
.
emitDecl
=
declId
return
true
}
export
function
genRuntimeEmits
(
ctx
:
ScriptCompileContext
):
string
|
undefined
{
let
emitsDecl
=
''
if
(
ctx
.
emitsRuntimeDecl
)
{
emitsDecl
=
ctx
.
getString
(
ctx
.
emitsRuntimeDecl
).
trim
()
}
else
if
(
ctx
.
emitsTypeDecl
)
{
const
typeDeclaredEmits
=
extractRuntimeEmits
(
ctx
)
emitsDecl
=
typeDeclaredEmits
.
size
?
`[
${
Array
.
from
(
typeDeclaredEmits
)
.
map
((
k
)
=>
JSON
.
stringify
(
k
))
.
join
(
'
,
'
)}
]`
:
``
}
if
(
ctx
.
hasDefineModelCall
)
{
let
modelEmitsDecl
=
`[
${
Object
.
keys
(
ctx
.
modelDecls
)
.
map
((
n
)
=>
JSON
.
stringify
(
`update:
${
n
}
`
))
.
join
(
'
,
'
)}
]`
emitsDecl
=
emitsDecl
?
`/*#__PURE__*/
${
ctx
.
helper
(
'
mergeModels
'
)}
(
${
emitsDecl
}
,
${
modelEmitsDecl
}
)`
:
modelEmitsDecl
}
return
emitsDecl
}
function
extractRuntimeEmits
(
ctx
:
ScriptCompileContext
):
Set
<
string
>
{
const
emits
=
new
Set
<
string
>
()
const
node
=
ctx
.
emitsTypeDecl
!
if
(
node
.
type
===
'
TSFunctionType
'
)
{
extractEventNames
(
ctx
,
node
.
parameters
[
0
],
emits
)
return
emits
}
const
{
props
,
calls
}
=
resolveTypeElements
(
ctx
,
node
)
let
hasProperty
=
false
for
(
const
key
in
props
)
{
emits
.
add
(
key
)
hasProperty
=
true
}
if
(
calls
)
{
if
(
hasProperty
)
{
ctx
.
error
(
`defineEmits() type cannot mixed call signature and property syntax.`
,
node
)
}
for
(
const
call
of
calls
)
{
extractEventNames
(
ctx
,
call
.
parameters
[
0
],
emits
)
}
}
return
emits
}
function
extractEventNames
(
ctx
:
ScriptCompileContext
,
eventName
:
ArrayPattern
|
Identifier
|
ObjectPattern
|
RestElement
,
emits
:
Set
<
string
>
)
{
if
(
eventName
.
type
===
'
Identifier
'
&&
eventName
.
typeAnnotation
&&
eventName
.
typeAnnotation
.
type
===
'
TSTypeAnnotation
'
)
{
const
types
=
resolveUnionType
(
ctx
,
eventName
.
typeAnnotation
.
typeAnnotation
)
for
(
const
type
of
types
)
{
if
(
type
.
type
===
'
TSLiteralType
'
)
{
if
(
type
.
literal
.
type
!==
'
UnaryExpression
'
&&
type
.
literal
.
type
!==
'
TemplateLiteral
'
)
{
emits
.
add
(
String
(
type
.
literal
.
value
))
}
}
}
}
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineExpose.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
Node
}
from
'
@babel/types
'
import
{
isCallOf
}
from
'
./utils
'
import
{
ScriptCompileContext
}
from
'
./context
'
export
const
DEFINE_EXPOSE
=
'
defineExpose
'
export
function
processDefineExpose
(
ctx
:
ScriptCompileContext
,
node
:
Node
):
boolean
{
if
(
isCallOf
(
node
,
DEFINE_EXPOSE
))
{
if
(
ctx
.
hasDefineExposeCall
)
{
ctx
.
error
(
`duplicate
${
DEFINE_EXPOSE
}
() call`
,
node
)
}
ctx
.
hasDefineExposeCall
=
true
return
true
}
return
false
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineModel.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
LVal
,
Node
,
ObjectProperty
,
TSType
}
from
'
@babel/types
'
import
{
ScriptCompileContext
}
from
'
./context
'
import
{
inferRuntimeType
}
from
'
./resolveType
'
import
{
UNKNOWN_TYPE
,
concatStrings
,
isCallOf
,
toRuntimeTypeString
,
unwrapTSNode
,
}
from
'
./utils
'
import
{
BindingTypes
}
from
'
@vue/compiler-dom
'
import
{
warnOnce
}
from
'
../warn
'
export
const
DEFINE_MODEL
=
'
defineModel
'
export
interface
ModelDecl
{
type
:
TSType
|
undefined
options
:
string
|
undefined
identifier
:
string
|
undefined
}
export
function
processDefineModel
(
ctx
:
ScriptCompileContext
,
node
:
Node
,
declId
?:
LVal
):
boolean
{
if
(
!
isCallOf
(
node
,
DEFINE_MODEL
))
{
return
false
}
if
(
!
ctx
.
options
.
defineModel
)
{
warnOnce
(
`defineModel() is an experimental feature and disabled by default.\n`
+
`To enable it, follow the RFC at https://github.com/vuejs/rfcs/discussions/503.`
)
return
false
}
warnOnce
(
`This project is using defineModel(), which is an experimental `
+
`feature. It may receive breaking changes or be removed in the future, so `
+
`use at your own risk.\n`
+
`To stay updated, follow the RFC at https://github.com/vuejs/rfcs/discussions/503.`
)
ctx
.
hasDefineModelCall
=
true
const
type
=
(
node
.
typeParameters
&&
node
.
typeParameters
.
params
[
0
])
||
undefined
let
modelName
:
string
let
options
:
Node
|
undefined
const
arg0
=
node
.
arguments
[
0
]
&&
unwrapTSNode
(
node
.
arguments
[
0
])
if
(
arg0
&&
arg0
.
type
===
'
StringLiteral
'
)
{
modelName
=
arg0
.
value
options
=
node
.
arguments
[
1
]
}
else
{
modelName
=
'
modelValue
'
options
=
arg0
}
if
(
ctx
.
modelDecls
[
modelName
])
{
ctx
.
error
(
`duplicate model name
${
JSON
.
stringify
(
modelName
)}
`
,
node
)
}
const
optionsString
=
options
&&
ctx
.
getString
(
options
)
ctx
.
modelDecls
[
modelName
]
=
{
type
,
options
:
optionsString
,
identifier
:
declId
&&
declId
.
type
===
'
Identifier
'
?
declId
.
name
:
undefined
,
}
// register binding type
ctx
.
bindingMetadata
[
modelName
]
=
BindingTypes
.
PROPS
let
runtimeOptions
=
''
if
(
options
)
{
if
(
options
.
type
===
'
ObjectExpression
'
)
{
const
local
=
options
.
properties
.
find
(
(
p
)
=>
p
.
type
===
'
ObjectProperty
'
&&
((
p
.
key
.
type
===
'
Identifier
'
&&
p
.
key
.
name
===
'
local
'
)
||
(
p
.
key
.
type
===
'
StringLiteral
'
&&
p
.
key
.
value
===
'
local
'
))
)
as
ObjectProperty
if
(
local
)
{
runtimeOptions
=
`{
${
ctx
.
getString
(
local
)}
}`
}
else
{
for
(
const
p
of
options
.
properties
)
{
if
(
p
.
type
===
'
SpreadElement
'
||
p
.
computed
)
{
runtimeOptions
=
optionsString
!
break
}
}
}
}
else
{
runtimeOptions
=
optionsString
!
}
}
ctx
.
s
.
overwrite
(
ctx
.
startOffset
!
+
node
.
start
!
,
ctx
.
startOffset
!
+
node
.
end
!
,
`
${
ctx
.
helper
(
'
useModel
'
)}
(__props,
${
JSON
.
stringify
(
modelName
)}${
runtimeOptions
?
`,
${
runtimeOptions
}
`
:
``
}
)`
)
return
true
}
export
function
genModelProps
(
ctx
:
ScriptCompileContext
)
{
if
(
!
ctx
.
hasDefineModelCall
)
return
const
isProd
=
!!
ctx
.
options
.
isProd
let
modelPropsDecl
=
''
for
(
const
[
name
,
{
type
,
options
}]
of
Object
.
entries
(
ctx
.
modelDecls
))
{
let
skipCheck
=
false
let
runtimeTypes
=
type
&&
inferRuntimeType
(
ctx
,
type
)
if
(
runtimeTypes
)
{
const
hasUnknownType
=
runtimeTypes
.
includes
(
UNKNOWN_TYPE
)
runtimeTypes
=
runtimeTypes
.
filter
((
el
)
=>
{
if
(
el
===
UNKNOWN_TYPE
)
return
false
return
isProd
?
el
===
'
Boolean
'
||
(
el
===
'
Function
'
&&
options
)
:
true
})
skipCheck
=
!
isProd
&&
hasUnknownType
&&
runtimeTypes
.
length
>
0
}
let
runtimeType
=
(
runtimeTypes
&&
runtimeTypes
.
length
>
0
&&
toRuntimeTypeString
(
runtimeTypes
))
||
undefined
const
codegenOptions
=
concatStrings
([
runtimeType
&&
`type:
${
runtimeType
}
`
,
skipCheck
&&
'
skipCheck: true
'
,
])
let
decl
:
string
if
(
runtimeType
&&
options
)
{
decl
=
`{
${
codegenOptions
}
, ...
${
options
}
}`
}
else
{
decl
=
options
||
(
runtimeType
?
`{
${
codegenOptions
}
}`
:
'
{}
'
)
}
modelPropsDecl
+=
`\n
${
JSON
.
stringify
(
name
)}
:
${
decl
}
,`
}
return
`{
${
modelPropsDecl
}
\n }`
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineOptions.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
Node
}
from
'
@babel/types
'
import
{
ScriptCompileContext
}
from
'
./context
'
import
{
isCallOf
,
unwrapTSNode
}
from
'
./utils
'
import
{
DEFINE_PROPS
}
from
'
./defineProps
'
import
{
DEFINE_EMITS
}
from
'
./defineEmits
'
import
{
DEFINE_EXPOSE
}
from
'
./defineExpose
'
import
{
DEFINE_SLOTS
}
from
'
./defineSlots
'
export
const
DEFINE_OPTIONS
=
'
defineOptions
'
export
function
processDefineOptions
(
ctx
:
ScriptCompileContext
,
node
:
Node
):
boolean
{
if
(
!
isCallOf
(
node
,
DEFINE_OPTIONS
))
{
return
false
}
if
(
ctx
.
hasDefineOptionsCall
)
{
ctx
.
error
(
`duplicate
${
DEFINE_OPTIONS
}
() call`
,
node
)
}
if
(
node
.
typeParameters
)
{
ctx
.
error
(
`
${
DEFINE_OPTIONS
}
() cannot accept type arguments`
,
node
)
}
if
(
!
node
.
arguments
[
0
])
return
true
ctx
.
hasDefineOptionsCall
=
true
ctx
.
optionsRuntimeDecl
=
unwrapTSNode
(
node
.
arguments
[
0
])
let
propsOption
=
undefined
let
emitsOption
=
undefined
let
exposeOption
=
undefined
let
slotsOption
=
undefined
if
(
ctx
.
optionsRuntimeDecl
.
type
===
'
ObjectExpression
'
)
{
for
(
const
prop
of
ctx
.
optionsRuntimeDecl
.
properties
)
{
if
(
(
prop
.
type
===
'
ObjectProperty
'
||
prop
.
type
===
'
ObjectMethod
'
)
&&
prop
.
key
.
type
===
'
Identifier
'
)
{
if
(
prop
.
key
.
name
===
'
props
'
)
propsOption
=
prop
if
(
prop
.
key
.
name
===
'
emits
'
)
emitsOption
=
prop
if
(
prop
.
key
.
name
===
'
expose
'
)
exposeOption
=
prop
if
(
prop
.
key
.
name
===
'
slots
'
)
slotsOption
=
prop
}
}
}
if
(
propsOption
)
{
ctx
.
error
(
`
${
DEFINE_OPTIONS
}
() cannot be used to declare props. Use
${
DEFINE_PROPS
}
() instead.`
,
propsOption
)
}
if
(
emitsOption
)
{
ctx
.
error
(
`
${
DEFINE_OPTIONS
}
() cannot be used to declare emits. Use
${
DEFINE_EMITS
}
() instead.`
,
emitsOption
)
}
if
(
exposeOption
)
{
ctx
.
error
(
`
${
DEFINE_OPTIONS
}
() cannot be used to declare expose. Use
${
DEFINE_EXPOSE
}
() instead.`
,
exposeOption
)
}
if
(
slotsOption
)
{
ctx
.
error
(
`
${
DEFINE_OPTIONS
}
() cannot be used to declare slots. Use
${
DEFINE_SLOTS
}
() instead.`
,
slotsOption
)
}
return
true
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineProps.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
Node
,
LVal
,
ObjectProperty
,
ObjectMethod
,
ObjectExpression
,
Expression
,
}
from
'
@babel/types
'
import
{
BindingTypes
,
isFunctionType
}
from
'
@vue/compiler-dom
'
import
{
ScriptCompileContext
}
from
'
./context
'
import
{
inferRuntimeType
,
resolveTypeElements
}
from
'
./resolveType
'
import
{
resolveObjectKey
,
UNKNOWN_TYPE
,
concatStrings
,
isLiteralNode
,
isCallOf
,
unwrapTSNode
,
toRuntimeTypeString
,
getEscapedPropName
,
}
from
'
./utils
'
import
{
genModelProps
}
from
'
./defineModel
'
import
{
getObjectOrArrayExpressionKeys
}
from
'
./analyzeScriptBindings
'
import
{
processPropsDestructure
}
from
'
./definePropsDestructure
'
export
const
DEFINE_PROPS
=
'
defineProps
'
export
const
WITH_DEFAULTS
=
'
withDefaults
'
export
interface
PropTypeData
{
key
:
string
type
:
string
[]
required
:
boolean
skipCheck
:
boolean
}
export
type
PropsDestructureBindings
=
Record
<
string
,
// public prop key
{
local
:
string
// local identifier, may be different
default
?:
Expression
}
>
export
function
processDefineProps
(
ctx
:
ScriptCompileContext
,
node
:
Node
,
declId
?:
LVal
)
{
if
(
!
isCallOf
(
node
,
DEFINE_PROPS
))
{
return
processWithDefaults
(
ctx
,
node
,
declId
)
}
if
(
ctx
.
hasDefinePropsCall
)
{
ctx
.
error
(
`duplicate
${
DEFINE_PROPS
}
() call`
,
node
)
}
ctx
.
hasDefinePropsCall
=
true
ctx
.
propsRuntimeDecl
=
node
.
arguments
[
0
]
// register bindings
if
(
ctx
.
propsRuntimeDecl
)
{
for
(
const
key
of
getObjectOrArrayExpressionKeys
(
ctx
.
propsRuntimeDecl
))
{
if
(
!
(
key
in
ctx
.
bindingMetadata
))
{
ctx
.
bindingMetadata
[
key
]
=
BindingTypes
.
PROPS
}
}
}
// call has type parameters - infer runtime types from it
if
(
node
.
typeParameters
)
{
if
(
ctx
.
propsRuntimeDecl
)
{
ctx
.
error
(
`
${
DEFINE_PROPS
}
() cannot accept both type and non-type arguments `
+
`at the same time. Use one or the other.`
,
node
)
}
ctx
.
propsTypeDecl
=
node
.
typeParameters
.
params
[
0
]
}
// handle props destructure
if
(
declId
&&
declId
.
type
===
'
ObjectPattern
'
)
{
processPropsDestructure
(
ctx
,
declId
)
}
ctx
.
propsCall
=
node
ctx
.
propsDecl
=
declId
return
true
}
function
processWithDefaults
(
ctx
:
ScriptCompileContext
,
node
:
Node
,
declId
?:
LVal
):
boolean
{
if
(
!
isCallOf
(
node
,
WITH_DEFAULTS
))
{
return
false
}
if
(
!
processDefineProps
(
ctx
,
node
.
arguments
[
0
],
declId
))
{
ctx
.
error
(
`
${
WITH_DEFAULTS
}
' first argument must be a
${
DEFINE_PROPS
}
call.`
,
node
.
arguments
[
0
]
||
node
)
}
if
(
ctx
.
propsRuntimeDecl
)
{
ctx
.
error
(
`
${
WITH_DEFAULTS
}
can only be used with type-based `
+
`
${
DEFINE_PROPS
}
declaration.`
,
node
)
}
if
(
ctx
.
propsDestructureDecl
)
{
ctx
.
error
(
`
${
WITH_DEFAULTS
}
() is unnecessary when using destructure with
${
DEFINE_PROPS
}
().\n`
+
`Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`
,
node
.
callee
)
}
ctx
.
propsRuntimeDefaults
=
node
.
arguments
[
1
]
if
(
!
ctx
.
propsRuntimeDefaults
)
{
ctx
.
error
(
`The 2nd argument of
${
WITH_DEFAULTS
}
is required.`
,
node
)
}
ctx
.
propsCall
=
node
return
true
}
export
function
genRuntimeProps
(
ctx
:
ScriptCompileContext
):
string
|
undefined
{
let
propsDecls
:
undefined
|
string
if
(
ctx
.
propsRuntimeDecl
)
{
propsDecls
=
ctx
.
getString
(
ctx
.
propsRuntimeDecl
).
trim
()
if
(
ctx
.
propsDestructureDecl
)
{
const
defaults
:
string
[]
=
[]
for
(
const
key
in
ctx
.
propsDestructuredBindings
)
{
const
d
=
genDestructuredDefaultValue
(
ctx
,
key
)
const
finalKey
=
getEscapedPropName
(
key
)
if
(
d
)
defaults
.
push
(
`
${
finalKey
}
:
${
d
.
valueString
}${
d
.
needSkipFactory
?
`, __skip_
${
finalKey
}
: true`
:
``
}
`
)
}
if
(
defaults
.
length
)
{
propsDecls
=
`/*#__PURE__*/
${
ctx
.
helper
(
`mergeDefaults`
)}
(
${
propsDecls
}
, {\n
${
defaults
.
join
(
'
,
\n
'
)}
\n})`
}
}
}
else
if
(
ctx
.
propsTypeDecl
)
{
propsDecls
=
genRuntimePropsFromTypes
(
ctx
)
}
const
modelsDecls
=
genModelProps
(
ctx
)
if
(
propsDecls
&&
modelsDecls
)
{
return
`/*#__PURE__*/
${
ctx
.
helper
(
'
mergeModels
'
)}
(
${
propsDecls
}
,
${
modelsDecls
}
)`
}
else
{
return
modelsDecls
||
propsDecls
}
}
function
genRuntimePropsFromTypes
(
ctx
:
ScriptCompileContext
)
{
// this is only called if propsTypeDecl exists
const
props
=
resolveRuntimePropsFromType
(
ctx
,
ctx
.
propsTypeDecl
!
)
if
(
!
props
.
length
)
{
return
}
const
propStrings
:
string
[]
=
[]
const
hasStaticDefaults
=
hasStaticWithDefaults
(
ctx
)
for
(
const
prop
of
props
)
{
propStrings
.
push
(
genRuntimePropFromType
(
ctx
,
prop
,
hasStaticDefaults
))
// register bindings
if
(
!
(
prop
.
key
in
ctx
.
bindingMetadata
))
{
ctx
.
bindingMetadata
[
prop
.
key
]
=
BindingTypes
.
PROPS
}
}
let
propsDecls
=
`{
${
propStrings
.
join
(
'
,
\n
'
)}
\n }`
if
(
ctx
.
propsRuntimeDefaults
&&
!
hasStaticDefaults
)
{
propsDecls
=
`/*#__PURE__*/
${
ctx
.
helper
(
'
mergeDefaults
'
)}
(
${
propsDecls
}
,
${
ctx
.
getString
(
ctx
.
propsRuntimeDefaults
)}
)`
}
return
propsDecls
}
function
resolveRuntimePropsFromType
(
ctx
:
ScriptCompileContext
,
node
:
Node
):
PropTypeData
[]
{
const
props
:
PropTypeData
[]
=
[]
const
elements
=
resolveTypeElements
(
ctx
,
node
)
for
(
const
key
in
elements
.
props
)
{
const
e
=
elements
.
props
[
key
]
let
type
=
inferRuntimeType
(
ctx
,
e
)
let
skipCheck
=
false
// skip check for result containing unknown types
if
(
type
.
includes
(
UNKNOWN_TYPE
))
{
if
(
type
.
includes
(
'
Boolean
'
)
||
type
.
includes
(
'
Function
'
))
{
type
=
type
.
filter
((
t
)
=>
t
!==
UNKNOWN_TYPE
)
skipCheck
=
true
}
else
{
type
=
[
'
null
'
]
}
}
props
.
push
({
key
,
required
:
!
e
.
optional
,
type
:
type
||
[
`null`
],
skipCheck
,
})
}
return
props
}
function
genRuntimePropFromType
(
ctx
:
ScriptCompileContext
,
{
key
,
required
,
type
,
skipCheck
}:
PropTypeData
,
hasStaticDefaults
:
boolean
):
string
{
let
defaultString
:
string
|
undefined
const
destructured
=
genDestructuredDefaultValue
(
ctx
,
key
,
type
)
if
(
destructured
)
{
defaultString
=
`default:
${
destructured
.
valueString
}${
destructured
.
needSkipFactory
?
`, skipFactory: true`
:
``
}
`
}
else
if
(
hasStaticDefaults
)
{
const
prop
=
(
ctx
.
propsRuntimeDefaults
as
ObjectExpression
).
properties
.
find
(
(
node
)
=>
{
if
(
node
.
type
===
'
SpreadElement
'
)
return
false
return
resolveObjectKey
(
node
.
key
,
node
.
computed
)
===
key
}
)
as
ObjectProperty
|
ObjectMethod
if
(
prop
)
{
if
(
prop
.
type
===
'
ObjectProperty
'
)
{
// prop has corresponding static default value
defaultString
=
`default:
${
ctx
.
getString
(
prop
.
value
)}
`
}
else
{
defaultString
=
`
${
prop
.
async
?
'
async
'
:
''
}${
prop
.
kind
!==
'
method
'
?
`
${
prop
.
kind
}
`
:
''
}
default()
${
ctx
.
getString
(
prop
.
body
)}
`
}
}
}
const
finalKey
=
getEscapedPropName
(
key
)
if
(
!
ctx
.
options
.
isProd
)
{
return
`
${
finalKey
}
: {
${
concatStrings
([
`type:
${
toRuntimeTypeString
(
type
)}
`
,
`required:
${
required
}
`
,
skipCheck
&&
'
skipCheck: true
'
,
defaultString
,
])}
}`
}
else
if
(
type
.
some
(
(
el
)
=>
el
===
'
Boolean
'
||
((
!
hasStaticDefaults
||
defaultString
)
&&
el
===
'
Function
'
)
)
)
{
// #4783 for boolean, should keep the type
// #7111 for function, if default value exists or it's not static, should keep it
// in production
return
`
${
finalKey
}
: {
${
concatStrings
([
`type:
${
toRuntimeTypeString
(
type
)}
`
,
defaultString
,
])}
}`
}
else
{
// production: checks are useless
return
`
${
finalKey
}
:
${
defaultString
?
`{
${
defaultString
}
}`
:
`{}`
}
`
}
}
/**
* check defaults. If the default object is an object literal with only
* static properties, we can directly generate more optimized default
* declarations. Otherwise we will have to fallback to runtime merging.
*/
function
hasStaticWithDefaults
(
ctx
:
ScriptCompileContext
)
{
return
!!
(
ctx
.
propsRuntimeDefaults
&&
ctx
.
propsRuntimeDefaults
.
type
===
'
ObjectExpression
'
&&
ctx
.
propsRuntimeDefaults
.
properties
.
every
(
(
node
)
=>
node
.
type
!==
'
SpreadElement
'
&&
(
!
node
.
computed
||
node
.
key
.
type
.
endsWith
(
'
Literal
'
))
)
)
}
function
genDestructuredDefaultValue
(
ctx
:
ScriptCompileContext
,
key
:
string
,
inferredType
?:
string
[]
):
|
{
valueString
:
string
needSkipFactory
:
boolean
}
|
undefined
{
const
destructured
=
ctx
.
propsDestructuredBindings
[
key
]
const
defaultVal
=
destructured
&&
destructured
.
default
if
(
defaultVal
)
{
const
value
=
ctx
.
getString
(
defaultVal
)
const
unwrapped
=
unwrapTSNode
(
defaultVal
)
if
(
inferredType
&&
inferredType
.
length
&&
!
inferredType
.
includes
(
'
null
'
))
{
const
valueType
=
inferValueType
(
unwrapped
)
if
(
valueType
&&
!
inferredType
.
includes
(
valueType
))
{
ctx
.
error
(
`Default value of prop "
${
key
}
" does not match declared type.`
,
unwrapped
)
}
}
// If the default value is a function or is an identifier referencing
// external value, skip factory wrap. This is needed when using
// destructure w/ runtime declaration since we cannot safely infer
// whether the expected runtime prop type is `Function`.
const
needSkipFactory
=
!
inferredType
&&
(
isFunctionType
(
unwrapped
)
||
unwrapped
.
type
===
'
Identifier
'
)
const
needFactoryWrap
=
!
needSkipFactory
&&
!
isLiteralNode
(
unwrapped
)
&&
!
inferredType
?.
includes
(
'
Function
'
)
return
{
valueString
:
needFactoryWrap
?
`() => (
${
value
}
)`
:
value
,
needSkipFactory
,
}
}
}
// non-comprehensive, best-effort type infernece for a runtime value
// this is used to catch default value / type declaration mismatches
// when using props destructure.
function
inferValueType
(
node
:
Node
):
string
|
undefined
{
switch
(
node
.
type
)
{
case
'
StringLiteral
'
:
return
'
String
'
case
'
NumericLiteral
'
:
return
'
Number
'
case
'
BooleanLiteral
'
:
return
'
Boolean
'
case
'
ObjectExpression
'
:
return
'
Object
'
case
'
ArrayExpression
'
:
return
'
Array
'
case
'
FunctionExpression
'
:
case
'
ArrowFunctionExpression
'
:
return
'
Function
'
}
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/definePropsDestructure.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
Node
,
Identifier
,
BlockStatement
,
Program
,
VariableDeclaration
,
ObjectPattern
,
Expression
,
}
from
'
@babel/types
'
import
{
walk
}
from
'
estree-walker
'
import
{
BindingTypes
,
extractIdentifiers
,
isFunctionType
,
isInDestructureAssignment
,
isReferencedIdentifier
,
isStaticProperty
,
walkFunctionParams
,
}
from
'
@vue/compiler-dom
'
import
{
genPropsAccessExp
}
from
'
@vue/shared
'
import
{
isCallOf
,
resolveObjectKey
,
unwrapTSNode
}
from
'
./utils
'
import
{
ScriptCompileContext
}
from
'
./context
'
import
{
DEFINE_PROPS
}
from
'
./defineProps
'
import
{
warnOnce
}
from
'
../warn
'
export
function
processPropsDestructure
(
ctx
:
ScriptCompileContext
,
declId
:
ObjectPattern
)
{
if
(
!
ctx
.
options
.
propsDestructure
&&
!
ctx
.
options
.
reactivityTransform
)
{
return
}
warnOnce
(
`This project is using reactive props destructure, which is an experimental `
+
`feature. It may receive breaking changes or be removed in the future, so `
+
`use at your own risk.\n`
+
`To stay updated, follow the RFC at https://github.com/vuejs/rfcs/discussions/502.`
)
ctx
.
propsDestructureDecl
=
declId
const
registerBinding
=
(
key
:
string
,
local
:
string
,
defaultValue
?:
Expression
)
=>
{
ctx
.
propsDestructuredBindings
[
key
]
=
{
local
,
default
:
defaultValue
}
if
(
local
!==
key
)
{
ctx
.
bindingMetadata
[
local
]
=
BindingTypes
.
PROPS_ALIASED
;(
ctx
.
bindingMetadata
.
__propsAliases
||
(
ctx
.
bindingMetadata
.
__propsAliases
=
{}))[
local
]
=
key
}
}
for
(
const
prop
of
declId
.
properties
)
{
if
(
prop
.
type
===
'
ObjectProperty
'
)
{
const
propKey
=
resolveObjectKey
(
prop
.
key
,
prop
.
computed
)
if
(
!
propKey
)
{
ctx
.
error
(
`
${
DEFINE_PROPS
}
() destructure cannot use computed key.`
,
prop
.
key
)
}
if
(
prop
.
value
.
type
===
'
AssignmentPattern
'
)
{
// default value { foo = 123 }
const
{
left
,
right
}
=
prop
.
value
if
(
left
.
type
!==
'
Identifier
'
)
{
ctx
.
error
(
`
${
DEFINE_PROPS
}
() destructure does not support nested patterns.`
,
left
)
}
registerBinding
(
propKey
,
left
.
name
,
right
)
}
else
if
(
prop
.
value
.
type
===
'
Identifier
'
)
{
// simple destructure
registerBinding
(
propKey
,
prop
.
value
.
name
)
}
else
{
ctx
.
error
(
`
${
DEFINE_PROPS
}
() destructure does not support nested patterns.`
,
prop
.
value
)
}
}
else
{
// rest spread
ctx
.
propsDestructureRestId
=
(
prop
.
argument
as
Identifier
).
name
// register binding
ctx
.
bindingMetadata
[
ctx
.
propsDestructureRestId
]
=
BindingTypes
.
SETUP_REACTIVE_CONST
}
}
}
/**
* true -> prop binding
* false -> local binding
*/
type
Scope
=
Record
<
string
,
boolean
>
export
function
transformDestructuredProps
(
ctx
:
ScriptCompileContext
,
vueImportAliases
:
Record
<
string
,
string
>
)
{
if
(
!
ctx
.
options
.
propsDestructure
&&
!
ctx
.
options
.
reactivityTransform
)
{
return
}
const
rootScope
:
Scope
=
{}
const
scopeStack
:
Scope
[]
=
[
rootScope
]
let
currentScope
:
Scope
=
rootScope
const
excludedIds
=
new
WeakSet
<
Identifier
>
()
const
parentStack
:
Node
[]
=
[]
const
propsLocalToPublicMap
:
Record
<
string
,
string
>
=
Object
.
create
(
null
)
for
(
const
key
in
ctx
.
propsDestructuredBindings
)
{
const
{
local
}
=
ctx
.
propsDestructuredBindings
[
key
]
rootScope
[
local
]
=
true
propsLocalToPublicMap
[
local
]
=
key
}
function
pushScope
()
{
scopeStack
.
push
((
currentScope
=
Object
.
create
(
currentScope
)))
}
function
popScope
()
{
scopeStack
.
pop
()
currentScope
=
scopeStack
[
scopeStack
.
length
-
1
]
||
null
}
function
registerLocalBinding
(
id
:
Identifier
)
{
excludedIds
.
add
(
id
)
if
(
currentScope
)
{
currentScope
[
id
.
name
]
=
false
}
else
{
ctx
.
error
(
'
registerBinding called without active scope, something is wrong.
'
,
id
)
}
}
function
walkScope
(
node
:
Program
|
BlockStatement
,
isRoot
=
false
)
{
for
(
const
stmt
of
node
.
body
)
{
if
(
stmt
.
type
===
'
VariableDeclaration
'
)
{
walkVariableDeclaration
(
stmt
,
isRoot
)
}
else
if
(
stmt
.
type
===
'
FunctionDeclaration
'
||
stmt
.
type
===
'
ClassDeclaration
'
)
{
if
(
stmt
.
declare
||
!
stmt
.
id
)
continue
registerLocalBinding
(
stmt
.
id
)
}
else
if
(
(
stmt
.
type
===
'
ForOfStatement
'
||
stmt
.
type
===
'
ForInStatement
'
)
&&
stmt
.
left
.
type
===
'
VariableDeclaration
'
)
{
walkVariableDeclaration
(
stmt
.
left
)
}
else
if
(
stmt
.
type
===
'
ExportNamedDeclaration
'
&&
stmt
.
declaration
&&
stmt
.
declaration
.
type
===
'
VariableDeclaration
'
)
{
walkVariableDeclaration
(
stmt
.
declaration
,
isRoot
)
}
else
if
(
stmt
.
type
===
'
LabeledStatement
'
&&
stmt
.
body
.
type
===
'
VariableDeclaration
'
)
{
walkVariableDeclaration
(
stmt
.
body
,
isRoot
)
}
}
}
function
walkVariableDeclaration
(
stmt
:
VariableDeclaration
,
isRoot
=
false
)
{
if
(
stmt
.
declare
)
{
return
}
for
(
const
decl
of
stmt
.
declarations
)
{
const
isDefineProps
=
isRoot
&&
decl
.
init
&&
isCallOf
(
unwrapTSNode
(
decl
.
init
),
'
defineProps
'
)
for
(
const
id
of
extractIdentifiers
(
decl
.
id
))
{
if
(
isDefineProps
)
{
// for defineProps destructure, only exclude them since they
// are already passed in as knownProps
excludedIds
.
add
(
id
)
}
else
{
registerLocalBinding
(
id
)
}
}
}
}
function
rewriteId
(
id
:
Identifier
,
parent
:
Node
,
parentStack
:
Node
[])
{
if
(
(
parent
.
type
===
'
AssignmentExpression
'
&&
id
===
parent
.
left
)
||
parent
.
type
===
'
UpdateExpression
'
)
{
ctx
.
error
(
`Cannot assign to destructured props as they are readonly.`
,
id
)
}
if
(
isStaticProperty
(
parent
)
&&
parent
.
shorthand
)
{
// let binding used in a property shorthand
// skip for destructure patterns
if
(
!
(
parent
as
any
).
inPattern
||
isInDestructureAssignment
(
parent
,
parentStack
)
)
{
// { prop } -> { prop: __props.prop }
ctx
.
s
.
appendLeft
(
id
.
end
!
+
ctx
.
startOffset
!
,
`:
${
genPropsAccessExp
(
propsLocalToPublicMap
[
id
.
name
])}
`
)
}
}
else
{
// x --> __props.x
ctx
.
s
.
overwrite
(
id
.
start
!
+
ctx
.
startOffset
!
,
id
.
end
!
+
ctx
.
startOffset
!
,
genPropsAccessExp
(
propsLocalToPublicMap
[
id
.
name
])
)
}
}
function
checkUsage
(
node
:
Node
,
method
:
string
,
alias
=
method
)
{
if
(
isCallOf
(
node
,
alias
))
{
const
arg
=
unwrapTSNode
(
node
.
arguments
[
0
])
if
(
arg
.
type
===
'
Identifier
'
&&
currentScope
[
arg
.
name
])
{
ctx
.
error
(
`"
${
arg
.
name
}
" is a destructured prop and should not be passed directly to
${
method
}
(). `
+
`Pass a getter () =>
${
arg
.
name
}
instead.`
,
arg
)
}
}
}
// check root scope first
const
ast
=
ctx
.
scriptSetupAst
!
walkScope
(
ast
,
true
)
walk
(
ast
,
{
enter
(
node
:
Node
,
parent
?:
Node
)
{
parent
&&
parentStack
.
push
(
parent
)
// skip type nodes
if
(
parent
&&
parent
.
type
.
startsWith
(
'
TS
'
)
&&
parent
.
type
!==
'
TSAsExpression
'
&&
parent
.
type
!==
'
TSNonNullExpression
'
&&
parent
.
type
!==
'
TSTypeAssertion
'
)
{
return
this
.
skip
()
}
checkUsage
(
node
,
'
watch
'
,
vueImportAliases
.
watch
)
checkUsage
(
node
,
'
toRef
'
,
vueImportAliases
.
toRef
)
// function scopes
if
(
isFunctionType
(
node
))
{
pushScope
()
walkFunctionParams
(
node
,
registerLocalBinding
)
if
(
node
.
body
.
type
===
'
BlockStatement
'
)
{
walkScope
(
node
.
body
)
}
return
}
// catch param
if
(
node
.
type
===
'
CatchClause
'
)
{
pushScope
()
if
(
node
.
param
&&
node
.
param
.
type
===
'
Identifier
'
)
{
registerLocalBinding
(
node
.
param
)
}
walkScope
(
node
.
body
)
return
}
// non-function block scopes
if
(
node
.
type
===
'
BlockStatement
'
&&
!
isFunctionType
(
parent
!
))
{
pushScope
()
walkScope
(
node
)
return
}
if
(
node
.
type
===
'
Identifier
'
)
{
if
(
isReferencedIdentifier
(
node
,
parent
!
,
parentStack
)
&&
!
excludedIds
.
has
(
node
)
)
{
if
(
currentScope
[
node
.
name
])
{
rewriteId
(
node
,
parent
!
,
parentStack
)
}
}
}
},
leave
(
node
:
Node
,
parent
?:
Node
)
{
parent
&&
parentStack
.
pop
()
if
(
(
node
.
type
===
'
BlockStatement
'
&&
!
isFunctionType
(
parent
!
))
||
isFunctionType
(
node
)
)
{
popScope
()
}
},
})
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/defineSlots.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
LVal
,
Node
}
from
'
@babel/types
'
import
{
isCallOf
}
from
'
./utils
'
import
{
ScriptCompileContext
}
from
'
./context
'
export
const
DEFINE_SLOTS
=
'
defineSlots
'
export
function
processDefineSlots
(
ctx
:
ScriptCompileContext
,
node
:
Node
,
declId
?:
LVal
):
boolean
{
if
(
!
isCallOf
(
node
,
DEFINE_SLOTS
))
{
return
false
}
if
(
ctx
.
hasDefineSlotsCall
)
{
ctx
.
error
(
`duplicate
${
DEFINE_SLOTS
}
() call`
,
node
)
}
ctx
.
hasDefineSlotsCall
=
true
if
(
node
.
arguments
.
length
>
0
)
{
ctx
.
error
(
`
${
DEFINE_SLOTS
}
() cannot accept arguments`
,
node
)
}
if
(
declId
)
{
ctx
.
s
.
overwrite
(
ctx
.
startOffset
!
+
node
.
start
!
,
ctx
.
startOffset
!
+
node
.
end
!
,
`
${
ctx
.
helper
(
'
useSlots
'
)}
()`
)
}
return
true
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/normalScript.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
analyzeScriptBindings
}
from
'
./analyzeScriptBindings
'
import
{
ScriptCompileContext
}
from
'
./context
'
import
MagicString
from
'
magic-string
'
import
{
rewriteDefaultAST
}
from
'
../rewriteDefault
'
export
const
normalScriptDefaultVar
=
`__default__`
export
function
processNormalScript
(
ctx
:
ScriptCompileContext
,
_scopeId
:
string
)
{
const
script
=
ctx
.
descriptor
.
script
!
// if (script.lang && !ctx.isJS && !ctx.isTS) {
// // do not process non js/ts script blocks
// return script
// }
try
{
let
content
=
script
.
content
let
map
=
script
.
map
const
scriptAst
=
ctx
.
scriptAst
!
const
bindings
=
analyzeScriptBindings
(
scriptAst
.
body
)
const
{
cssVars
}
=
ctx
.
descriptor
const
{
genDefaultAs
}
=
ctx
.
options
if
(
cssVars
.
length
||
genDefaultAs
)
{
const
defaultVar
=
genDefaultAs
||
normalScriptDefaultVar
const
s
=
new
MagicString
(
content
)
rewriteDefaultAST
(
scriptAst
.
body
,
s
,
defaultVar
)
content
=
s
.
toString
()
if
(
!
genDefaultAs
)
{
content
+=
`\nexport default
${
defaultVar
}
`
}
}
return
{
...
script
,
content
,
map
,
bindings
,
scriptAst
:
scriptAst
.
body
,
}
}
catch
(
e
:
any
)
{
// silently fallback if parse fails since user may be using custom
// babel syntax
return
script
}
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/resolveType.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/topLevelAwait.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
AwaitExpression
}
from
'
@babel/types
'
import
{
ScriptCompileContext
}
from
'
./context
'
/**
* Support context-persistence between top-level await expressions:
*
* ```js
* const instance = getCurrentInstance()
* await foo()
* expect(getCurrentInstance()).toBe(instance)
* ```
*
* In the future we can potentially get rid of this when Async Context
* becomes generally available: https://github.com/tc39/proposal-async-context
*
* ```js
* // input
* await foo()
* // output
* ;(
* ([__temp,__restore] = withAsyncContext(() => foo())),
* await __temp,
* __restore()
* )
*
* // input
* const a = await foo()
* // output
* const a = (
* ([__temp, __restore] = withAsyncContext(() => foo())),
* __temp = await __temp,
* __restore(),
* __temp
* )
* ```
*/
export
function
processAwait
(
ctx
:
ScriptCompileContext
,
node
:
AwaitExpression
,
needSemi
:
boolean
,
isStatement
:
boolean
)
{
const
argumentStart
=
node
.
argument
.
extra
&&
node
.
argument
.
extra
.
parenthesized
?
(
node
.
argument
.
extra
.
parenStart
as
number
)
:
node
.
argument
.
start
!
const
startOffset
=
ctx
.
startOffset
!
const
argumentStr
=
ctx
.
descriptor
.
source
.
slice
(
argumentStart
+
startOffset
,
node
.
argument
.
end
!
+
startOffset
)
const
containsNestedAwait
=
/
\b
await
\b
/
.
test
(
argumentStr
)
ctx
.
s
.
overwrite
(
node
.
start
!
+
startOffset
,
argumentStart
+
startOffset
,
`
${
needSemi
?
`;`
:
``
}
(\n ([__temp,__restore] =
${
ctx
.
helper
(
`withAsyncContext`
)}
(
${
containsNestedAwait
?
`async `
:
``
}
() => `
)
ctx
.
s
.
appendLeft
(
node
.
end
!
+
startOffset
,
`)),\n
${
isStatement
?
``
:
`__temp = `
}
await __temp,\n __restore()
${
isStatement
?
``
:
`,\n __temp`
}
\n)`
)
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/script/utils.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
CallExpression
,
Expression
,
Identifier
,
ImportDefaultSpecifier
,
ImportNamespaceSpecifier
,
ImportSpecifier
,
Node
,
StringLiteral
,
}
from
'
@babel/types
'
import
path
from
'
path
'
import
{
TS_NODE_TYPES
}
from
'
@vue/compiler-dom
'
export
const
UNKNOWN_TYPE
=
'
Unknown
'
export
function
resolveObjectKey
(
node
:
Node
,
computed
:
boolean
)
{
switch
(
node
.
type
)
{
case
'
StringLiteral
'
:
case
'
NumericLiteral
'
:
return
String
(
node
.
value
)
case
'
Identifier
'
:
if
(
!
computed
)
return
node
.
name
}
return
undefined
}
export
function
concatStrings
(
strs
:
Array
<
string
|
null
|
undefined
|
false
>
)
{
return
strs
.
filter
((
s
):
s
is
string
=>
!!
s
).
join
(
'
,
'
)
}
export
function
isLiteralNode
(
node
:
Node
)
{
return
node
.
type
.
endsWith
(
'
Literal
'
)
}
export
function
unwrapTSNode
(
node
:
Node
):
Node
{
if
(
TS_NODE_TYPES
.
includes
(
node
.
type
))
{
return
unwrapTSNode
((
node
as
any
).
expression
)
}
else
{
return
node
}
}
export
function
isCallOf
(
node
:
Node
|
null
|
undefined
,
test
:
string
|
((
id
:
string
)
=>
boolean
)
|
null
|
undefined
):
node
is
CallExpression
{
return
!!
(
node
&&
test
&&
node
.
type
===
'
CallExpression
'
&&
node
.
callee
.
type
===
'
Identifier
'
&&
(
typeof
test
===
'
string
'
?
node
.
callee
.
name
===
test
:
test
(
node
.
callee
.
name
))
)
}
export
function
toRuntimeTypeString
(
types
:
string
[])
{
return
types
.
length
>
1
?
`[
${
types
.
join
(
'
,
'
)}
]`
:
types
[
0
]
}
export
function
getImportedName
(
specifier
:
ImportSpecifier
|
ImportDefaultSpecifier
|
ImportNamespaceSpecifier
)
{
if
(
specifier
.
type
===
'
ImportSpecifier
'
)
return
specifier
.
imported
.
type
===
'
Identifier
'
?
specifier
.
imported
.
name
:
specifier
.
imported
.
value
else
if
(
specifier
.
type
===
'
ImportNamespaceSpecifier
'
)
return
'
*
'
return
'
default
'
}
export
function
getId
(
node
:
Identifier
|
StringLiteral
):
string
export
function
getId
(
node
:
Expression
):
string
|
null
export
function
getId
(
node
:
Expression
)
{
return
node
.
type
===
'
Identifier
'
?
node
.
name
:
node
.
type
===
'
StringLiteral
'
?
node
.
value
:
null
}
const
identity
=
(
str
:
string
)
=>
str
const
fileNameLowerCaseRegExp
=
/
[^\u
0130
\u
0131
\u
00DFa-z0-9
\\/
:
\-
_
\.
]
+/g
const
toLowerCase
=
(
str
:
string
)
=>
str
.
toLowerCase
()
function
toFileNameLowerCase
(
x
:
string
)
{
return
fileNameLowerCaseRegExp
.
test
(
x
)
?
x
.
replace
(
fileNameLowerCaseRegExp
,
toLowerCase
)
:
x
}
/**
* We need `getCanonicalFileName` when creating ts module resolution cache,
* but TS does not expose it directly. This implementation is repllicated from
* the TS source code.
*/
export
function
createGetCanonicalFileName
(
useCaseSensitiveFileNames
:
boolean
)
{
return
useCaseSensitiveFileNames
?
identity
:
toFileNameLowerCase
}
// in the browser build, the polyfill doesn't expose posix, but defaults to
// posix behavior.
const
normalize
=
(
path
.
posix
||
path
).
normalize
const
windowsSlashRE
=
/
\\
/g
export
function
normalizePath
(
p
:
string
)
{
return
normalize
(
p
.
replace
(
windowsSlashRE
,
'
/
'
))
}
export
const
joinPaths
=
(
path
.
posix
||
path
).
join
/**
* key may contain symbols
* e.g. onUpdate:modelValue -> "onUpdate:modelValue"
*/
export
const
propNameEscapeSymbolsRE
=
/
[
!"#$%&'()*+,.
/
:;<=>?@[
\\\]
^`{|}~
\-]
/
export
function
getEscapedPropName
(
key
:
string
)
{
return
propNameEscapeSymbolsRE
.
test
(
key
)
?
JSON
.
stringify
(
key
)
:
key
}
export
const
cssVarNameEscapeSymbolsRE
=
/
[
!"#$%&'()*+,.
/
:;<=>?@[
\\\]
^`{|}~
]
/g
export
function
getEscapedCssVarName
(
key
:
string
,
doubleEscape
:
boolean
)
{
return
key
.
replace
(
cssVarNameEscapeSymbolsRE
,
(
s
)
=>
doubleEscape
?
`\\\
\$
{s}`
:
`\
\$
{s}`
)
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/shims.d.ts
0 → 100644
浏览文件 @
fe038fa6
declare
module
'
merge-source-map
'
{
export
default
function
merge
(
oldMap
:
object
,
newMap
:
object
):
object
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/template/templateUtils.ts
0 → 100644
浏览文件 @
fe038fa6
import
{
UrlWithStringQuery
,
parse
as
uriParse
}
from
'
url
'
import
{
isString
}
from
'
@vue/shared
'
export
function
isRelativeUrl
(
url
:
string
):
boolean
{
const
firstChar
=
url
.
charAt
(
0
)
return
firstChar
===
'
.
'
||
firstChar
===
'
~
'
||
firstChar
===
'
@
'
}
const
externalRE
=
/^
(
https
?
:
)?\/\/
/
export
function
isExternalUrl
(
url
:
string
):
boolean
{
return
externalRE
.
test
(
url
)
}
const
dataUrlRE
=
/^
\s
*data:/i
export
function
isDataUrl
(
url
:
string
):
boolean
{
return
dataUrlRE
.
test
(
url
)
}
/**
* Parses string url into URL object.
*/
export
function
parseUrl
(
url
:
string
):
UrlWithStringQuery
{
const
firstChar
=
url
.
charAt
(
0
)
if
(
firstChar
===
'
~
'
)
{
const
secondChar
=
url
.
charAt
(
1
)
url
=
url
.
slice
(
secondChar
===
'
/
'
?
2
:
1
)
}
return
parseUriParts
(
url
)
}
/**
* vuejs/component-compiler-utils#22 Support uri fragment in transformed require
* @param urlString - an url as a string
*/
function
parseUriParts
(
urlString
:
string
):
UrlWithStringQuery
{
// A TypeError is thrown if urlString is not a string
// @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost
return
uriParse
(
isString
(
urlString
)
?
urlString
:
''
,
false
,
true
)
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/template/transformAssetUrl.ts
0 → 100644
浏览文件 @
fe038fa6
import
path
from
'
path
'
import
{
ConstantTypes
,
createSimpleExpression
,
ExpressionNode
,
NodeTransform
,
NodeTypes
,
SimpleExpressionNode
,
SourceLocation
,
TransformContext
,
}
from
'
@vue/compiler-core
'
import
{
isRelativeUrl
,
parseUrl
,
isExternalUrl
,
isDataUrl
,
}
from
'
./templateUtils
'
import
{
isArray
}
from
'
@vue/shared
'
export
interface
AssetURLTagConfig
{
[
name
:
string
]:
string
[]
}
export
interface
AssetURLOptions
{
/**
* If base is provided, instead of transforming relative asset urls into
* imports, they will be directly rewritten to absolute urls.
*/
base
?:
string
|
null
/**
* If true, also processes absolute urls.
*/
includeAbsolute
?:
boolean
tags
?:
AssetURLTagConfig
}
export
const
defaultAssetUrlOptions
:
Required
<
AssetURLOptions
>
=
{
base
:
null
,
includeAbsolute
:
false
,
tags
:
{
video
:
[
'
src
'
,
'
poster
'
],
source
:
[
'
src
'
],
img
:
[
'
src
'
],
image
:
[
'
xlink:href
'
,
'
href
'
],
use
:
[
'
xlink:href
'
,
'
href
'
],
},
}
export
const
normalizeOptions
=
(
options
:
AssetURLOptions
|
AssetURLTagConfig
):
Required
<
AssetURLOptions
>
=>
{
if
(
Object
.
keys
(
options
).
some
((
key
)
=>
isArray
((
options
as
any
)[
key
])))
{
// legacy option format which directly passes in tags config
return
{
...
defaultAssetUrlOptions
,
tags
:
options
as
any
,
}
}
return
{
...
defaultAssetUrlOptions
,
...
options
,
}
}
export
const
createAssetUrlTransformWithOptions
=
(
options
:
Required
<
AssetURLOptions
>
):
NodeTransform
=>
{
return
(
node
,
context
)
=>
(
transformAssetUrl
as
Function
)(
node
,
context
,
options
)
}
/**
* A `@vue/compiler-core` plugin that transforms relative asset urls into
* either imports or absolute urls.
*
* ``` js
* // Before
* createVNode('img', { src: './logo.png' })
*
* // After
* import _imports_0 from './logo.png'
* createVNode('img', { src: _imports_0 })
* ```
*/
export
const
transformAssetUrl
:
NodeTransform
=
(
node
,
context
,
options
:
AssetURLOptions
=
defaultAssetUrlOptions
)
=>
{
if
(
node
.
type
===
NodeTypes
.
ELEMENT
)
{
if
(
!
node
.
props
.
length
)
{
return
}
const
tags
=
options
.
tags
||
defaultAssetUrlOptions
.
tags
const
attrs
=
tags
[
node
.
tag
]
const
wildCardAttrs
=
tags
[
'
*
'
]
if
(
!
attrs
&&
!
wildCardAttrs
)
{
return
}
const
assetAttrs
=
(
attrs
||
[]).
concat
(
wildCardAttrs
||
[])
node
.
props
.
forEach
((
attr
,
index
)
=>
{
if
(
attr
.
type
!==
NodeTypes
.
ATTRIBUTE
||
!
assetAttrs
.
includes
(
attr
.
name
)
||
!
attr
.
value
||
isExternalUrl
(
attr
.
value
.
content
)
||
isDataUrl
(
attr
.
value
.
content
)
||
attr
.
value
.
content
[
0
]
===
'
#
'
||
(
!
options
.
includeAbsolute
&&
!
isRelativeUrl
(
attr
.
value
.
content
))
)
{
return
}
const
url
=
parseUrl
(
attr
.
value
.
content
)
if
(
options
.
base
&&
attr
.
value
.
content
[
0
]
===
'
.
'
)
{
// explicit base - directly rewrite relative urls into absolute url
// to avoid generating extra imports
// Allow for full hostnames provided in options.base
const
base
=
parseUrl
(
options
.
base
)
const
protocol
=
base
.
protocol
||
''
const
host
=
base
.
host
?
protocol
+
'
//
'
+
base
.
host
:
''
const
basePath
=
base
.
path
||
'
/
'
// when packaged in the browser, path will be using the posix-
// only version provided by rollup-plugin-node-builtins.
attr
.
value
.
content
=
host
+
(
path
.
posix
||
path
).
join
(
basePath
,
url
.
path
+
(
url
.
hash
||
''
))
return
}
// otherwise, transform the url into an import.
// this assumes a bundler will resolve the import into the correct
// absolute url (e.g. webpack file-loader)
const
exp
=
getImportsExpressionExp
(
url
.
path
,
url
.
hash
,
attr
.
loc
,
context
)
node
.
props
[
index
]
=
{
type
:
NodeTypes
.
DIRECTIVE
,
name
:
'
bind
'
,
arg
:
createSimpleExpression
(
attr
.
name
,
true
,
attr
.
loc
),
exp
,
modifiers
:
[],
loc
:
attr
.
loc
,
}
})
}
}
function
getImportsExpressionExp
(
path
:
string
|
null
,
hash
:
string
|
null
,
loc
:
SourceLocation
,
context
:
TransformContext
):
ExpressionNode
{
if
(
path
)
{
let
name
:
string
let
exp
:
SimpleExpressionNode
const
existingIndex
=
context
.
imports
.
findIndex
((
i
)
=>
i
.
path
===
path
)
if
(
existingIndex
>
-
1
)
{
name
=
`_imports_
${
existingIndex
}
`
exp
=
context
.
imports
[
existingIndex
].
exp
as
SimpleExpressionNode
}
else
{
name
=
`_imports_
${
context
.
imports
.
length
}
`
exp
=
createSimpleExpression
(
name
,
false
,
loc
,
ConstantTypes
.
CAN_STRINGIFY
)
// We need to ensure the path is not encoded (to %2F),
// so we decode it back in case it is encoded
context
.
imports
.
push
({
exp
,
path
:
decodeURIComponent
(
path
),
})
}
if
(
!
hash
)
{
return
exp
}
const
hashExp
=
`
${
name
}
+ '
${
hash
}
'`
const
finalExp
=
createSimpleExpression
(
hashExp
,
false
,
loc
,
ConstantTypes
.
CAN_STRINGIFY
)
if
(
!
context
.
hoistStatic
)
{
return
finalExp
}
const
existingHoistIndex
=
context
.
hoists
.
findIndex
((
h
)
=>
{
return
(
h
&&
h
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
!
h
.
isStatic
&&
h
.
content
===
hashExp
)
})
if
(
existingHoistIndex
>
-
1
)
{
return
createSimpleExpression
(
`_hoisted_
${
existingHoistIndex
+
1
}
`
,
false
,
loc
,
ConstantTypes
.
CAN_STRINGIFY
)
}
return
context
.
hoist
(
finalExp
)
}
else
{
return
createSimpleExpression
(
`''`
,
false
,
loc
,
ConstantTypes
.
CAN_STRINGIFY
)
}
}
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/template/transformSrcset.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/warn.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/index.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/main.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/script.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-app-uts/src/plugins/android/uvue/sfc/template.ts
0 → 100644
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
packages/uni-cli-shared/src/vite/plugins/inject.ts
浏览文件 @
fe038fa6
...
@@ -201,7 +201,7 @@ export function uniViteInjectPlugin(
...
@@ -201,7 +201,7 @@ export function uniViteInjectPlugin(
return
return
}
}
if
(
isReference
(
node
,
parent
))
{
if
(
isReference
(
node
,
parent
!
))
{
const
{
name
,
keypath
}
=
flatten
(
node
)
const
{
name
,
keypath
}
=
flatten
(
node
)
const
handled
=
handleReference
(
node
,
name
,
keypath
,
parent
)
const
handled
=
handleReference
(
node
,
name
,
keypath
,
parent
)
if
(
handled
)
{
if
(
handled
)
{
...
...
packages/uni-mp-compiler/src/transforms/utils.ts
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
pnpm-lock.yaml
浏览文件 @
fe038fa6
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录