1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16var parser = require("@babel/parser") 17var traverse = require("@babel/traverse").default 18var generate = require("@babel/generator").default 19 20function parseExpression(expression, isEventFunc) { 21 const keyWordsReg = new RegExp(`^(NaN\\b|isNaN\\b|isFinite\\b|decodeURI\\b|decodeURIComponent\\b|Math\\b|Date\\b|this\\b|true\\b|false\\b| 22 encodeURI\\b|encodeURIComponent\\b|parseInt\\b|parseFloat\\b|null\\b|undefined\\b|Infinity\\b)`, 'g') 23 const internalKeyWords = new RegExp(`^(var\\b|while\\b|with\\b|yield\\b|enum\\b|await\\b|implements\\b|package\\b|for\\b|function\\b|if\\b|import\\b| 24 protected\\b|static\\b|interface\\b|private\\b|public\\b|break\\b|case\\b|class\\b|catch\\b|const\\b|continue\\b|debugger\\b| 25 default\\b|delete\\b|do\\b|else\\b|export\\b|extends\\b|finally\\b|in\\b|instanceof\\b|let\\b|return\\b|super\\b|switch\\b|throw\\b|try\\b)`, 'g') 26 const reservedKeyWords = new RegExp(`^(var\\b|while\\b|with\\b|yield\\b|enum\\b|await\\b|implements\\b|package\\b|for\\b|function\\b|if\\b|import\\b| 27 protected\\b|static\\b|interface\\b|private\\b|public\\b|break\\b|case\\b|class\\b|catch\\b|const\\b|continue\\b|debugger\\b| 28 default\\b|delete\\b|do\\b|else\\b|export\\b|extends\\b|finally\\b|in\\b|instanceof\\b|let\\b|return\\b|super\\b|switch\\b|throw\\b|try\\b|show\\b|tid\\b)$`, 'g') 29 try { 30 if (reservedKeyWords.test(expression)) { 31 throw Error("A data binding parsing error occurred. Do not use the reserved:" + expression).message 32 } 33 let expAst = isEventFunc ? parser.parse('(' + expression + ')') : parser.parse(expression) 34 traverse(expAst, { 35 enter(path) { 36 if (path.parent && path.node.type === "Identifier") { 37 let flag = false 38 if (['ConditionalExpression', 'BinaryExpression'].includes(path.parent.type) || 39 path.parent.type === 'CallExpression' && path.parent.callee === path.node) { 40 flag = true 41 } 42 else if (path.parent.type === "ObjectProperty" && !path.parent.computed && path.parent.value === path.node) { 43 flag = true 44 } 45 else { 46 flag = addPrefix(path.node, path.parent) 47 } 48 if (flag && !keyWordsReg.test(path.node.name)) { 49 path.node.name = 'this.' + path.node.name 50 } 51 } 52 } 53 }) 54 return generate(expAst, { compact: true }).code.replace(';', '').replace(/\"/g, '\'').replace(/\n/g, '') 55 } catch (e) { 56 if (isEventFunc) { 57 throw internalKeyWords.test(expression) ? Error("An event parsing error occurred. Do not use the reserved:" + expression).message : 58 Error("An event parsing error occurred:" + expression).message 59 } else { 60 throw internalKeyWords.test(expression) ? Error("A data binding parsing error occurred. Do not use the reserved:" + expression).message : 61 Error("A data binding parsing error occurred:" + expression).message 62 } 63 } 64} 65 66function addPrefix(node, parent) { 67 const attrArr1 = ['expression', 'argument', 'arguments', 'expressions', 'elements', 'left', 'right'] 68 const attrArr2 = ['object', 'property', 'id', 'key'] 69 let keyArr = Object.keys(parent) 70 for (let i = 0; i < attrArr1.length; i++) { 71 if (keyArr.includes(attrArr1[i])) { 72 if (parent[attrArr1[i]] === node || ['expressions', 'elements'].includes(attrArr1[i]) && 73 parent[attrArr1[i]].includes(node)) { 74 return true 75 } 76 if('arguments' === attrArr1[i] && parent.arguments[0].type === 'Identifier') { 77 return true 78 } 79 } 80 } 81 for (let i = 0; i < attrArr2.length; i++) { 82 if (keyArr.includes(attrArr2[i])) { 83 if (parent.computed && parent[attrArr2[i]] === node) { 84 return true 85 } else { 86 if (parent.type === "Property" && parent.key.range[0] === parent.value.range[0] && 87 parent.key.range[1] === parent.value.range[1]) { 88 node.name = node.name + ":this." + node.name 89 } else if (parent.object === node) { 90 return true 91 } 92 } 93 } 94 } 95 return false 96} 97 98exports.parseExpression = parseExpression 99