浏览代码

`stringArray` calls wrappers now inserted as `FunctionDeclaration` nodes at random indexes

sanex 4 年之前
父节点
当前提交
4f9df91320
共有 17 个文件被更改,包括 144 次插入140 次删除
  1. 4 0
      CHANGELOG.md
  2. 0 0
      dist/index.browser.js
  3. 0 0
      dist/index.cli.js
  4. 0 0
      dist/index.js
  5. 1 1
      package.json
  6. 11 2
      src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts
  7. 2 2
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts
  8. 12 12
      src/node/NodeAppender.ts
  9. 14 13
      test/dev/dev.ts
  10. 1 1
      test/functional-tests/custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper.spec.ts
  11. 3 3
      test/functional-tests/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.spec.ts
  12. 9 9
      test/functional-tests/custom-code-helpers/string-array/templates/string-array-calls-wrapper-node-template/StringArrayCallsWrapperTemplate.spec.ts
  13. 4 6
      test/functional-tests/node-transformers/finalizing-transformers/escape-sequence-transformer/EscapeSequenceTransformer.spec.ts
  14. 1 1
      test/functional-tests/node-transformers/preparing-transformers/obfuscating-guards/force-transform-string-obfuscating-guard/ForceTransformStringObfuscatingGuard.spec.ts
  15. 4 4
      test/functional-tests/node-transformers/preparing-transformers/obfuscating-guards/ignored-require-import-obfuscating-guard/IgnoredRequireImportObfuscatingGuard.spec.ts
  16. 64 72
      test/functional-tests/node-transformers/string-array-transformers/string-array-scope-calls-wrapper-transformer/StringArrayScopeCallsWrapperTransformer.spec.ts
  17. 14 14
      test/functional-tests/storages/string-array-transformers/string-array-storage/StringArrayStorage.spec.ts

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 
+v2.12.0
+---
+* `stringArray` calls wrappers now inserted as `FunctionDeclaration` nodes at random indexes
+
 v2.11.1
 ---
 * **CLI**: now it's possible to specify the path to the input file after specifying the obfuscator options. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/904 

文件差异内容过多而无法显示
+ 0 - 0
dist/index.browser.js


文件差异内容过多而无法显示
+ 0 - 0
dist/index.cli.js


文件差异内容过多而无法显示
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "2.11.1",
+  "version": "2.12.0",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",

+ 11 - 2
src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts

@@ -22,6 +22,7 @@ import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGro
 import { NodeAppender } from '../../../node/NodeAppender';
 import { StringArrayCallsWrapperCodeHelper } from '../StringArrayCallsWrapperCodeHelper';
 import { StringArrayCodeHelper } from '../StringArrayCodeHelper';
+import { TStatement } from '../../../types/node/TStatement';
 
 @injectable()
 export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
@@ -90,14 +91,22 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
 
         // stringArrayCallsWrapper helper nodes append
         const stringArrayEncodingsLength: number = this.options.stringArrayEncoding.length;
-        for (let i = 0; i < stringArrayEncodingsLength; i++) {
+        // Stating from index 1 and forward. 0 index is reserved for string array itself.
+        let randomIndex: number = 1;
+        for (let i = 0; i < stringArrayEncodingsLength; i++, randomIndex++) {
             const stringArrayEncoding: TStringArrayEncoding = this.options.stringArrayEncoding[i];
             const stringArrayCallsWrapperCodeHelperName: CustomCodeHelper = this.getStringArrayCallsWrapperCodeHelperName(stringArrayEncoding);
 
+            const scopeStatements: TStatement[] = NodeAppender.getScopeStatements(nodeWithStatements);
+            randomIndex = this.randomGenerator.getRandomInteger(
+                randomIndex,
+                scopeStatements.length - 1
+            );
+
             this.appendCustomNodeIfExist(
                 stringArrayCallsWrapperCodeHelperName,
                 (customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>>) => {
-                    NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), i + 1);
+                    NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), randomIndex);
                 }
             );
         }

+ 2 - 2
src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts

@@ -3,7 +3,7 @@
  */
 export function StringArrayCallsWrapperTemplate (): string {
     return `
-        const {stringArrayCallsWrapperName} = function (index, key) {
+         function {stringArrayCallsWrapperName} (index, key) {
             index = index - {indexShiftAmount};
             
             let value = {stringArrayName}[index];
@@ -11,6 +11,6 @@ export function StringArrayCallsWrapperTemplate (): string {
             {decodeCodeHelperTemplate}
         
             return value;
-        };
+        }
     `;
 }

