浏览代码

Merge pull request #614 from javascript-obfuscator/mangled-memory-leak

Removed memory leak with `identifierNamesGenerator: 'mangled'`
Timofey Kachalov 5 年之前
父节点
当前提交
e76148cfac

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 
+v0.28.3
+---
+* Removed memory leak with `identifierNamesGenerator: 'mangled'`
+
 v0.28.2
 ---
 * Fixed change of kinds of variables for dead code with `deadCodeInjection` option

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


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


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


+ 7 - 6
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.28.2",
+  "version": "0.28.3",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -59,18 +59,18 @@
     "@types/sinon": "9.0.4",
     "@types/string-template": "1.0.2",
     "@types/webpack-env": "1.15.2",
-    "@typescript-eslint/eslint-plugin": "3.0.1",
-    "@typescript-eslint/parser": "3.0.1",
+    "@typescript-eslint/eslint-plugin": "3.0.2",
+    "@typescript-eslint/parser": "3.0.2",
     "chai": "4.2.0",
     "coveralls": "3.1.0",
     "eslint": "7.1.0",
     "eslint-plugin-import": "2.20.2",
-    "eslint-plugin-jsdoc": "25.4.2",
+    "eslint-plugin-jsdoc": "26.0.0",
     "eslint-plugin-no-null": "1.0.2",
     "eslint-plugin-prefer-arrow": "1.2.1",
-    "eslint-plugin-unicorn": "20.0.0",
+    "eslint-plugin-unicorn": "20.1.0",
     "fork-ts-checker-notifier-webpack-plugin": "2.0.0",
-    "fork-ts-checker-webpack-plugin": "4.1.5",
+    "fork-ts-checker-webpack-plugin": "4.1.6",
     "mocha": "7.2.0",
     "nyc": "15.0.1",
     "pjson": "1.0.9",
@@ -104,6 +104,7 @@
     "test:full": "scripts/test-full",
     "test:coveralls": "scripts/test-coveralls",
     "test:mocha": "scripts/test-mocha",
+    "test:mocha-memory-performance": "scripts/test-mocha-memory-performance",
     "test:removeTmpDir": "scripts/test-remove-tmp-dir",
     "test": "scripts/test",
     "eslint": "scripts/eslint",

+ 2 - 1
scripts/test-full

@@ -4,4 +4,5 @@ yarn run test:removeTmpDir &&
 yarn run test:compile &&
 node test-tmp/test/dev/dev.js &&
 $(yarn bin)/nyc --reporter text-summary $(yarn bin)/mocha -- test-tmp/test/index.spec.js --exit &&
-yarn run test:removeTmpDir
+yarn run test:removeTmpDir &&
+yarn run test:mocha-memory-performance

+ 6 - 0
scripts/test-mocha-memory-performance

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+yarn run test:removeTmpDir &&
+yarn run test:compile &&
+NODE_OPTIONS=--max-old-space-size=200 $(yarn bin)/mocha test-tmp/test/performance-tests/JavaScriptObfuscatorMemory.spec.js &&
+yarn run test:removeTmpDir

+ 2 - 2
src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts

@@ -17,9 +17,9 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
     private static readonly initMangledNameCharacter: string = '9';
 
     /**
-     * @type {Map<TNodeWithLexicalScope, string>}
+     * @type {WeakMap<TNodeWithLexicalScope, string>}
      */
