Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
uni-app
提交
f59898be
U
uni-app
项目概览
DCloud
/
uni-app
3 个月 前同步成功
通知
725
Star
38705
Fork
3642
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
7
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
7
Issue
7
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f59898be
编写于
10月 12, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(mp): vOn
上级
b68ad612
变更
23
隐藏空白更改
内联
并排
Showing
23 changed file
with
862 addition
and
61 deletion
+862
-61
packages/uni-app-plus/dist/uni-app-view.umd.js
packages/uni-app-plus/dist/uni-app-view.umd.js
+6
-6
packages/uni-cli-shared/src/mp/event.ts
packages/uni-cli-shared/src/mp/event.ts
+5
-2
packages/uni-mp-compiler/__tests__/test.spec.ts
packages/uni-mp-compiler/__tests__/test.spec.ts
+14
-8
packages/uni-mp-compiler/__tests__/vFor.spec.ts
packages/uni-mp-compiler/__tests__/vFor.spec.ts
+24
-24
packages/uni-mp-compiler/__tests__/vOn.mp.spec.ts
packages/uni-mp-compiler/__tests__/vOn.mp.spec.ts
+32
-0
packages/uni-mp-compiler/__tests__/vOn.spec.ts
packages/uni-mp-compiler/__tests__/vOn.spec.ts
+275
-0
packages/uni-mp-compiler/src/ast.ts
packages/uni-mp-compiler/src/ast.ts
+6
-2
packages/uni-mp-compiler/src/compile.ts
packages/uni-mp-compiler/src/compile.ts
+19
-11
packages/uni-mp-compiler/src/errors.ts
packages/uni-mp-compiler/src/errors.ts
+5
-0
packages/uni-mp-compiler/src/index.ts
packages/uni-mp-compiler/src/index.ts
+2
-0
packages/uni-mp-compiler/src/options.ts
packages/uni-mp-compiler/src/options.ts
+1
-0
packages/uni-mp-compiler/src/runtimeHelpers.ts
packages/uni-mp-compiler/src/runtimeHelpers.ts
+9
-0
packages/uni-mp-compiler/src/template/codegen.ts
packages/uni-mp-compiler/src/template/codegen.ts
+16
-2
packages/uni-mp-compiler/src/transform.ts
packages/uni-mp-compiler/src/transform.ts
+42
-1
packages/uni-mp-compiler/src/transforms/transformElement.ts
packages/uni-mp-compiler/src/transforms/transformElement.ts
+106
-0
packages/uni-mp-compiler/src/transforms/transformIdentifier.ts
...ges/uni-mp-compiler/src/transforms/transformIdentifier.ts
+0
-1
packages/uni-mp-compiler/src/transforms/vFor.ts
packages/uni-mp-compiler/src/transforms/vFor.ts
+1
-1
packages/uni-mp-compiler/src/transforms/vOn.ts
packages/uni-mp-compiler/src/transforms/vOn.ts
+183
-0
packages/uni-mp-vue/dist/vue.runtime.esm.js
packages/uni-mp-vue/dist/vue.runtime.esm.js
+42
-1
packages/uni-mp-vue/src/helpers/vOn.ts
packages/uni-mp-vue/src/helpers/vOn.ts
+71
-0
packages/uni-mp-vue/src/index.ts
packages/uni-mp-vue/src/index.ts
+1
-0
packages/uni-stat/dist/uni-stat.cjs.js
packages/uni-stat/dist/uni-stat.cjs.js
+1
-1
packages/uni-stat/dist/uni-stat.es.js
packages/uni-stat/dist/uni-stat.es.js
+1
-1
未找到文件。
packages/uni-app-plus/dist/uni-app-view.umd.js
浏览文件 @
f59898be
因为 它太大了无法显示 source diff 。你可以改为
查看blob
。
packages/uni-cli-shared/src/mp/event.ts
浏览文件 @
f59898be
...
@@ -8,6 +8,9 @@ export function formatMiniProgramEvent(
...
@@ -8,6 +8,9 @@ export function formatMiniProgramEvent(
isCapture
?:
boolean
isCapture
?:
boolean
}
}
)
{
)
{
if
(
eventName
===
'
click
'
)
{
eventName
=
'
tap
'
}
let
eventType
=
'
bind
'
let
eventType
=
'
bind
'
if
(
isCatch
)
{
if
(
isCatch
)
{
eventType
=
'
catch
'
eventType
=
'
catch
'
...
@@ -15,6 +18,6 @@ export function formatMiniProgramEvent(
...
@@ -15,6 +18,6 @@ export function formatMiniProgramEvent(
if
(
isCapture
)
{
if
(
isCapture
)
{
return
`capture-
${
eventType
}
:
${
eventName
}
`
return
`capture-
${
eventType
}
:
${
eventName
}
`
}
}
//
原生组件不支持 bind:input 等写法,统一使用 bindinput
//
bind:foo-bar
return
`
${
eventType
}${
eventName
}
`
return
eventType
+
(
eventName
.
indexOf
(
'
-
'
)
>
-
1
?
'
:
'
:
''
)
+
eventName
}
}
packages/uni-mp-compiler/__tests__/test.spec.ts
浏览文件 @
f59898be
// import { inspect } from './testUtils'
// import { inspect } from './testUtils'
import
{
compile
}
from
'
../src
'
import
{
compile
}
from
'
../src
'
import
{
CompilerOptions
}
from
'
../src/options
'
function
assert
(
template
:
string
,
templateCode
:
string
,
renderCode
:
string
)
{
function
assert
(
template
:
string
,
templateCode
:
string
,
renderCode
:
string
,
options
:
CompilerOptions
)
{
const
res
=
compile
(
template
,
{
const
res
=
compile
(
template
,
{
filename
:
'
foo.vue
'
,
filename
:
'
foo.vue
'
,
prefixIdentifiers
:
true
,
prefixIdentifiers
:
true
,
...
@@ -14,6 +20,7 @@ function assert(template: string, templateCode: string, renderCode: string) {
...
@@ -14,6 +20,7 @@ function assert(template: string, templateCode: string, renderCode: string) {
return
''
return
''
},
},
},
},
...
options
,
})
})
// expect(res.template).toBe(templateCode)
// expect(res.template).toBe(templateCode)
// expect(res.code).toBe(renderCode)
// expect(res.code).toBe(renderCode)
...
@@ -24,17 +31,16 @@ function assert(template: string, templateCode: string, renderCode: string) {
...
@@ -24,17 +31,16 @@ function assert(template: string, templateCode: string, renderCode: string) {
}
}
describe
(
'
compiler
'
,
()
=>
{
describe
(
'
compiler
'
,
()
=>
{
test
(
`keyed v-for`
,
()
=>
{
test
(
'
should wrap as function if expression is inline statement
'
,
()
=>
{
assert
(
assert
(
`<
view v-for="(item) in items" :key="item
" />`
,
`<
div v-on:click="foo
" />`
,
`<view
wx:for="{{a}}" wx:for-item="item" wx:key="*this
"/>`
,
`<view
bindtap="{{a}}
"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a: _vOn(_ctx.foo)
return {};
})
}
}
}`
}`
,
{}
)
)
})
})
})
})
packages/uni-mp-compiler/__tests__/vFor.spec.ts
浏览文件 @
f59898be
...
@@ -30,7 +30,7 @@ describe(`compiler: v-for`, () => {
...
@@ -30,7 +30,7 @@ describe(`compiler: v-for`, () => {
`<view wx:for="{{a}}" wx:for-item="index"/>`
,
`<view wx:for="{{a}}" wx:for-item="index"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor([1, 2, 3, 4, 5], index => {
a:
_
vFor([1, 2, 3, 4, 5], index => {
return {};
return {};
})
})
}
}
...
@@ -43,7 +43,7 @@ return {
...
@@ -43,7 +43,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item"/>`
,
`<view wx:for="{{a}}" wx:for-item="item"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -56,7 +56,7 @@ return {
...
@@ -56,7 +56,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, ({
a:
_
vFor(_ctx.items, ({
id,
id,
value
value
}) => {
}) => {
...
@@ -72,7 +72,7 @@ return {
...
@@ -72,7 +72,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, ([id, value]) => {
a:
_
vFor(_ctx.items, ([id, value]) => {
return {};
return {};
})
})
}
}
...
@@ -85,7 +85,7 @@ return {
...
@@ -85,7 +85,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item" wx:for-index="key"/>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:for-index="key"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (item, key) => {
a:
_
vFor(_ctx.items, (item, key) => {
return {};
return {};
})
})
}
}
...
@@ -98,7 +98,7 @@ return {
...
@@ -98,7 +98,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item" wx:for-index="key"/>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:for-index="key"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (item, key, index) => {
a:
_
vFor(_ctx.items, (item, key, index) => {
return {};
return {};
})
})
}
}
...
@@ -111,7 +111,7 @@ return {
...
@@ -111,7 +111,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="value"/>`
,
`<view wx:for="{{a}}" wx:for-item="value"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (value, __, index) => {
a:
_
vFor(_ctx.items, (value, __, index) => {
return {};
return {};
})
})
}
}
...
@@ -124,7 +124,7 @@ return {
...
@@ -124,7 +124,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (_, __, index) => {
a:
_
vFor(_ctx.items, (_, __, index) => {
return {};
return {};
})
})
}
}
...
@@ -137,7 +137,7 @@ return {
...
@@ -137,7 +137,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item"/>`
,
`<view wx:for="{{a}}" wx:for-item="item"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -150,7 +150,7 @@ return {
...
@@ -150,7 +150,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item" wx:for-index="key"/>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:for-index="key"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (item, key) => {
a:
_
vFor(_ctx.items, (item, key) => {
return {};
return {};
})
})
}
}
...
@@ -163,7 +163,7 @@ return {
...
@@ -163,7 +163,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="value" wx:for-index="key"/>`
,
`<view wx:for="{{a}}" wx:for-item="value" wx:for-index="key"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (value, key, index) => {
a:
_
vFor(_ctx.items, (value, key, index) => {
return {};
return {};
})
})
}
}
...
@@ -176,7 +176,7 @@ return {
...
@@ -176,7 +176,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="value"/>`
,
`<view wx:for="{{a}}" wx:for-item="value"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (value, __, index) => {
a:
_
vFor(_ctx.items, (value, __, index) => {
return {};
return {};
})
})
}
}
...
@@ -189,7 +189,7 @@ return {
...
@@ -189,7 +189,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`<view wx:for="{{a}}" wx:for-item="v0"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, (_, __, index) => {
a:
_
vFor(_ctx.items, (_, __, index) => {
return {};
return {};
})
})
}
}
...
@@ -202,7 +202,7 @@ return {
...
@@ -202,7 +202,7 @@ return {
`<block wx:for="{{a}}" wx:for-item="item">hello<view/></block>`
,
`<block wx:for="{{a}}" wx:for-item="item">hello<view/></block>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -215,7 +215,7 @@ return {
...
@@ -215,7 +215,7 @@ return {
`<block wx:for="{{a}}" wx:for-item="item"><slot/></block>`
,
`<block wx:for="{{a}}" wx:for-item="item"><slot/></block>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -229,7 +229,7 @@ return {
...
@@ -229,7 +229,7 @@ return {
`<block wx:for="{{a}}" wx:for-item="item" wx:key="b"><view id="{{item.a}}"/></block>`
,
`<block wx:for="{{a}}" wx:for-item="item" wx:key="b"><view id="{{item.a}}"/></block>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {
return {
a: item.id,
a: item.id,
b: item.id
b: item.id
...
@@ -245,7 +245,7 @@ return {
...
@@ -245,7 +245,7 @@ return {
`<slot wx:for="{{a}}" wx:for-item="item"></slot>`
,
`<slot wx:for="{{a}}" wx:for-item="item"></slot>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -258,7 +258,7 @@ return {
...
@@ -258,7 +258,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item" wx:key="*this"/>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:key="*this"/>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -271,7 +271,7 @@ return {
...
@@ -271,7 +271,7 @@ return {
`<block wx:for="{{a}}" wx:for-item="item" wx:key="*this">hello<view/></block>`
,
`<block wx:for="{{a}}" wx:for-item="item" wx:key="*this">hello<view/></block>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
@@ -286,7 +286,7 @@ return {
...
@@ -286,7 +286,7 @@ return {
return {
return {
b: _ctx.ok,
b: _ctx.ok,
...(_ctx.ok ? {
...(_ctx.ok ? {
a: vFor(_ctx.list, i => {
a:
_
vFor(_ctx.list, i => {
return {};
return {};
})
})
} : {})
} : {})
...
@@ -303,7 +303,7 @@ return {
...
@@ -303,7 +303,7 @@ return {
return {
return {
b: _ctx.ok,
b: _ctx.ok,
...(_ctx.ok ? {
...(_ctx.ok ? {
a: vFor(_ctx.list, i => {
a:
_
vFor(_ctx.list, i => {
return {};
return {};
})
})
} : {})
} : {})
...
@@ -709,7 +709,7 @@ return {
...
@@ -709,7 +709,7 @@ return {
`<view wx:for="{{a}}" wx:for-item="item" wx:key="a">test</view>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:key="a">test</view>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {
return {
a: _ctx.itemKey(item)
a: _ctx.itemKey(item)
};
};
...
@@ -726,7 +726,7 @@ return {
...
@@ -726,7 +726,7 @@ return {
`<block wx:for="{{a}}" wx:for-item="item" wx:key="a">test</block>`
,
`<block wx:for="{{a}}" wx:for-item="item" wx:key="a">test</block>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {
return {
a: _ctx.itemKey(item)
a: _ctx.itemKey(item)
};
};
...
@@ -742,7 +742,7 @@ return {
...
@@ -742,7 +742,7 @@ return {
`<block wx:for="{{a}}" wx:for-item="item" key="key">test</block>`
,
`<block wx:for="{{a}}" wx:for-item="item" key="key">test</block>`
,
`(_ctx, _cache) => {
`(_ctx, _cache) => {
return {
return {
a: vFor(_ctx.items, item => {
a:
_
vFor(_ctx.items, item => {
return {};
return {};
})
})
}
}
...
...
packages/uni-mp-compiler/__tests__/vOn.mp.spec.ts
0 → 100644
浏览文件 @
f59898be
import
{
ElementNode
}
from
'
@vue/compiler-core
'
import
{
compile
}
from
'
../src
'
import
{
X_V_ON_DYNAMIC_EVENT
}
from
'
../src/errors
'
import
{
CompilerOptions
}
from
'
../src/options
'
function
parseWithVOn
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
const
{
ast
}
=
compile
(
template
,
options
)
return
{
root
:
ast
,
node
:
ast
.
children
[
0
]
as
ElementNode
,
}
}
describe
(
'
compiler(mp): transform v-on
'
,
()
=>
{
test
(
'
should error if dynamic event
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVOn
(
`<div v-on:[event]="onClick" />`
,
{
onError
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
X_V_ON_DYNAMIC_EVENT
,
loc
:
{
start
:
{
line
:
1
,
column
:
6
,
},
end
:
{
line
:
1
,
column
:
28
,
},
},
})
})
})
packages/uni-mp-compiler/__tests__/vOn.spec.ts
0 → 100644
浏览文件 @
f59898be
import
{
ElementNode
,
ErrorCodes
}
from
'
@vue/compiler-core
'
import
{
compile
}
from
'
../src
'
import
{
CompilerOptions
}
from
'
../src/options
'
import
{
assert
}
from
'
./testUtils
'
function
parseWithVOn
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
const
{
ast
}
=
compile
(
template
,
options
)
return
{
root
:
ast
,
node
:
ast
.
children
[
0
]
as
ElementNode
,
}
}
describe
(
'
compiler: transform v-on
'
,
()
=>
{
test
(
'
basic
'
,
()
=>
{
assert
(
`<view v-on:click="onClick"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(_ctx.onClick)
}
}`
)
})
test
(
'
dynamic arg
'
,
()
=>
{
// <view v-on:[event]="handler"/>
})
test
(
'
dynamic arg with prefixing
'
,
()
=>
{
// <view v-on:[event]="handler"/>
})
test
(
'
dynamic arg with complex exp prefixing
'
,
()
=>
{
// <view v-on:[event(foo)]="handler"/>
})
test
(
'
should wrap as function if expression is inline statement
'
,
()
=>
{
assert
(
`<view @click="i++"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => _ctx.i++)
}
}`
)
})
test
(
'
should handle multiple inline statement
'
,
()
=>
{
assert
(
`<view @click="foo();bar()"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => {
_ctx.foo();
_ctx.bar();
})
}
}`
)
})
test
(
'
should handle multi-line statement
'
,
()
=>
{
assert
(
`<view @click="\nfoo();\nbar()\n"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => {
foo();
bar();
})
}
}`
,
{
prefixIdentifiers
:
false
}
)
})
test
(
'
inline statement w/ prefixIdentifiers: true
'
,
()
=>
{
assert
(
`<view @click="foo($event)"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => _ctx.foo($event))
}
}`
)
})
test
(
'
multiple inline statements w/ prefixIdentifiers: true
'
,
()
=>
{
assert
(
`<view @click="foo($event);bar()"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => {
_ctx.foo($event);
_ctx.bar();
})
}
}`
)
})
test
(
'
should NOT wrap as function if expression is already function expression
'
,
()
=>
{
assert
(
`<view @click="$event => foo($event)"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => _ctx.foo($event))
}
}`
)
})
test
(
'
should NOT wrap as function if expression is already function expression (with newlines)
'
,
()
=>
{
assert
(
`<view @click="
$event => {
foo($event)
}
"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn($event => {
_ctx.foo($event);
})
}
}`
)
})
test
(
'
should NOT wrap as function if expression is already function expression (with newlines + function keyword)
'
,
()
=>
{
assert
(
`<view @click="
function($event) {
foo($event)
}
"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(function ($event) {
_ctx.foo($event);
})
}
}`
)
})
test
(
'
should NOT wrap as function if expression is complex member expression
'
,
()
=>
{
assert
(
`<view @click="a['b' + c]"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(a['b' + c])
}
}`
,
{
prefixIdentifiers
:
false
,
}
)
})
test
(
'
complex member expression w/ prefixIdentifiers: true
'
,
()
=>
{
assert
(
`<view @click="a['b' + c]"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(_ctx.a['b' + _ctx.c])
}
}`
)
})
test
(
'
function expression w/ prefixIdentifiers: true
'
,
()
=>
{
assert
(
`<view @click="e => foo(e)"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(e => _ctx.foo(e))
}
}`
)
})
test
(
'
should error if no expression AND no modifier
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVOn
(
`<div v-on:click />`
,
{
onError
})
expect
(
onError
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
code
:
ErrorCodes
.
X_V_ON_NO_EXPRESSION
,
loc
:
{
start
:
{
line
:
1
,
column
:
6
,
},
end
:
{
line
:
1
,
column
:
16
,
},
},
})
})
test
(
'
should NOT error if no expression but has modifier
'
,
()
=>
{
const
onError
=
jest
.
fn
()
parseWithVOn
(
`<div v-on:click.prevent />`
,
{
onError
})
expect
(
onError
).
not
.
toHaveBeenCalled
()
})
test
(
'
case conversion for kebab-case events
'
,
()
=>
{
assert
(
`<view v-on:foo-bar="onMount"/>`
,
`<view bind:foo-bar="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(_ctx.onMount)
}
}`
)
})
test
(
'
case conversion for vnode hooks
'
,
()
=>
{
assert
(
`<view v-on:vnode-mounted="onMount"/>`
,
`<view bind:vnode-mounted="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(_ctx.onMount)
}
}`
)
})
describe
(
'
cacheHandler
'
,
()
=>
{
test
(
'
empty handler
'
,
()
=>
{
assert
(
`<view v-on:click.prevent />`
,
`<view catchtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return {
a: _vOn(() => {})
}
}`
)
})
test
(
'
member expression handler
'
,
()
=>
{
// <div v-on:click="foo" />
})
test
(
'
compound member expression handler
'
,
()
=>
{
// <div v-on:click="foo.bar" />
})
test
(
'
bail on component member expression handler
'
,
()
=>
{
// <comp v-on:click="foo" />
})
test
(
'
should not be cached inside v-once
'
,
()
=>
{
// <div v-once><div v-on:click="foo"/></div>
})
test
(
'
inline function expression handler
'
,
()
=>
{
// <div v-on:click="() => foo()" />
})
test
(
'
inline async arrow function expression handler
'
,
()
=>
{
// <div v-on:click="async () => await foo()" />
})
test
(
'
inline async function expression handler
'
,
()
=>
{
// <div v-on:click="async function () { await foo() } " />
})
test
(
'
inline statement handler
'
,
()
=>
{
// <div v-on:click="foo++" />
})
})
})
packages/uni-mp-compiler/src/ast.ts
浏览文件 @
f59898be
...
@@ -32,6 +32,7 @@ import {
...
@@ -32,6 +32,7 @@ import {
import
{
CodegenScope
,
CodegenVForScope
,
CodegenVIfScope
}
from
'
./options
'
import
{
CodegenScope
,
CodegenVForScope
,
CodegenVIfScope
}
from
'
./options
'
import
{
TransformContext
}
from
'
./transform
'
import
{
TransformContext
}
from
'
./transform
'
import
{
genExpr
}
from
'
./codegen
'
import
{
genExpr
}
from
'
./codegen
'
import
{
V_FOR
}
from
'
./runtimeHelpers
'
export
function
createIdentifier
(
name
:
string
)
{
export
function
createIdentifier
(
name
:
string
)
{
return
identifier
(
name
)
return
identifier
(
name
)
...
@@ -78,12 +79,15 @@ function numericLiteralToArrayExpr(num: number) {
...
@@ -78,12 +79,15 @@ function numericLiteralToArrayExpr(num: number) {
return
arrayExpression
(
elements
)
return
arrayExpression
(
elements
)
}
}
export
function
createVForCallExpression
(
vForScope
:
CodegenVForScope
)
{
export
function
createVForCallExpression
(
vForScope
:
CodegenVForScope
,
context
:
TransformContext
)
{
let
sourceExpr
:
Expression
=
vForScope
.
sourceExpr
!
let
sourceExpr
:
Expression
=
vForScope
.
sourceExpr
!
if
(
isNumericLiteral
(
sourceExpr
))
{
if
(
isNumericLiteral
(
sourceExpr
))
{
sourceExpr
=
numericLiteralToArrayExpr
((
sourceExpr
as
NumericLiteral
).
value
)
sourceExpr
=
numericLiteralToArrayExpr
((
sourceExpr
as
NumericLiteral
).
value
)
}
}
return
callExpression
(
identifier
(
'
vFor
'
),
[
return
callExpression
(
identifier
(
context
.
helperString
(
V_FOR
)
),
[
sourceExpr
,
sourceExpr
,
createVForArrowFunctionExpression
(
vForScope
),
createVForArrowFunctionExpression
(
vForScope
),
])
])
...
...
packages/uni-mp-compiler/src/compile.ts
浏览文件 @
f59898be
...
@@ -9,37 +9,45 @@ import { transformIdentifier } from './transforms/transformIdentifier'
...
@@ -9,37 +9,45 @@ import { transformIdentifier } from './transforms/transformIdentifier'
import
{
transformIf
}
from
'
./transforms/vIf
'
import
{
transformIf
}
from
'
./transforms/vIf
'
import
{
transformFor
}
from
'
./transforms/vFor
'
import
{
transformFor
}
from
'
./transforms/vFor
'
import
{
generate
as
genTemplate
}
from
'
./template/codegen
'
import
{
generate
as
genTemplate
}
from
'
./template/codegen
'
import
{
transformOn
}
from
'
./transforms/vOn
'
import
{
transformElement
}
from
'
./transforms/transformElement
'
export
type
TransformPreset
=
[
export
type
TransformPreset
=
[
NodeTransform
[],
NodeTransform
[],
Record
<
string
,
DirectiveTransform
>
Record
<
string
,
DirectiveTransform
>
]
]
export
function
getBaseTransformPreset
(
export
function
getBaseTransformPreset
({
prefixIdentifiers
?:
boolean
prefixIdentifiers
,
):
TransformPreset
{
skipTransformIdentifier
,
}:
{
prefixIdentifiers
:
boolean
skipTransformIdentifier
:
boolean
}):
TransformPreset
{
const
nodeTransforms
=
[
transformIf
,
transformFor
]
const
nodeTransforms
=
[
transformIf
,
transformFor
]
if
(
!
skipTransformIdentifier
)
{
nodeTransforms
.
push
(
transformIdentifier
)
}
nodeTransforms
.
push
(
transformElement
)
if
(
prefixIdentifiers
)
{
if
(
prefixIdentifiers
)
{
nodeTransforms
.
push
(
transformExpression
)
nodeTransforms
.
push
(
transformExpression
)
}
}
return
[
nodeTransforms
,
{}]
return
[
nodeTransforms
,
{
on
:
transformOn
}]
}
}
export
function
baseCompile
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
export
function
baseCompile
(
template
:
string
,
options
:
CompilerOptions
=
{})
{
const
prefixIdentifiers
=
const
prefixIdentifiers
=
options
.
prefixIdentifiers
===
true
||
options
.
mode
===
'
module
'
options
.
prefixIdentifiers
===
true
||
options
.
mode
===
'
module
'
const
ast
=
isString
(
template
)
?
baseParse
(
template
,
options
)
:
template
const
ast
=
isString
(
template
)
?
baseParse
(
template
,
options
)
:
template
const
[
nodeTransforms
,
directiveTransforms
]
=
const
[
nodeTransforms
,
directiveTransforms
]
=
getBaseTransformPreset
({
getBaseTransformPreset
(
prefixIdentifiers
)
prefixIdentifiers
,
skipTransformIdentifier
:
options
.
skipTransformIdentifier
===
true
,
})
const
context
=
transform
(
const
context
=
transform
(
ast
,
ast
,
extend
({},
options
,
{
extend
({},
options
,
{
prefixIdentifiers
,
prefixIdentifiers
,
nodeTransforms
:
[
nodeTransforms
:
[...
nodeTransforms
,
...(
options
.
nodeTransforms
||
[])],
...
nodeTransforms
,
...(
options
.
nodeTransforms
||
[]),
...(
options
.
skipTransformIdentifier
?
[]
:
[
transformIdentifier
]),
],
directiveTransforms
:
extend
(
directiveTransforms
:
extend
(
{},
{},
directiveTransforms
,
directiveTransforms
,
...
...
packages/uni-mp-compiler/src/errors.ts
0 → 100644
浏览文件 @
f59898be
export
const
X_V_ON_DYNAMIC_EVENT
=
0
export
const
errorMessages
:
Record
<
number
,
string
>
=
{
[
X_V_ON_DYNAMIC_EVENT
]:
'
v-on:[event] is not supported.
'
,
}
packages/uni-mp-compiler/src/index.ts
浏览文件 @
f59898be
...
@@ -10,6 +10,8 @@ import { baseCompile } from './compile'
...
@@ -10,6 +10,8 @@ import { baseCompile } from './compile'
import
{
parserOptions
}
from
'
./parserOptions
'
import
{
parserOptions
}
from
'
./parserOptions
'
import
{
CompilerOptions
}
from
'
./options
'
import
{
CompilerOptions
}
from
'
./options
'
export
*
from
'
./runtimeHelpers
'
export
function
parse
(
template
:
string
,
options
:
ParserOptions
=
{}):
RootNode
{
export
function
parse
(
template
:
string
,
options
:
ParserOptions
=
{}):
RootNode
{
return
baseParse
(
template
,
extend
({},
parserOptions
,
options
))
return
baseParse
(
template
,
extend
({},
parserOptions
,
options
))
}
}
...
...
packages/uni-mp-compiler/src/options.ts
浏览文件 @
f59898be
...
@@ -21,6 +21,7 @@ interface SharedTransformCodegenOptions {
...
@@ -21,6 +21,7 @@ interface SharedTransformCodegenOptions {
export
interface
TransformOptions
export
interface
TransformOptions
extends
SharedTransformCodegenOptions
,
extends
SharedTransformCodegenOptions
,
ErrorHandlingOptions
{
ErrorHandlingOptions
{
cacheHandlers
?:
boolean
nodeTransforms
?:
NodeTransform
[]
nodeTransforms
?:
NodeTransform
[]
directiveTransforms
?:
Record
<
string
,
DirectiveTransform
|
undefined
>
directiveTransforms
?:
Record
<
string
,
DirectiveTransform
|
undefined
>
isBuiltInComponent
?:
(
tag
:
string
)
=>
symbol
|
void
isBuiltInComponent
?:
(
tag
:
string
)
=>
symbol
|
void
...
...
packages/uni-mp-compiler/src/runtimeHelpers.ts
0 → 100644
浏览文件 @
f59898be
import
{
registerRuntimeHelpers
}
from
'
@vue/compiler-core
'
export
const
V_ON
=
Symbol
(
`vOn`
)
export
const
V_FOR
=
Symbol
(
`vFor`
)
registerRuntimeHelpers
({
[
V_ON
]:
'
vOn
'
,
[
V_FOR
]:
'
vFor
'
,
})
packages/uni-mp-compiler/src/template/codegen.ts
浏览文件 @
f59898be
import
{
formatMiniProgramEvent
}
from
'
@dcloudio/uni-cli-shared
'
import
{
import
{
AttributeNode
,
AttributeNode
,
DirectiveNode
,
DirectiveNode
,
...
@@ -141,13 +142,26 @@ export function genElementProps(
...
@@ -141,13 +142,26 @@ export function genElementProps(
}
}
}
else
{
}
else
{
const
{
name
}
=
prop
const
{
name
}
=
prop
if
(
name
===
'
bind
'
)
{
push
(
` `
)
push
(
` `
)
if
(
name
===
'
on
'
)
{
genOn
(
prop
,
context
)
}
else
{
genDirectiveNode
(
prop
,
context
)
genDirectiveNode
(
prop
,
context
)
}
}
}
}
})
})
}
}
function
genOn
(
prop
:
DirectiveNode
,
{
push
}:
TemplateCodegenContext
)
{
const
arg
=
(
prop
.
arg
as
SimpleExpressionNode
).
content
const
exp
=
(
prop
.
exp
as
SimpleExpressionNode
).
content
const
modifiers
=
prop
.
modifiers
push
(
`
${
formatMiniProgramEvent
(
arg
,
{
isCatch
:
modifiers
.
includes
(
'
stop
'
)
||
modifiers
.
includes
(
'
prevent
'
),
isCapture
:
modifiers
.
includes
(
'
capture
'
),
})}
="{{
${
exp
}
}}"`
)
}
function
genDirectiveNode
(
function
genDirectiveNode
(
prop
:
DirectiveNode
,
prop
:
DirectiveNode
,
...
...
packages/uni-mp-compiler/src/transform.ts
浏览文件 @
f59898be
import
{
NOOP
,
EMPTY_OBJ
,
extend
,
isString
,
isArray
}
from
'
@vue/shared
'
import
{
NOOP
,
EMPTY_OBJ
,
extend
,
isString
,
isArray
,
capitalize
,
camelize
,
}
from
'
@vue/shared
'
import
{
import
{
DirectiveNode
,
DirectiveNode
,
...
@@ -15,6 +23,9 @@ import {
...
@@ -15,6 +23,9 @@ import {
ExpressionNode
,
ExpressionNode
,
ElementTypes
,
ElementTypes
,
isVSlot
,
isVSlot
,
JSChildNode
,
CacheExpression
,
locStub
,
}
from
'
@vue/compiler-core
'
}
from
'
@vue/compiler-core
'
import
IdentifierGenerator
from
'
./identifier
'
import
IdentifierGenerator
from
'
./identifier
'
import
{
import
{
...
@@ -51,16 +62,20 @@ export interface ErrorHandlingOptions {
...
@@ -51,16 +62,20 @@ export interface ErrorHandlingOptions {
export
interface
TransformContext
export
interface
TransformContext
extends
Required
<
Omit
<
TransformOptions
,
'
filename
'
>>
{
extends
Required
<
Omit
<
TransformOptions
,
'
filename
'
>>
{
selfName
:
string
|
null
currentNode
:
RootNode
|
TemplateChildNode
|
null
currentNode
:
RootNode
|
TemplateChildNode
|
null
parent
:
ParentNode
|
null
parent
:
ParentNode
|
null
childIndex
:
number
childIndex
:
number
helpers
:
Map
<
symbol
,
number
>
helpers
:
Map
<
symbol
,
number
>
components
:
Set
<
string
>
identifiers
:
{
[
name
:
string
]:
number
|
undefined
}
identifiers
:
{
[
name
:
string
]:
number
|
undefined
}
cached
:
number
scopes
:
{
scopes
:
{
vFor
:
number
vFor
:
number
}
}
scope
:
CodegenRootScope
scope
:
CodegenRootScope
currentScope
:
CodegenScope
currentScope
:
CodegenScope
inVOnce
:
boolean
helper
<
T
extends
symbol
>
(
name
:
T
):
T
helper
<
T
extends
symbol
>
(
name
:
T
):
T
removeHelper
<
T
extends
symbol
>
(
name
:
T
):
void
removeHelper
<
T
extends
symbol
>
(
name
:
T
):
void
helperString
(
name
:
symbol
):
string
helperString
(
name
:
symbol
):
string
...
@@ -72,6 +87,7 @@ export interface TransformContext
...
@@ -72,6 +87,7 @@ export interface TransformContext
popScope
():
CodegenScope
|
undefined
popScope
():
CodegenScope
|
undefined
addVIfScope
(
initScope
:
CodegenVIfScopeInit
):
CodegenVIfScope
addVIfScope
(
initScope
:
CodegenVIfScopeInit
):
CodegenVIfScope
addVForScope
(
initScope
:
CodegenVForScopeInit
):
CodegenVForScope
addVForScope
(
initScope
:
CodegenVForScopeInit
):
CodegenVForScope
cache
<
T
extends
JSChildNode
>
(
exp
:
T
,
isVNode
?:
boolean
):
CacheExpression
|
T
}
}
export
function
isRootScope
(
scope
:
CodegenScope
):
scope
is
CodegenRootScope
{
export
function
isRootScope
(
scope
:
CodegenScope
):
scope
is
CodegenRootScope
{
...
@@ -175,9 +191,11 @@ function defaultOnWarn(msg: CompilerError) {
...
@@ -175,9 +191,11 @@ function defaultOnWarn(msg: CompilerError) {
export
function
createTransformContext
(
export
function
createTransformContext
(
root
:
RootNode
,
root
:
RootNode
,
{
{
filename
=
''
,
isTS
=
false
,
isTS
=
false
,
inline
=
false
,
inline
=
false
,
bindingMetadata
=
EMPTY_OBJ
,
bindingMetadata
=
EMPTY_OBJ
,
cacheHandlers
=
false
,
prefixIdentifiers
=
false
,
prefixIdentifiers
=
false
,
skipTransformIdentifier
=
false
,
skipTransformIdentifier
=
false
,
nodeTransforms
=
[],
nodeTransforms
=
[],
...
@@ -212,11 +230,14 @@ export function createTransformContext(
...
@@ -212,11 +230,14 @@ export function createTransformContext(
}
}
const
identifiers
=
Object
.
create
(
null
)
const
identifiers
=
Object
.
create
(
null
)
const
scopes
:
CodegenScope
[]
=
[
scope
]
const
scopes
:
CodegenScope
[]
=
[
scope
]
const
nameMatch
=
filename
.
replace
(
/
\?
.*$/
,
''
).
match
(
/
([^/\\]
+
)\.\w
+$/
)
const
context
:
TransformContext
=
{
const
context
:
TransformContext
=
{
// options
// options
selfName
:
nameMatch
&&
capitalize
(
camelize
(
nameMatch
[
1
])),
isTS
,
isTS
,
inline
,
inline
,
bindingMetadata
,
bindingMetadata
,
cacheHandlers
,
prefixIdentifiers
,
prefixIdentifiers
,
nodeTransforms
,
nodeTransforms
,
directiveTransforms
,
directiveTransforms
,
...
@@ -230,6 +251,8 @@ export function createTransformContext(
...
@@ -230,6 +251,8 @@ export function createTransformContext(
parent
:
null
,
parent
:
null
,
childIndex
:
0
,
childIndex
:
0
,
helpers
:
new
Map
(),
helpers
:
new
Map
(),
components
:
new
Set
(),
cached
:
0
,
identifiers
,
identifiers
,
scope
,
scope
,
scopes
:
{
scopes
:
{
...
@@ -239,6 +262,7 @@ export function createTransformContext(
...
@@ -239,6 +262,7 @@ export function createTransformContext(
return
scopes
[
scopes
.
length
-
1
]
return
scopes
[
scopes
.
length
-
1
]
},
},
currentNode
:
root
,
currentNode
:
root
,
inVOnce
:
false
,
// methods
// methods
popScope
()
{
popScope
()
{
return
scopes
.
pop
()
return
scopes
.
pop
()
...
@@ -327,6 +351,9 @@ export function createTransformContext(
...
@@ -327,6 +351,9 @@ export function createTransformContext(
removeId
(
exp
.
content
)
removeId
(
exp
.
content
)
}
}
},
},
cache
(
exp
,
isVNode
=
false
)
{
return
createCacheExpression
(
context
.
cached
++
,
exp
,
isVNode
)
},
}
}
function
addId
(
id
:
string
)
{
function
addId
(
id
:
string
)
{
...
@@ -344,6 +371,20 @@ export function createTransformContext(
...
@@ -344,6 +371,20 @@ export function createTransformContext(
return
context
return
context
}
}
function
createCacheExpression
(
index
:
number
,
value
:
JSChildNode
,
isVNode
:
boolean
=
false
):
CacheExpression
{
return
{
type
:
NodeTypes
.
JS_CACHE_EXPRESSION
,
index
,
value
,
isVNode
,
loc
:
locStub
,
}
}
export
declare
type
StructuralDirectiveTransform
=
(
export
declare
type
StructuralDirectiveTransform
=
(
node
:
ElementNode
,
node
:
ElementNode
,
dir
:
DirectiveNode
,
dir
:
DirectiveNode
,
...
...
packages/uni-mp-compiler/src/transforms/transformElement.ts
0 → 100644
浏览文件 @
f59898be
import
{
NodeTypes
,
ElementTypes
,
createCompilerError
,
ErrorCodes
,
ElementNode
,
isBindKey
,
TemplateLiteral
,
Property
,
ExpressionNode
,
}
from
'
@vue/compiler-core
'
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
export
interface
DirectiveTransformResult
{
props
:
Property
[]
needRuntime
?:
boolean
|
symbol
ssrTagParts
?:
TemplateLiteral
[
'
elements
'
]
}
export
const
transformElement
:
NodeTransform
=
(
node
,
context
)
=>
{
return
function
postTransformElement
()
{
node
=
context
.
currentNode
!
if
(
!
(
node
.
type
===
NodeTypes
.
ELEMENT
&&
(
node
.
tagType
===
ElementTypes
.
ELEMENT
||
node
.
tagType
===
ElementTypes
.
COMPONENT
)
)
)
{
return
}
const
{
props
}
=
node
if
(
props
.
length
>
0
)
{
processProps
(
node
,
context
)
}
}
}
function
processProps
(
node
:
ElementNode
,
context
:
TransformContext
)
{
const
{
tag
,
props
}
=
node
const
isComponent
=
node
.
tagType
===
ElementTypes
.
COMPONENT
for
(
let
i
=
0
;
i
<
props
.
length
;
i
++
)
{
const
prop
=
props
[
i
]
if
(
prop
.
type
===
NodeTypes
.
DIRECTIVE
)
{
// directives
const
{
name
,
arg
,
exp
,
loc
}
=
prop
const
isVBind
=
name
===
'
bind
'
const
isVOn
=
name
===
'
on
'
// skip v-slot - it is handled by its dedicated transform.
if
(
name
===
'
slot
'
)
{
if
(
!
isComponent
)
{
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_SLOT_MISPLACED
,
loc
)
)
}
continue
}
// skip v-once/v-memo - they are handled by dedicated transforms.
if
(
name
===
'
once
'
||
name
===
'
memo
'
)
{
continue
}
// skip v-is and :is on <component>
if
(
name
===
'
is
'
||
(
isVBind
&&
isBindKey
(
arg
,
'
is
'
)
&&
isComponentTag
(
tag
))
)
{
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
)
)
}
}
else
{
context
.
onError
(
createCompilerError
(
isVBind
?
ErrorCodes
.
X_V_BIND_NO_EXPRESSION
:
ErrorCodes
.
X_V_ON_NO_EXPRESSION
,
loc
)
)
}
continue
}
const
directiveTransform
=
context
.
directiveTransforms
[
name
]
if
(
directiveTransform
)
{
const
{
props
}
=
directiveTransform
(
prop
,
node
,
context
)
prop
.
exp
=
props
[
0
].
value
as
ExpressionNode
console
.
log
(
'
prop
'
,
prop
)
}
}
}
}
function
isComponentTag
(
tag
:
string
)
{
return
tag
[
0
].
toLowerCase
()
+
tag
.
slice
(
1
)
===
'
component
'
}
packages/uni-mp-compiler/src/transforms/transformIdentifier.ts
浏览文件 @
f59898be
...
@@ -45,7 +45,6 @@ export const transformIdentifier: NodeTransform = (node, context) => {
...
@@ -45,7 +45,6 @@ export const transformIdentifier: NodeTransform = (node, context) => {
exp
.
content
=
'
*this
'
exp
.
content
=
'
*this
'
continue
continue
}
}
dir
.
exp
=
rewriteExpression
(
exp
,
context
)
dir
.
exp
=
rewriteExpression
(
exp
,
context
)
}
}
}
}
...
...
packages/uni-mp-compiler/src/transforms/vFor.ts
浏览文件 @
f59898be
...
@@ -149,7 +149,7 @@ export const transformFor = createStructuralDirectiveTransform(
...
@@ -149,7 +149,7 @@ export const transformFor = createStructuralDirectiveTransform(
const
id
=
parentScope
.
id
.
next
()
const
id
=
parentScope
.
id
.
next
()
vFor
.
sourceAlias
=
id
vFor
.
sourceAlias
=
id
parentScope
.
properties
.
push
(
parentScope
.
properties
.
push
(
createObjectProperty
(
id
,
createVForCallExpression
(
vForScope
))
createObjectProperty
(
id
,
createVForCallExpression
(
vForScope
,
context
))
)
)
popScope
()
popScope
()
}
}
...
...
packages/uni-mp-compiler/src/transforms/vOn.ts
0 → 100644
浏览文件 @
f59898be
import
{
createCompilerError
,
createCompoundExpression
,
createObjectProperty
,
createSimpleExpression
,
DirectiveNode
,
ElementTypes
,
ErrorCodes
,
ExpressionNode
,
hasScopeRef
,
isMemberExpression
,
NodeTypes
,
SimpleExpressionNode
,
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
{
DirectiveTransform
,
TransformContext
}
from
'
../transform
'
import
{
DirectiveTransformResult
}
from
'
./transformElement
'
import
{
processExpression
}
from
'
./transformExpression
'
const
fnExpRE
=
/^
\s
*
([\w
$_
]
+|
(
async
\s
*
)?\([^
)
]
*
?\))\s
*=>|^
\s
*
(
async
\s
+
)?
function
(?:\s
+
[\w
$
]
+
)?\s
*
\(
/
export
interface
VOnDirectiveNode
extends
DirectiveNode
{
// v-on without arg is handled directly in ./transformElements.ts due to it affecting
// codegen for the entire props object. This transform here is only for v-on
// *with* args.
arg
:
ExpressionNode
// exp is guaranteed to be a simple expression here because v-on w/ arg is
// skipped by transformExpression as a special case.
exp
:
SimpleExpressionNode
|
undefined
}
export
const
transformOn
:
DirectiveTransform
=
(
dir
,
node
,
context
,
augmentor
)
=>
{
const
{
loc
,
modifiers
,
arg
}
=
dir
as
VOnDirectiveNode
if
(
!
dir
.
exp
&&
!
modifiers
.
length
)
{
context
.
onError
(
createCompilerError
(
ErrorCodes
.
X_V_ON_NO_EXPRESSION
,
loc
))
}
let
eventName
:
ExpressionNode
if
(
arg
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
)
{
if
(
arg
.
isStatic
)
{
const
rawName
=
arg
.
content
// for all event listeners, auto convert it to camelCase. See issue #2249
eventName
=
createSimpleExpression
(
toHandlerKey
(
camelize
(
rawName
)),
true
,
arg
.
loc
)
}
else
{
// TODO 不支持动态事件
context
.
onError
(
createCompilerError
(
X_V_ON_DYNAMIC_EVENT
,
loc
,
errorMessages
)
)
// #2388
eventName
=
createCompoundExpression
([
// `${context.helperString(TO_HANDLER_KEY)}(`,
arg
,
// `)`,
])
}
}
else
{
// already a compound expression.
eventName
=
arg
eventName
.
children
.
unshift
(
`
${
context
.
helperString
(
TO_HANDLER_KEY
)}
(`
)
eventName
.
children
.
push
(
`)`
)
}
// handler processing
let
exp
:
ExpressionNode
|
undefined
=
dir
.
exp
as
|
SimpleExpressionNode
|
undefined
if
(
exp
&&
!
exp
.
content
.
trim
())
{
exp
=
undefined
}
let
shouldCache
:
boolean
=
context
.
cacheHandlers
&&
!
exp
&&
!
context
.
inVOnce
if
(
exp
)
{
const
isMemberExp
=
isMemberExpression
(
exp
.
content
,
context
as
any
)
const
isInlineStatement
=
!
(
isMemberExp
||
fnExpRE
.
test
(
exp
.
content
))
const
hasMultipleStatements
=
exp
.
content
.
includes
(
`;`
)
// process the expression since it's been skipped
if
(
context
.
prefixIdentifiers
)
{
isInlineStatement
&&
context
.
addIdentifiers
(
`$event`
)
exp
=
dir
.
exp
=
processExpression
(
exp
,
context
,
false
,
hasMultipleStatements
)
isInlineStatement
&&
context
.
removeIdentifiers
(
`$event`
)
// with scope analysis, the function is hoistable if it has no reference
// to scope variables.
shouldCache
=
context
.
cacheHandlers
&&
// unnecessary to cache inside v-once
!
context
.
inVOnce
&&
// runtime constants don't need to be cached
// (this is analyzed by compileScript in SFC <script setup>)
!
(
exp
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
exp
.
constType
>
0
)
&&
// #1541 bail if this is a member exp handler passed to a component -
// we need to use the original function to preserve arity,
// e.g. <transition> relies on checking cb.length to determine
// transition end handling. Inline function is ok since its arity
// is preserved even when cached.
!
(
isMemberExp
&&
node
.
tagType
===
ElementTypes
.
COMPONENT
)
&&
// bail if the function references closure variables (v-for, v-slot)
// it must be passed fresh to avoid stale values.
!
hasScopeRef
(
exp
,
context
.
identifiers
)
// If the expression is optimizable and is a member expression pointing
// to a function, turn it into invocation (and wrap in an arrow function
// below) so that it always accesses the latest value when called - thus
// avoiding the need to be patched.
if
(
shouldCache
&&
isMemberExp
)
{
if
(
exp
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
)
{
exp
.
content
=
`
${
exp
.
content
}
&&
${
exp
.
content
}
(...args)`
}
else
{
exp
.
children
=
[...
exp
.
children
,
` && `
,
...
exp
.
children
,
`(...args)`
]
}
}
}
if
(
isInlineStatement
||
(
shouldCache
&&
isMemberExp
))
{
// wrap inline statement in a function expression
exp
=
createCompoundExpression
([
`
${
isInlineStatement
?
context
.
isTS
?
`($event: any)`
:
`$event`
:
`
${
context
.
isTS
?
`\n//@ts-ignore\n`
:
``
}
(...args)`
}
=>
${
hasMultipleStatements
?
`{`
:
`(`
}
`
,
exp
,
hasMultipleStatements
?
`}`
:
`)`
,
])
}
}
let
ret
:
DirectiveTransformResult
=
{
props
:
[
createObjectProperty
(
eventName
,
exp
||
createSimpleExpression
(
`() => {}`
,
false
,
loc
)
),
],
}
// apply extended compiler augmentor
if
(
augmentor
)
{
ret
=
augmentor
(
ret
)
}
// TODO
if
(
shouldCache
)
{
// cache handlers so that it's always the same handler being passed down.
// this avoids unnecessary re-renders when users use inline handlers on
// components.
// ret.props[0].value = wrapper(
// context.cache(ret.props[0].value) as ExpressionNode,
// context
// )
ret
.
props
[
0
].
value
=
wrapper
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
context
)
}
else
{
ret
.
props
[
0
].
value
=
wrapper
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
context
)
}
// mark the key as handler for props normalization check
ret
.
props
.
forEach
((
p
)
=>
(
p
.
key
.
isHandlerKey
=
true
))
return
ret
}
function
wrapper
(
value
:
ExpressionNode
,
context
:
TransformContext
)
{
return
createCompoundExpression
([
`
${
context
.
helperString
(
V_ON
)}
(`
,
value
,
`)`
,
])
}
packages/uni-mp-vue/dist/vue.runtime.esm.js
浏览文件 @
f59898be
...
@@ -4951,10 +4951,51 @@ var plugin = {
...
@@ -4951,10 +4951,51 @@ var plugin = {
},
},
};
};
function
vOn
(
value
)
{
const
instance
=
getCurrentInstance
();
const
name
=
'
e
'
+
instance
.
$ei
++
;
const
mpInstance
=
instance
.
ctx
.
$scope
;
if
(
!
value
)
{
// remove
delete
mpInstance
[
name
];
return
name
;
}
const
existingInvoker
=
mpInstance
[
name
];
if
(
existingInvoker
)
{
// patch
existingInvoker
.
value
=
value
;
}
else
{
// add
mpInstance
[
name
]
=
createInvoker
(
value
,
instance
);
}
return
name
;
}
function
createInvoker
(
initialValue
,
instance
)
{
const
invoker
=
(
e
)
=>
{
callWithAsyncErrorHandling
(
patchStopImmediatePropagation
(
e
,
invoker
.
value
),
instance
,
5
/* NATIVE_EVENT_HANDLER */
,
[
e
]);
};
invoker
.
value
=
initialValue
;
return
invoker
;
}
function
patchStopImmediatePropagation
(
e
,
value
)
{
if
(
isArray
(
value
))
{
const
originalStop
=
e
.
stopImmediatePropagation
;
e
.
stopImmediatePropagation
=
()
=>
{
originalStop
&&
originalStop
.
call
(
e
);
e
.
_stopped
=
true
;
};
return
value
.
map
((
fn
)
=>
(
e
)
=>
!
e
.
_stopped
&&
fn
(
e
));
}
else
{
return
value
;
}
}
function
createApp
(
rootComponent
,
rootProps
=
null
)
{
function
createApp
(
rootComponent
,
rootProps
=
null
)
{
rootComponent
&&
(
rootComponent
.
mpType
=
'
app
'
);
rootComponent
&&
(
rootComponent
.
mpType
=
'
app
'
);
return
createVueApp
(
rootComponent
,
rootProps
).
use
(
plugin
);
return
createVueApp
(
rootComponent
,
rootProps
).
use
(
plugin
);
}
}
const
createSSRApp
=
createApp
;
const
createSSRApp
=
createApp
;
export
{
EffectScope
,
ReactiveEffect
,
callWithAsyncErrorHandling
,
callWithErrorHandling
,
computed
,
createApp
,
createSSRApp
,
createVNode$1
as
createVNode
,
createVueApp
,
customRef
,
defineComponent
,
defineEmits
,
defineExpose
,
defineProps
,
effect
,
effectScope
,
getCurrentInstance
,
getCurrentScope
,
inject
,
injectHook
,
isInSSRComponentSetup
,
isProxy
,
isReactive
,
isReadonly
,
isRef
,
logError
,
markRaw
,
mergeDefaults
,
mergeProps
,
nextTick
,
onActivated
,
onBeforeMount
,
onBeforeUnmount
,
onBeforeUpdate
,
onDeactivated
,
onErrorCaptured
,
onMounted
,
onRenderTracked
,
onRenderTriggered
,
onScopeDispose
,
onUnmounted
,
onUpdated
,
provide
,
proxyRefs
,
queuePostFlushCb
,
reactive
,
readonly
,
ref
,
resolveComponent
,
resolveDirective
,
resolveFilter
,
shallowReactive
,
shallowReadonly
,
shallowRef
,
stop
,
toHandlers
,
toRaw
,
toRef
,
toRefs
,
triggerRef
,
unref
,
useAttrs
,
useSSRContext
,
useSlots
,
version
,
warn$1
as
warn
,
watch
,
watchEffect
,
watchPostEffect
,
watchSyncEffect
,
withAsyncContext
,
withCtx
,
withDefaults
,
withDirectives
,
withModifiers
,
withScopeId
};
export
{
EffectScope
,
ReactiveEffect
,
callWithAsyncErrorHandling
,
callWithErrorHandling
,
computed
,
createApp
,
createSSRApp
,
createVNode$1
as
createVNode
,
createVueApp
,
customRef
,
defineComponent
,
defineEmits
,
defineExpose
,
defineProps
,
effect
,
effectScope
,
getCurrentInstance
,
getCurrentScope
,
inject
,
injectHook
,
isInSSRComponentSetup
,
isProxy
,
isReactive
,
isReadonly
,
isRef
,
logError
,
markRaw
,
mergeDefaults
,
mergeProps
,
nextTick
,
onActivated
,
onBeforeMount
,
onBeforeUnmount
,
onBeforeUpdate
,
onDeactivated
,
onErrorCaptured
,
onMounted
,
onRenderTracked
,
onRenderTriggered
,
onScopeDispose
,
onUnmounted
,
onUpdated
,
provide
,
proxyRefs
,
queuePostFlushCb
,
reactive
,
readonly
,
ref
,
resolveComponent
,
resolveDirective
,
resolveFilter
,
shallowReactive
,
shallowReadonly
,
shallowRef
,
stop
,
toHandlers
,
toRaw
,
toRef
,
toRefs
,
triggerRef
,
unref
,
useAttrs
,
useSSRContext
,
useSlots
,
v
On
,
v
ersion
,
warn$1
as
warn
,
watch
,
watchEffect
,
watchPostEffect
,
watchSyncEffect
,
withAsyncContext
,
withCtx
,
withDefaults
,
withDirectives
,
withModifiers
,
withScopeId
};
packages/uni-mp-vue/src/helpers/vOn.ts
0 → 100644
浏览文件 @
f59898be
import
{
isArray
}
from
'
@vue/shared
'
import
{
callWithAsyncErrorHandling
,
ComponentInternalInstance
,
ErrorCodes
,
getCurrentInstance
,
}
from
'
vue
'
type
EventValue
=
Function
|
Function
[]
interface
Invoker
extends
EventListener
{
value
:
EventValue
}
export
function
vOn
(
value
:
EventValue
|
undefined
)
{
const
instance
=
getCurrentInstance
()
!
as
unknown
as
{
$ei
:
number
ctx
:
{
$scope
:
Record
<
string
,
any
>
}
}
const
name
=
'
e
'
+
instance
.
$ei
++
const
mpInstance
=
instance
.
ctx
.
$scope
if
(
!
value
)
{
// remove
delete
mpInstance
[
name
]
return
name
}
const
existingInvoker
=
mpInstance
[
name
]
as
Invoker
if
(
existingInvoker
)
{
// patch
existingInvoker
.
value
=
value
}
else
{
// add
mpInstance
[
name
]
=
createInvoker
(
value
,
instance
as
unknown
as
ComponentInternalInstance
)
}
return
name
}
function
createInvoker
(
initialValue
:
EventValue
,
instance
:
ComponentInternalInstance
|
null
)
{
const
invoker
:
Invoker
=
(
e
:
Event
)
=>
{
callWithAsyncErrorHandling
(
patchStopImmediatePropagation
(
e
,
invoker
.
value
),
instance
,
ErrorCodes
.
NATIVE_EVENT_HANDLER
,
[
e
]
)
}
invoker
.
value
=
initialValue
return
invoker
}
function
patchStopImmediatePropagation
(
e
:
Event
,
value
:
EventValue
):
EventValue
{
if
(
isArray
(
value
))
{
const
originalStop
=
e
.
stopImmediatePropagation
e
.
stopImmediatePropagation
=
()
=>
{
originalStop
&&
originalStop
.
call
(
e
)
;(
e
as
any
).
_stopped
=
true
}
return
value
.
map
((
fn
)
=>
(
e
:
Event
)
=>
!
(
e
as
any
).
_stopped
&&
fn
(
e
))
}
else
{
return
value
}
}
packages/uni-mp-vue/src/index.ts
浏览文件 @
f59898be
...
@@ -5,6 +5,7 @@ export function createApp(rootComponent: unknown, rootProps = null) {
...
@@ -5,6 +5,7 @@ export function createApp(rootComponent: unknown, rootProps = null) {
rootComponent
&&
((
rootComponent
as
any
).
mpType
=
'
app
'
)
rootComponent
&&
((
rootComponent
as
any
).
mpType
=
'
app
'
)
return
createVueApp
(
rootComponent
,
rootProps
).
use
(
plugin
)
return
createVueApp
(
rootComponent
,
rootProps
).
use
(
plugin
)
}
}
export
{
vOn
}
from
'
./helpers/vOn
'
export
const
createSSRApp
=
createApp
export
const
createSSRApp
=
createApp
// @ts-ignore
// @ts-ignore
export
*
from
'
../lib/vue.runtime.esm.js
'
export
*
from
'
../lib/vue.runtime.esm.js
'
packages/uni-stat/dist/uni-stat.cjs.js
浏览文件 @
f59898be
'
use strict
'
;
'
use strict
'
;
var
version
=
"
3.0.0-alpha-302102021101200
4
"
;
var
version
=
"
3.0.0-alpha-302102021101200
5
"
;
const
STAT_VERSION
=
version
;
const
STAT_VERSION
=
version
;
const
STAT_URL
=
'
https://tongji.dcloud.io/uni/stat
'
;
const
STAT_URL
=
'
https://tongji.dcloud.io/uni/stat
'
;
...
...
packages/uni-stat/dist/uni-stat.es.js
浏览文件 @
f59898be
var
version
=
"
3.0.0-alpha-302102021101200
4
"
;
var
version
=
"
3.0.0-alpha-302102021101200
5
"
;
const
STAT_VERSION
=
version
;
const
STAT_VERSION
=
version
;
const
STAT_URL
=
'
https://tongji.dcloud.io/uni/stat
'
;
const
STAT_URL
=
'
https://tongji.dcloud.io/uni/stat
'
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录