Ver código fonte

Merge pull request #899 from erikdubbelboer/domain-dest

Add domainDest option
Timofey Kachalov 3 anos atrás
pai
commit
5019500c07

+ 9 - 0
README.md

@@ -361,6 +361,7 @@ Following options are available for the JS Obfuscator:
     debugProtectionInterval: false,
     disableConsoleOutput: false,
     domainLock: [],
+    domainDest: 'about:blank',
     forceTransformStrings: [],
     identifierNamesCache: null,
     identifierNamesGenerator: 'hexadecimal',
@@ -421,6 +422,7 @@ Following options are available for the JS Obfuscator:
     --debug-protection-interval <boolean>
     --disable-console-output <boolean>
     --domain-lock '<list>' (comma separated)
+    --domain-dest 'url' <string>
     --exclude '<list>' (comma separated)
     --force-transform-strings '<list>' (comma separated)
     --identifier-names-cache-path <string>
@@ -691,6 +693,13 @@ Allows to run the obfuscated source code only on specific domains and/or sub-dom
 ##### Multiple domains and sub-domains
 It's possible to lock your code to more than one domain or sub-domain. For instance, to lock it so the code only runs on **www.example.com** add `www.example.com`. To make it work on the root domain including any sub-domains (`example.com`, `sub.example.com`), use `.example.com`.
 
+### `domainDest`
+Type: `string` Default: `about:blank`
+
+##### :warning: This option does not work with `target: 'node'`
+
+Location to redirect the browser to when domainLock is triggered.
+
 ### `exclude`
 Type: `string[]` Default: `[]`
 

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/index.browser.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/index.cli.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/index.js


+ 4 - 0
src/cli/JavaScriptObfuscatorCLI.ts

@@ -236,6 +236,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
                 'Allows to run the obfuscated source code only on specific domains and/or sub-domains (comma separated)',
                 ArraySanitizer
             )
