Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
uni-app
提交
7d7f03b2
U
uni-app
项目概览
DCloud
/
uni-app
5 天 前同步成功
通知
815
Star
38709
Fork
3642
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
8
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
8
Issue
8
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
7d7f03b2
编写于
12月 20, 2023
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(uvue): transformExpression 支持 inline (增加 transformExpression.spec.ts)
上级
b96e1206
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
777 addition
and
11 deletion
+777
-11
packages/uni-app-uts/__tests__/android/transforms/__snapshots__/transformExpressions.spec.ts.snap
...ransforms/__snapshots__/transformExpressions.spec.ts.snap
+35
-0
packages/uni-app-uts/__tests__/android/transforms/transformExpressions.spec.ts
...__tests__/android/transforms/transformExpressions.spec.ts
+629
-0
packages/uni-app-uts/src/plugins/android/uvue/compiler/transforms/transformExpression.ts
...s/android/uvue/compiler/transforms/transformExpression.ts
+113
-11
未找到文件。
packages/uni-app-uts/__tests__/android/transforms/__snapshots__/transformExpressions.spec.ts.snap
0 → 100644
浏览文件 @
7d7f03b2
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`compiler: expression transform bindingMetadata inline mode 1`] = `"createElementVNode("view", null, toDisplayString(__props.props) + " " + toDisplayString(unref(setup)) + " " + toDisplayString(setupConst) + " " + toDisplayString(_ctx.data) + " " + toDisplayString(_ctx.options) + " " + toDisplayString(isNaN), 1 /* TEXT */)"`;
exports[`compiler: expression transform bindingMetadata non-inline mode 1`] = `"createElementVNode("view", null, toDisplayString($props.props) + " " + toDisplayString($setup.setup) + " " + toDisplayString($data.data) + " " + toDisplayString($options.options) + " " + toDisplayString(isNaN), 1 /* TEXT */)"`;
exports[`compiler: expression transform bindingMetadata should not prefix temp variable of for loop 1`] = `
"createVNode(_component_div, utsMapOf({
onClick: () => {
for (let i = 0; i < _ctx.list.length; i++) {
_ctx.log(i)
}
}
}), null, 8 /* PROPS */, ["onClick"])"
`;
exports[`compiler: expression transform bindingMetadata should not prefix temp variable of for...in 1`] = `
"createVNode(_component_div, utsMapOf({
onClick: () => {
for (const x in _ctx.list) {
_ctx.log(x)
}
}
}), null, 8 /* PROPS */, ["onClick"])"
`;
exports[`compiler: expression transform bindingMetadata should not prefix temp variable of for...of 1`] = `
"createVNode(_component_div, utsMapOf({
onClick: () => {
for (const x of _ctx.list) {
_ctx.log(x)
}
}
}), null, 8 /* PROPS */, ["onClick"])"
`;
packages/uni-app-uts/__tests__/android/transforms/transformExpressions.spec.ts
0 → 100644
浏览文件 @
7d7f03b2
// import { PatchFlagNames, PatchFlags } from '@vue/shared'
import
{
BindingTypes
,
ConstantTypes
,
DirectiveNode
,
ElementNode
,
InterpolationNode
,
NodeTypes
,
baseParse
as
parse
,
}
from
'
@vue/compiler-core
'
import
{
transform
}
from
'
../../../src/plugins/android/uvue/compiler/transform
'
import
{
transformIf
}
from
'
../../../src/plugins/android/uvue/compiler/transforms/vIf
'
import
{
transformExpression
}
from
'
../../../src/plugins/android/uvue/compiler/transforms/transformExpression
'
import
{
compile
as
baseCompile
}
from
'
../../../src/plugins/android/uvue/compiler
'
import
{
TemplateCompilerOptions
}
from
'
../../../src/plugins/android/uvue/compiler/options
'
function
parseWithExpressionTransform
(
template
:
string
,
options
:
TemplateCompilerOptions
=
{}
)
{
const
ast
=
parse
(
template
)
transform
(
ast
,
{
prefixIdentifiers
:
true
,
nodeTransforms
:
[
transformIf
,
transformExpression
],
...
options
,
})
return
ast
.
children
[
0
]
}
describe
(
'
compiler: expression transform
'
,
()
=>
{
test
(
'
interpolation (root)
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ foo }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`_ctx.foo`
,
})
})
test
(
'
empty interpolation
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{}}`
)
as
InterpolationNode
const
node2
=
parseWithExpressionTransform
(
`{{ }}`
)
as
InterpolationNode
const
node3
=
parseWithExpressionTransform
(
`<view>{{ }}</view>`
)
as
ElementNode
const
objectToBeMatched
=
{
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
``
,
}
expect
(
node
.
content
).
toMatchObject
(
objectToBeMatched
)
expect
(
node2
.
content
).
toMatchObject
(
objectToBeMatched
)
expect
((
node3
.
children
[
0
]
as
InterpolationNode
).
content
).
toMatchObject
(
objectToBeMatched
)
})
test
(
'
interpolation (children)
'
,
()
=>
{
const
el
=
parseWithExpressionTransform
(
`<view>{{ foo }}</view>`
)
as
ElementNode
const
node
=
el
.
children
[
0
]
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`_ctx.foo`
,
})
})
test
(
'
interpolation (complex)
'
,
()
=>
{
const
el
=
parseWithExpressionTransform
(
`<view>{{ foo + bar(baz.qux) }}</view>`
)
as
ElementNode
const
node
=
el
.
children
[
0
]
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
{
content
:
`_ctx.foo`
},
` + `
,
{
content
:
`_ctx.bar`
},
`(`
,
{
content
:
`_ctx.baz`
},
`.`
,
{
content
:
`qux`
},
`)`
,
],
})
})
test
(
'
directive value
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`<div v-foo:arg="baz"/>`
)
as
ElementNode
const
arg
=
(
node
.
props
[
0
]
as
DirectiveNode
).
arg
!
expect
(
arg
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`arg`
,
})
const
exp
=
(
node
.
props
[
0
]
as
DirectiveNode
).
exp
!
expect
(
exp
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`_ctx.baz`
,
})
})
test
(
'
dynamic directive arg
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`<div v-foo:[arg]="baz"/>`
)
as
ElementNode
const
arg
=
(
node
.
props
[
0
]
as
DirectiveNode
).
arg
!
expect
(
arg
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`_ctx.arg`
,
})
const
exp
=
(
node
.
props
[
0
]
as
DirectiveNode
).
exp
!
expect
(
exp
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`_ctx.baz`
,
})
})
test
(
'
should prefix complex expressions
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ foo(baz + 1, { key: kuz }) }}`
)
as
InterpolationNode
// should parse into compound expression
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
{
content
:
`_ctx.foo`
,
loc
:
{
source
:
`foo`
,
start
:
{
offset
:
3
,
line
:
1
,
column
:
4
,
},
end
:
{
offset
:
6
,
line
:
1
,
column
:
7
,
},
},
},
`(`
,
{
content
:
`_ctx.baz`
,
loc
:
{
source
:
`baz`
,
start
:
{
offset
:
7
,
line
:
1
,
column
:
8
,
},
end
:
{
offset
:
10
,
line
:
1
,
column
:
11
,
},
},
},
` + 1, { key: `
,
{
content
:
`_ctx.kuz`
,
loc
:
{
source
:
`kuz`
,
start
:
{
offset
:
23
,
line
:
1
,
column
:
24
,
},
end
:
{
offset
:
26
,
line
:
1
,
column
:
27
,
},
},
},
` })`
,
],
})
})
test
(
'
should not prefix whitelisted globals
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ Math.max(1, 2) }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[{
content
:
`Math`
},
`.`
,
{
content
:
`max`
},
`(1, 2)`
],
})
})
test
(
'
should not prefix reserved literals
'
,
()
=>
{
function
assert
(
exp
:
string
)
{
const
node
=
parseWithExpressionTransform
(
`{{
${
exp
}
}}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
exp
,
})
}
assert
(
`true`
)
assert
(
`false`
)
assert
(
`null`
)
assert
(
`this`
)
})
test
(
'
should not prefix id of a function declaration
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ function foo() { return bar } }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`function `
,
{
content
:
`foo`
},
`() { return `
,
{
content
:
`_ctx.bar`
},
` }`
,
],
})
})
test
(
'
should not prefix params of a function expression
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ foo => foo + bar }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
{
content
:
`foo`
},
` => `
,
{
content
:
`foo`
},
` + `
,
{
content
:
`_ctx.bar`
},
],
})
})
test
(
'
should prefix default value of a function expression param
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ (foo = baz) => foo + bar }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`(`
,
{
content
:
`foo`
},
` = `
,
{
content
:
`_ctx.baz`
},
`) => `
,
{
content
:
`foo`
},
` + `
,
{
content
:
`_ctx.bar`
},
],
})
})
test
(
'
should not prefix function param destructuring
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ ({ foo }) => foo + bar }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`({ `
,
{
content
:
`foo`
},
` }) => `
,
{
content
:
`foo`
},
` + `
,
{
content
:
`_ctx.bar`
},
],
})
})
test
(
'
function params should not affect out of scope identifiers
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ { a: foo => foo, b: foo } }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`{ a: `
,
{
content
:
`foo`
},
` => `
,
{
content
:
`foo`
},
`, b: `
,
{
content
:
`_ctx.foo`
},
` }`
,
],
})
})
test
(
'
should prefix default value of function param destructuring
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ ({ foo = bar }) => foo + bar }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`({ `
,
{
content
:
`foo`
},
` = `
,
{
content
:
`_ctx.bar`
},
` }) => `
,
{
content
:
`foo`
},
` + `
,
{
content
:
`_ctx.bar`
},
],
})
})
test
(
'
should not prefix an object property key
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ { foo() { baz() }, value: bar } }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`{ foo() { `
,
{
content
:
`_ctx.baz`
},
`() }, value: `
,
{
content
:
`_ctx.bar`
},
` }`
,
],
})
})
test
(
'
should not duplicate object key with same name as value
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ { foo: foo } }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`{ foo: `
,
{
content
:
`_ctx.foo`
},
` }`
],
})
})
test
(
'
should prefix a computed object property key
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ { [foo]: bar } }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`{ [`
,
{
content
:
`_ctx.foo`
},
`]: `
,
{
content
:
`_ctx.bar`
},
` }`
,
],
})
})
test
(
'
should prefix object property shorthand value
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ { foo } }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`{ foo: `
,
{
content
:
`_ctx.foo`
},
` }`
],
})
})
test
(
'
should not prefix id in a member expression
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ foo.bar.baz }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
{
content
:
`_ctx.foo`
},
`.`
,
{
content
:
`bar`
},
`.`
,
{
content
:
`baz`
},
],
})
})
test
(
'
should prefix computed id in a member expression
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ foo[bar][baz] }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
{
content
:
`_ctx.foo`
},
`[`
,
{
content
:
`_ctx.bar`
},
`][`
,
{
content
:
'
_ctx.baz
'
},
`]`
,
],
})
})
test
(
'
should handle parse error
'
,
()
=>
{
// const onError = vi.fn()
// parseWithExpressionTransform(`{{ a( }}`, { onError })
// expect(onError.mock.calls[0][0].message).toMatch(
// `Error parsing JavaScript expression: Unexpected token`
// )
})
test
(
'
should prefix in assignment
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ x = 1 }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[{
content
:
`_ctx.x`
},
` = 1`
],
})
})
test
(
'
should prefix in assignment pattern
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ { x, y: [z] } = obj }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
`{ x: `
,
{
content
:
`_ctx.x`
},
`, y: [`
,
{
content
:
`_ctx.z`
},
`] } = `
,
{
content
:
`_ctx.obj`
},
],
})
})
// #8295
test
(
'
should treat floating point number literals as constant
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ [1, 2.1] }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
constType
:
ConstantTypes
.
CAN_STRINGIFY
,
})
})
describe
(
'
ES Proposals support
'
,
()
=>
{
test
(
'
bigInt
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ 13000n }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
SIMPLE_EXPRESSION
,
content
:
`13000n`
,
isStatic
:
false
,
constType
:
ConstantTypes
.
CAN_STRINGIFY
,
})
})
test
(
'
nullish coalescing
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ a ?? b }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[{
content
:
`_ctx.a`
},
` ?? `
,
{
content
:
`_ctx.b`
}],
})
})
test
(
'
optional chaining
'
,
()
=>
{
const
node
=
parseWithExpressionTransform
(
`{{ a?.b?.c }}`
)
as
InterpolationNode
expect
(
node
.
content
).
toMatchObject
({
type
:
NodeTypes
.
COMPOUND_EXPRESSION
,
children
:
[
{
content
:
`_ctx.a`
},
`?.`
,
{
content
:
`b`
},
`?.`
,
{
content
:
`c`
},
],
})
})
test
(
'
Enabling additional plugins
'
,
()
=>
{
// enabling pipeline operator to replace filters:
// const node = parseWithExpressionTransform(`{{ a |> uppercase }}`, {
// expressionPlugins: [
// [
// 'pipelineOperator',
// {
// proposal: 'minimal',
// },
// ],
// ],
// }) as InterpolationNode
// expect(node.content).toMatchObject({
// type: NodeTypes.COMPOUND_EXPRESSION,
// children: [
// { content: `_ctx.a` },
// ` |> `,
// { content: `_ctx.uppercase` },
// ],
// })
})
})
describe
(
'
bindingMetadata
'
,
()
=>
{
const
bindingMetadata
=
{
props
:
BindingTypes
.
PROPS
,
setup
:
BindingTypes
.
SETUP_MAYBE_REF
,
setupConst
:
BindingTypes
.
SETUP_CONST
,
data
:
BindingTypes
.
DATA
,
options
:
BindingTypes
.
OPTIONS
,
reactive
:
BindingTypes
.
SETUP_REACTIVE_CONST
,
literal
:
BindingTypes
.
LITERAL_CONST
,
isNaN
:
BindingTypes
.
SETUP_REF
,
}
function
compileWithBindingMetadata
(
template
:
string
,
options
?:
TemplateCompilerOptions
)
{
return
baseCompile
(
template
,
{
prefixIdentifiers
:
true
,
bindingMetadata
,
...
options
,
})
}
test
(
'
non-inline mode
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<view>{{ props }} {{ setup }} {{ data }} {{ options }} {{ isNaN }}</view>`
)
expect
(
code
).
toMatch
(
`$props.props`
)
expect
(
code
).
toMatch
(
`$setup.setup`
)
// expect(code).toMatch(`$setup.isNaN`)
expect
(
code
).
toMatch
(
`$data.data`
)
expect
(
code
).
toMatch
(
`$options.options`
)
// expect(code).toMatch(`_ctx, _cache, $props, $setup, $data, $options`)
expect
(
code
).
toMatchSnapshot
()
})
test
(
'
should not prefix temp variable of for...in
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<div @click="() => {
for (const x in list) {
log(x)
}
}"/>`
)
expect
(
code
).
not
.
toMatch
(
`_ctx.x`
)
expect
(
code
).
toMatchSnapshot
()
})
test
(
'
should not prefix temp variable of for...of
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<div @click="() => {
for (const x of list) {
log(x)
}
}"/>`
)
expect
(
code
).
not
.
toMatch
(
`_ctx.x`
)
expect
(
code
).
toMatchSnapshot
()
})
test
(
'
should not prefix temp variable of for loop
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<div @click="() => {
for (let i = 0; i < list.length; i++) {
log(i)
}
}"/>`
)
expect
(
code
).
not
.
toMatch
(
`_ctx.i`
)
expect
(
code
).
toMatchSnapshot
()
})
test
(
'
inline mode
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<view>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</view>`
,
{
inline
:
true
}
)
expect
(
code
).
toMatch
(
`__props.props`
)
expect
(
code
).
toMatch
(
`unref(setup)`
)
expect
(
code
).
toMatch
(
`toDisplayString(setupConst)`
)
expect
(
code
).
toMatch
(
`_ctx.data`
)
expect
(
code
).
toMatch
(
`_ctx.options`
)
// isNaN 设置了全局方法
// expect(code).toMatch(`isNaN.value`)
expect
(
code
).
toMatchSnapshot
()
})
test
(
'
literal const handling
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<view>{{ literal }}</view>`
,
{
inline
:
true
,
}
)
expect
(
code
).
toMatch
(
`toDisplayString(literal)`
)
// #7973 should skip patch for literal const
// TODO
// expect(code).not.toMatch(
// `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
// )
})
test
(
'
literal const handling, non-inline mode
'
,
()
=>
{
const
{
code
}
=
compileWithBindingMetadata
(
`<view>{{ literal }}</view>`
)
expect
(
code
).
toMatch
(
`toDisplayString($setup.literal)`
)
// #7973 should skip patch for literal const
// TODO
// expect(code).not.toMatch(
// `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
// )
})
test
(
'
reactive const handling
'
,
()
=>
{
// const { code } = compileWithBindingMetadata(`<view>{{ reactive }}</view>`, {
// inline: true,
// })
// #7973 should not skip patch for reactive const
// TODO
// expect(code).toMatch(
// `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
// )
})
})
})
packages/uni-app-uts/src/plugins/android/uvue/compiler/transforms/transformExpression.ts
浏览文件 @
7d7f03b2
...
@@ -9,8 +9,13 @@
...
@@ -9,8 +9,13 @@
// support and the code is wrapped in `with (this) { ... }`.
// support and the code is wrapped in `with (this) { ... }`.
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
import
{
NodeTransform
,
TransformContext
}
from
'
../transform
'
import
{
makeMap
,
hasOwn
,
isString
}
from
'
@vue/shared
'
import
{
makeMap
,
hasOwn
,
isString
,
genPropsAccessExp
}
from
'
@vue/shared
'
import
{
Node
,
Identifier
}
from
'
@babel/types
'
import
{
Node
,
Identifier
,
UpdateExpression
,
AssignmentExpression
,
}
from
'
@babel/types
'
import
{
parse
}
from
'
@babel/parser
'
import
{
parse
}
from
'
@babel/parser
'
import
{
import
{
...
@@ -21,11 +26,14 @@ import {
...
@@ -21,11 +26,14 @@ import {
createCompoundExpression
,
createCompoundExpression
,
createSimpleExpression
,
createSimpleExpression
,
ExpressionNode
,
ExpressionNode
,
IS_REF
,
isInDestructureAssignment
,
isSimpleIdentifier
,
isSimpleIdentifier
,
isStaticProperty
,
isStaticProperty
,
isStaticPropertyKey
,
isStaticPropertyKey
,
NodeTypes
,
NodeTypes
,
SimpleExpressionNode
,
SimpleExpressionNode
,
UNREF
,
walkIdentifiers
,
walkIdentifiers
,
}
from
'
@vue/compiler-core
'
}
from
'
@vue/compiler-core
'
...
@@ -40,6 +48,10 @@ const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED)
...
@@ -40,6 +48,10 @@ const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED)
const
isLiteralWhitelisted
=
/*#__PURE__*/
makeMap
(
'
true,false,null,this
'
)
const
isLiteralWhitelisted
=
/*#__PURE__*/
makeMap
(
'
true,false,null,this
'
)
// a heuristic safeguard to bail constant expressions on presence of
// likely function invocation and member access
const
constantBailRE
=
/
\w\s
*
\(
|
\.[^\d]
/
export
const
transformExpression
:
NodeTransform
=
(
node
,
context
)
=>
{
export
const
transformExpression
:
NodeTransform
=
(
node
,
context
)
=>
{
if
(
node
.
type
===
NodeTypes
.
INTERPOLATION
)
{
if
(
node
.
type
===
NodeTypes
.
INTERPOLATION
)
{
node
.
content
=
processExpression
(
node
.
content
=
processExpression
(
...
@@ -101,16 +113,100 @@ export function processExpression(
...
@@ -101,16 +113,100 @@ export function processExpression(
return
node
return
node
}
}
const
{
bindingMetadata
}
=
context
const
{
inline
,
bindingMetadata
}
=
context
const
rewriteIdentifier
=
(
raw
:
string
,
parent
?:
Node
,
id
?:
Identifier
)
=>
{
const
rewriteIdentifier
=
(
raw
:
string
,
parent
?:
Node
,
id
?:
Identifier
)
=>
{
const
type
=
hasOwn
(
bindingMetadata
,
raw
)
&&
bindingMetadata
[
raw
]
const
type
=
hasOwn
(
bindingMetadata
,
raw
)
&&
bindingMetadata
[
raw
]
if
(
type
&&
type
.
startsWith
(
'
setup
'
))
{
if
(
inline
)
{
// setup bindings in non-inline mode
// x = y
return
`$setup.
${
raw
}
`
const
isAssignmentLVal
=
}
else
if
(
type
===
BindingTypes
.
PROPS_ALIASED
)
{
parent
&&
parent
.
type
===
'
AssignmentExpression
'
&&
parent
.
left
===
id
return
`$props['
${
bindingMetadata
.
__propsAliases
!
[
raw
]}
']`
// x++
}
else
if
(
type
)
{
const
isUpdateArg
=
return
`$
${
type
}
.
${
raw
}
`
parent
&&
parent
.
type
===
'
UpdateExpression
'
&&
parent
.
argument
===
id
// ({ x } = y)
const
isDestructureAssignment
=
parent
&&
isInDestructureAssignment
(
parent
,
parentStack
)
if
(
isConst
(
type
)
||
type
===
BindingTypes
.
SETUP_REACTIVE_CONST
||
localVars
[
raw
]
)
{
return
raw
}
else
if
(
type
===
BindingTypes
.
SETUP_REF
)
{
return
`
${
raw
}
.value`
}
else
if
(
type
===
BindingTypes
.
SETUP_MAYBE_REF
)
{
// const binding that may or may not be ref
// if it's not a ref, then assignments don't make sense -
// so we ignore the non-ref assignment case and generate code
// that assumes the value to be a ref for more efficiency
return
isAssignmentLVal
||
isUpdateArg
||
isDestructureAssignment
?
`
${
raw
}
.value`
:
`
${
context
.
helperString
(
UNREF
)}
(
${
raw
}
)`
}
else
if
(
type
===
BindingTypes
.
SETUP_LET
)
{
if
(
isAssignmentLVal
)
{
// let binding.
// this is a bit more tricky as we need to cover the case where
// let is a local non-ref value, and we need to replicate the
// right hand side value.
// x = y --> isRef(x) ? x.value = y : x = y
const
{
right
:
rVal
,
operator
}
=
parent
as
AssignmentExpression
const
rExp
=
rawExp
.
slice
(
rVal
.
start
!
-
1
,
rVal
.
end
!
-
1
)
const
rExpString
=
stringifyExpression
(
processExpression
(
createSimpleExpression
(
rExp
,
false
),
context
,
false
,
false
,
knownIds
)
)
return
`
${
context
.
helperString
(
IS_REF
)}
(
${
raw
}
) ?
${
raw
}
.value
${
operator
}
${
rExpString
}
:
${
raw
}
`
}
else
if
(
isUpdateArg
)
{
// make id replace parent in the code range so the raw update operator
// is removed
id
!
.
start
=
parent
!
.
start
id
!
.
end
=
parent
!
.
end
const
{
prefix
:
isPrefix
,
operator
}
=
parent
as
UpdateExpression
const
prefix
=
isPrefix
?
operator
:
``
const
postfix
=
isPrefix
?
``
:
operator
// let binding.
// x++ --> isRef(a) ? a.value++ : a++
return
`
${
context
.
helperString
(
IS_REF
)}
(
${
raw
}
) ?
${
prefix
}${
raw
}
.value
${
postfix
}
:
${
prefix
}${
raw
}${
postfix
}
`
}
else
if
(
isDestructureAssignment
)
{
// TODO
// let binding in a destructure assignment - it's very tricky to
// handle both possible cases here without altering the original
// structure of the code, so we just assume it's not a ref here
// for now
return
raw
}
else
{
return
`
${
context
.
helperString
(
UNREF
)}
(
${
raw
}
)`
}
}
else
if
(
type
===
BindingTypes
.
PROPS
)
{
// use __props which is generated by compileScript so in ts mode
// it gets correct type
return
genPropsAccessExp
(
raw
)
}
else
if
(
type
===
BindingTypes
.
PROPS_ALIASED
)
{
// prop with a different local alias (from defineProps() destructure)
return
genPropsAccessExp
(
bindingMetadata
.
__propsAliases
!
[
raw
])
}
}
else
{
if
(
(
type
&&
type
.
startsWith
(
'
setup
'
))
||
type
===
BindingTypes
.
LITERAL_CONST
)
{
// setup bindings in non-inline mode
return
`$setup.
${
raw
}
`
}
else
if
(
type
===
BindingTypes
.
PROPS_ALIASED
)
{
return
`$props['
${
bindingMetadata
.
__propsAliases
!
[
raw
]}
']`
}
else
if
(
type
)
{
return
`$
${
type
}
.
${
raw
}
`
}
}
}
// fallback to ctx
// fallback to ctx
return
`_ctx.
${
raw
}
`
return
`_ctx.
${
raw
}
`
...
@@ -119,7 +215,7 @@ export function processExpression(
...
@@ -119,7 +215,7 @@ export function processExpression(
// fast path if expression is a simple identifier.
// fast path if expression is a simple identifier.
const
rawExp
=
node
.
content
const
rawExp
=
node
.
content
// bail constant on parens (function invocation) and dot (member access)
// bail constant on parens (function invocation) and dot (member access)
const
bailConstant
=
rawExp
.
indexOf
(
`(`
)
>
-
1
||
rawExp
.
indexOf
(
'
.
'
)
>
0
const
bailConstant
=
constantBailRE
.
test
(
rawExp
)
if
(
isSimpleIdentifier
(
rawExp
))
{
if
(
isSimpleIdentifier
(
rawExp
))
{
const
isScopeVarReference
=
context
.
identifiers
[
rawExp
]
const
isScopeVarReference
=
context
.
identifiers
[
rawExp
]
...
@@ -275,3 +371,9 @@ export function stringifyExpression(exp: ExpressionNode | string): string {
...
@@ -275,3 +371,9 @@ export function stringifyExpression(exp: ExpressionNode | string): string {
.
join
(
''
)
.
join
(
''
)
}
}
}
}
function
isConst
(
type
:
unknown
)
{
return
(
type
===
BindingTypes
.
SETUP_CONST
||
type
===
BindingTypes
.
LITERAL_CONST
)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录