Skip to content

Commit 5f7319f

Browse files
committed
fix: fix some js widget and lite widget expression result bugs
Signed-off-by: lileirjyb <[email protected]>
1 parent e7a8d5d commit 5f7319f

File tree

3 files changed

+100
-96
lines changed

3 files changed

+100
-96
lines changed

packages/hap-packager/src/post-handler/js-card-post.js

Lines changed: 14 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
* Copyright (c) 2024-present, the hapjs-platform Project Contributors
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5-
5+
import {
6+
isExpr,
7+
isFunctionStr,
8+
isObject,
9+
isConstObjOrArray,
10+
isSimpleArr,
11+
isSimplePath
12+
} from './utils'
613
import { templater } from '@hap-toolkit/compiler'
714
const { validator } = templater
815

@@ -11,11 +18,6 @@ const TYPE_IMPORT = 'import'
1118
// 需要进行后处理的模块key
1219
const TEMPLATE_KEY = 'template'
1320

14-
const pathTestRE =
15-
/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/
16-
17-
const literalValueRE = /^(?:true|false|null|undefined|Infinity|NaN)$/
18-
1921
// 节点标记,同一节点可能同时符合多个kind定义,按priority高的进行标记
2022
const ENUM_KIND_TYPE = {
2123
ELEMENT: {
@@ -235,69 +237,26 @@ function markAttr(template) {
235237
}
236238
}
237239

238-
function isExpr(val) {
239-
if (!val) return false
240-
return validator.isExpr(val)
241-
}
242-
243-
function isFunctionStr(str) {
244-
const pattern = /^\s*function\s*\([\w\s,$]*\)\s*\{[\s\S]*\}\s*$/
245-
return pattern.test(str.trim())
246-
}
247-
248-
function isObject(obj) {
249-
return obj && Object.prototype.toString.call(obj) === '[object Object]' && obj !== null
250-
}
251-
252240
function getExprRes(exprRaw, expr) {
253241
const tokens = validator.parseText(exprRaw.trim())
254242
if (tokens.length > 1) {
255243
return expr
256244
}
257245

258246
const parsed = tokens[0].value
259-
if (isObjOrArray(parsed) || (isSimplePath(parsed) && isSimpleArr(parsed))) {
260-
// 简单表达式
261-
// 目前只有 {{name}}、{{title.name}}、{{title[0]}}、{{[1,2,3]}}、{{ {a: 1} }} 算作简单表达式
247+
if (isConstObjOrArray(parsed)) {
248+
// 简单表达式 {{ [1,2,3] }}、{{ {a: 1} }}
249+
// eslint-disable-next-line no-eval
250+
return eval(`(${parsed})`)
251+
} else if (isSimplePath(parsed) && isSimpleArr(parsed)) {
252+
// 简单表达式 {{name}}、{{title.name}}、{{title['name']}}、{{title[0]}}
262253
return parsed // {{ name }} -> name
263254
} else {
264255
// 复杂表达式,返回function形式的表达式结果
265256
return expr // {{a + b}} -> function () { return this.a + this.b }
266257
}
267258
}
268259

269-
function isObjOrArray(exp) {
270-
return Object.prototype.toString.call(exp) === '[object Object]' || Array.isArray(exp)
271-
}
272-
function isSimpleArr(exp) {
273-
// eslint-disable-next-line no-useless-escape
274-
const regex = /\[([^\[\]]+)\]/g
275-
let match
276-
const results = []
277-
278-
while ((match = regex.exec(exp)) !== null) {
279-
results.push(match[1])
280-
}
281-
282-
let res = true
283-
// 检查所有[]匹配项是否全部为数字或常量字符串
284-
results.forEach((content) => {
285-
if (!/^\d+$/.test(content) && !/^('|")(.*)\1$/.test(content)) {
286-
res = false
287-
}
288-
})
289-
return res
290-
}
291-
function isSimplePath(exp) {
292-
return (
293-
pathTestRE.test(exp) &&
294-
// true/false/null/undefined/Infinity/NaN
295-
!literalValueRE.test(exp) &&
296-
// Math常量
297-
exp.slice(0, 5) !== 'Math.'
298-
)
299-
}
300-
301260
export function postHandleJSCardRes(JsCardRes) {
302261
const uxList = Object.keys(JsCardRes)
303262

packages/hap-packager/src/post-handler/lite-card-post.js

Lines changed: 23 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
*/
55

66
import { templateValueToCardCode } from '@aiot-toolkit/card-expression'
7+
import { isExpr, isObject, isConstObjOrArray, isSimpleArr, isSimplePath } from './utils'
78
import { templater } from '@hap-toolkit/compiler'
89
const { validator } = templater
910

1011
const TYPE_IMPORT = 'import'
1112
// 需要进行后处理的模块key
1213
const TEMPLATE_KEY = 'template'
1314
const ACTIONS_KEY = 'actions'
14-
const SIMPLE_EXPR_MODIFIERS = ['$', '.', '[]', '~', '{}']
1515

1616
// 节点标记,同一节点可能同时符合多个kind定义,按priority高的进行标记
1717
const ENUM_KIND_TYPE = {
@@ -334,52 +334,34 @@ function markAttr(template) {
334334
}
335335
}
336336

337-
function isExpr(val) {
338-
if (!val) return false
339-
return validator.isExpr(val)
340-
}
341-
342-
function isObject(obj) {
343-
return obj && Object.prototype.toString.call(obj) === '[object Object]' && obj !== null
344-
}
337+
function getExprRes(exprRaw) {
338+
const tokens = validator.parseText(exprRaw.trim())
339+
if (tokens.length > 1) {
340+
return exprRaw
341+
}
345342

346-
function getPrefixExpr(expr) {
347-
const res = templateValueToCardCode(expr)
348-
const parsed = JSON.parse(res)
349-
if (isSimpleExpr(parsed)) {
350-
// 简单表达式
351-
// 目前只有 {{name}}、{{title.name}}、{{title[0]}}、{{[1,2,3]}}、{{ {a: 1} }} 算作简单表达式
352-
return {
353-
rawExpr: validator.parseText(expr)[0].value, // {{ name }} -> name
354-
prefixExpr: parsed // {{ name }} -> ['$', 'name']
355-
}
343+
const parsed = tokens[0].value
344+
if (isConstObjOrArray(parsed)) {
345+
// 简单表达式 {{ [1,2,3] }}、{{ {a: 1} }}
346+
// eslint-disable-next-line no-eval
347+
return eval(`(${parsed})`)
348+
} else if (isSimplePath(parsed) && isSimpleArr(parsed)) {
349+
// 简单表达式 {{name}}、{{title.name}}、{{title['name']}}、{{title[0]}}
350+
return parsed // {{ name }} -> name
356351
} else {
357-
// 复杂表达式
358-
return {
359-
rawExpr: expr, // {{ a + b }} -> {{ a + b }}
360-
prefixExpr: parsed // {{ a + b }} -> ["+",["$","a"],["$","b"]]
361-
}
352+
// 复杂表达式,返回function形式的表达式结果
353+
return exprRaw // {{a + b}} -> function () { return this.a + this.b }
362354
}
363355
}
364356

365-
// 根据操作符来判断是否为简单表达式
366-
function isSimpleExpr(expr) {
367-
if (!expr || !Array.isArray(expr)) return false
368-
369-
const modifierList = []
370-
getAllModifiers(expr, modifierList)
371-
return modifierList.every((modifier) => SIMPLE_EXPR_MODIFIERS.includes(modifier))
372-
}
373-
374-
function getAllModifiers(exprList, modifierList) {
375-
modifierList.push(exprList[0])
376-
for (let i = 1; i < exprList.length; i++) {
377-
if (Array.isArray(exprList[i])) {
378-
// 如果当前元素是数组,递归调用,找出所有的操作符
379-
getAllModifiers(exprList[i], modifierList)
380-
}
357+
function getPrefixExpr(exprRaw) {
358+
const res = templateValueToCardCode(exprRaw)
359+
const parsed = JSON.parse(res)
360+
const rawExpr = getExprRes(exprRaw)
361+
return {
362+
rawExpr: rawExpr, // {{ name }} -> name
363+
prefixExpr: parsed // {{ name }} -> ['$', 'name']
381364
}
382-
return modifierList
383365
}
384366

385367
export function postHandleLiteCardRes(liteCardRes) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { templater } from '@hap-toolkit/compiler'
2+
const { validator } = templater
3+
4+
const pathTestRE =
5+
/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/
6+
7+
const literalValueRE = /^(?:true|false|null|undefined|Infinity|NaN)$/
8+
9+
export function isExpr(val) {
10+
if (!val) return false
11+
return validator.isExpr(val)
12+
}
13+
14+
export function isFunctionStr(str) {
15+
const pattern = /^\s*function\s*\([\w\s,$]*\)\s*\{[\s\S]*\}\s*$/
16+
return pattern.test(str.trim())
17+
}
18+
19+
export function isObject(obj) {
20+
return obj && Object.prototype.toString.call(obj) === '[object Object]' && obj !== null
21+
}
22+
23+
export function isConstObjOrArray(exp) {
24+
try {
25+
// "[1, 2, 3]"、"{a: 1}" 常量作为模板内容时
26+
// eslint-disable-next-line no-eval
27+
eval(`(${exp})`)
28+
return true
29+
} catch (e) {
30+
return false
31+
}
32+
}
33+
34+
export function isSimpleArr(exp) {
35+
// a.b.c,或 a['b']['c'] 返回 true
36+
// eslint-disable-next-line no-useless-escape
37+
const regex = /\[([^\[\]]+)\]/g
38+
let match
39+
const results = []
40+
41+
while ((match = regex.exec(exp)) !== null) {
42+
results.push(match[1])
43+
}
44+
45+
let res = true
46+
// 检查所有[]匹配项是否全部为数字或常量字符串
47+
results.forEach((content) => {
48+
if (!/^\d+$/.test(content) && !/^('|"|`)(.*)\1$/.test(content)) {
49+
res = false
50+
}
51+
})
52+
return res
53+
}
54+
55+
export function isSimplePath(exp) {
56+
return (
57+
pathTestRE.test(exp) &&
58+
// true/false/null/undefined/Infinity/NaN
59+
!literalValueRE.test(exp) &&
60+
// Math常量
61+
exp.slice(0, 5) !== 'Math.'
62+
)
63+
}

0 commit comments

Comments
 (0)