Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MuGuiLin
uni-app
提交
63e307eb
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,发现更多精彩内容 >>
提交
63e307eb
编写于
10月 08, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(mp): vif
上级
57d61c3d
变更
15
显示空白变更内容
内联
并排
Showing
15 changed file
with
695 addition
and
162 deletion
+695
-162
packages/uni-mp-compiler/__tests__/compiler.ts
packages/uni-mp-compiler/__tests__/compiler.ts
+0
-0
packages/uni-mp-compiler/__tests__/test.spec.ts
packages/uni-mp-compiler/__tests__/test.spec.ts
+5
-10
packages/uni-mp-compiler/__tests__/testUtils.ts
packages/uni-mp-compiler/__tests__/testUtils.ts
+32
-0
packages/uni-mp-compiler/__tests__/vIf.spec.ts
packages/uni-mp-compiler/__tests__/vIf.spec.ts
+255
-0
packages/uni-mp-compiler/dist/template/codegen.js
packages/uni-mp-compiler/dist/template/codegen.js
+26
-17
packages/uni-mp-compiler/dist/transform.d.ts
packages/uni-mp-compiler/dist/transform.d.ts
+1
-0
packages/uni-mp-compiler/dist/transform.js
packages/uni-mp-compiler/dist/transform.js
+28
-0
packages/uni-mp-compiler/dist/transforms/vFor.d.ts
packages/uni-mp-compiler/dist/transforms/vFor.d.ts
+6
-2
packages/uni-mp-compiler/dist/transforms/vFor.js
packages/uni-mp-compiler/dist/transforms/vFor.js
+10
-7
packages/uni-mp-compiler/dist/transforms/vIf.d.ts
packages/uni-mp-compiler/dist/transforms/vIf.d.ts
+10
-3
packages/uni-mp-compiler/dist/transforms/vIf.js
packages/uni-mp-compiler/dist/transforms/vIf.js
+102
-38
packages/uni-mp-compiler/src/template/codegen.ts
packages/uni-mp-compiler/src/template/codegen.ts
+26
-20
packages/uni-mp-compiler/src/transform.ts
packages/uni-mp-compiler/src/transform.ts
+28
-0
packages/uni-mp-compiler/src/transforms/vFor.ts
packages/uni-mp-compiler/src/transforms/vFor.ts
+13
-8
packages/uni-mp-compiler/src/transforms/vIf.ts
packages/uni-mp-compiler/src/transforms/vIf.ts
+153
-57
未找到文件。
packages/uni-mp-compiler/__tests__/compiler.
spec.
ts
→
packages/uni-mp-compiler/__tests__/compiler.ts
浏览文件 @
63e307eb
文件已移动
packages/uni-mp-compiler/__tests__/test.spec.ts
浏览文件 @
63e307eb
...
...
@@ -20,19 +20,14 @@ function assert(template: string, templateCode: string, renderCode: string) {
}
describe
(
'
compiler
'
,
()
=>
{
test
(
`
generate v-for with
v-if`
,
()
=>
{
test
(
`
basic
v-if`
,
()
=>
{
assert
(
`<view v-
for="item in items"><view v-if="item.show">{{item.title}}</view></view
>`
,
`<view wx:
for="{{a}}" wx:for-item="item"><view wx:if="{{item.b}}">{{item.a}}</view></view
>`
,
`<view v-
if="ok"/
>`
,
`<view wx:
if="{{a}}"/
>`
,
`(_ctx, _cache) => {
return {
a: vFor(_ctx.items, item => {
return {
a: item.title,
b: item.show,
...(item.show ? {} : {})
};
})
a: _ctx.ok,
...(_ctx.ok ? {} : {})
}
}`
)
...
...
packages/uni-mp-compiler/__tests__/testUtils.ts
0 → 100644
浏览文件 @
63e307eb
import
{
compile
}
from
'
../src/index
'
import
{
CompilerOptions
}
from
'
../src/options
'
export
function
inspect
(
obj
:
any
)
{
console
.
log
(
require
(
'
util
'
).
inspect
(
obj
,
{
colors
:
true
,
depth
:
null
}))
}
export
function
assert
(
template
:
string
,
templateCode
:
string
,
renderCode
:
string
,
options
:
CompilerOptions
=
{}
)
{
const
res
=
compile
(
template
,
{
filename
:
'
foo.vue
'
,
prefixIdentifiers
:
true
,
inline
:
true
,
emitFile
({
source
})
{
// console.log(source)
if
(
!
options
.
onError
)
{
expect
(
source
).
toBe
(
templateCode
)
}
return
''
},
...
options
,
})
// expect(res.template).toBe(templateCode)
// expect(res.code).toBe(renderCode)
// console.log(require('util').inspect(res.code, { colors: true, depth: null }))
// console.log(require('util').inspect(res, { colors: true, depth: null }))
if
(
!
options
.
onError
)
{
expect
(
res
.
code
).
toBe
(
renderCode
)
}
}
packages/uni-mp-compiler/__tests__/vIf.spec.ts
0 → 100644
浏览文件 @
63e307eb
import
{
ErrorCodes
,
IfNode
,
NodeTypes
}
from
'
@vue/compiler-core
'
import
{
compile
}
from
'
../src
'
import
{
CompilerOptions
}
from
'
../src/options
'
import
{
assert
}
from
'
./testUtils
'
function
compileWithIfTransform
(
template
:
string
,
options
:
CompilerOptions
=
{},
returnIndex
:
number
=
0
,
childrenLen
:
number
=
1
)
{
const
{
ast
}
=
compile
(
template
,
options
)
if
(
!
options
.
onError
)
{
expect
(
ast
.
children
.
length
).
toBe
(
childrenLen
)
for
(
let
i
=
0
;
i
<
childrenLen
;
i
++
)
{
expect
(
ast
.
children
[
i
].
type
).
toBe
(
NodeTypes
.
IF
)
}
}
return
{
root
:
ast
,
node
:
ast
.
children
[
returnIndex
]
as
IfNode
,
}
}
describe
(
`compiler: v-if`
,
()
=>
{
describe
(
`codegen`
,
()
=>
{
test
(
`basic v-if`
,
()
=>
{
assert
(
`<view v-if="ok"/>`
,
`<view wx:if="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : {})
}
}`
)
})
test
(
`template v-if`
,
()
=>
{
assert
(
`<template v-if="ok"><view/>hello<view/></template>`
,
`<block wx:if="{{a}}"><view/>hello<view/></block>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : {})
}
}`
)
})
test
(
`component v-if`
,
()
=>
{
assert
(
`<Component v-if="ok"></Component>`
,
`<Component wx:if="{{a}}"></Component>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : {})
}
}`
)
})
test
(
`v-if + v-else`
,
()
=>
{
assert
(
`<view v-if="ok"/><view v-else/>`
,
`<view wx:if="{{a}}"/><view wx:else/>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : {})
}
}`
)
})
test
(
`v-if + v-else-if`
,
()
=>
{
assert
(
`<view v-if="ok"/><view v-else-if="orNot"/>`
,
`<view wx:if="{{a}}"/><view wx:elif="{{b}}"/>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : _ctx.orNot ? {} : {}),
b: _ctx.orNot
}
}`
)
})
test
(
`v-if + v-else-if + v-else`
,
()
=>
{
assert
(
`<view v-if="ok"/><view v-else-if="orNot"/><template v-else>fine</template>`
,
`<view wx:if="{{a}}"/><view wx:elif="{{b}}"/><block wx:else>fine</block>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : _ctx.orNot ? {} : {}),
b: _ctx.orNot
}
}`
)
})
test
(
`v-if + v-else-if + v-else-if + v-else`
,
()
=>
{
assert
(
`<view v-if="ok"/><view v-else-if="orNot"/><view v-else-if="3"/><template v-else>fine</template>`
,
`<view wx:if="{{a}}"/><view wx:elif="{{b}}"/><view wx:elif="{{3}}"/><block wx:else>fine</block>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : _ctx.orNot ? {} : 3 ? {} : {}),
b: _ctx.orNot
}
}`
)
})
test
(
`comment between branches`
,
()
=>
{
assert
(
`
<view v-if="ok"/>
<!--foo-->
<view v-else-if="orNot"/>
<!--bar-->
<template v-else>fine</template>
`
,
`<view wx:if="{{a}}"/><view wx:elif="{{b}}"/><block wx:else>fine</block>`
,
`(_ctx, _cache) => {
return {
a: _ctx.ok,
...(_ctx.ok ? {} : _ctx.orNot ? {} : {}),
b: _ctx.orNot
}
}`
)
})
})
describe
(
'
errors
'
,
()
=>
{
test
(
'
error on v-else missing adjacent v-if
'
,
()
=>
{
const
onError
=
jest
.
fn
()
const
{
node
:
node1
}
=
compileWithIfTransform
(
`<view v-else/>`
,
{
onError
,
})
expect
(
onError
.
mock
.
calls
[
0
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
node1
.
loc
,
},
])
const
{
node
:
node2
}
=
compileWithIfTransform
(
`<view/><view v-else/>`
,
{
onError
},
1
)
expect
(
onError
.
mock
.
calls
[
1
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
node2
.
loc
,
},
])
const
{
node
:
node3
}
=
compileWithIfTransform
(
`<view/>foo<view v-else/>`
,
{
onError
},
2
)
expect
(
onError
.
mock
.
calls
[
2
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
node3
.
loc
,
},
])
})
test
(
'
error on v-else-if missing adjacent v-if or v-else-if
'
,
()
=>
{
const
onError
=
jest
.
fn
()
const
{
node
:
node1
}
=
compileWithIfTransform
(
`<view v-else-if="foo"/>`
,
{
onError
,
}
)
expect
(
onError
.
mock
.
calls
[
0
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
node1
.
loc
,
},
])
const
{
node
:
node2
}
=
compileWithIfTransform
(
`<view/><view v-else-if="foo"/>`
,
{
onError
},
1
)
expect
(
onError
.
mock
.
calls
[
1
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
node2
.
loc
,
},
])
const
{
node
:
node3
}
=
compileWithIfTransform
(
`<view/>foo<view v-else-if="foo"/>`
,
{
onError
},
2
)
expect
(
onError
.
mock
.
calls
[
2
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
node3
.
loc
,
},
])
const
{
node
:
{
branches
},
}
=
compileWithIfTransform
(
`<view v-if="notOk"/><view v-else/><view v-else-if="ok"/>`
,
{
onError
},
0
)
expect
(
onError
.
mock
.
calls
[
3
]).
toMatchObject
([
{
code
:
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
loc
:
branches
[
branches
.
length
-
1
].
loc
,
},
])
})
// test('error on user key', () => {
// const onError = jest.fn()
// // dynamic
// compileWithIfTransform(
// `<view v-if="ok" :key="a + 1" /><view v-else :key="a + 1" />`,
// { onError }
// )
// expect(onError.mock.calls[0]).toMatchObject([
// {
// code: ErrorCodes.X_V_IF_SAME_KEY,
// },
// ])
// // static
// compileWithIfTransform(
// `<view v-if="ok" key="1" /><view v-else key="1" />`,
// {
// onError,
// }
// )
// expect(onError.mock.calls[1]).toMatchObject([
// {
// code: ErrorCodes.X_V_IF_SAME_KEY,
// },
// ])
// })
})
})
packages/uni-mp-compiler/dist/template/codegen.js
浏览文件 @
63e307eb
...
...
@@ -2,6 +2,8 @@
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
genElementProps
=
exports
.
genElement
=
exports
.
genNode
=
exports
.
generate
=
void
0
;
const
codegen_1
=
require
(
"
../codegen
"
);
const
vFor_1
=
require
(
"
../transforms/vFor
"
);
const
vIf_1
=
require
(
"
../transforms/vIf
"
);
function
generate
({
children
},
{
emitFile
,
filename
})
{
const
context
=
{
code
:
''
,
...
...
@@ -17,6 +19,10 @@ function generate({ children }, { emitFile, filename }) {
exports
.
generate
=
generate
;
function
genNode
(
node
,
context
)
{
switch
(
node
.
type
)
{
case
9
/* IF */
:
return
node
.
branches
.
forEach
((
node
)
=>
{
genElement
(
node
,
context
);
});
case
2
/* TEXT */
:
return
genText
(
node
,
context
);
case
5
/* INTERPOLATION */
:
...
...
@@ -41,13 +47,13 @@ function genVElseIf(exp, { push }) {
function
genVElse
({
push
})
{
push
(
` wx:else`
);
}
function
genVFor
(
node
,
props
,
{
push
})
{
push
(
` wx:for="{{
${
node
.
source
}
}}"`
);
if
(
node
.
value
)
{
push
(
` wx:for-item="
${
node
.
value
}
"`
);
function
genVFor
(
opts
,
props
,
{
push
})
{
push
(
` wx:for="{{
${
opts
.
source
}
}}"`
);
if
(
opts
.
value
)
{
push
(
` wx:for-item="
${
opts
.
value
}
"`
);
}
if
(
node
.
key
)
{
push
(
` wx:for-index="
${
node
.
key
}
"`
);
if
(
opts
.
key
)
{
push
(
` wx:for-index="
${
opts
.
key
}
"`
);
}
const
keyIndex
=
props
.
findIndex
((
prop
)
=>
prop
.
type
===
7
/* DIRECTIVE */
&&
prop
.
name
===
'
bind
'
&&
...
...
@@ -61,25 +67,28 @@ function genVFor(node, props, { push }) {
props
.
splice
(
keyIndex
,
1
);
}
}
const
tagMap
=
{
template
:
'
block
'
,
};
function
genElement
(
node
,
context
)
{
const
{
tag
,
children
,
isSelfClosing
,
props
}
=
node
;
const
{
children
,
isSelfClosing
,
props
}
=
node
;
const
tag
=
tagMap
[
node
.
tag
]
||
node
.
tag
;
const
{
push
}
=
context
;
push
(
`<
${
tag
}
`
);
const
ifNode
=
node
.
ifNode
;
if
(
ifNode
)
{
if
(
ifNode
.
name
===
'
if
'
)
{
genVIf
(
ifNode
.
condition
,
context
);
if
((
0
,
vIf_1
.
isIfElementNode
)(
node
))
{
const
{
name
,
condition
}
=
node
.
vIf
;
if
(
name
===
'
if
'
)
{
genVIf
(
condition
,
context
);
}
else
if
(
ifNode
.
name
===
'
else-if
'
)
{
genVElseIf
(
ifNode
.
condition
,
context
);
else
if
(
name
===
'
else-if
'
)
{
genVElseIf
(
condition
,
context
);
}
else
if
(
ifNode
.
name
===
'
else
'
)
{
else
if
(
name
===
'
else
'
)
{
genVElse
(
context
);
}
}
const
forNode
=
node
.
forNode
;
if
(
forNode
)
{
genVFor
(
forNode
,
props
,
context
);
if
((
0
,
vFor_1
.
isForElementNode
)(
node
))
{
genVFor
(
node
.
vFor
,
props
,
context
);
}
if
(
props
.
length
)
{
genElementProps
(
props
,
context
);
...
...
packages/uni-mp-compiler/dist/transform.d.ts
浏览文件 @
63e307eb
...
...
@@ -24,6 +24,7 @@ export interface TransformContext extends Required<Omit<TransformOptions, 'filen
removeHelper
<
T
extends
symbol
>
(
name
:
T
):
void
;
helperString
(
name
:
symbol
):
string
;
replaceNode
(
node
:
TemplateChildNode
):
void
;
removeNode
(
node
?:
TemplateChildNode
):
void
;
onNodeRemoved
():
void
;
addIdentifiers
(
exp
:
ExpressionNode
|
string
):
void
;
removeIdentifiers
(
exp
:
ExpressionNode
|
string
):
void
;
...
...
packages/uni-mp-compiler/dist/transform.js
浏览文件 @
63e307eb
...
...
@@ -176,6 +176,34 @@ function createTransformContext(root, { isTS = false, inline = false, bindingMet
replaceNode
(
node
)
{
context
.
parent
.
children
[
context
.
childIndex
]
=
context
.
currentNode
=
node
;
},
removeNode
(
node
)
{
if
(
!
context
.
parent
)
{
throw
new
Error
(
`Cannot remove root node.`
);
}
const
list
=
context
.
parent
.
children
;
const
removalIndex
=
node
?
list
.
indexOf
(
node
)
:
context
.
currentNode
?
context
.
childIndex
:
-
1
;
/* istanbul ignore if */
if
(
removalIndex
<
0
)
{
throw
new
Error
(
`node being removed is not a child of current parent`
);
}
if
(
!
node
||
node
===
context
.
currentNode
)
{
// current node removed
context
.
currentNode
=
null
;
context
.
onNodeRemoved
();
}
else
{
// sibling node removed
if
(
context
.
childIndex
>
removalIndex
)
{
context
.
childIndex
--
;
context
.
onNodeRemoved
();
}
}
context
.
parent
.
children
.
splice
(
removalIndex
,
1
);
},
onNodeRemoved
:
()
=>
{
},
addIdentifiers
(
exp
)
{
if
((
0
,
shared_1
.
isString
)(
exp
))
{
...
...
packages/uni-mp-compiler/dist/transforms/vFor.d.ts
浏览文件 @
63e307eb
import
{
ExpressionNode
,
SimpleExpressionNode
,
ElementTypes
}
from
'
@vue/compiler-core
'
;
import
{
ExpressionNode
,
SimpleExpressionNode
,
ElementTypes
,
ElementNode
}
from
'
@vue/compiler-core
'
;
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
;
export
interface
ForNode
{
export
interface
VForOptions
{
source
:
string
;
value
:
string
;
key
:
string
;
index
:
string
;
}
export
declare
type
ForElementNode
=
ElementNode
&
{
vFor
:
VForOptions
;
};
export
declare
function
isForElementNode
(
node
:
unknown
):
node
is
ForElementNode
;
export
declare
const
transformFor
:
NodeTransform
;
export
interface
ForParseResult
{
source
:
ExpressionNode
;
...
...
packages/uni-mp-compiler/dist/transforms/vFor.js
浏览文件 @
63e307eb
"
use strict
"
;
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
createForLoopParams
=
exports
.
parseForExpression
=
exports
.
transformFor
=
void
0
;
exports
.
createForLoopParams
=
exports
.
parseForExpression
=
exports
.
transformFor
=
exports
.
isForElementNode
=
void
0
;
const
compiler_core_1
=
require
(
"
@vue/compiler-core
"
);
const
ast_1
=
require
(
"
../ast
"
);
const
transformExpression_1
=
require
(
"
./transformExpression
"
);
function
isForElementNode
(
node
)
{
return
!!
node
.
vFor
;
}
exports
.
isForElementNode
=
isForElementNode
;
exports
.
transformFor
=
(
0
,
compiler_core_1
.
createStructuralDirectiveTransform
)(
'
for
'
,
(
node
,
dir
,
_context
)
=>
{
const
context
=
_context
;
if
(
!
dir
.
exp
)
{
...
...
@@ -18,7 +22,6 @@ exports.transformFor = (0, compiler_core_1.createStructuralDirectiveTransform)('
parseResult
.
tagType
=
node
.
tagType
;
const
{
addIdentifiers
,
removeIdentifiers
}
=
context
;
const
{
source
,
value
,
key
,
index
}
=
parseResult
;
// scopes.index++
if
(
context
.
prefixIdentifiers
)
{
value
&&
addIdentifiers
(
value
);
key
&&
addIdentifiers
(
key
);
...
...
@@ -29,24 +32,24 @@ exports.transformFor = (0, compiler_core_1.createStructuralDirectiveTransform)('
key
:
key
?
key
.
content
:
''
,
index
:
index
?
index
.
content
:
''
,
};
const
{
currentScope
:
parentScope
,
popScope
}
=
context
;
const
vForScope
=
context
.
addVForScope
({
source
:
source
.
content
,
...
vForData
,
});
return
()
=>
{
// scopes.index--
if
(
context
.
prefixIdentifiers
)
{
value
&&
removeIdentifiers
(
value
);
key
&&
removeIdentifiers
(
key
);
index
&&
removeIdentifiers
(
index
);
}
const
{
currentScope
}
=
context
;
const
id
=
currentScope
.
id
.
next
();
node
.
forNode
=
{
const
id
=
parentScope
.
id
.
next
();
node
.
vFor
=
{
source
:
id
,
...
vForData
,
};
currentScope
.
properties
.
push
((
0
,
ast_1
.
createObjectProperty
)(
id
,
(
0
,
ast_1
.
createVForCallExpression
)(
vForScope
)));
parentScope
.
properties
.
push
((
0
,
ast_1
.
createObjectProperty
)(
id
,
(
0
,
ast_1
.
createVForCallExpression
)(
vForScope
)));
popScope
();
};
});
const
forAliasRE
=
/
([\s\S]
*
?)\s
+
(?:
in|of
)\s
+
([\s\S]
*
)
/
;
...
...
packages/uni-mp-compiler/dist/transforms/vIf.d.ts
浏览文件 @
63e307eb
import
{
NodeTransform
}
from
'
../transform
'
;
export
interface
IfNode
{
import
{
DirectiveNode
,
ElementNode
,
IfNode
}
from
'
@vue/compiler-core
'
;
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
;
interface
IfOptions
{
name
:
string
;
condition
:
string
;
condition
?
:
string
;
}
export
declare
type
IfElementNode
=
ElementNode
&
{
vIf
:
IfOptions
;
};
export
declare
function
isIfElementNode
(
node
:
unknown
):
node
is
IfElementNode
;
export
declare
const
transformIf
:
NodeTransform
;
export
declare
function
processIf
(
node
:
ElementNode
,
dir
:
DirectiveNode
,
context
:
TransformContext
,
processCodegen
?:
(
node
:
IfNode
,
branch
:
IfElementNode
,
isRoot
:
boolean
)
=>
(()
=>
void
)
|
undefined
):
(()
=>
void
)
|
undefined
;
export
{};
packages/uni-mp-compiler/dist/transforms/vIf.js
浏览文件 @
63e307eb
"
use strict
"
;
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
transformIf
=
void
0
;
exports
.
processIf
=
exports
.
transformIf
=
exports
.
isIfElementNode
=
void
0
;
const
parser_1
=
require
(
"
@babel/parser
"
);
const
types_1
=
require
(
"
@babel/types
"
);
const
compiler_core_1
=
require
(
"
@vue/compiler-core
"
);
const
ast_1
=
require
(
"
../ast
"
);
const
codegen_1
=
require
(
"
../codegen
"
);
const
transform_1
=
require
(
"
../transform
"
);
const
transformExpression_1
=
require
(
"
./transformExpression
"
);
const
transformIdentifier_1
=
require
(
"
./transformIdentifier
"
);
function
isIfElementNode
(
node
)
{
return
!!
node
.
vIf
;
}
exports
.
isIfElementNode
=
isIfElementNode
;
exports
.
transformIf
=
(
0
,
compiler_core_1
.
createStructuralDirectiveTransform
)(
/^
(
if|else|else-if
)
$/
,
(
node
,
dir
,
_context
)
=>
{
const
context
=
_context
;
if
(
dir
.
name
!==
'
else
'
&&
(
!
dir
.
exp
||
!
dir
.
exp
.
content
.
trim
()))
{
const
loc
=
dir
.
exp
?
dir
.
exp
.
loc
:
node
.
loc
;
context
.
onError
((
0
,
compiler_core_1
.
createCompilerError
)(
28
/* X_V_IF_NO_EXPRESSION */
,
dir
.
loc
));
dir
.
exp
=
(
0
,
compiler_core_1
.
createSimpleExpression
)(
`true`
,
false
,
loc
);
}
if
(
context
.
prefixIdentifiers
&&
dir
.
exp
)
{
dir
.
exp
=
(
0
,
transformExpression_1
.
processExpression
)(
dir
.
exp
,
context
);
}
return
processIf
(
node
,
dir
,
context
,
(
ifNode
,
branch
,
isRoot
)
=>
{
const
{
currentScope
:
parentScope
,
popScope
}
=
context
;
const
ifOptions
=
{
name
:
dir
.
name
,
};
branch
.
vIf
=
ifOptions
;
const
condition
=
dir
.
exp
?
(
0
,
parser_1
.
parseExpression
)((
0
,
codegen_1
.
genNode
)(
dir
.
exp
).
code
)
:
undefined
;
const
{
currentScope
:
parentScope
,
popScope
}
=
context
;
const
vIfScope
=
context
.
addVIfScope
({
name
:
dir
.
name
,
condition
,
});
return
()
=>
{
const
ifNode
=
{
name
:
dir
.
name
,
condition
:
''
,
};
if
(
condition
)
{
if
(
!
(
0
,
types_1
.
isLiteral
)(
condition
))
{
ifNode
.
condition
=
(
0
,
transformIdentifier_1
.
rewriteExpression
)(
dir
.
exp
,
parentScope
,
condition
).
content
;
ifOptions
.
condition
=
(
0
,
transformIdentifier_1
.
rewriteExpression
)(
dir
.
exp
,
parentScope
,
condition
).
content
;
}
else
{
ifNode
.
condition
=
dir
.
exp
.
content
;
ifOptions
.
condition
=
dir
.
exp
.
content
;
}
}
;
node
.
ifNode
=
ifNode
;
if
(
dir
.
name
===
'
if
'
)
{
if
(
isRoot
)
{
parentScope
.
properties
.
push
((
0
,
ast_1
.
createVIfSpreadElement
)(
vIfScope
));
}
else
{
const
vIfSpreadElement
=
findVIfSpreadElement
(
parentScope
);
if
(
!
vIfSpreadElement
)
{
popScope
();
return
context
.
onError
((
0
,
compiler_core_1
.
createCompilerError
)(
30
/* X_V_ELSE_NO_ADJACENT_IF */
,
dir
.
loc
));
return
context
.
onError
((
0
,
compiler_core_1
.
createCompilerError
)(
30
/* X_V_ELSE_NO_ADJACENT_IF */
,
node
.
loc
));
}
let
alternate
=
(
0
,
ast_1
.
createObjectExpression
)([]);
if
(
dir
.
name
===
'
else-if
'
)
{
...
...
@@ -62,7 +57,76 @@ exports.transformIf = (0, compiler_core_1.createStructuralDirectiveTransform)(/^
}
popScope
();
};
});
});
function
processIf
(
node
,
dir
,
context
,
processCodegen
)
{
if
(
dir
.
name
!==
'
else
'
&&
(
!
dir
.
exp
||
!
dir
.
exp
.
content
.
trim
()))
{
const
loc
=
dir
.
exp
?
dir
.
exp
.
loc
:
node
.
loc
;
context
.
onError
((
0
,
compiler_core_1
.
createCompilerError
)(
28
/* X_V_IF_NO_EXPRESSION */
,
dir
.
loc
));
dir
.
exp
=
(
0
,
compiler_core_1
.
createSimpleExpression
)(
`true`
,
false
,
loc
);
}
if
(
context
.
prefixIdentifiers
&&
dir
.
exp
)
{
// dir.exp can only be simple expression because vIf transform is applied
// before expression transform.
dir
.
exp
=
(
0
,
transformExpression_1
.
processExpression
)(
dir
.
exp
,
context
);
}
if
(
dir
.
name
===
'
if
'
)
{
const
ifNode
=
{
type
:
9
/* IF */
,
loc
:
node
.
loc
,
branches
:
[
node
],
};
context
.
replaceNode
(
ifNode
);
if
(
processCodegen
)
{
return
processCodegen
(
ifNode
,
node
,
true
);
}
}
else
{
// locate the adjacent v-if
const
siblings
=
context
.
parent
.
children
;
let
i
=
siblings
.
indexOf
(
node
);
while
(
i
--
>=
-
1
)
{
const
sibling
=
siblings
[
i
];
if
(
sibling
&&
sibling
.
type
===
3
/* COMMENT */
)
{
context
.
removeNode
(
sibling
);
continue
;
}
if
(
sibling
&&
sibling
.
type
===
2
/* TEXT */
&&
!
sibling
.
content
.
trim
().
length
)
{
context
.
removeNode
(
sibling
);
continue
;
}
if
(
sibling
&&
sibling
.
type
===
9
/* IF */
)
{
// Check if v-else was followed by v-else-if
if
(
dir
.
name
===
'
else-if
'
&&
sibling
.
branches
[
sibling
.
branches
.
length
-
1
].
vIf
.
condition
===
undefined
)
{
context
.
onError
((
0
,
compiler_core_1
.
createCompilerError
)(
30
/* X_V_ELSE_NO_ADJACENT_IF */
,
node
.
loc
));
}
// move the node to the if node's branches
context
.
removeNode
();
sibling
.
branches
.
push
(
node
);
const
onExit
=
processCodegen
&&
processCodegen
(
sibling
,
node
,
false
);
// since the branch was removed, it will not be traversed.
// make sure to traverse here.
(
0
,
transform_1
.
traverseNode
)(
node
,
context
);
// call on exit
if
(
onExit
)
onExit
();
// make sure to reset currentNode after traversal to indicate this
// node has been removed.
context
.
currentNode
=
null
;
}
else
{
context
.
onError
((
0
,
compiler_core_1
.
createCompilerError
)(
30
/* X_V_ELSE_NO_ADJACENT_IF */
,
node
.
loc
));
}
break
;
}
}
}
exports
.
processIf
=
processIf
;
function
findVIfSpreadElement
({
properties
})
{
const
len
=
properties
.
length
;
for
(
let
i
=
len
-
1
;
i
>=
0
;
i
--
)
{
...
...
packages/uni-mp-compiler/src/template/codegen.ts
浏览文件 @
63e307eb
...
...
@@ -11,8 +11,8 @@ import {
}
from
'
@vue/compiler-core
'
import
{
TemplateCodegenOptions
}
from
'
../options
'
import
{
genNode
as
genCodeNode
}
from
'
../codegen
'
import
{
ForNode
}
from
'
../transforms/vFor
'
import
{
IfNode
}
from
'
../transforms/vIf
'
import
{
isForElementNode
,
VForOptions
}
from
'
../transforms/vFor
'
import
{
If
ElementNode
,
isIfElement
Node
}
from
'
../transforms/vIf
'
interface
TemplateCodegenContext
{
code
:
string
push
(
code
:
string
):
void
...
...
@@ -39,6 +39,10 @@ export function genNode(
context
:
TemplateCodegenContext
)
{
switch
(
node
.
type
)
{
case
NodeTypes
.
IF
:
return
node
.
branches
.
forEach
((
node
)
=>
{
genElement
(
node
as
unknown
as
IfElementNode
,
context
)
})
case
NodeTypes
.
TEXT
:
return
genText
(
node
,
context
)
case
NodeTypes
.
INTERPOLATION
:
...
...
@@ -67,16 +71,16 @@ function genVElse({ push }: TemplateCodegenContext) {
}
function
genVFor
(
node
:
ForNode
,
opts
:
VForOptions
,
props
:
(
AttributeNode
|
DirectiveNode
)[],
{
push
}:
TemplateCodegenContext
)
{
push
(
` wx:for="{{
${
node
.
source
}
}}"`
)
if
(
node
.
value
)
{
push
(
` wx:for-item="
${
node
.
value
}
"`
)
push
(
` wx:for="{{
${
opts
.
source
}
}}"`
)
if
(
opts
.
value
)
{
push
(
` wx:for-item="
${
opts
.
value
}
"`
)
}
if
(
node
.
key
)
{
push
(
` wx:for-index="
${
node
.
key
}
"`
)
if
(
opts
.
key
)
{
push
(
` wx:for-index="
${
opts
.
key
}
"`
)
}
const
keyIndex
=
props
.
findIndex
(
(
prop
)
=>
...
...
@@ -93,24 +97,26 @@ function genVFor(
props
.
splice
(
keyIndex
,
1
)
}
}
const
tagMap
:
Record
<
string
,
string
>
=
{
template
:
'
block
'
,
}
export
function
genElement
(
node
:
ElementNode
,
context
:
TemplateCodegenContext
)
{
const
{
tag
,
children
,
isSelfClosing
,
props
}
=
node
const
{
children
,
isSelfClosing
,
props
}
=
node
const
tag
=
tagMap
[
node
.
tag
]
||
node
.
tag
const
{
push
}
=
context
push
(
`<
${
tag
}
`
)
const
ifNode
=
(
node
as
any
).
ifNode
as
IfNode
if
(
ifNode
)
{
if
(
ifNode
.
name
===
'
if
'
)
{
genVIf
(
ifNode
.
condition
,
context
)
}
else
if
(
ifNode
.
name
===
'
else-if
'
)
{
genVElseIf
(
ifNode
.
condition
,
context
)
}
else
if
(
ifNode
.
name
===
'
else
'
)
{
if
(
isIfElementNode
(
node
))
{
const
{
name
,
condition
}
=
node
.
vIf
if
(
name
===
'
if
'
)
{
genVIf
(
condition
!
,
context
)
}
else
if
(
name
===
'
else-if
'
)
{
genVElseIf
(
condition
!
,
context
)
}
else
if
(
name
===
'
else
'
)
{
genVElse
(
context
)
}
}
const
forNode
=
(
node
as
any
).
forNode
as
ForNode
if
(
forNode
)
{
genVFor
(
forNode
,
props
,
context
)
if
(
isForElementNode
(
node
))
{
genVFor
(
node
.
vFor
,
props
,
context
)
}
if
(
props
.
length
)
{
genElementProps
(
props
,
context
)
...
...
packages/uni-mp-compiler/src/transform.ts
浏览文件 @
63e307eb
...
...
@@ -62,6 +62,7 @@ export interface TransformContext
removeHelper
<
T
extends
symbol
>
(
name
:
T
):
void
helperString
(
name
:
symbol
):
string
replaceNode
(
node
:
TemplateChildNode
):
void
removeNode
(
node
?:
TemplateChildNode
):
void
onNodeRemoved
():
void
addIdentifiers
(
exp
:
ExpressionNode
|
string
):
void
removeIdentifiers
(
exp
:
ExpressionNode
|
string
):
void
...
...
@@ -272,6 +273,33 @@ export function createTransformContext(
replaceNode
(
node
)
{
context
.
parent
!
.
children
[
context
.
childIndex
]
=
context
.
currentNode
=
node
},
removeNode
(
node
)
{
if
(
!
context
.
parent
)
{
throw
new
Error
(
`Cannot remove root node.`
)
}
const
list
=
context
.
parent
!
.
children
const
removalIndex
=
node
?
list
.
indexOf
(
node
)
:
context
.
currentNode
?
context
.
childIndex
:
-
1
/* istanbul ignore if */
if
(
removalIndex
<
0
)
{
throw
new
Error
(
`node being removed is not a child of current parent`
)
}
if
(
!
node
||
node
===
context
.
currentNode
)
{
// current node removed
context
.
currentNode
=
null
context
.
onNodeRemoved
()
}
else
{
// sibling node removed
if
(
context
.
childIndex
>
removalIndex
)
{
context
.
childIndex
--
context
.
onNodeRemoved
()
}
}
context
.
parent
!
.
children
.
splice
(
removalIndex
,
1
)
},
onNodeRemoved
:
()
=>
{},
addIdentifiers
(
exp
)
{
if
(
isString
(
exp
))
{
...
...
packages/uni-mp-compiler/src/transforms/vFor.ts
浏览文件 @
63e307eb
...
...
@@ -8,18 +8,24 @@ import {
SourceLocation
,
createStructuralDirectiveTransform
,
ElementTypes
,
ElementNode
,
}
from
'
@vue/compiler-core
'
import
{
createObjectProperty
,
createVForCallExpression
}
from
'
../ast
'
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
import
{
processExpression
}
from
'
./transformExpression
'
export
interface
ForNode
{
export
interface
VForOptions
{
source
:
string
value
:
string
key
:
string
index
:
string
}
export
type
ForElementNode
=
ElementNode
&
{
vFor
:
VForOptions
}
export
function
isForElementNode
(
node
:
unknown
):
node
is
ForElementNode
{
return
!!
(
node
as
ForElementNode
).
vFor
}
export
const
transformFor
=
createStructuralDirectiveTransform
(
'
for
'
,
(
node
,
dir
,
_context
)
=>
{
...
...
@@ -44,7 +50,6 @@ export const transformFor = createStructuralDirectiveTransform(
parseResult
.
tagType
=
node
.
tagType
const
{
addIdentifiers
,
removeIdentifiers
}
=
context
const
{
source
,
value
,
key
,
index
}
=
parseResult
// scopes.index++
if
(
context
.
prefixIdentifiers
)
{
value
&&
addIdentifiers
(
value
)
key
&&
addIdentifiers
(
key
)
...
...
@@ -55,26 +60,26 @@ export const transformFor = createStructuralDirectiveTransform(
key
:
key
?
(
key
as
SimpleExpressionNode
).
content
:
''
,
index
:
index
?
(
index
as
SimpleExpressionNode
).
content
:
''
,
}
const
{
currentScope
:
parentScope
,
popScope
}
=
context
const
vForScope
=
context
.
addVForScope
({
source
:
(
source
as
SimpleExpressionNode
).
content
,
...
vForData
,
})
return
()
=>
{
// scopes.index--
if
(
context
.
prefixIdentifiers
)
{
value
&&
removeIdentifiers
(
value
)
key
&&
removeIdentifiers
(
key
)
index
&&
removeIdentifiers
(
index
)
}
const
{
currentScope
}
=
context
const
id
=
currentScope
.
id
.
next
()
;(
node
as
any
).
forNode
=
{
const
id
=
parentScope
.
id
.
next
()
;(
node
as
ForElementNode
).
vFor
=
{
source
:
id
,
...
vForData
,
}
cur
rentScope
.
properties
.
push
(
pa
rentScope
.
properties
.
push
(
createObjectProperty
(
id
,
createVForCallExpression
(
vForScope
))
)
popScope
()
}
}
)
as
unknown
as
NodeTransform
...
...
packages/uni-mp-compiler/src/transforms/vIf.ts
浏览文件 @
63e307eb
...
...
@@ -10,7 +10,12 @@ import {
createCompilerError
,
createSimpleExpression
,
createStructuralDirectiveTransform
,
DirectiveNode
,
ElementNode
,
ErrorCodes
,
IfBranchNode
,
IfNode
,
NodeTypes
,
SimpleExpressionNode
,
}
from
'
@vue/compiler-core
'
import
{
...
...
@@ -20,66 +25,59 @@ import {
}
from
'
../ast
'
import
{
genNode
}
from
'
../codegen
'
import
{
CodegenScope
}
from
'
../options
'
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
import
{
NodeTransform
,
TransformContext
,
traverseNode
}
from
'
../transform
'
import
{
processExpression
}
from
'
./transformExpression
'
import
{
rewriteExpression
}
from
'
./transformIdentifier
'
export
interface
IfNode
{
interface
IfOptions
{
name
:
string
condition
:
string
condition
?:
string
}
export
type
IfElementNode
=
ElementNode
&
{
vIf
:
IfOptions
}
export
function
isIfElementNode
(
node
:
unknown
):
node
is
IfElementNode
{
return
!!
(
node
as
IfElementNode
).
vIf
}
export
const
transformIf
=
createStructuralDirectiveTransform
(
/^
(
if|else|else-if
)
$/
,
(
node
,
dir
,
_context
)
=>
{
const
context
=
_context
as
unknown
as
TransformContext
if
(
dir
.
name
!==
'
else
'
&&
(
!
dir
.
exp
||
!
(
dir
.
exp
as
SimpleExpressionNode
).
content
.
trim
())
)
{
const
loc
=
dir
.
exp
?
dir
.
exp
.
loc
:
node
.
loc
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_IF_NO_EXPRESSION
,
dir
.
loc
)
)
dir
.
exp
=
createSimpleExpression
(
`true`
,
false
,
loc
)
}
if
(
context
.
prefixIdentifiers
&&
dir
.
exp
)
{
dir
.
exp
=
processExpression
(
dir
.
exp
as
SimpleExpressionNode
,
context
)
return
processIf
(
node
,
dir
,
context
,
(
ifNode
,
branch
,
isRoot
)
=>
{
const
{
currentScope
:
parentScope
,
popScope
}
=
context
const
ifOptions
:
IfOptions
=
{
name
:
dir
.
name
,
}
branch
.
vIf
=
ifOptions
const
condition
=
dir
.
exp
?
parseExpression
(
genNode
(
dir
.
exp
).
code
)
:
undefined
const
{
currentScope
:
parentScope
,
popScope
}
=
context
const
vIfScope
=
context
.
addVIfScope
({
name
:
dir
.
name
,
condition
,
})
return
()
=>
{
const
ifNode
:
IfNode
=
{
name
:
dir
.
name
,
condition
:
''
,
}
if
(
condition
)
{
if
(
!
isLiteral
(
condition
))
{
ifNode
.
condition
=
rewriteExpression
(
ifOptions
.
condition
=
rewriteExpression
(
dir
.
exp
!
,
parentScope
,
condition
).
content
}
else
{
ifNode
.
condition
=
(
dir
.
exp
as
SimpleExpressionNode
).
content
ifOptions
.
condition
=
(
dir
.
exp
as
SimpleExpressionNode
).
content
}
}
;(
node
as
any
).
ifNode
=
ifNode
if
(
dir
.
name
===
'
if
'
)
{
if
(
isRoot
)
{
parentScope
.
properties
.
push
(
createVIfSpreadElement
(
vIfScope
))
}
else
{
const
vIfSpreadElement
=
findVIfSpreadElement
(
parentScope
)
if
(
!
vIfSpreadElement
)
{
popScope
()
return
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
dir
.
loc
)
createCompilerError
(
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
node
.
loc
)
)
}
let
alternate
:
ConditionalExpression
|
ObjectExpression
=
...
...
@@ -95,9 +93,107 @@ export const transformIf = createStructuralDirectiveTransform(
}
popScope
()
}
})
}
)
as
unknown
as
NodeTransform
export
function
processIf
(
node
:
ElementNode
,
dir
:
DirectiveNode
,
context
:
TransformContext
,
processCodegen
?:
(
node
:
IfNode
,
branch
:
IfElementNode
,
isRoot
:
boolean
)
=>
(()
=>
void
)
|
undefined
)
{
if
(
dir
.
name
!==
'
else
'
&&
(
!
dir
.
exp
||
!
(
dir
.
exp
as
SimpleExpressionNode
).
content
.
trim
())
)
{
const
loc
=
dir
.
exp
?
dir
.
exp
.
loc
:
node
.
loc
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_IF_NO_EXPRESSION
,
dir
.
loc
)
)
dir
.
exp
=
createSimpleExpression
(
`true`
,
false
,
loc
)
}
if
(
context
.
prefixIdentifiers
&&
dir
.
exp
)
{
// dir.exp can only be simple expression because vIf transform is applied
// before expression transform.
dir
.
exp
=
processExpression
(
dir
.
exp
as
SimpleExpressionNode
,
context
)
}
if
(
dir
.
name
===
'
if
'
)
{
const
ifNode
:
IfNode
=
{
type
:
NodeTypes
.
IF
,
loc
:
node
.
loc
,
branches
:
[
node
as
unknown
as
IfBranchNode
],
}
context
.
replaceNode
(
ifNode
)
if
(
processCodegen
)
{
return
processCodegen
(
ifNode
,
node
as
IfElementNode
,
true
)
}
}
else
{
// locate the adjacent v-if
const
siblings
=
context
.
parent
!
.
children
let
i
=
siblings
.
indexOf
(
node
)
while
(
i
--
>=
-
1
)
{
const
sibling
=
siblings
[
i
]
if
(
sibling
&&
sibling
.
type
===
NodeTypes
.
COMMENT
)
{
context
.
removeNode
(
sibling
)
continue
}
if
(
sibling
&&
sibling
.
type
===
NodeTypes
.
TEXT
&&
!
sibling
.
content
.
trim
().
length
)
{
context
.
removeNode
(
sibling
)
continue
}
if
(
sibling
&&
sibling
.
type
===
NodeTypes
.
IF
)
{
// Check if v-else was followed by v-else-if
if
(
dir
.
name
===
'
else-if
'
&&
(
sibling
.
branches
[
sibling
.
branches
.
length
-
1
]
as
unknown
as
IfElementNode
).
vIf
.
condition
===
undefined
)
{
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
node
.
loc
)
)
}
// move the node to the if node's branches
context
.
removeNode
()
sibling
.
branches
.
push
(
node
as
unknown
as
IfBranchNode
)
const
onExit
=
processCodegen
&&
processCodegen
(
sibling
,
node
as
IfElementNode
,
false
)
// since the branch was removed, it will not be traversed.
// make sure to traverse here.
traverseNode
(
node
,
context
)
// call on exit
if
(
onExit
)
onExit
()
// make sure to reset currentNode after traversal to indicate this
// node has been removed.
context
.
currentNode
=
null
}
else
{
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_ELSE_NO_ADJACENT_IF
,
node
.
loc
)
)
}
break
}
}
}
function
findVIfSpreadElement
({
properties
}:
CodegenScope
)
{
const
len
=
properties
.
length
for
(
let
i
=
len
-
1
;
i
>=
0
;
i
--
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录