+ 12 - 12
src/node/NodeAppender.ts

@@ -82,6 +82,18 @@ export class NodeAppender {
         }
     }
 
+    /**
+     * @param {TNodeWithStatements} nodeWithStatements
+     * @returns {TStatement[]}
+     */
+    public static getScopeStatements (nodeWithStatements: TNodeWithStatements): TStatement[] {
+        if (NodeGuards.isSwitchCaseNode(nodeWithStatements)) {
+            return nodeWithStatements.consequent;
+        }
+
+        return nodeWithStatements.body;
+    }
+
     /**
      * @param {TNodeWithStatements} nodeWithStatements
      * @param {TStatement[]} statements
@@ -148,18 +160,6 @@ export class NodeAppender {
         ]);
     }
 
-    /**
-     * @param {TNodeWithStatements} nodeWithStatements
-     * @returns {TStatement[]}
-     */
-    private static getScopeStatements (nodeWithStatements: TNodeWithStatements): TStatement[] {
-        if (NodeGuards.isSwitchCaseNode(nodeWithStatements)) {
-            return nodeWithStatements.consequent;
-        }
-
-        return nodeWithStatements.body;
-    }
-
     /**
      * @param {TNodeWithStatements} nodeWithStatements
      * @param {TStatement[]} statements

+ 14 - 13
test/dev/dev.ts

@@ -1,29 +1,30 @@
 'use strict';
 
 import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
-import { RenamePropertiesMode } from '../../src/enums/node-transformers/rename-properties-transformers/RenamePropertiesMode';
 
 (function () {
     const JavaScriptObfuscator: any = require('../../index');
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
-            const object = {
-                foo: 1,
-                bar: 2,
-                baz: 3
-            };
-            
-            var excluded1 = 'bar';
-            var excluded2 = 'baz';
-            
-            console.log(object.foo, object['bar'], object.baz);
+            var variable1 = '5' - 3;
+            var variable2 = '5' + 3;
+            var variable3 = '5' + - '2';
+            var variable4 = ['10','10','10','10','10'].map(parseInt);
+            var variable5 = 'foo ' + 1 + 1;
+            console.log(variable1);
+            console.log(variable2);
+            console.log(variable3);
+            console.log(variable4);
+            console.log(variable5);
         `,
         {
             ...NO_ADDITIONAL_NODES_PRESET,
             compact: false,
-            renameProperties: true,
-            renamePropertiesMode: RenamePropertiesMode.Safe
+            stringArray: true,
+            stringArrayThreshold: 1,
+            rotateStringArray: true,
+            stringArrayWrappersCount: 3
         }
     ).getObfuscatedCode();
 

+ 1 - 1
test/functional-tests/custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper.spec.ts

@@ -55,7 +55,7 @@ describe('StringArrayCallsWrapperCodeHelper', () => {
 
     describe('Preserve string array name', () => {
         const callsWrapperRegExp: RegExp = new RegExp(`` +
-            `var b *= *function *\\(c, *d\\) *{ *` +
+            `function *b *\\(c, *d\\) *{ *` +
             `c *= *c *- *0x0; *` +
             `var e *= *a\\[c]; *` +
         ``);

+ 3 - 3
test/functional-tests/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.spec.ts

@@ -11,9 +11,9 @@ import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFac
 
 describe('StringArrayCodeHelperGroup', () => {
     const regExp: RegExp = new RegExp(
-        'var b *= *function\\(\\w, *\\w\\) *{.*return \\w;}; *' +
-        'var c *= *function\\(\\w, *\\w\\) *{.*return \\w;}; *' +
-        'var d *= *function\\(\\w, *\\w\\) *{.*return \\w;};'
+        'function *b *\\(\\w, *\\w\\) *{.*return \\w;}.*' +
+        'function *c *\\(\\w, *\\w\\) *{.*return \\w;}.*' +
+        'function *d *\\(\\w, *\\w\\) *{.*return \\w;}'
     );
 
     describe('StringArrayCallsWrapper code helper names', () => {

+ 9 - 9
test/functional-tests/custom-code-helpers/string-array/templates/string-array-calls-wrapper-node-template/StringArrayCallsWrapperTemplate.spec.ts

@@ -273,7 +273,7 @@ describe('StringArrayCallsWrapperTemplate', () => {
     describe('Prevailing kind of variables', () => {
         describe('`var` kind', () => {
             let obfuscatedCode: string,
-                stringArrayCallsWrapperRegExp: RegExp = /var (_0x(\w){4}) *= *function/;
+                stringArrayCallsWrapperVariableRegExp: RegExp = /var (_0x(\w){4,6}) *= *(_0x(\w){4,6})\[(_0x(\w){4,6})];/;
 
             beforeEach(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
@@ -289,8 +289,8 @@ describe('StringArrayCallsWrapperTemplate', () => {
                 obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
             });
 
-            it('Should return correct kind of variables for string array calls wrapper', () => {
-                assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
+            it('Should return correct kind of variables for string array calls wrapper code', () => {
+                assert.match(obfuscatedCode, stringArrayCallsWrapperVariableRegExp);
             });
 
             it('Should does not break on obfuscating', () => {
@@ -300,7 +300,7 @@ describe('StringArrayCallsWrapperTemplate', () => {
 
         describe('`const` kind', () => {
             let obfuscatedCode: string,
-                stringArrayCallsWrapperRegExp: RegExp = /const (_0x(\w){4}) *= *function/;
+                stringArrayCallsWrapperVariableRegExp: RegExp = /let (_0x(\w){4,6}) *= *(_0x(\w){4,6})\[(_0x(\w){4,6})];/;
 
             beforeEach(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
@@ -316,8 +316,8 @@ describe('StringArrayCallsWrapperTemplate', () => {
                 obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
             });
 
-            it('Should return correct kind of variables for string array calls wrapper', () => {
-                assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
+            it('Should return correct kind of variables for string array calls wrapper code', () => {
+                assert.match(obfuscatedCode, stringArrayCallsWrapperVariableRegExp);
             });
 
             it('Should does not break on obfuscating', () => {
@@ -327,7 +327,7 @@ describe('StringArrayCallsWrapperTemplate', () => {
 
         describe('`let` kind', () => {
             let obfuscatedCode: string,
-                stringArrayCallsWrapperRegExp: RegExp = /const (_0x(\w){4}) *= *function/;
+                stringArrayCallsWrapperVariableRegExp: RegExp = /let (_0x(\w){4,6}) *= *(_0x(\w){4,6})\[(_0x(\w){4,6})];/;
 
             beforeEach(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
@@ -343,8 +343,8 @@ describe('StringArrayCallsWrapperTemplate', () => {
                 obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
             });
 
-            it('Should return correct kind of variables for string array calls wrapper', () => {
-                assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
+            it('Should return correct kind of variables for string array calls wrapper code', () => {
+                assert.match(obfuscatedCode, stringArrayCallsWrapperVariableRegExp);
             });
 
             it('Should does not break on obfuscating', () => {

+ 4 - 6
test/functional-tests/node-transformers/finalizing-transformers/escape-sequence-transformer/EscapeSequenceTransformer.spec.ts

@@ -170,12 +170,10 @@ describe('EscapeSequenceTransformer', function () {
 
     describe('Variant #6: `stringArrayWrappersCount` option enabled', () => {
         const stringArrayCallRegExp: RegExp = new RegExp(
-                'return e;' +
-            '};' +
-            'const f *= *b;' +
-            'const foo *= *f\\(\'\\\\x30\\\\x78\\\\x30\'\\);' +
-            'const bar *= *f\\(\'\\\\x30\\\\x78\\\\x31\'\\);' +
-            'const baz *= *f\\(\'\\\\x30\\\\x78\\\\x32\'\\);' +
+            'const f *= *b;.*' +
+            'const foo *= *f\\(\'\\\\x30\\\\x78\\\\x30\'\\);.*' +
+            'const bar *= *f\\(\'\\\\x30\\\\x78\\\\x31\'\\);.*' +
+            'const baz *= *f\\(\'\\\\x30\\\\x78\\\\x32\'\\);.*' +
             'function test\\( *\\) *{' +
                 'const g *= *f;' +
                 'const c *= *g\\(\'\\\\x30\\\\x78\\\\x33\'\\);' +

+ 1 - 1
test/functional-tests/node-transformers/preparing-transformers/obfuscating-guards/force-transform-string-obfuscating-guard/ForceTransformStringObfuscatingGuard.spec.ts

@@ -12,7 +12,7 @@ describe('ForceTransformStringObfuscatingGuard', () => {
     describe('check', () => {
         describe('`forceTransformStrings` option is enabled', () => {
             const obfuscatingGuardRegExp: RegExp = new RegExp(
-                'var foo *= *\'foo\';' +
+                'var foo *= *\'foo\';.*' +
                 'var bar *= *b\\(0x0\\);'
             );
 

+ 4 - 4
test/functional-tests/node-transformers/preparing-transformers/obfuscating-guards/ignored-require-import-obfuscating-guard/IgnoredRequireImportObfuscatingGuard.spec.ts

@@ -10,8 +10,8 @@ describe('IgnoredRequireImportObfuscatingGuard', () => {
     describe('check', () => {
         describe('`ignoreRequireImports` option is enabled', () => {
             const obfuscatingGuardRegExp: RegExp = new RegExp(
-                'const foo *= *require\\(\'\\./foo\'\\); *' +
-                'import _0x(?:[a-f0-9]){4,6} from *\'\\./bar\'; *' +
+                'const foo *= *require\\(\'\\./foo\'\\);.*' +
+                'import _0x(?:[a-f0-9]){4,6} from *\'\\./bar\';.*' +
                 'const baz *= *_0x(?:[a-f0-9]){4,6}\\(0x0\\);'
             );
 
@@ -38,8 +38,8 @@ describe('IgnoredRequireImportObfuscatingGuard', () => {
 
         describe('`ignoreRequireImports` option is disabled', () => {
             const obfuscatingGuardRegExp: RegExp = new RegExp(
-                'const foo *= *require\\(_0x(?:[a-f0-9]){4,6}\\(0x0\\)\\); *' +
-                'import _0x(?:[a-f0-9]){4,6} from *\'\\./bar\'; *' +
+                'const foo *= *require\\(_0x(?:[a-f0-9]){4,6}\\(0x0\\)\\);.*' +
+                'import _0x(?:[a-f0-9]){4,6} from *\'\\./bar\';.*' +
                 'const baz *= *_0x(?:[a-f0-9]){4,6}\\(0x1\\);'
             );
 

+ 64 - 72
test/functional-tests/node-transformers/string-array-transformers/string-array-scope-calls-wrapper-transformer/StringArrayScopeCallsWrapperTransformer.spec.ts

@@ -17,14 +17,13 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
     describe('Variant #1: base', () => {
         describe('Variant #1: root scope', () => {
-            describe('Variant #1: option value value is lower then count `literal` nodes in the scope', () => {
+            describe('Variant #1: option value is lower then count `literal` nodes in the scope', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                        'return _0x([a-f0-9]){4,6};' +
-                    '};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);' +
-                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);' +
+                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    '(const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};(function .*)?){2}' +
+                    '(?!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);.*' +
+                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);.*' +
                     'const baz *= *_0x([a-f0-9]){4,6}\\(0x2\\);'
                 );
 
@@ -51,13 +50,11 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #2: option value is bigger then count `literal` nodes in the scope', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                        'return _0x([a-f0-9]){4,6};' +
-                    '};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);' +
-                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);' +
+                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    '(const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};(function .*)?){3}' +
+                    '(?!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);.*' +
+                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);.*' +
                     'const baz *= *_0x([a-f0-9]){4,6}\\(0x2\\);'
                 );
 
@@ -84,10 +81,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #3: correct wrappers order', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                    'const f *= *b;' +
-                    'const g *= *b;' +
-                    'const foo *= *[f|g]\\(0x0\\);' +
-                    'const bar *= *[f|g]\\(0x1\\);' +
+                    'const f *= *b;.*' +
+                    'const g *= *b;.*' +
+                    'const foo *= *[f|g]\\(0x0\\);.*' +
+                    'const bar *= *[f|g]\\(0x1\\);.*' +
                     'const baz *= *[f|g]\\(0x2\\);'
                 );
 
@@ -115,10 +112,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #4: `identifiersPrefix` option is set', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                    'const foo_d *= *foo_b;' +
-                    'const foo_e *= *foo_b;' +
-                    'const foo *= *foo_[d|e]\\(0x0\\);' +
-                    'const bar *= *foo_[d|e]\\(0x1\\);' +
+                    'const foo_d *= *foo_b;.*' +
+                    'const foo_e *= *foo_b;.*' +
+                    'const foo *= *foo_[d|e]\\(0x0\\);.*' +
+                    'const bar *= *foo_[d|e]\\(0x1\\);.*' +
                     'const baz *= *foo_[d|e]\\(0x2\\);'
                 );
 
@@ -247,8 +244,8 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #4: correct wrapper for the function default parameter', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                    'const e *= *b;' +
-                    'const foo *= *e\\(0x0\\);' +
+                    'const e *= *b;.*' +
+                    'const foo *= *e\\(0x0\\);.*' +
                     'function test *\\(c *= *e\\(0x1\\)\\) *{' +
                         'const f *= *b;' +
                         'const d *= *f\\(0x2\\);' +
@@ -315,7 +312,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
         describe('Variant #3: prohibited scopes', () => {
             describe('Variant #1: if statement scope', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                    'var c *= *b;' +
+                    'var c *= *b;.*' +
                     'if *\\(!!\\[]\\) *{' +
                         'var foo *= *c\\(0x0\\);' +
                     '}'
@@ -345,7 +342,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #2: arrow function scope without statements', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                    'var c *= *b;' +
+                    'var c *= *b;.*' +
                     '\\[]\\[c\\(0x0\\)]\\(\\(\\) *=> *c\\(0x1\\)\\);'
                 );
 
@@ -374,12 +371,11 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
         describe('Variant #4: prevailing kind of variables', () => {
             const stringArrayCallRegExp: RegExp = new RegExp(
-                    'return _0x([a-f0-9]){4,6};' +
-                '};' +
-                'var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                'var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                'var foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);' +
-                'var bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);' +
+                '(?<!var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                '(var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};(function .*)?){2}' +
+                '(?!var _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                'var foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);.*' +
+                'var bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);.*' +
                 'var baz *= *_0x([a-f0-9]){4,6}\\(0x2\\);'
             );
 
@@ -433,8 +429,8 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
             describe('Variant #1: correct chained calls', () => {
                 describe('Variant #1: `Mangled` identifier names generator', () => {
                     const stringArrayCallRegExp: RegExp = new RegExp(
-                        'const q *= *b;' +
-                        'const foo *= *q\\(0x0\\);' +
+                        'const q *= *b;.*' +
+                        'const foo *= *q\\(0x0\\);.*' +
                         'function test\\(c, *d\\) *{' +
                             'const r *= *q;' +
                             'const e *= *r\\(0x1\\);' +
@@ -651,10 +647,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     const stringArrayCallRegExp: RegExp = new RegExp(
                         'const f *= *function *\\(c, *d\\) *{' +
                             `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
-                        '};' +
-                        `const foo *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);` +
-                        `const bar *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);` +
-                        `const baz *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);` +
+                        '};.*' +
+                        `const foo *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
+                        `const bar *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
+                        `const baz *= *f\\(-? *${hexadecimalIndexMatch}\\, *-? *${hexadecimalIndexMatch}\\);.*` +
                         'function test *\\( *\\) *{' +
                             'const g *= *function *\\(c, *d\\) *{' +
                                 `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
@@ -706,10 +702,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     const stringArrayCallRegExp: RegExp = new RegExp(
                         'const f *= *function *\\(c, *d\\) *{' +
                             `return b\\([cd] *-(?: -)?'${hexadecimalIndexMatch}', *[cd]\\);` +
-                        '};' +
-                        `const foo *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);` +
-                        `const bar *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);` +
-                        `const baz *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);` +
+                        '};.*' +
+                        `const foo *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
+                        `const bar *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
+                        `const baz *= *f\\(-? *'${hexadecimalIndexMatch}', *-? *'${hexadecimalIndexMatch}'\\);.*` +
                         'function test *\\( *\\) *{' +
                             'const g *= *function *\\(c, *d\\) *{' +
                                 `return b\\([cd] *-(?: -)?'${hexadecimalIndexMatch}', *[cd]\\);` +
@@ -762,10 +758,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                 const stringArrayCallRegExp: RegExp = new RegExp(
                     'const f *= *function *\\(c, *d\\) *{' +
                         `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
-                    '};' +
-                    `const foo *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
-                    `const bar *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
-                    `const baz *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);` +
+                    '};.*' +
+                    `const foo *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                    `const bar *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
+                    `const baz *= *f\\(-? *${hexadecimalIndexMatch}, *-? *${hexadecimalIndexMatch}\\);.*` +
                     'function test *\\( *\\) *{' +
                         'const g *= *function *\\(c, *d\\) *{' +
                             `return f\\(` +
@@ -816,8 +812,7 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #3: no wrappers on a root scope', () => {
                 const stringArrayCallRegExp: RegExp = new RegExp(
-                        'return e;' +
-                    '};' +
+                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
                     'function test *\\( *\\) *{' +
                         'const f *= *function *\\(c, *d\\) *{' +
                             `return b\\([cd] *-(?: -)?${hexadecimalIndexMatch}, *[cd]\\);` +
@@ -1034,10 +1029,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     const stringArrayCallRegExp: RegExp = new RegExp(
                         'const f *= *function *\\(c, *d, *e, *h, *i\\) *{' +
                             `return b\\([cdehi] *-(?: -)?${hexadecimalIndexMatch}, *[cdehi]\\);` +
-                        '};' +
-                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
+                        '};.*' +
+                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
                         'function test *\\( *\\) *{' +
                             'const g *= *function *\\(c, *d, *e, *h, *i\\) *{' +
                                 `return f\\(` +
@@ -1097,10 +1092,10 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
                     const stringArrayCallRegExp: RegExp = new RegExp(
                         'const f *= *function *\\(c, *d, *e, *h, *i\\) *{' +
                             `return b\\([cdehi] *-(?: -)?${hexadecimalIndexMatch}, *[cdehi]\\);` +
-                        '};' +
-                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
-                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);` +
+                        '};.*' +
+                        `const foo *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const bar *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
+                        `const baz *= *f\\(${stringArrayWrapperArgumentsRegExpString}\\);.*` +
                         'function test *\\( *\\) *{' +
                             'const g *= *function *\\(c, *d, *e, *h, *i\\) *{' +
                                 `return f\\(` +
@@ -1163,15 +1158,14 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
         describe('Variant #1: root scope', () => {
             describe('Variant #1: `1` scope calls wrapper for each encoding type', () => {
                 const stringArrayWrappersRegExp: RegExp = new RegExp(
-                        'return _0x([a-f0-9]){4,6};' +
-                    '};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    // this one may be added or not depends on:
+                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    // second one may be added or not depends on:
                     // if all literal values encoded with a single encoding or not
-                    '(?:const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};)?' +
-                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);' +
-                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);' +
-                    'const baz *= *_0x([a-f0-9]){4,6}\\(0x2\\);'
+                    '(const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};(function .*)?){1,2}' +
+                    '(?!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);.*' +
+                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);.*' +
+                    'const baz *= *_0x([a-f0-9]){4,6}\\(0x2\\);.*'
                 );
 
                 let obfuscatedCode: string;
@@ -1201,15 +1195,13 @@ describe('StringArrayScopeCallsWrapperTransformer', function () {
 
             describe('Variant #2: `2` scope calls wrappers for each encoding type', () => {
                 const stringArrayWrappersRegExp: RegExp = new RegExp(
-                        'return _0x([a-f0-9]){4,6};' +
-                    '};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    'const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};' +
-                    // this one may be added or not depends on:
+                    '(?<!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    // third one may be added or not depends on:
                     // if all literal values encoded with a single encoding or not
-                    '(?:const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};)?' +
-                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);' +
-                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);' +
+                    '(const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};(function .*)?){2,3}' +
+                    '(?!const _0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4};.*)' +
+                    'const foo *= *_0x([a-f0-9]){4,6}\\(0x0\\);.*' +
+                    'const bar *= *_0x([a-f0-9]){4,6}\\(0x1\\);.*' +
                     'const baz *= *_0x([a-f0-9]){4,6}\\(0x2\\);'
                 );
 

+ 14 - 14
test/functional-tests/storages/string-array-transformers/string-array-storage/StringArrayStorage.spec.ts

@@ -79,8 +79,8 @@ describe('StringArrayStorage', () => {
             ];
             const literalNodeVariantRegExps: RegExp[] = [
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x.\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x.\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x.\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x.\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x.\\);`
                 )
             ];
@@ -222,33 +222,33 @@ describe('StringArrayStorage', () => {
 
             const literalNodeVariantRegExps: RegExp[] = [
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x0\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x1\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x0\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x1\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x2\\);`
                 ),
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x0\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x2\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x0\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x2\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x1\\);`
                 ),
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x1\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x0\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x1\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x0\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x2\\);`
                 ),
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x1\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x2\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x1\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x2\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x0\\);`
                 ),
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x2\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x0\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x2\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x0\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x1\\);`
                 ),
                 new RegExp(
-                    `var foo *= *_0x([a-f0-9]){4}\\(0x2\\); *` +
-                    `var bar *= *_0x([a-f0-9]){4}\\(0x1\\); *` +
+                    `var foo *= *_0x([a-f0-9]){4}\\(0x2\\);.*` +
+                    `var bar *= *_0x([a-f0-9]){4}\\(0x1\\);.*` +
                     `var baz *= *_0x([a-f0-9]){4}\\(0x0\\);`
                 )
             ];

部分文件因为文件数量过多而无法显示