Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MuGuiLin
uni-app
提交
f209ff01
U
uni-app
项目概览
MuGuiLin
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f209ff01
编写于
10月 13, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(mp): vBind
上级
e5f28c4e
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
428 addition
and
29 deletion
+428
-29
packages/uni-mp-compiler/__tests__/test.spec.ts
packages/uni-mp-compiler/__tests__/test.spec.ts
+3
-3
packages/uni-mp-compiler/__tests__/vBind.spec.ts
packages/uni-mp-compiler/__tests__/vBind.spec.ts
+302
-0
packages/uni-mp-compiler/__tests__/vOn.mp.spec.ts
packages/uni-mp-compiler/__tests__/vOn.mp.spec.ts
+2
-2
packages/uni-mp-compiler/src/compile.ts
packages/uni-mp-compiler/src/compile.ts
+2
-1
packages/uni-mp-compiler/src/errors.ts
packages/uni-mp-compiler/src/errors.ts
+15
-2
packages/uni-mp-compiler/src/transforms/transformElement.ts
packages/uni-mp-compiler/src/transforms/transformElement.ts
+26
-13
packages/uni-mp-compiler/src/transforms/transformIdentifier.ts
...ges/uni-mp-compiler/src/transforms/transformIdentifier.ts
+7
-2
packages/uni-mp-compiler/src/transforms/vBind.ts
packages/uni-mp-compiler/src/transforms/vBind.ts
+70
-0
packages/uni-mp-compiler/src/transforms/vOn.ts
packages/uni-mp-compiler/src/transforms/vOn.ts
+1
-6
未找到文件。
packages/uni-mp-compiler/__tests__/test.spec.ts
浏览文件 @
f209ff01
...
...
@@ -33,10 +33,10 @@ function assert(
describe
(
'
compiler
'
,
()
=>
{
test
(
'
should wrap as function if expression is inline statement
'
,
()
=>
{
assert
(
`
{{hello}}
`
,
`
{{a}}
`
,
`
<div v-on:click.prevent />
`
,
`
<view id="{{id}}"/>
`
,
`(_ctx, _cache) => {
return { a: _
toDisplayString(_ctx.hello
) }
return { a: _
vOn(() => {}
) }
}`
,
{}
)
...
...
packages/uni-mp-compiler/__tests__/vBind.spec.ts
0 → 100644
浏览文件 @
f209ff01
import
{
ElementNode
,
ErrorCodes
}
from
'
@vue/compiler-core
'
import
{
compile
}
from
'
../src
'
import
{
MPErrorCodes
}
from
'
../src/errors
'
import
{
CompilerOptions
}
from
'
../src/options
'
import
{
assert
}
from
'
./testUtils
'
function
parseWithVBind
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
const
{
ast
,
code
}
=
compile
(
template
,
options
)
return
{
code
,
node
:
ast
.
children
[
0
]
as
ElementNode
,
}
}
describe
(
'
compiler: transform v-bind
'
,
()
=>
{
test
(
'
basic
'
,
()
=>
{
assert
(
`<view v-bind:id="id"/>`
,
`<view id="{{a}}"/>`
,
`(_ctx, _cache) => {
return { a: _ctx.id }
}`
,
{}
)
})
test
(
'
dynamic arg
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:[id]="id" />`
,
{
onError
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view/>`
)
return
''
},
},
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
23
,
},
},
})
parseWithVBind
(
`<view v-bind:[foo.id]="id" />`
,
{
onError
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view/>`
)
return
''
},
},
})
expect
(
onError
.
mock
.
calls
[
1
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
27
,
},
},
})
})
test
(
'
should error if no expression
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind />`
,
{
onError
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_NO_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
13
,
},
},
})
parseWithVBind
(
`<view v-bind:arg />`
,
{
onError
})
expect
(
onError
.
mock
.
calls
[
1
][
0
]).
toMatchObject
({
code
:
ErrorCodes
.
X_V_BIND_NO_EXPRESSION
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
17
,
},
},
})
})
test
(
'
.camel modifier
'
,
()
=>
{
assert
(
`<view v-bind:foo-bar.camel="id"/>`
,
'
<view fooBar="{{a}}"/>
'
,
`(_ctx, _cache) => {
return { a: _ctx.id }
}`
)
})
test
(
'
.camel modifier w/ dynamic arg
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:[foo].camel="id"/>`
,
{
onError
,
prefixIdentifiers
:
false
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view/>`
)
return
''
},
},
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
30
,
},
},
})
})
test
(
'
.camel modifier w/ dynamic arg + prefixIdentifiers
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:[foo].camel="id"/>`
,
{
onError
,
prefixIdentifiers
:
true
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view/>`
)
return
''
},
},
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
30
,
},
},
})
})
test
(
'
.prop modifier
'
,
()
=>
{
const
onWarn
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:fooBar.prop="id"/>`
,
{
onWarn
})
expect
(
onWarn
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_MODIFIER_PROP
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
30
,
},
},
})
})
test
(
'
.prop modifier w/ dynamic arg
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:[fooBar].prop="id"/>`
,
{
onError
,
filename
:
'
foo.vue
'
,
prefixIdentifiers
:
false
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view/>`
)
return
''
},
},
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
32
,
},
},
})
})
test
(
'
.prop modifier w/ dynamic arg + prefixIdentifiers
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:[foo(bar)].prop="id"/>`
,
{
onError
,
prefixIdentifiers
:
true
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view/>`
)
return
''
},
},
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
34
,
},
},
})
})
test
(
'
.prop modifier (shorthand)
'
,
()
=>
{
const
onWarn
=
jest
.
fn
()
parseWithVBind
(
`<view .fooBar="id"/>`
,
{
onWarn
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view fooBar="{{a}}"/>`
)
return
''
},
},
})
expect
(
onWarn
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_MODIFIER_PROP
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
19
,
},
},
})
})
test
(
'
.attr modifier
'
,
()
=>
{
const
onWarn
=
jest
.
fn
()
parseWithVBind
(
`<view v-bind:foo-bar.attr="id"/>`
,
{
onWarn
,
filename
:
'
foo.vue
'
,
miniProgram
:
{
emitFile
({
source
})
{
expect
(
source
).
toBe
(
`<view foo-bar="{{a}}"/>`
)
return
''
},
},
})
expect
(
onWarn
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
MPErrorCodes
.
X_V_BIND_MODIFIER_ATTR
,
loc
:
{
start
:
{
line
:
1
,
column
:
7
,
},
end
:
{
line
:
1
,
column
:
31
,
},
},
})
})
})
packages/uni-mp-compiler/__tests__/vOn.mp.spec.ts
浏览文件 @
f209ff01
import
{
ElementNode
}
from
'
@vue/compiler-core
'
import
{
compile
}
from
'
../src
'
import
{
X_V_ON_DYNAMIC_EVENT
}
from
'
../src/errors
'
import
{
MPErrorCodes
}
from
'
../src/errors
'
import
{
CompilerOptions
}
from
'
../src/options
'
function
parseWithVOn
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
...
...
@@ -16,7 +16,7 @@ describe('compiler(mp): transform v-on', () => {
const
onError
=
jest
.
fn
()
parseWithVOn
(
`<div v-on:[event]="onClick" />`
,
{
onError
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
X_V_ON_DYNAMIC_EVENT
,
code
:
MPErrorCodes
.
X_V_ON_DYNAMIC_EVENT
,
loc
:
{
start
:
{
line
:
1
,
...
...
packages/uni-mp-compiler/src/compile.ts
浏览文件 @
f209ff01
...
...
@@ -11,6 +11,7 @@ import { transformFor } from './transforms/vFor'
import
{
generate
as
genTemplate
}
from
'
./template/codegen
'
import
{
transformOn
}
from
'
./transforms/vOn
'
import
{
transformElement
}
from
'
./transforms/transformElement
'
import
{
transformBind
}
from
'
./transforms/vBind
'
export
type
TransformPreset
=
[
NodeTransform
[],
...
...
@@ -32,7 +33,7 @@ export function getBaseTransformPreset({
if
(
prefixIdentifiers
)
{
nodeTransforms
.
push
(
transformExpression
)
}
return
[
nodeTransforms
,
{
on
:
transformOn
}]
return
[
nodeTransforms
,
{
on
:
transformOn
,
bind
:
transformBind
}]
}
export
function
baseCompile
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
...
...
packages/uni-mp-compiler/src/errors.ts
浏览文件 @
f209ff01
export
const
X_V_ON_DYNAMIC_EVENT
=
0
export
const
enum
MPErrorCodes
{
X_V_ON_NO_ARGUMENT
,
X_V_ON_DYNAMIC_EVENT
,
X_V_BIND_NO_ARGUMENT
,
X_V_BIND_DYNAMIC_ARGUMENT
,
X_V_BIND_MODIFIER_PROP
,
X_V_BIND_MODIFIER_ATTR
,
}
export
const
errorMessages
:
Record
<
number
,
string
>
=
{
[
X_V_ON_DYNAMIC_EVENT
]:
'
v-on:[event] is not supported.
'
,
[
MPErrorCodes
.
X_V_ON_NO_ARGUMENT
]:
'
v-on="" is not supported
'
,
[
MPErrorCodes
.
X_V_ON_DYNAMIC_EVENT
]:
'
v-on:[event]="" is not supported.
'
,
[
MPErrorCodes
.
X_V_BIND_NO_ARGUMENT
]:
'
v-bind="" is not supported.
'
,
[
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
]:
'
v-bind:[name]="" is not supported.
'
,
[
MPErrorCodes
.
X_V_BIND_MODIFIER_PROP
]:
'
v-bind .prop is not supported
'
,
[
MPErrorCodes
.
X_V_BIND_MODIFIER_ATTR
]:
'
v-bind .attr is not supported
'
,
}
packages/uni-mp-compiler/src/transforms/transformElement.ts
浏览文件 @
f209ff01
...
...
@@ -9,6 +9,7 @@ import {
Property
,
ExpressionNode
,
}
from
'
@vue/compiler-core
'
import
{
errorMessages
,
MPErrorCodes
}
from
'
../errors
'
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
...
...
@@ -46,7 +47,7 @@ function processProps(node: ElementNode, context: TransformContext) {
const
prop
=
props
[
i
]
if
(
prop
.
type
===
NodeTypes
.
DIRECTIVE
)
{
// directives
const
{
name
,
arg
,
exp
,
loc
}
=
prop
const
{
name
,
arg
,
loc
}
=
prop
const
isVBind
=
name
===
'
bind
'
const
isVOn
=
name
===
'
on
'
// skip v-slot - it is handled by its dedicated transform.
...
...
@@ -70,25 +71,37 @@ function processProps(node: ElementNode, context: TransformContext) {
continue
}
// special case for v-bind and v-on with no argument
if
(
!
arg
&&
(
isVBind
||
isVOn
))
{
if
(
exp
)
{
if
(
isVOn
)
{
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_ON_NO_EXPRESSION
,
loc
)
if
(
isVBind
||
isVOn
)
{
// v-on=""
// v-bind=""
if
(
!
arg
)
{
context
.
onError
(
createCompilerError
(
isVBind
?
MPErrorCodes
.
X_V_BIND_NO_ARGUMENT
:
MPErrorCodes
.
X_V_ON_NO_ARGUMENT
,
loc
,
errorMessages
)
}
}
else
{
)
continue
}
// v-on:[a]=""
// v-on:[a.b]=""
// v-bind:[a]=""
// v-bind:[a.b]=""
if
(
!
(
arg
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
arg
.
isStatic
))
{
context
.
onError
(
createCompilerError
(
isVBind
?
ErrorCodes
.
X_V_BIND_NO_EXPRESSION
:
ErrorCodes
.
X_V_ON_NO_EXPRESSION
,
loc
?
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
:
MPErrorCodes
.
X_V_ON_DYNAMIC_EVENT
,
loc
,
errorMessages
)
)
continue
}
continue
}
const
directiveTransform
=
context
.
directiveTransforms
[
name
]
...
...
packages/uni-mp-compiler/src/transforms/transformIdentifier.ts
浏览文件 @
f209ff01
...
...
@@ -37,11 +37,16 @@ export const transformIdentifier: NodeTransform = (node, context) => {
for
(
let
i
=
0
;
i
<
node
.
props
.
length
;
i
++
)
{
const
dir
=
node
.
props
[
i
]
if
(
dir
.
type
===
NodeTypes
.
DIRECTIVE
)
{
const
exp
=
dir
.
exp
const
arg
=
dir
.
arg
if
(
arg
)
{
dir
.
arg
=
rewriteExpression
(
arg
,
context
)
// TODO 指令暂不不支持动态参数,v-bind:[arg] v-on:[event]
if
(
!
(
arg
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
arg
.
isStatic
))
{
node
.
props
.
splice
(
i
,
1
)
i
--
continue
}
}
const
exp
=
dir
.
exp
if
(
exp
)
{
if
(
vFor
&&
...
...
packages/uni-mp-compiler/src/transforms/vBind.ts
0 → 100644
浏览文件 @
f209ff01
import
{
camelize
}
from
'
@vue/shared
'
import
{
NodeTypes
,
CAMELIZE
,
createCompilerError
,
ErrorCodes
,
createObjectProperty
,
createSimpleExpression
,
}
from
'
@vue/compiler-core
'
import
{
DirectiveTransform
}
from
'
../transform
'
import
{
errorMessages
,
MPErrorCodes
}
from
'
../errors
'
export
const
transformBind
:
DirectiveTransform
=
(
dir
,
_node
,
context
)
=>
{
const
{
exp
,
modifiers
,
loc
}
=
dir
const
arg
=
dir
.
arg
!
if
(
arg
.
type
!==
NodeTypes
.
SIMPLE_EXPRESSION
)
{
arg
.
children
.
unshift
(
`(`
)
arg
.
children
.
push
(
`) || ""`
)
}
else
if
(
!
arg
.
isStatic
)
{
arg
.
content
=
`
${
arg
.
content
}
|| ""`
}
// .sync is replaced by v-model:arg
if
(
modifiers
.
includes
(
'
camel
'
))
{
if
(
arg
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
)
{
if
(
arg
.
isStatic
)
{
arg
.
content
=
camelize
(
arg
.
content
)
}
else
{
arg
.
content
=
`
${
context
.
helperString
(
CAMELIZE
)}
(
${
arg
.
content
}
)`
}
}
else
{
// arg.children.unshift(`${context.helperString(CAMELIZE)}(`)
// arg.children.push(`)`)
}
}
if
(
modifiers
.
includes
(
'
prop
'
))
{
context
.
onWarn
(
createCompilerError
(
MPErrorCodes
.
X_V_BIND_MODIFIER_PROP
,
loc
,
errorMessages
)
)
}
if
(
modifiers
.
includes
(
'
attr
'
))
{
context
.
onWarn
(
createCompilerError
(
MPErrorCodes
.
X_V_BIND_MODIFIER_ATTR
,
loc
,
errorMessages
)
)
}
if
(
!
exp
||
(
exp
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
!
exp
.
content
.
trim
())
)
{
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_BIND_NO_EXPRESSION
,
loc
))
return
{
props
:
[
createObjectProperty
(
arg
,
createSimpleExpression
(
''
,
true
,
loc
))],
}
}
return
{
props
:
[
createObjectProperty
(
arg
,
exp
)],
}
}
packages/uni-mp-compiler/src/transforms/vOn.ts
浏览文件 @
f209ff01
...
...
@@ -14,8 +14,7 @@ import {
TO_HANDLER_KEY
,
}
from
'
@vue/compiler-core
'
import
{
camelize
,
toHandlerKey
}
from
'
@vue/shared
'
import
{
V_ON
}
from
'
..
'
import
{
errorMessages
,
X_V_ON_DYNAMIC_EVENT
}
from
'
../errors
'
import
{
V_ON
}
from
'
../runtimeHelpers
'
import
{
DirectiveTransform
,
TransformContext
}
from
'
../transform
'
import
{
DirectiveTransformResult
}
from
'
./transformElement
'
import
{
processExpression
}
from
'
./transformExpression
'
...
...
@@ -54,10 +53,6 @@ export const transformOn: DirectiveTransform = (
arg
.
loc
)
}
else
{
// TODO 不支持动态事件
context
.
onError
(
createCompilerError
(
X_V_ON_DYNAMIC_EVENT
,
loc
,
errorMessages
)
)
// #2388
eventName
=
createCompoundExpression
([
// `${context.helperString(TO_HANDLER_KEY)}(`,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录