@@ -42,24 +42,25 @@ function safeDeleteNode(name, path) {
4242 binding = path . scope . getBinding ( name )
4343 }
4444 if ( ! binding ) {
45- return
45+ return false
4646 }
4747 binding . scope . crawl ( )
4848 binding = binding . scope . getBinding ( name )
4949 if ( binding . references ) {
50- return
50+ return false
5151 }
5252 for ( const item of binding . constantViolations ) {
5353 item . remove ( )
5454 }
5555 const decl = binding . path
5656 if ( decl . removed ) {
57- return
57+ return true
5858 }
5959 if ( ! decl . isVariableDeclarator ( ) && ! decl . isFunctionDeclaration ( ) ) {
60- return
60+ return true
6161 }
6262 binding . path . remove ( )
63+ return true
6364}
6465
6566function deAntiToolingCheckFunc ( path ) {
@@ -845,9 +846,6 @@ function insertDepItemVar(deps, name, path) {
845846 */
846847function findGlobalFn ( path ) {
847848 const glo_fn_name = path . node . id ?. name
848- if ( path . parentPath . getFunctionParent ( ) ) {
849- return null
850- }
851849 if ( ! glo_fn_name ) {
852850 return null
853851 }
@@ -1197,7 +1195,10 @@ const deStringConcealing = {
11971195 FunctionDeclaration ( path ) {
11981196 const obj = findGlobalFn ( path )
11991197 if ( ! obj ) {
1200- return
1198+ return null
1199+ }
1200+ if ( obj . glo_fn_path . parentPath . getFunctionParent ( ) ) {
1201+ return null
12011202 }
12021203 findGlobalFnRef ( obj )
12031204 if ( ! findBufferToString ( obj ) ) {
@@ -1239,6 +1240,26 @@ function tryStringConcealingPlace(path) {
12391240}
12401241
12411242const deStringConcealingPlace = {
1243+ StringLiteral ( path ) {
1244+ if ( path . key !== 'right' || ! path . parentPath . isAssignmentExpression ( ) ) {
1245+ return
1246+ }
1247+ const name = safeGetName ( path . parentPath . get ( 'left' ) )
1248+ if ( ! name ) {
1249+ return
1250+ }
1251+ const binding = path . scope . getBinding ( name )
1252+ if ( binding . constantViolations . length !== 1 ) {
1253+ return
1254+ }
1255+ for ( const ref of binding . referencePaths ) {
1256+ if ( ref . node . start < path . node . start ) {
1257+ continue
1258+ }
1259+ ref . replaceWith ( path . node )
1260+ }
1261+ safeDeleteNode ( name , path . parentPath )
1262+ } ,
12421263 ArrayExpression ( path ) {
12431264 let valid = true
12441265 if ( path . node . elements . length === 0 ) {
@@ -1414,6 +1435,125 @@ const deOpaquePredicates = {
14141435 } ,
14151436}
14161437
1438+ function findGlobalVar ( glo_name , glo_path ) {
1439+ let tmp_path = glo_path . parentPath . getFunctionParent ( )
1440+ if (
1441+ ! tmp_path ||
1442+ ! tmp_path . parentPath . isMemberExpression ( ) ||
1443+ ! tmp_path . parentPath . parentPath . isCallExpression ( )
1444+ ) {
1445+ return null
1446+ }
1447+ const tmp_body = tmp_path . node . body . body
1448+ tmp_path = tmp_path . parentPath . parentPath
1449+ const ret_node = tmp_body [ tmp_body . length - 1 ]
1450+ if (
1451+ ! t . isReturnStatement ( ret_node ) ||
1452+ ! t . isAssignmentExpression ( ret_node . argument )
1453+ ) {
1454+ return null
1455+ }
1456+ const code = generator ( ret_node . argument . right ) . code
1457+ const template = `${ glo_name } call(this)`
1458+ if ( ! checkPattern ( code , template ) ) {
1459+ return null
1460+ }
1461+ const glo_var = ret_node . argument . left . name
1462+ const binding = glo_path . scope . getBinding ( glo_var )
1463+ for ( const ref of binding . referencePaths ) {
1464+ if (
1465+ ! ref . parentPath . isMemberExpression ( ) ||
1466+ ! ref . parentPath . parentPath . isReturnStatement ( )
1467+ ) {
1468+ continue
1469+ }
1470+ const func_path = ref . getFunctionParent ( )
1471+ const func_name = func_path . node . id . name
1472+ return {
1473+ glo_var : glo_var ,
1474+ tmp_path : tmp_path ,
1475+ glo_fn_name : func_name ,
1476+ glo_fn_path : func_path ,
1477+ }
1478+ }
1479+ return null
1480+ }
1481+
1482+ function getGlobalConcealingNames ( glo_fn_path ) {
1483+ const obj = { }
1484+ glo_fn_path . traverse ( {
1485+ SwitchCase ( path ) {
1486+ const key = parseInt ( generator ( path . node . test ) . code )
1487+ let consequent = path . node . consequent [ 0 ]
1488+ if ( t . isReturnStatement ( consequent ) ) {
1489+ obj [ key ] = consequent . argument . property . value
1490+ } else {
1491+ if ( t . isExpressionStatement ( consequent ) ) {
1492+ consequent = consequent . expression
1493+ }
1494+ obj [ key ] = consequent . right . left . value
1495+ }
1496+ } ,
1497+ } )
1498+ return obj
1499+ }
1500+
1501+ /**
1502+ * Hide the global vars found by module GlobalAnalysis
1503+ *
1504+ * Template:
1505+ * ```javascript
1506+ * // Add to head:
1507+ * var globalVar, tempVar = function () {
1508+ * getGlobalVariableFnName = createGetGlobalTemplate()
1509+ * return globalVar = getGlobalVariableFnName.call(this)
1510+ * }["call"]()
1511+ * // Add to foot:
1512+ * function globalFn (indexParamName) {
1513+ * var returnName
1514+ * switch (indexParamName) {
1515+ * case state_x: {
1516+ * return globalVar[name]
1517+ * }
1518+ * case state_y: {
1519+ * returnName = name || globalVar[name]
1520+ * break
1521+ * }
1522+ * }
1523+ * return globalVar[returnName]
1524+ * }
1525+ * // References:
1526+ * // name -> globalFn(state)
1527+ * ```
1528+ */
1529+ const deGlobalConcealing = {
1530+ FunctionDeclaration ( path ) {
1531+ const glo_obj = findGlobalFn ( path )
1532+ if ( ! glo_obj ) {
1533+ return null
1534+ }
1535+ const obj = findGlobalVar ( glo_obj . glo_fn_name , glo_obj . glo_fn_path )
1536+ if ( ! obj ) {
1537+ return null
1538+ }
1539+ console . log ( `[GlobalConcealing] globalVar: ${ obj . glo_var } ` )
1540+ const glo_vars = getGlobalConcealingNames ( obj . glo_fn_path )
1541+ console . log ( `[GlobalConcealing] globalFn: ${ obj . glo_fn_name } ` )
1542+ let binding = obj . glo_fn_path . parentPath . scope . getBinding ( obj . glo_fn_name )
1543+ for ( const ref of binding . referencePaths ) {
1544+ const repl_path = ref . parentPath
1545+ if ( ref . key !== 'callee' || ! repl_path . isCallExpression ( ) ) {
1546+ continue
1547+ }
1548+ const key = parseInt ( generator ( repl_path . node . arguments [ 0 ] ) . code )
1549+ repl_path . replaceWith ( t . identifier ( glo_vars [ key ] ) )
1550+ }
1551+ if ( safeDeleteNode ( obj . glo_fn_name , obj . glo_fn_path ) ) {
1552+ obj . tmp_path . remove ( )
1553+ }
1554+ } ,
1555+ }
1556+
14171557module . exports = function ( code ) {
14181558 let ast
14191559 try {
@@ -1442,6 +1582,8 @@ module.exports = function (code) {
14421582 traverse ( ast , deOpaquePredicates )
14431583 traverse ( ast , calculateConstantExp )
14441584 traverse ( ast , pruneIfBranch )
1585+ // GlobalConcealing
1586+ traverse ( ast , deGlobalConcealing )
14451587 code = generator ( ast , {
14461588 comments : false ,
14471589 jsescOption : { minimal : true } ,
0 commit comments