js-confuser 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # `1.7.1`
2
+ Updates
3
+
4
+ - Fixed [#107](https://github.com/MichaelXF/js-confuser/issues/107)
5
+ - - RGF and Integrity clash issue fixed
6
+
7
+ - Fixed [#106](https://github.com/MichaelXF/js-confuser/issues/106)
8
+ - - Object Extraction to properly handle `const` objects
9
+
10
+ - Fixed [#105](https://github.com/MichaelXF/js-confuser/issues/105)
11
+ - - Duplicate Literals Removal updated to not cause this error
12
+
13
+ - Fixed [#103](https://github.com/MichaelXF/js-confuser/issues/103)
14
+ - - Dispatcher will no longer apply to these types of functions to prevent this error
15
+
16
+ - Added documentation page for [ES5](https://github.com/MichaelXF/js-confuser/blob/master/docs/ES5.md)
17
+
18
+ - Rollup Plugin created: https://github.com/ayecue/rollup-js-confuser (Thanks @ayecue !)
19
+
1
20
  # `1.7.0`
2
21
  Updates
3
22
 
package/README.md CHANGED
@@ -737,7 +737,6 @@ function iVQoGQD(...iVQoGQD){
737
737
  stringSplitting: 0.75,
738
738
 
739
739
  // Use at own risk
740
- eval: false,
741
740
  rgf: false
742
741
  }
743
742
  ```
@@ -828,7 +827,6 @@ These features are experimental or a security concern.
828
827
  ```js
829
828
  {
830
829
  target: "node",
831
- eval: true, // (security concern)
832
830
  rgf: true, // (security concern)
833
831
 
834
832
  // set to false for web-related scripts
@@ -123,6 +123,12 @@ class Dispatcher extends _transform.default {
123
123
  illegalFnNames.add(name);
124
124
  return "EXIT";
125
125
  }
126
+ } // Avoid functions with function expressions as they have a different scope
127
+
128
+
129
+ if ((oo.type === "FunctionExpression" || oo.type === "ArrowFunctionExpression") && pp.find(x => x == o.params)) {
130
+ illegalFnNames.add(name);
131
+ return "EXIT";
126
132
  }
127
133
  });
128
134
  functionDeclarations[name] = [o, p];
@@ -25,6 +25,8 @@ var _random = require("../../util/random");
25
25
 
26
26
  var _traverse = require("../../traverse");
27
27
 
28
+ var _identifiers = require("../../util/identifiers");
29
+
28
30
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
31
 
30
32
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -163,7 +165,10 @@ class DuplicateLiteralsRemoval extends _transform.default {
163
165
 
164
166
  transform(object, parents) {
165
167
  return () => {
166
- var value = object.value;
168
+ if (object.type === "Identifier") {
169
+ var info = (0, _identifiers.getIdentifierInfo)(object, parents);
170
+ if (info.isLabel || info.spec.isDefined) return;
171
+ }
167
172
 
168
173
  if (object.regex) {
169
174
  return;
@@ -236,7 +236,12 @@ class ObjectExtraction extends _transform.default {
236
236
  var v = property.value;
237
237
  variableDeclarators.push((0, _gen.VariableDeclarator)(nn, this.addComment(v, "".concat(name, ".").concat(keyName))));
238
238
  });
239
- declaration.declarations.splice(declaration.declarations.indexOf(declarator), 1, ...variableDeclarators); // update all identifiers that pointed to the old object
239
+ declaration.declarations.splice(declaration.declarations.indexOf(declarator), 1, ...variableDeclarators);
240
+
241
+ if (declaration.kind === "const") {
242
+ declaration.kind = "var";
243
+ } // update all identifiers that pointed to the old object
244
+
240
245
 
241
246
  objectDefChanges[name] && objectDefChanges[name].forEach(change => {
242
247
  if (!change.key) {
@@ -23,6 +23,8 @@ var _identifiers = require("../util/identifiers");
23
23
 
24
24
  var _insert = require("../util/insert");
25
25
 
26
+ var _integrity = _interopRequireDefault(require("./lock/integrity"));
27
+
26
28
  var _transform = _interopRequireDefault(require("./transform"));
27
29
 
28
30
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -170,7 +172,13 @@ class RGF extends _transform.default {
170
172
  });
171
173
 
172
174
  if (obfuscator.options.lock) {
173
- delete obfuscator.options.lock.countermeasures;
175
+ delete obfuscator.options.lock.countermeasures; // Integrity will not recursively apply to RGF'd functions. This is intended.
176
+
177
+ var lockTransform = obfuscator.transforms["Lock"];
178
+
179
+ if (lockTransform) {
180
+ lockTransform.before = lockTransform.before.filter(beforeTransform => !(beforeTransform instanceof _integrity.default));
181
+ }
174
182
  }
175
183
 
176
184
  var transforms = obfuscator.array.filter(x => x.priority > this.priority);
@@ -86,10 +86,11 @@ function getIdentifierInfo(object, parents) {
86
86
  }
87
87
 
88
88
  var varIndex = parents.findIndex(x => x.type == "VariableDeclarator");
89
- var isVariableDeclaration = varIndex != -1 && parents[varIndex].id == (parents[varIndex - 1] || object) && parents.find(x => x.type == "VariableDeclaration") && objectPatternCheck(object, parents); // Assignment pattern check!
89
+ var isVariableDeclaration = varIndex != -1 && parents[varIndex].id == (parents[varIndex - 1] || object) && parents.find(x => x.type == "VariableDeclaration") && objectPatternCheck(object, parents);
90
+ var functionIndex = parents.findIndex(x => (0, _insert.isFunction)(x)); // Assignment pattern check!
90
91
 
91
92
  if (isVariableDeclaration) {
92
- var slicedParents = parents.slice(0, varIndex - 1);
93
+ var slicedParents = parents.slice(0, functionIndex != -1 ? Math.min(varIndex, functionIndex) : varIndex);
93
94
  var i = 0;
94
95
 
95
96
  for (var parent of slicedParents) {
@@ -106,7 +107,6 @@ function getIdentifierInfo(object, parents) {
106
107
 
107
108
  var forIndex = parents.findIndex(x => x.type == "ForStatement");
108
109
  var isForInitializer = forIndex != -1 && parents[forIndex].init == (parents[forIndex - 1] || object);
109
- var functionIndex = parents.findIndex(x => (0, _insert.isFunction)(x));
110
110
  var isFunctionDeclaration = functionIndex != -1 && parents[functionIndex].type == "FunctionDeclaration" && parents[functionIndex].id == object;
111
111
  var isNamedFunctionExpression = functionIndex != -1 && parents[functionIndex].type === "FunctionExpression" && parents[functionIndex].id === object;
112
112
  var isAFunctionParameter = isFunctionParameter(object, parents);
@@ -137,7 +137,7 @@ while (mJMdMhJ + A1Nyvv + xDwpOk6 != 83) {
137
137
  }
138
138
  ```
139
139
 
140
- As seen in the example, your code will bee wrapped in a large, complicated switch statement. The makes the behavior of your program very hard to understand and is resistent to deobfuscators. This comes with a large performance reduction.
140
+ As seen in the example, your code will be wrapped in a large, complicated switch statement. The makes the behavior of your program very hard to understand and is resistent to deobfuscators. This comes with a large performance reduction.
141
141
 
142
142
  ## Flattening Control Structures
143
143
 
package/docs/ES5.md ADDED
@@ -0,0 +1,197 @@
1
+ ## `ES5`
2
+
3
+ The ES5 option converts most ES6+ features into ES5 compatible code.
4
+
5
+ Option name: `es5`
6
+
7
+ Option values: `true/false`
8
+
9
+ Note: Does not cover all cases such as Promises or Generator functions. Use [Babel](https://babel.dev/).
10
+
11
+ The ES5 option is intended to undo any ES6 feature the obfuscator adds to your code. If you input ES5 code, and enable the `es5` option, you can be guaranteed to have ES5 compatible output.
12
+
13
+ ## Example
14
+
15
+ ```js
16
+ // Input
17
+ function print(...messages){
18
+ console.log(...messages); // The spread operator (...)
19
+ // was introduced in ES6!
20
+ }
21
+
22
+ print("Hello", "World"); // "Hello World"
23
+
24
+ // Output
25
+ var __p_2580918143;
26
+ function print() {
27
+ var __p_7607361496;
28
+ var messages, __p_2591841272 = (__p_7607361496 = Array.prototype.slice.call(arguments), messages = __p_7607361496.slice(0));
29
+ (__p_2580918143 = console).log.apply(__p_2580918143, [].concat(Array.prototype.slice.call(messages)));
30
+ }
31
+ print('Hello', 'World'); // "Hello World"
32
+ ```
33
+
34
+ ## Polyfill Array Methods
35
+
36
+ When the ES5 option is enabled, array method polyfills will be injected to the top of your script.
37
+
38
+ ```js
39
+ if (!Array.prototype.forEach) {
40
+ Array.prototype.forEach = function forEach(callback, thisArg) {
41
+ if (typeof callback !== 'function') {
42
+ throw new TypeError(callback + ' is not a function');
43
+ }
44
+ var array = this;
45
+ thisArg = thisArg || this;
46
+ for (var i = 0, l = array.length; i !== l; ++i) {
47
+ callback.call(thisArg, array[i], i, array);
48
+ }
49
+ };
50
+ }
51
+ ```
52
+
53
+ ## Destructuring
54
+
55
+ The ES5 option supports transpiling the destructuring patterns.
56
+
57
+ ```js
58
+ // Input
59
+ var {userName, email} = { userName: "John", email: "email@exampe.com" };
60
+
61
+ // Output
62
+ var __p_7467473759;
63
+ var userName, email, __p_4755992742 = (__p_7467473759 = {
64
+ userName: 'John',
65
+ email: 'email@exampe.com'
66
+ }, userName = __p_7467473759.userName, email = __p_7467473759.email);
67
+ ```
68
+
69
+ ## Spread Operator
70
+
71
+ The ES5 option supports transpiling the spread operator.
72
+
73
+ ```js
74
+ // Input
75
+ array.push(...objects);
76
+
77
+ // Output
78
+ var __p_6344935930;
79
+ (__p_6344935930 = array).push.apply(__p_6344935930, [].concat(Array.prototype.slice.call(objects)));
80
+ ```
81
+
82
+ ## Template String
83
+
84
+ The ES5 option supports transpiling template strings.
85
+
86
+ ```js
87
+ // Input
88
+ var myString = `Hello ${userName}`;
89
+
90
+ // Output
91
+ var myString = 'Hello ' + (userName + '');
92
+ ```
93
+
94
+ ## Object getters/setters
95
+
96
+ The ES5 option supports transpiling getter and setter methods.
97
+
98
+ ```js
99
+ // Input
100
+ var _name;
101
+ var myObject = {
102
+ get name(){
103
+ return _name;
104
+ },
105
+ set name(newName){
106
+ _name = newName;
107
+ }
108
+ };
109
+
110
+ // Output
111
+ function __p_6886881506(base, computedProps, getters, setters) {
112
+ for (var i = 0; i < computedProps.length; i++) {
113
+ base[computedProps[i][0]] = computedProps[i][1];
114
+ }
115
+ var keys = Object.create(null);
116
+ Object.keys(getters).forEach(function (key) {
117
+ return keys[key] = 1;
118
+ });
119
+ Object.keys(setters).forEach(function (key) {
120
+ return keys[key] = 1;
121
+ });
122
+ Object.keys(keys).forEach(function (key) {
123
+ Object.defineProperty(base, key, {
124
+ set: setters[key],
125
+ get: getters[key],
126
+ configurable: true
127
+ });
128
+ });
129
+ return base;
130
+ }
131
+ var _name;
132
+ var myObject = __p_6886881506({}, [], {
133
+ 'name': function () {
134
+ return _name;
135
+ }
136
+ }, {
137
+ 'name': function (newName) {
138
+ _name = newName;
139
+ }
140
+ });
141
+ ```
142
+
143
+ ## Arrow Functions
144
+
145
+ The ES5 option converts arrow functions into regular functions.
146
+
147
+ ```js
148
+ // Input
149
+ var print = message => console.log(message);
150
+
151
+ // Output
152
+ var print = function (message) {
153
+ return console.log(message);
154
+ };
155
+ ```
156
+
157
+ ## Const/Let
158
+
159
+ The ES5 option converts `const` and `let` to a regular `var` keyword.
160
+
161
+ ```js
162
+ // Input
163
+ let myVar1 = true;
164
+ const myVar2 = "String";
165
+
166
+ // Output
167
+ var myVar1 = true;
168
+ var myVar2 = 'String';
169
+ ```
170
+
171
+ ## Classes
172
+
173
+ The ES5 option partially supports transpiling classes.
174
+
175
+ ## Reserved Identifiers
176
+
177
+ The ES5 option will change any illegal uses of reserved identifiers.
178
+
179
+ ```js
180
+ // Input
181
+ var myObject = {true: 1};
182
+ myObject.for = true;
183
+
184
+ // Output
185
+ var myObject = {"true": 1};
186
+ myObject["for"] = true;
187
+ ```
188
+
189
+ ## Features not supported
190
+
191
+ - Promises
192
+ - Async / Await
193
+ - Generator functions
194
+ - Nullish coalescing
195
+ - Optional chaining
196
+
197
+ Use [Babel](https://babel.dev/) to transpile these features. JS-Confuser will only support features the obfuscator may potentially add to your code.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-confuser",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "JavaScript Obfuscation Tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "author": "MichaelXF",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "acorn": "^8.8.2",
25
+ "acorn": "^8.10.0",
26
26
  "escodegen": "^2.0.0"
27
27
  },
28
28
  "devDependencies": {
@@ -157,6 +157,16 @@ export default class Dispatcher extends Transform {
157
157
  return "EXIT";
158
158
  }
159
159
  }
160
+
161
+ // Avoid functions with function expressions as they have a different scope
162
+ if (
163
+ (oo.type === "FunctionExpression" ||
164
+ oo.type === "ArrowFunctionExpression") &&
165
+ pp.find((x) => x == o.params)
166
+ ) {
167
+ illegalFnNames.add(name);
168
+ return "EXIT";
169
+ }
160
170
  });
161
171
 
162
172
  functionDeclarations[name] = [o, p];
@@ -24,6 +24,7 @@ import { ComputeProbabilityMap } from "../../probability";
24
24
  import { ok } from "assert";
25
25
  import { chance, choice, getRandomInteger } from "../../util/random";
26
26
  import { getBlock } from "../../traverse";
27
+ import { getIdentifierInfo } from "../../util/identifiers";
27
28
 
28
29
  /**
29
30
  * [Duplicate Literals Removal](https://docs.jscrambler.com/code-integrity/documentation/transformations/duplicate-literals-removal) replaces duplicate literals with a variable name.
@@ -221,7 +222,10 @@ export default class DuplicateLiteralsRemoval extends Transform {
221
222
 
222
223
  transform(object: Node, parents: Node[]) {
223
224
  return () => {
224
- var value = object.value;
225
+ if (object.type === "Identifier") {
226
+ var info = getIdentifierInfo(object, parents);
227
+ if (info.isLabel || info.spec.isDefined) return;
228
+ }
225
229
  if (object.regex) {
226
230
  return;
227
231
  }
@@ -316,6 +316,10 @@ export default class ObjectExtraction extends Transform {
316
316
  ...variableDeclarators
317
317
  );
318
318
 
319
+ if (declaration.kind === "const") {
320
+ declaration.kind = "var";
321
+ }
322
+
319
323
  // update all identifiers that pointed to the old object
320
324
  objectDefChanges[name] &&
321
325
  objectDefChanges[name].forEach((change) => {
@@ -20,6 +20,7 @@ import {
20
20
  } from "../util/gen";
21
21
  import { getIdentifierInfo } from "../util/identifiers";
22
22
  import { prepend, getDefiningContext } from "../util/insert";
23
+ import Integrity from "./lock/integrity";
23
24
  import Transform from "./transform";
24
25
 
25
26
  /**
@@ -200,6 +201,14 @@ export default class RGF extends Transform {
200
201
 
201
202
  if (obfuscator.options.lock) {
202
203
  delete obfuscator.options.lock.countermeasures;
204
+
205
+ // Integrity will not recursively apply to RGF'd functions. This is intended.
206
+ var lockTransform = obfuscator.transforms["Lock"];
207
+ if (lockTransform) {
208
+ lockTransform.before = lockTransform.before.filter(
209
+ (beforeTransform) => !(beforeTransform instanceof Integrity)
210
+ );
211
+ }
203
212
  }
204
213
 
205
214
  var transforms = obfuscator.array.filter(
@@ -94,9 +94,14 @@ export function getIdentifierInfo(object: Node, parents: Node[]) {
94
94
  parents.find((x) => x.type == "VariableDeclaration") &&
95
95
  objectPatternCheck(object, parents);
96
96
 
97
+ var functionIndex = parents.findIndex((x) => isFunction(x));
98
+
97
99
  // Assignment pattern check!
98
100
  if (isVariableDeclaration) {
99
- var slicedParents = parents.slice(0, varIndex - 1);
101
+ var slicedParents = parents.slice(
102
+ 0,
103
+ functionIndex != -1 ? Math.min(varIndex, functionIndex) : varIndex
104
+ );
100
105
  var i = 0;
101
106
  for (var parent of slicedParents) {
102
107
  var childNode = slicedParents[i - 1] || object;
@@ -113,8 +118,6 @@ export function getIdentifierInfo(object: Node, parents: Node[]) {
113
118
  forIndex != -1 &&
114
119
  parents[forIndex].init == (parents[forIndex - 1] || object);
115
120
 
116
- var functionIndex = parents.findIndex((x) => isFunction(x));
117
-
118
121
  var isFunctionDeclaration =
119
122
  functionIndex != -1 &&
120
123
  parents[functionIndex].type == "FunctionDeclaration" &&
@@ -373,3 +373,30 @@ test("Variant #16: Don't change functions that use 'eval'", async () => {
373
373
 
374
374
  expect(TEST_OUTPUT).toStrictEqual(2);
375
375
  });
376
+
377
+ // https://github.com/MichaelXF/js-confuser/issues/103
378
+ test("Variant #17: Don't break default parameter, function expression", async () => {
379
+ var output = await JsConfuser(
380
+ `
381
+ var X = "Correct Value";
382
+
383
+ function printX(
384
+ getX = function () {
385
+ return X;
386
+ }
387
+ ) {
388
+ var X = "Incorrect Value";
389
+
390
+ TEST_OUTPUT = getX();
391
+ }
392
+
393
+ printX();
394
+ `,
395
+ { target: "node", dispatcher: true }
396
+ );
397
+
398
+ var TEST_OUTPUT;
399
+ eval(output);
400
+
401
+ expect(TEST_OUTPUT).toStrictEqual("Correct Value");
402
+ });
@@ -1,6 +1,6 @@
1
1
  import JsConfuser from "../../../src/index";
2
2
 
3
- it("should remove duplicate literals", async () => {
3
+ test("Variant #1: Remove duplicate literals", async () => {
4
4
  var code = `
5
5
 
6
6
  var TEST_ARRAY = [5,5];
@@ -15,7 +15,7 @@ it("should remove duplicate literals", async () => {
15
15
  expect(output).toContain("5");
16
16
  });
17
17
 
18
- it("should remove duplicate literals and execute correctly", async () => {
18
+ test("Variant #2: Remove duplicate literals and execute correctly", async () => {
19
19
  var code = `
20
20
 
21
21
  TEST_ARRAY = [5,5];
@@ -36,7 +36,7 @@ it("should remove duplicate literals and execute correctly", async () => {
36
36
  expect(TEST_ARRAY).toEqual([5, 5]);
37
37
  });
38
38
 
39
- it("should remove 'undefined' and 'null' values", async () => {
39
+ test("Variant #3: Remove 'undefined' and 'null' values", async () => {
40
40
  var code = `
41
41
 
42
42
  TEST_ARRAY = [undefined,undefined,null,null];
@@ -60,7 +60,7 @@ it("should remove 'undefined' and 'null' values", async () => {
60
60
  expect(TEST_ARRAY).toEqual([undefined, undefined, null, null]);
61
61
  });
62
62
 
63
- it("should not remove empty strings", async () => {
63
+ test("Variant #4: Do not remove empty strings", async () => {
64
64
  var code = `
65
65
 
66
66
  TEST_ARRAY = ['','','',''];
@@ -80,7 +80,7 @@ it("should not remove empty strings", async () => {
80
80
  expect(TEST_ARRAY).toEqual(["", "", "", ""]);
81
81
  });
82
82
 
83
- it("should work with NaN values", async () => {
83
+ test("Variant #5: Work with NaN values", async () => {
84
84
  var code = `
85
85
 
86
86
  TEST_ARRAY = [NaN];
@@ -98,7 +98,7 @@ it("should work with NaN values", async () => {
98
98
  expect(TEST_ARRAY[0] === TEST_ARRAY[0]).toStrictEqual(false);
99
99
  });
100
100
 
101
- it("should work on property keys", async () => {
101
+ test("Variant #6: Work on property keys", async () => {
102
102
  var code = `
103
103
  var myObject = {
104
104
  myKey: 100
@@ -124,7 +124,7 @@ it("should work on property keys", async () => {
124
124
  expect(TEST_VAR).toStrictEqual(100);
125
125
  });
126
126
 
127
- it("should work on class keys", async () => {
127
+ test("Variant #7: Work on class keys", async () => {
128
128
  var code = `
129
129
  class MyClass {
130
130
  myMethod(){
@@ -150,7 +150,7 @@ it("should work on class keys", async () => {
150
150
  expect(TEST_VAR).toStrictEqual(100);
151
151
  });
152
152
 
153
- it("should not encode constructor key", async () => {
153
+ test("Variant #8: Do not encode constructor key", async () => {
154
154
  var code = `
155
155
  class MyClass {
156
156
  constructor(){
@@ -177,3 +177,16 @@ it("should not encode constructor key", async () => {
177
177
 
178
178
  expect(TEST_VAR).toStrictEqual(100);
179
179
  });
180
+
181
+ // https://github.com/MichaelXF/js-confuser/issues/105
182
+ test("Variant #9: Undefined as variable name", async () => {
183
+ var output = await JsConfuser(
184
+ `
185
+ var undefined = 0;
186
+ var undefined = 1;
187
+ `,
188
+ { target: "node", duplicateLiteralsRemoval: true }
189
+ );
190
+
191
+ eval(output);
192
+ });
@@ -1,6 +1,6 @@
1
1
  import JsConfuser from "../../../src/index";
2
2
 
3
- it("should extract properties", async () => {
3
+ test("Variant #1: Extract properties", async () => {
4
4
  var code = `
5
5
  var TEST_OBJECT = {
6
6
  TEST_1: "Hello World",
@@ -34,7 +34,7 @@ it("should extract properties", async () => {
34
34
  eval(output);
35
35
  });
36
36
 
37
- it("should extract function properties correctly", async () => {
37
+ test("Variant #2: Extract function properties correctly", async () => {
38
38
  var code = `
39
39
  var TEST_OBJECT = {
40
40
  isBoolean: x=>typeof x === "boolean",
@@ -68,7 +68,7 @@ it("should extract function properties correctly", async () => {
68
68
  eval(output);
69
69
  });
70
70
 
71
- it("should not extract properties on with dynamically added keys", async () => {
71
+ test("Variant #3: Not extract properties on with dynamically added keys", async () => {
72
72
  var code = `
73
73
  var TEST_OBJECT = {
74
74
  first_key: 1
@@ -100,7 +100,7 @@ it("should not extract properties on with dynamically added keys", async () => {
100
100
  eval(output);
101
101
  });
102
102
 
103
- it("should not extract properties on with dynamically added keys even when in nested contexts", async () => {
103
+ test("Variant #4: Not extract properties on with dynamically added keys even when in nested contexts", async () => {
104
104
  var code = `
105
105
  var TEST_OBJECT = {
106
106
  first_key: 1
@@ -135,7 +135,7 @@ it("should not extract properties on with dynamically added keys even when in ne
135
135
  eval(output);
136
136
  });
137
137
 
138
- it("should not extract properties on objects with computed properties", async () => {
138
+ test("Variant #5: Not extract properties on objects with computed properties", async () => {
139
139
  var code = `
140
140
 
141
141
  var key = "111"
@@ -166,7 +166,7 @@ it("should not extract properties on objects with computed properties", async ()
166
166
  eval(output);
167
167
  });
168
168
 
169
- it("should not extract properties on objects with computed properties (string)", async () => {
169
+ test("Variant #6: Not extract properties on objects with computed properties (string)", async () => {
170
170
  var code = `
171
171
 
172
172
  var v = "key";
@@ -197,7 +197,7 @@ it("should not extract properties on objects with computed properties (string)",
197
197
  eval(output);
198
198
  });
199
199
 
200
- it("should not extract properties on objects when the object is referenced independently", async () => {
200
+ test("Variant #7: Not extract properties on objects when the object is referenced independently", async () => {
201
201
  var code = `
202
202
 
203
203
  var TEST_OBJECT = {
@@ -229,7 +229,7 @@ it("should not extract properties on objects when the object is referenced indep
229
229
  eval(output);
230
230
  });
231
231
 
232
- it("should not extract properties on objects when the variable gets redefined", async () => {
232
+ test("Variant #8: Not extract properties on objects when the variable gets redefined", async () => {
233
233
  var code = `
234
234
 
235
235
  var TEST_OBJECT = {
@@ -260,7 +260,7 @@ it("should not extract properties on objects when the variable gets redefined",
260
260
  eval(output);
261
261
  });
262
262
 
263
- it("should not extract properties on objects when the variable gets reassigned", async () => {
263
+ test("Variant #9: Not extract properties on objects when the variable gets reassigned", async () => {
264
264
  var code = `
265
265
 
266
266
  var TEST_OBJECT = {
@@ -292,7 +292,7 @@ it("should not extract properties on objects when the variable gets reassigned",
292
292
  eval(output);
293
293
  });
294
294
 
295
- it("should not extract properties on objects with methods referencing 'this'", async () => {
295
+ test("Variant #10: Not extract properties on objects with methods referencing 'this'", async () => {
296
296
  var code = `
297
297
 
298
298
  var TEST_OBJECT = {
@@ -325,7 +325,7 @@ it("should not extract properties on objects with methods referencing 'this'", a
325
325
  eval(output);
326
326
  });
327
327
 
328
- it("should not extract properties on objects when properties are dynamically deleted", async () => {
328
+ test("Variant #11: Not extract properties on objects when properties are dynamically deleted", async () => {
329
329
  var code = `
330
330
 
331
331
  var TEST_OBJECT = {
@@ -356,7 +356,7 @@ it("should not extract properties on objects when properties are dynamically del
356
356
  eval(output);
357
357
  });
358
358
 
359
- it("should not extract properties on objects with computed accessors", async () => {
359
+ test("Variant #12: Not extract properties on objects with computed accessors", async () => {
360
360
  var code = `
361
361
 
362
362
  var TEST_OBJECT = {
@@ -388,7 +388,7 @@ it("should not extract properties on objects with computed accessors", async ()
388
388
  eval(output);
389
389
  });
390
390
 
391
- it("should properly use custom callback to exclude certain names from being changed", async () => {
391
+ test("Variant #13: Properly use custom callback to exclude certain names from being changed", async () => {
392
392
  var code = `
393
393
 
394
394
  var TEST_OBJECT = {
@@ -424,7 +424,7 @@ it("should properly use custom callback to exclude certain names from being chan
424
424
  eval(output);
425
425
  });
426
426
 
427
- it("should not apply to objects with non-init properties (method, set, get)", async () => {
427
+ test("Variant #14: Not apply to objects with non-init properties (method, set, get)", async () => {
428
428
  var code = `
429
429
 
430
430
  var realValue = 0;
@@ -448,7 +448,7 @@ it("should not apply to objects with non-init properties (method, set, get)", as
448
448
  });
449
449
 
450
450
  // https://github.com/MichaelXF/js-confuser/issues/78
451
- it("should handle objects with spread elements", async () => {
451
+ test("Variant #15: Handle objects with spread elements", async () => {
452
452
  var output = await JsConfuser(
453
453
  `
454
454
  var x = { firstName: "John", lastName: "Doe" }
@@ -467,3 +467,23 @@ it("should handle objects with spread elements", async () => {
467
467
 
468
468
  expect(TEST_OUTPUT).toStrictEqual({ firstName: "John", lastName: "Doe" });
469
469
  });
470
+
471
+ // https://github.com/MichaelXF/js-confuser/issues/106
472
+ test("Variant #16: Handle const declarations", async () => {
473
+ var output = await JsConfuser(
474
+ `
475
+ const obj = {prop: 0};
476
+ obj.prop = 1;
477
+ TEST_OUTPUT = obj.prop;
478
+ `,
479
+ {
480
+ target: "node",
481
+ objectExtraction: true,
482
+ }
483
+ );
484
+
485
+ var TEST_OUTPUT;
486
+ eval(output);
487
+
488
+ expect(TEST_OUTPUT).toStrictEqual(1);
489
+ });
@@ -1,6 +1,6 @@
1
1
  import JsConfuser from "../../../src/index";
2
2
 
3
- it("should hide global names (such as Math)", async () => {
3
+ test("Variant #1: Hide global names (such as Math)", async () => {
4
4
  var code = `
5
5
  var TEST_RESULT = Math.floor(10.1);
6
6
  `;
@@ -16,7 +16,7 @@ it("should hide global names (such as Math)", async () => {
16
16
  expect(output).toContain("window");
17
17
  });
18
18
 
19
- it("should not rename global variables", async () => {
19
+ test("Variant #2: Do not hide modified identifiers", async () => {
20
20
  var code = `
21
21
  var Math = 50;
22
22
 
@@ -30,3 +30,24 @@ it("should not rename global variables", async () => {
30
30
 
31
31
  expect(output).toContain("log'](Math)");
32
32
  });
33
+
34
+ test("Variant #3: Properly hide in default parameter, function expression", async () => {
35
+ var output = await JsConfuser(
36
+ `
37
+ function myFunction( myParameter = function(){
38
+ var myVariable = true;
39
+ return myVariable;
40
+ } ) {
41
+ return myParameter();
42
+ }
43
+
44
+ TEST_OUTPUT = myFunction(); // true
45
+ `,
46
+ { target: "node", globalConcealing: true }
47
+ );
48
+
49
+ var TEST_OUTPUT;
50
+ eval(output);
51
+
52
+ expect(TEST_OUTPUT).toStrictEqual(true);
53
+ });
@@ -135,3 +135,27 @@ it("should work on High Preset", async () => {
135
135
 
136
136
  expect(TEST_OUTPUT).toStrictEqual("Hello World");
137
137
  });
138
+
139
+ it("should work with RGF enabled", async () => {
140
+ var output = await JsConfuser(
141
+ `
142
+ function getTestOutput(){
143
+ return "Hello World";
144
+ }
145
+
146
+ TEST_OUTPUT = getTestOutput();
147
+ `,
148
+ {
149
+ target: "node",
150
+ rgf: true,
151
+ lock: {
152
+ integrity: true,
153
+ },
154
+ }
155
+ );
156
+
157
+ var TEST_OUTPUT;
158
+ eval(output);
159
+
160
+ expect(TEST_OUTPUT).toStrictEqual("Hello World");
161
+ });
@@ -153,6 +153,27 @@ describe("getIdentifierInfo", () => {
153
153
  expect(nonModifiedInfo.spec.isModified).toStrictEqual(false);
154
154
  expect(nonModifiedInfo.spec.isReferenced).toStrictEqual(false);
155
155
  });
156
+
157
+ test("Variant #7: Default parameter, function expression", async () => {
158
+ var tree = parseSync(`
159
+ function myFunction( myParameter = function() {
160
+ var myNestedDeclaration = true;
161
+ } ){
162
+
163
+ }
164
+ `);
165
+
166
+ var myNestedDeclaration = findIdentifier(tree, "myNestedDeclaration");
167
+ var myNestedDeclarationInfo = getIdentifierInfo(
168
+ myNestedDeclaration[0],
169
+ myNestedDeclaration[1]
170
+ );
171
+
172
+ expect(myNestedDeclarationInfo.isVariableDeclaration).toStrictEqual(true);
173
+ expect(myNestedDeclarationInfo.spec.isDefined).toStrictEqual(true);
174
+ expect(myNestedDeclarationInfo.spec.isReferenced).toStrictEqual(true);
175
+ expect(myNestedDeclarationInfo.spec.isModified).toStrictEqual(false);
176
+ });
156
177
  });
157
178
 
158
179
  describe("validateChain", () => {