-    private static readonly lastMangledNameInScopeMap: Map <TNodeWithLexicalScope, string> = new Map();
+    private static readonly lastMangledNameInScopeMap: WeakMap <TNodeWithLexicalScope, string> = new WeakMap();
 
     /**
      * @type {string[]}

+ 73 - 0
test/performance-tests/JavaScriptObfuscatorMemory.spec.ts

@@ -0,0 +1,73 @@
+import { assert } from 'chai';
+
+import { readFileAsString } from '../helpers/readFileAsString';
+
+import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscatorFacade';
+
+const heapValueToMB = (value: number) => Math.round(value / 1024 / 1024 * 100) / 100;
+
+describe('JavaScriptObfuscator memory', function () {
+    const iterationsCount: number = 500;
+    const gcDiffThreshold: number = 10;
+    const allowedHeapDiffThreshold: number = 40;
+
+    this.timeout(100000);
+
+    describe('memory: heap usage', () => {
+        it('should keep heap usage without memory leaks', () => {
+            const sourceCode: string = readFileAsString('./test/fixtures/sample.js');
+
+            const maxHeapUsed: number[] = [];
+            let prevHeapUsed: number | null = null;
+
+            for (let i: number = 0; i < iterationsCount; i++) {
+                JavaScriptObfuscator.obfuscate(
+                    sourceCode,
+                    {
+                        compact: true,
+                        controlFlowFlattening: true,
+                        controlFlowFlatteningThreshold: 0.75,
+                        deadCodeInjection: true,
+                        deadCodeInjectionThreshold: 0.4,
+                        debugProtection: false,
+                        debugProtectionInterval: false,
+                        disableConsoleOutput: true,
+                        identifierNamesGenerator: 'mangled',
+                        log: false,
+                        renameGlobals: false,
+                        rotateStringArray: true,
+                        selfDefending: true,
+                        shuffleStringArray: true,
+                        splitStrings: true,
+                        splitStringsChunkLength: 2,
+                        stringArray: true,
+                        stringArrayEncoding: 'base64',
+                        stringArrayThreshold: 0.75,
+                        transformObjectKeys: true,
+                        unicodeEscapeSequence: false
+                    }
+                );
+
+                const heap = process.memoryUsage();
+                const heapUsed: number = heapValueToMB(heap.heapUsed);
+
+                const gcDiff: number = (prevHeapUsed ?? heapUsed) - heapUsed;
+
+                if (prevHeapUsed && gcDiff > gcDiffThreshold) {
+                    maxHeapUsed.push(prevHeapUsed);
+                }
+
+                prevHeapUsed = heapUsed;
+            }
+
+            const sortedMaxHeapUsed: number[] = [...maxHeapUsed].sort((a: number, b: number) => a - b);
+
+            const firstMaxHeapMBUsed: number = sortedMaxHeapUsed[0];
+            const lastMaxHeapMbUsed: number = sortedMaxHeapUsed[sortedMaxHeapUsed.length - 1];
+
+            const diff: number = lastMaxHeapMbUsed - firstMaxHeapMBUsed;
+
+            assert.closeTo(diff, 0, allowedHeapDiffThreshold);
+        });
+    });
+});

+ 46 - 49
yarn.lock

@@ -409,41 +409,41 @@
   resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.2.tgz#927997342bb9f4a5185a86e6579a0a18afc33b0a"
   integrity sha512-67ZgZpAlhIICIdfQrB5fnDvaKFcDxpKibxznfYRVAT4mQE41Dido/3Ty+E3xGBmTogc5+0Qb8tWhna+5B8z1iQ==
 
-"@typescript-eslint/[email protected].1":
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.0.1.tgz#368fe7d4c3d927e9fd27b7ba150b4b7e83ddfabe"
-  integrity sha512-RxGldRQD3hgOK2xtBfNfA5MMV3rn5gVChe+MIf14hKm51jO2urqF64xOyVrGtzThkrd4rS1Kihqx2nkSxkXHvA==
+"@typescript-eslint/[email protected].2":
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.0.2.tgz#4a114a066e2f9659b25682ee59d4866e15a17ec3"
+  integrity sha512-ER3bSS/A/pKQT/hjMGCK8UQzlL0yLjuCZ/G8CDFJFVTfl3X65fvq2lNYqOG8JPTfrPa2RULCdwfOyFjZEMNExQ==
   dependencies:
-    "@typescript-eslint/experimental-utils" "3.0.1"
+    "@typescript-eslint/experimental-utils" "3.0.2"
     functional-red-black-tree "^1.0.1"
     regexpp "^3.0.0"
     semver "^7.3.2"
     tsutils "^3.17.1"
 
-"@typescript-eslint/[email protected].1":
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.0.1.tgz#e2721c970068fabd6621709234809c98cd3343ad"
-  integrity sha512-GdwOVz80MOWxbc/br1DC30eeqlxfpVzexHgHtf3L0hcbOu1xAs1wSCNcaBTLMOMZbh1gj/cKZt0eB207FxWfFA==
+"@typescript-eslint/[email protected].2":
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.0.2.tgz#bb2131baede8df28ec5eacfa540308ca895e5fee"
+  integrity sha512-4Wc4EczvoY183SSEnKgqAfkj1eLtRgBQ04AAeG+m4RhTVyaazxc1uI8IHf0qLmu7xXe9j1nn+UoDJjbmGmuqXQ==
   dependencies:
     "@types/json-schema" "^7.0.3"
-    "@typescript-eslint/typescript-estree" "3.0.1"
+    "@typescript-eslint/typescript-estree" "3.0.2"
     eslint-scope "^5.0.0"
     eslint-utils "^2.0.0"
 
-"@typescript-eslint/[email protected].1":
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.0.1.tgz#f5163e3a789422f5c62f4daf822bfa03b7e4472d"
-  integrity sha512-Pn2tDmOc4Ri93VQnT70W0pqQr6i/pEZqIPXfWXm4RuiIprL0t6SG13ViVXHgfScknL2Fm2G4IqXhUzxSRCWXCw==
+"@typescript-eslint/[email protected].2":
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.0.2.tgz#a92ef339added9bf7fb92605ac99c93ef243e834"
+  integrity sha512-80Z7s83e8QXHNUspqVlWwb4t5gdz/1bBBmafElbK1wwAwiD/yvJsFyHRxlEpNrt4rdK6eB3p+2WEFkEDHAKk9w==
   dependencies:
     "@types/eslint-visitor-keys" "^1.0.0"
-    "@typescript-eslint/experimental-utils" "3.0.1"
-    "@typescript-eslint/typescript-estree" "3.0.1"
+    "@typescript-eslint/experimental-utils" "3.0.2"
+    "@typescript-eslint/typescript-estree" "3.0.2"
     eslint-visitor-keys "^1.1.0"
 
-"@typescript-eslint/[email protected].1":
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.0.1.tgz#8c0cfb7cda64bd6f54185a7b7d1923d25d36b2a8"
-  integrity sha512-FrbMdgVCeIGHKaP9OYTttFTlF8Ds7AkjMca2GzYCE7pVch10PAJc1mmAFt+DfQPgu/2TrLAprg2vI0PK/WTdcg==
+"@typescript-eslint/[email protected].2":
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.0.2.tgz#67a1ce4307ebaea43443fbf3f3be7e2627157293"
+  integrity sha512-cs84mxgC9zQ6viV8MEcigfIKQmKtBkZNDYf8Gru2M+MhnA6z9q0NFMZm2IEzKqAwN8lY5mFVd1Z8DiHj6zQ3Tw==
   dependencies:
     debug "^4.1.1"
     eslint-visitor-keys "^1.1.0"
@@ -1847,10 +1847,10 @@ [email protected]:
     read-pkg-up "^2.0.0"
     resolve "^1.12.0"
 
-eslint-plugin-jsdoc@25.4.2:
-  version "25.4.2"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-25.4.2.tgz#1a8480e880c4d343ba9bc77caf6c91e4500d7a71"
-  integrity sha512-IFZnxBBt2fGYZ9yaLt+KP/jHa6u8LQPwH9QzRlhbU+WKBq7ou6XTXoxG0EZVn9ohcbJ0sM8X70iRRX/J3Wu37w==
+eslint-plugin-jsdoc@26.0.0:
+  version "26.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-26.0.0.tgz#91d0d958eec1a2b8915a60462a7a57a665c58ef1"
+  integrity sha512-/oEywHPBn6eVDExTgDTwdwyQlVIuJziovXOPXBROW8yW93vk6/IGezW5jbzmA2pX4tVRCQc/jz5/mZea+FCmfw==
   dependencies:
     comment-parser "^0.7.4"
     debug "^4.1.1"
@@ -1870,18 +1870,19 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.1.tgz#9e2943cdae4476e41f94f50dd7a250f267db6865"
   integrity sha512-CPAvdTGG0YbFAJrUKdRBrOJ0X1I7jTtF5VIM4m2Bw1/A2jrhfUeUAcPy4pAEB5DNaUuDqc59f3pKTeiVeamS1A==
 
-eslint-plugin-unicorn@20.0.0:
-  version "20.0.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-20.0.0.tgz#40c71f7b8bfac7994c64f2698088b4859ff5ef3e"
-  integrity sha512-Uob50ZUfqKO4kK3YI3johD3Mnlzs2mWHGELbxFPEWj/2sOAMTV5769t9gGQNzarif+HXRmsKnqZS6XMkfb80Bg==
+eslint-plugin-unicorn@20.1.0:
+  version "20.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-20.1.0.tgz#a43f60ffc98406d72ec2a5fcc6dad24ba0192bc9"
+  integrity sha512-XQxLBJT/gnwyRR6cfYsIK1AdekQchAt5tmcsnldevGjgR2xoZsRUa5/i6e0seNHy2RoT57CkTnbVHwHF8No8LA==
   dependencies:
     ci-info "^2.0.0"
     clean-regexp "^1.0.0"
     eslint-ast-utils "^1.1.0"
-    eslint-template-visitor "^1.1.0"
+    eslint-template-visitor "^2.0.0"
     eslint-utils "^2.0.0"
     import-modules "^2.0.0"
     lodash "^4.17.15"
+    pluralize "^8.0.0"
     read-pkg-up "^7.0.1"
     regexp-tree "^0.1.21"
     reserved-words "^0.1.2"
@@ -1904,14 +1905,14 @@ eslint-scope@^4.0.3:
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
 
-eslint-template-visitor@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-1.1.0.tgz#f090d124d1a52e05552149fc50468ed59608b166"
-  integrity sha512-Lmy6QVlmFiIGl5fPi+8ACnov3sare+0Ouf7deJAGGhmUfeWJ5fVarELUxZRpsZ9sHejiJUq8626d0dn9uvcZTw==
+eslint-template-visitor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-2.0.0.tgz#7cb6471ed29a53ab28a1dcbfca38355251c2be06"
+  integrity sha512-WijrLXWk/TiiG9FBTeEeb2pj/nD8H4eKIYx1DhTv/c7QoFmelE5P+3gzKUcXWZz88AI2+Wjse9DTV8lXrhcUsw==
   dependencies:
     eslint-visitor-keys "^1.1.0"
-    espree "^6.1.1"
-    multimap "^1.0.2"
+    espree "^7.0.0"
+    multimap "^1.1.0"
 
 eslint-utils@^2.0.0:
   version "2.0.0"
@@ -1972,15 +1973,6 @@ esm@^3.2.25:
   resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
   integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
 
-espree@^6.1.1:
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
-  integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
-  dependencies:
-    acorn "^7.1.1"
-    acorn-jsx "^5.2.0"
-    eslint-visitor-keys "^1.1.0"
-
 espree@^7.0.0:
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e"
@@ -2288,10 +2280,10 @@ [email protected]:
   dependencies:
     node-notifier "^6.0.0"
 
[email protected].5:
-  version "4.1.5"
-  resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.5.tgz#780d52c65183742d8c885fff42a9ec9ea7006672"
-  integrity sha512-nuD4IDqoOfkEIlS6shhjLGaLBDSNyVJulAlr5lFbPe0saGqlsTo+/HmhtIrs/cNLFtmaudL10byivhxr+Qhh4w==
[email protected].6:
+  version "4.1.6"
+  resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz#5055c703febcf37fa06405d400c122b905167fc5"
+  integrity sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==
   dependencies:
     "@babel/code-frame" "^7.5.5"
     chalk "^2.4.1"
@@ -3581,7 +3573,7 @@ ms@^2.1.1:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
   integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
-multimap@^1.0.2:
+multimap@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/multimap/-/multimap-1.1.0.tgz#5263febc085a1791c33b59bb3afc6a76a2a10ca8"
   integrity sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==
@@ -4162,6 +4154,11 @@ pkg-dir@^4.1.0:
   dependencies:
     find-up "^4.0.0"
 
+pluralize@^8.0.0:
+  version "8.0.0"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
+  integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
+
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"

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