+            .option(
+                '--domain-dest <string>',
+                'Allows the browser to be redirected to this domain if the source code isn\'t run on the domains specified by --domain-lock',
+            )
             .option(
                 '--exclude <list> (comma separated, without whitespaces)',
                 'A filename or glob which indicates files to exclude from obfuscation',

+ 9 - 2
src/custom-code-helpers/domain-lock/DomainLockCodeHelper.ts

@@ -89,10 +89,15 @@ export class DomainLockCodeHelper extends AbstractCustomCodeHelper {
      */
     protected override getCodeHelperTemplate (): string {
         const domainsString: string = this.options.domainLock.join(';');
-        const [hiddenDomainsString, diff]: string[] = this.cryptUtils.hideString(
+        const domainsDest: string = this.options.domainDest;
+        const [hiddenDomainsString, domainsStringDiff]: string[] = this.cryptUtils.hideString(
             domainsString,
             domainsString.length * 3
         );
+        const [hiddenDomainDest, domainDestDiff]: string[] = this.cryptUtils.hideString(
+            domainsDest,
+            domainsDest.length * 3
+        );
         const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
@@ -100,8 +105,10 @@ export class DomainLockCodeHelper extends AbstractCustomCodeHelper {
         return this.customCodeHelperFormatter.formatTemplate(DomainLockTemplate(), {
             callControllerFunctionName: this.callsControllerFunctionName,
             domainLockFunctionName: this.domainLockFunctionName,
-            diff,
+            domainsStringDiff,
             domains: hiddenDomainsString,
+            domainDestDiff,
+            domainDest: hiddenDomainDest,
             globalVariableTemplate
         });
     }

+ 45 - 37
src/custom-code-helpers/domain-lock/templates/DomainLockTemplate.ts

@@ -7,34 +7,43 @@ export function DomainLockTemplate (): string {
             
             {globalVariableTemplate}
             
-            const func = function () {
-                return {
-                    key: 'item',
-                    value: 'attribute',
-                    getAttribute: function () {
-                        for (let i = 0; i < 1000; i--) {
-                            const isPositive = i > 0;
-                            
-                            switch (isPositive) {
-                                case true:
-                                    return this.item + '_' + this.value + '_' + i;
-                                default:
-                                    this.item + '_' + this.value;
-                            }
-                        }
-                    }()
-                };
-            };
-                        
-            const regExp = new RegExp("[{diff}]", "g");
+            const regExp = new RegExp("[{domainsStringDiff}]", "g");
             const domains = "{domains}".replace(regExp, "").split(";");
             let document;
             let domain;
             let location;
             let hostname;
 
+            const isName = function(name, length, cs) {
+                if (name.length != length) {
+                    return false;
+                }
+
+                for (let i = 0; i < length; i++) {
+                    for (let j = 0; j < cs.length; j += 2) {
+                        if (i == cs[j] && name.charCodeAt(i) != cs[j+1]) {
+                            return false;
+                        }
+                    }
+                }
+
+                return true;
+            };
+
+            const isNameVariant1 = function(cs, name, length) {
+              return isName(name, length, cs);
+            };
+
+            const isNameVariant2 = function(name, cs, length) {
+              return isNameVariant1(cs, name, length);
+            };
+
+            const isNameVariant3 = function(length, name, cs) {
+              return isNameVariant2(name, cs, length);
+            };
+
             for (let d in that) {
-                if (d.length == 8 && d.charCodeAt(7) == 116 && d.charCodeAt(5) == 101 && d.charCodeAt(3) == 117 && d.charCodeAt(0) == 100) {
+                if (isName(d, 8, [7, 116, 5, 101, 3, 117, 0, 100])) {
                     document = d;
                 
                     break;
@@ -42,24 +51,24 @@ export function DomainLockTemplate (): string {
             }
 
             for (let d1 in that[document]) {
-                if (d1.length == 6 && d1.charCodeAt(5) == 110 && d1.charCodeAt(0) == 100) {
+                if (isNameVariant3(6, d1, [5, 110, 0, 100])) {
                     domain = d1;
-                    
+
                     break;
                 }
             }
 
-            if (!("~" > domain)) {
-                for (let d2 in that[document]) {
-                    if (d2.length == 8 && d2.charCodeAt(7) == 110 && d2.charCodeAt(0) == 108) {
-                        location = d2;
-                        
-                        break;
-                    }
+            for (let d2 in that[document]) {
+                if (isNameVariant2(d2, [7, 110, 0, 108], 8)) {
+                    location = d2;
+
+                    break;
                 }
+            }
 
+            if (!("~" > domain)) {
                 for (let d3 in that[document][location]) {
-                    if (d3.length == 8 && d3.charCodeAt(7) == 101 && d3.charCodeAt(0) == 104) {
+                    if (isNameVariant1([7, 101, 0, 104], d3, 8)) {
                         hostname = d3;
                         
                         break;
@@ -96,14 +105,13 @@ export function DomainLockTemplate (): string {
                     }
                 }
             }
-               
+
             if (!ok) {
-                data;
-            } else {
-                return;
+                const regExp2 = new RegExp("[{domainDestDiff}]", "g");
+                const domainDest = "{domainDest}".replace(regExp2, "");
+
+                that[document][location] = domainDest;
             }
-            
-            func();
         });
 
         {domainLockFunctionName}();

+ 1 - 0
src/interfaces/options/IOptions.ts

@@ -20,6 +20,7 @@ export interface IOptions {
     readonly debugProtectionInterval: boolean;
     readonly disableConsoleOutput: boolean;
     readonly domainLock: string[];
+    readonly domainDest: string;
     readonly forceTransformStrings: string[];
     readonly identifierNamesCache: TIdentifierNamesCache;
     readonly identifierNamesGenerator: TTypeFromEnum<typeof IdentifierNamesGenerator>;

+ 10 - 0
src/options/Options.ts

@@ -134,6 +134,16 @@ export class Options implements IOptions {
     ])
     public readonly domainLock!: string[];
 
+    /**
+     * @type {string}
+     */
+    @IsString()
+    @IsAllowedForObfuscationTargets([
+        ObfuscationTarget.Browser,
+        ObfuscationTarget.BrowserNoEval,
+    ])
+    public readonly domainDest!: string;
+
     /**
      * @type {string[]}
      */

+ 1 - 0
src/options/presets/Default.ts

@@ -20,6 +20,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
     debugProtectionInterval: false,
     disableConsoleOutput: false,
     domainLock: [],
+    domainDest: 'about:blank',
     exclude: [],
     forceTransformStrings: [],
     identifierNamesCache: null,

+ 1 - 0
src/options/presets/NoCustomNodes.ts

@@ -18,6 +18,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
     debugProtectionInterval: false,
     disableConsoleOutput: false,
     domainLock: [],
+    domainDest: 'about:blank',
     exclude: [],
     forceTransformStrings: [],
     identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,

+ 424 - 170
test/functional-tests/custom-code-helpers/domain-lock/templates/DomainLockNodeTemplate.spec.ts

@@ -13,53 +13,11 @@ import { IObfuscationResult } from '../../../../../src/interfaces/source-code/IO
 import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { DomainLockTemplate } from '../../../../../src/custom-code-helpers/domain-lock/templates/DomainLockTemplate';
-import { GlobalVariableTemplate1 } from '../../../../../src/custom-code-helpers/common/templates/GlobalVariableTemplate1';
 
 import { InversifyContainerFacade } from '../../../../../src/container/InversifyContainerFacade';
 import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
-/**
- * @param {string} currentDomain
- * @returns {string}
- */
-function getDocumentDomainTemplate (currentDomain: string): string {
-    return `
-        document = {
-            domain: '${currentDomain}'
-        };
-    `
-}
-
-/**
- * @param {string} currentDomain
- * @returns {string}
- */
-function getDocumentLocationTemplate (currentDomain: string): string {
-    return `
-        document = {
-            location: {
-                hostname: '${currentDomain}'
-            }
-        };
-    `
-}
-
-/**
- * @param {string} currentDomain
- * @returns {string}
- */
-function getDocumentDomainAndLocationTemplate (currentDomain: string): string {
-    return `
-        document = {
-            domain: '${currentDomain}',
-            location: {
-                hostname: '${currentDomain}'
-            }
-        };
-    `
-}
-
 /**
  * @param templateData
  * @param {string} callsControllerFunctionName
@@ -85,11 +43,12 @@ function getFunctionFromTemplate (
         })();
 
         ${domainLockTemplate}
-    `)();
+    `);
 }
 
 describe('DomainLockTemplate', () => {
     const singleCallControllerFunctionName: string = 'callsController';
+    const thatThisTemplate = 'const that = this;';
 
     let cryptUtils: ICryptUtils;
 
@@ -102,393 +61,614 @@ describe('DomainLockTemplate', () => {
 
     describe('Variant #1: current domain matches with `domainsString`', () => {
         const domainsString: string = ['www.example.com'].join(';');
+        const domainDest: string = 'about:blank';
         const currentDomain: string = 'www.example.com';
 
-        let testFunc: () => void;
+        let testFunc: Function;
+        let root: any;
 
         before(() => {
             const [
                 hiddenDomainsString,
-                diff
+                domainsStringDiff
             ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-            testFunc = () => getFunctionFromTemplate(
+            const [
+                hiddenDomainDest,
+                domainDestDiff
+            ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+            root = {
+                document: {
+                    domain: currentDomain,
+                    location: undefined,
+                },
+            };
+
+            testFunc = getFunctionFromTemplate(
                 {
                     domainLockFunctionName: 'domainLockFunction',
-                    diff: diff,
+                    domainsStringDiff,
                     domains: hiddenDomainsString,
-                    globalVariableTemplate: GlobalVariableTemplate1(),
+                    domainDestDiff,
+                    hiddenDomainDest,
+                    globalVariableTemplate: '',
                     singleCallControllerFunctionName
                 },
                 singleCallControllerFunctionName,
-                getDocumentDomainTemplate(currentDomain)
+                thatThisTemplate
             );
         });
 
         it('should correctly run code inside template', () => {
-            assert.doesNotThrow(testFunc);
+            assert.doesNotThrow(() => testFunc.apply(root));
+            assert.isUndefined(root.document.location);
         });
     });
 
     describe('Variant #2: current domain matches with base domain of `domainsString`', () => {
         const domainsString: string = ['.example.com'].join(';');
+        const domainDest: string = 'about:blank';
         const currentDomain: string = 'www.example.com';
 
-        let testFunc: () => void;
+        let testFunc: Function;
+        let root: any;
 
         before(() => {
             const [
                 hiddenDomainsString,
-                diff
+                domainsStringDiff
             ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-            testFunc = () => getFunctionFromTemplate(
+            const [
+                hiddenDomainDest,
+                domainDestDiff
+            ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+            root = {
+                document: {
+                    domain: currentDomain,
+                    location: undefined,
+                },
+            };
+
+            testFunc = getFunctionFromTemplate(
                 {
                     domainLockFunctionName: 'domainLockFunction',
-                    diff: diff,
+                    domainsStringDiff,
                     domains: hiddenDomainsString,
-                    globalVariableTemplate: GlobalVariableTemplate1(),
+                    domainDestDiff,
+                    hiddenDomainDest,
+                    globalVariableTemplate: '',
                     singleCallControllerFunctionName
                 },
                 singleCallControllerFunctionName,
-                getDocumentDomainTemplate(currentDomain)
+                thatThisTemplate
             );
         });
 
         it('should correctly run code inside template', () => {
-            assert.doesNotThrow(testFunc);
+            assert.doesNotThrow(() => testFunc.apply(root));
+            assert.isUndefined(root.document.location);
         });
     });
 
     describe('Variant #3: current domain matches with root domain of `domainsString`', () => {
         const domainsString: string = ['.example.com'].join(';');
+        const domainDest: string = 'about:blank';
         const currentDomain: string = 'example.com';
 
-        let testFunc: () => void;
+        let testFunc: Function;
+        let root: any;
 
         before(() => {
             const [
                 hiddenDomainsString,
-                diff
+                domainsStringDiff
             ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-            testFunc = () => getFunctionFromTemplate(
+            const [
+                hiddenDomainDest,
+                domainDestDiff
+            ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+            root = {
+                document: {
+                    domain: currentDomain,
+                    location: undefined,
+                },
+            };
+
+            testFunc = getFunctionFromTemplate(
                 {
                     domainLockFunctionName: 'domainLockFunction',
-                    diff: diff,
+                    domainsStringDiff,
                     domains: hiddenDomainsString,
-                    globalVariableTemplate: GlobalVariableTemplate1(),
+                    domainDestDiff,
+                    hiddenDomainDest,
+                    globalVariableTemplate: '',
                     singleCallControllerFunctionName
                 },
                 singleCallControllerFunctionName,
-                getDocumentDomainTemplate(currentDomain)
+                thatThisTemplate
             );
         });
 
         it('should correctly run code inside template', () => {
-            assert.doesNotThrow(testFunc);
+            assert.doesNotThrow(() => testFunc.apply(root));
+            assert.isUndefined(root.document.location);
         });
     });
 
     describe('Variant #4: current root domain matches with `domainsString`', () => {
         describe('Variant #1', () => {
             const domainsString: string = ['example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
             it('should correctly run code inside template', () => {
-                assert.doesNotThrow(testFunc);
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.isUndefined(root.document.location);
             });
         });
 
         describe('Variant #2', () => {
             const domainsString: string = ['example.com', '.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'subdomain.example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
             it('should correctly run code inside template', () => {
-                assert.doesNotThrow(testFunc);
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.isUndefined(root.document.location);
             });
         });
 
         describe('Variant #3', () => {
             const domainsString: string = ['.example.com', 'example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'subdomain.example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
             it('should correctly run code inside template', () => {
-                assert.doesNotThrow(testFunc);
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.isUndefined(root.document.location);
             });
         });
 
         describe('Variant #4', () => {
             const domainsString: string = ['sub1.example.com', 'sub2.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'sub1.example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
             it('should correctly run code inside template', () => {
-                assert.doesNotThrow(testFunc);
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.isUndefined(root.document.location);
             });
         });
     });
 
     describe('Variant #5: current domain matches with base domain of `domainsString` item', () => {
         const domainsString: string = ['www.test.com', '.example.com'].join(';');
+        const domainDest: string = 'about:blank';
         const currentDomain: string = 'subdomain.example.com';
 
-        let testFunc: () => void;
+        let testFunc: Function;
+        let root: any;
 
         before(() => {
             const [
                 hiddenDomainsString,
-                diff
+                domainsStringDiff
             ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-            testFunc = () => getFunctionFromTemplate(
+            const [
+                hiddenDomainDest,
+                domainDestDiff
+            ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+            root = {
+                document: {
+                    domain: currentDomain,
+                    location: undefined,
+                },
+            };
+
+            testFunc = getFunctionFromTemplate(
                 {
                     domainLockFunctionName: 'domainLockFunction',
-                    diff: diff,
+                    domainsStringDiff,
                     domains: hiddenDomainsString,
-                    globalVariableTemplate: GlobalVariableTemplate1(),
+                    domainDestDiff,
+                    hiddenDomainDest,
+                    globalVariableTemplate: '',
                     singleCallControllerFunctionName
                 },
                 singleCallControllerFunctionName,
-                getDocumentDomainTemplate(currentDomain)
+                thatThisTemplate
             );
         });
 
         it('should correctly run code inside template', () => {
-            assert.doesNotThrow(testFunc);
+            assert.doesNotThrow(() => testFunc.apply(root));
+            assert.isUndefined(root.document.location);
         });
     });
 
     describe('Variant #6: current domain doesn\'t match with `domainsString`', () => {
         describe('Variant #1', () => {
             const domainsString: string = ['www.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'www.test.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
 
         describe('Variant #2', () => {
             const domainsString: string = ['sub1.test.com', 'sub2.test.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'sub3.test.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate({
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate({
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
 
         describe('Variant #3', () => {
             const domainsString: string = ['www.example.com', '.example.com', 'sub.test.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'www.test.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
 
         describe('Variant #4', () => {
             const domainsString: string = ['.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'example1.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
 
-        describe('Variant #4', () => {
+        describe('Variant #5', () => {
             const domainsString: string = ['example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentDomain: string = 'sub.example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentDomain,
+                        location: undefined,
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainTemplate(currentDomain)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
     });
@@ -496,61 +676,97 @@ describe('DomainLockTemplate', () => {
     describe('Variant #7: location.hostname', () => {
         describe('Variant #1: current location.hostname matches with `domainsString`', () => {
             const domainsString: string = ['www.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentHostName: string = 'www.example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        location: {
+                            hostname: currentHostName,
+                        },
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentLocationTemplate(currentHostName)
+                    thatThisTemplate
                 );
             });
 
             it('should correctly run code inside template', () => {
-                assert.doesNotThrow(testFunc);
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.isObject(root.document.location);
             });
         });
 
         describe('Variant #2: current location.hostname doesn\'t match with `domainsString`', () => {
             const domainsString: string = ['www.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentHostName: string = 'www.test.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        location: {
+                            hostname: currentHostName,
+                        },
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentLocationTemplate(currentHostName)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
     });
@@ -558,61 +774,99 @@ describe('DomainLockTemplate', () => {
     describe('Variant #8: domain and location.hostname presented', () => {
         describe('Variant #1: current domain matches with `domainsString`', () => {
             const domainsString: string = ['www.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentHostName: string = 'www.example.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentHostName,
+                        location: {
+                            hostname: currentHostName,
+                        },
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainAndLocationTemplate(currentHostName)
+                    thatThisTemplate
                 );
             });
 
             it('should correctly run code inside template', () => {
-                assert.doesNotThrow(testFunc);
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.isObject(root.document.location);
             });
         });
 
         describe('Variant #2: current domain doesn\'t match with `domainsString`', () => {
             const domainsString: string = ['www.example.com'].join(';');
+            const domainDest: string = 'about:blank';
             const currentHostName: string = 'www.test.com';
 
-            let testFunc: () => void;
+            let testFunc: Function;
+            let root: any;
 
             before(() => {
                 const [
                     hiddenDomainsString,
-                    diff
+                    domainsStringDiff
                 ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
-                testFunc = () => getFunctionFromTemplate(
+                const [
+                    hiddenDomainDest,
+                    domainDestDiff
+                ] = cryptUtils.hideString(domainDest, domainDest.length * 3);
+
+                root = {
+                    document: {
+                        domain: currentHostName,
+                        location: {
+                            hostname: currentHostName,
+                        },
+                    },
+                };
+
+                testFunc = getFunctionFromTemplate(
                     {
                         domainLockFunctionName: 'domainLockFunction',
-                        diff: diff,
+                        domainsStringDiff,
                         domains: hiddenDomainsString,
-                        globalVariableTemplate: GlobalVariableTemplate1(),
+                        domainDestDiff,
+                        domainDest: hiddenDomainDest,
+                        globalVariableTemplate: '',
                         singleCallControllerFunctionName
                     },
                     singleCallControllerFunctionName,
-                    getDocumentDomainAndLocationTemplate(currentHostName)
+                    thatThisTemplate
                 );
             });
 
-            it('should throw an error', () => {
-                assert.throws(testFunc);
+            it('should change document.location', () => {
+                assert.doesNotThrow(() => testFunc.apply(root));
+                assert.equal(root.document.location, domainDest);
             });
         });
     });

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff