js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.3

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +24 -6
  2. package/dist/constants.js +6 -2
  3. package/dist/index.js +12 -0
  4. package/dist/obfuscator.js +117 -6
  5. package/dist/order.js +0 -1
  6. package/dist/probability.js +1 -96
  7. package/dist/templates/getGlobalTemplate.js +4 -1
  8. package/dist/templates/stringCompressionTemplate.js +3 -3
  9. package/dist/templates/tamperProtectionTemplates.js +1 -1
  10. package/dist/templates/template.js +17 -12
  11. package/dist/transforms/controlFlowFlattening.js +2 -6
  12. package/dist/transforms/deadCode.js +8 -15
  13. package/dist/transforms/dispatcher.js +1 -2
  14. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -0
  15. package/dist/transforms/extraction/objectExtraction.js +1 -2
  16. package/dist/transforms/finalizer.js +1 -1
  17. package/dist/transforms/flatten.js +2 -19
  18. package/dist/transforms/identifier/globalConcealing.js +1 -2
  19. package/dist/transforms/identifier/movedDeclarations.js +12 -5
  20. package/dist/transforms/identifier/renameVariables.js +7 -6
  21. package/dist/transforms/lock/lock.js +9 -2
  22. package/dist/transforms/minify.js +14 -1
  23. package/dist/transforms/opaquePredicates.js +5 -6
  24. package/dist/transforms/pack.js +5 -0
  25. package/dist/transforms/plugin.js +20 -39
  26. package/dist/transforms/renameLabels.js +1 -2
  27. package/dist/transforms/rgf.js +29 -11
  28. package/dist/transforms/shuffle.js +10 -11
  29. package/dist/transforms/string/stringCompression.js +14 -10
  30. package/dist/transforms/string/stringConcealing.js +4 -4
  31. package/dist/transforms/string/stringEncoding.js +4 -2
  32. package/dist/transforms/string/stringSplitting.js +4 -2
  33. package/dist/transforms/variableMasking.js +1 -2
  34. package/dist/utils/NameGen.js +3 -2
  35. package/dist/utils/PredicateGen.js +62 -0
  36. package/dist/utils/ast-utils.js +24 -9
  37. package/dist/validateOptions.js +2 -2
  38. package/package.json +2 -2
  39. package/src/constants.ts +6 -5
  40. package/src/index.ts +1 -0
  41. package/src/obfuscator.ts +148 -7
  42. package/src/options.ts +14 -6
  43. package/src/order.ts +0 -2
  44. package/src/probability.ts +0 -110
  45. package/src/templates/getGlobalTemplate.ts +5 -1
  46. package/src/templates/stringCompressionTemplate.ts +4 -28
  47. package/src/templates/tamperProtectionTemplates.ts +7 -3
  48. package/src/templates/template.ts +5 -3
  49. package/src/transforms/controlFlowFlattening.ts +2 -7
  50. package/src/transforms/deadCode.ts +11 -23
  51. package/src/transforms/dispatcher.ts +1 -2
  52. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +10 -1
  53. package/src/transforms/extraction/objectExtraction.ts +1 -2
  54. package/src/transforms/finalizer.ts +1 -1
  55. package/src/transforms/flatten.ts +3 -22
  56. package/src/transforms/identifier/globalConcealing.ts +4 -2
  57. package/src/transforms/identifier/movedDeclarations.ts +18 -6
  58. package/src/transforms/identifier/renameVariables.ts +10 -6
  59. package/src/transforms/lock/lock.ts +14 -3
  60. package/src/transforms/minify.ts +24 -2
  61. package/src/transforms/opaquePredicates.ts +5 -8
  62. package/src/transforms/pack.ts +6 -0
  63. package/src/transforms/plugin.ts +47 -69
  64. package/src/transforms/renameLabels.ts +1 -2
  65. package/src/transforms/rgf.ts +39 -14
  66. package/src/transforms/shuffle.ts +28 -26
  67. package/src/transforms/string/encoding.ts +1 -1
  68. package/src/transforms/string/stringCompression.ts +22 -13
  69. package/src/transforms/string/stringConcealing.ts +11 -7
  70. package/src/transforms/string/stringEncoding.ts +6 -2
  71. package/src/transforms/string/stringSplitting.ts +9 -4
  72. package/src/transforms/variableMasking.ts +1 -2
  73. package/src/utils/NameGen.ts +4 -2
  74. package/src/utils/PredicateGen.ts +61 -0
  75. package/src/utils/ast-utils.ts +16 -9
  76. package/src/validateOptions.ts +7 -4
  77. package/src/transforms/functionOutlining.ts +0 -225
  78. package/src/utils/ControlObject.ts +0 -141
package/src/obfuscator.ts CHANGED
@@ -3,10 +3,9 @@ import * as t from "@babel/types";
3
3
  import generate from "@babel/generator";
4
4
  import traverse from "@babel/traverse";
5
5
  import { parse } from "@babel/parser";
6
- import { ObfuscateOptions } from "./options";
6
+ import { ObfuscateOptions, ProbabilityMap } from "./options";
7
7
  import { applyDefaultsToOptions, validateOptions } from "./validateOptions";
8
8
  import { ObfuscationResult, ProfilerCallback } from "./obfuscationResult";
9
- import { isProbabilityMapProbable } from "./probability";
10
9
  import { NameGen } from "./utils/NameGen";
11
10
  import { Order } from "./order";
12
11
  import {
@@ -22,7 +21,6 @@ import variableMasking from "./transforms/variableMasking";
22
21
  import dispatcher from "./transforms/dispatcher";
23
22
  import duplicateLiteralsRemoval from "./transforms/extraction/duplicateLiteralsRemoval";
24
23
  import objectExtraction from "./transforms/extraction/objectExtraction";
25
- import functionOutlining from "./transforms/functionOutlining";
26
24
  import globalConcealing from "./transforms/identifier/globalConcealing";
27
25
  import stringCompression from "./transforms/string/stringCompression";
28
26
  import deadCode from "./transforms/deadCode";
@@ -42,6 +40,7 @@ import minify from "./transforms/minify";
42
40
  import finalizer from "./transforms/finalizer";
43
41
  import integrity from "./transforms/lock/integrity";
44
42
  import pack from "./transforms/pack";
43
+ import { createObject } from "./utils/object-utils";
45
44
 
46
45
  export const DEFAULT_OPTIONS: ObfuscateOptions = {
47
46
  target: "node",
@@ -161,7 +160,7 @@ export default class Obfuscator {
161
160
  (Object.keys(this.options.lock).filter(
162
161
  (key) =>
163
162
  key !== "customLocks" &&
164
- isProbabilityMapProbable(this.options.lock[key])
163
+ this.isProbabilityMapProbable(this.options.lock[key])
165
164
  ).length > 0 ||
166
165
  this.options.lock.customLocks.length > 0);
167
166
 
@@ -169,7 +168,7 @@ export default class Obfuscator {
169
168
 
170
169
  const push = (probabilityMap, ...pluginFns) => {
171
170
  this.totalPossibleTransforms += pluginFns.length;
172
- if (!isProbabilityMapProbable(probabilityMap)) return;
171
+ if (!this.isProbabilityMapProbable(probabilityMap)) return;
173
172
 
174
173
  allPlugins.push(...pluginFns);
175
174
  };
@@ -185,10 +184,15 @@ export default class Obfuscator {
185
184
  push(this.options.calculator, calculator);
186
185
  push(this.options.globalConcealing, globalConcealing);
187
186
  push(this.options.opaquePredicates, opaquePredicates);
188
- push(this.options.functionOutlining, functionOutlining);
189
187
  push(this.options.stringSplitting, stringSplitting);
190
188
  push(this.options.stringConcealing, stringConcealing);
191
- push(this.options.stringCompression, stringCompression);
189
+ // String Compression is only applied to the main obfuscator
190
+ // Any RGF functions will not have string compression due to the size of the decompression function
191
+
192
+ push(
193
+ !parentObfuscator && this.options.stringCompression,
194
+ stringCompression
195
+ );
192
196
  push(this.options.variableMasking, variableMasking);
193
197
  push(this.options.duplicateLiteralsRemoval, duplicateLiteralsRemoval);
194
198
  push(this.options.shuffle, shuffle);
@@ -354,4 +358,141 @@ export default class Obfuscator {
354
358
 
355
359
  return ast;
356
360
  }
361
+
362
+ probabilityMapCounter = new WeakMap<Object, number>();
363
+
364
+ /**
365
+ * Evaluates a ProbabilityMap.
366
+ * @param map The setting object.
367
+ * @param customFnArgs Args given to user-implemented function, such as a variable name.
368
+ */
369
+ computeProbabilityMap<
370
+ T,
371
+ F extends (...args: any[]) => any = (...args: any[]) => any
372
+ >(
373
+ map: ProbabilityMap<T, F>,
374
+ ...customImplementationArgs: F extends (...args: infer P) => any ? P : never
375
+ ): boolean | string {
376
+ // Check if this probability map uses the {value: ..., limit: ...} format
377
+ if (typeof map === "object" && map && "value" in map) {
378
+ // Check for the limit property
379
+ if ("limit" in map && typeof map.limit === "number" && map.limit >= 0) {
380
+ // Check if the limit has been reached
381
+ if (this.probabilityMapCounter.get(map) >= map.limit) {
382
+ return false;
383
+ }
384
+ }
385
+
386
+ var value = this.computeProbabilityMap(
387
+ map.value as ProbabilityMap<T, F>,
388
+ ...customImplementationArgs
389
+ );
390
+
391
+ if (value) {
392
+ // Increment the counter for this map
393
+ this.probabilityMapCounter.set(
394
+ map,
395
+ this.probabilityMapCounter.get(map) + 1 || 1
396
+ );
397
+ }
398
+
399
+ return value;
400
+ }
401
+
402
+ if (!map) {
403
+ return false;
404
+ }
405
+ if (map === true || map === 1) {
406
+ return true;
407
+ }
408
+ if (typeof map === "number") {
409
+ return Math.random() < map;
410
+ }
411
+
412
+ if (typeof map === "function") {
413
+ return (map as Function)(...customImplementationArgs);
414
+ }
415
+
416
+ if (typeof map === "string") {
417
+ return map;
418
+ }
419
+
420
+ var asObject: { [mode: string]: number } = {};
421
+ if (Array.isArray(map)) {
422
+ map.forEach((x: any) => {
423
+ asObject[x.toString()] = 1;
424
+ });
425
+ } else {
426
+ asObject = map as any;
427
+ }
428
+
429
+ var total = Object.values(asObject).reduce((a, b) => a + b);
430
+ var percentages = createObject(
431
+ Object.keys(asObject),
432
+ Object.values(asObject).map((x) => x / total)
433
+ );
434
+
435
+ var ticket = Math.random();
436
+
437
+ var count = 0;
438
+ var winner = null;
439
+ Object.keys(percentages).forEach((key) => {
440
+ var x = Number(percentages[key]);
441
+
442
+ if (ticket >= count && ticket < count + x) {
443
+ winner = key;
444
+ }
445
+ count += x;
446
+ });
447
+
448
+ return winner;
449
+ }
450
+
451
+ /**
452
+ * Determines if a probability map can return a positive result (true, or some string mode).
453
+ * - Negative probability maps are used to remove transformations from running entirely.
454
+ * @param map
455
+ */
456
+ isProbabilityMapProbable<T>(map: ProbabilityMap<T>): boolean {
457
+ ok(!Number.isNaN(map), "Numbers cannot be NaN");
458
+
459
+ if (!map || typeof map === "undefined") {
460
+ return false;
461
+ }
462
+ if (typeof map === "function") {
463
+ return true;
464
+ }
465
+ if (typeof map === "number") {
466
+ if (map > 1 || map < 0) {
467
+ throw new Error(`Numbers must be between 0 and 1 for 0% - 100%`);
468
+ }
469
+ }
470
+ if (Array.isArray(map)) {
471
+ ok(
472
+ map.length != 0,
473
+ "Empty arrays are not allowed for options. Use false instead."
474
+ );
475
+
476
+ if (map.length == 1) {
477
+ return !!map[0];
478
+ }
479
+ }
480
+ if (typeof map === "object") {
481
+ if (map instanceof Date) return true;
482
+ if (map instanceof RegExp) return true;
483
+ if ("value" in map && !map.value) return false;
484
+ if ("limit" in map && map.limit === 0) return false;
485
+
486
+ var keys = Object.keys(map);
487
+ ok(
488
+ keys.length != 0,
489
+ "Empty objects are not allowed for options. Use false instead."
490
+ );
491
+
492
+ if (keys.length == 1) {
493
+ return !!map[keys[0]];
494
+ }
495
+ }
496
+ return true;
497
+ }
357
498
  }
package/src/options.ts CHANGED
@@ -2,7 +2,7 @@ import Template from "./templates/template";
2
2
 
3
3
  // JS-Confuser.com imports this file for Type support, therefore some additional types are included here.
4
4
 
5
- type Stringed<V> = (V extends string ? V : never) | "true" | "false";
5
+ type Stringed<V> = V extends string ? V : never;
6
6
 
7
7
  /**
8
8
  * Configurable probabilities for obfuscator options.
@@ -16,9 +16,19 @@ type Stringed<V> = (V extends string ? V : never) | "true" | "false";
16
16
  * - **`function(x){ return "custom_implementation" }`** - enabled, use specified function
17
17
  */
18
18
  export type ProbabilityMap<
19
- T,
19
+ T = boolean,
20
20
  F extends (...args: any[]) => any = () => boolean // Default to a generic function
21
- > = false | true | number | T | T[] | { [key in Stringed<T>]?: number } | F;
21
+ > =
22
+ | false
23
+ | true
24
+ | number
25
+ | F
26
+ | (T extends never | boolean
27
+ ? {
28
+ value: ProbabilityMap<never, F>;
29
+ limit?: number;
30
+ }
31
+ : T | T[] | { [key in Stringed<T>]?: number });
22
32
 
23
33
  export interface CustomLock {
24
34
  /**
@@ -342,8 +352,6 @@ export interface ObfuscateOptions {
342
352
  customLocks?: CustomLock[];
343
353
  };
344
354
 
345
- functionOutlining?: ProbabilityMap<boolean>;
346
-
347
355
  /**
348
356
  * Moves variable declarations to the top of the context.
349
357
  */
@@ -375,7 +383,7 @@ export interface ObfuscateOptions {
375
383
  *
376
384
  * Designed to escape strict mode constraints.
377
385
  */
378
- pack?: boolean;
386
+ pack?: ProbabilityMap<boolean, (globalName: string) => boolean>;
379
387
 
380
388
  /**
381
389
  * Set of global variables. *Optional*.
package/src/order.ts CHANGED
@@ -38,8 +38,6 @@ export enum Order {
38
38
 
39
39
  MovedDeclarations = 25,
40
40
 
41
- FunctionOutlining = 26,
42
-
43
41
  RenameLabels = 27,
44
42
 
45
43
  Minify = 28,
@@ -1,110 +0,0 @@
1
- import { ok } from "assert";
2
- import { createObject } from "./utils/object-utils";
3
- import { ProbabilityMap } from "./options";
4
-
5
- /**
6
- * Evaluates a ProbabilityMap.
7
- * @param map The setting object.
8
- * @param customFnArgs Args given to user-implemented function, such as a variable name.
9
- */
10
- export function computeProbabilityMap<
11
- T,
12
- F extends (...args: any[]) => any = (...args: any[]) => any
13
- >(
14
- map: ProbabilityMap<T, F>,
15
- ...customImplementationArgs: F extends (...args: infer P) => any ? P : never
16
- ): boolean | string {
17
- if (!map) {
18
- return false;
19
- }
20
- if (map === true || map === 1) {
21
- return true;
22
- }
23
- if (typeof map === "number") {
24
- return Math.random() < map;
25
- }
26
-
27
- if (typeof map === "function") {
28
- return (map as Function)(...customImplementationArgs);
29
- }
30
-
31
- if (typeof map === "string") {
32
- return map;
33
- }
34
-
35
- var asObject: { [mode: string]: number } = {};
36
- if (Array.isArray(map)) {
37
- map.forEach((x: any) => {
38
- asObject[x.toString()] = 1;
39
- });
40
- } else {
41
- asObject = map as any;
42
- }
43
-
44
- var total = Object.values(asObject).reduce((a, b) => a + b);
45
- var percentages = createObject(
46
- Object.keys(asObject),
47
- Object.values(asObject).map((x) => x / total)
48
- );
49
-
50
- var ticket = Math.random();
51
-
52
- var count = 0;
53
- var winner = null;
54
- Object.keys(percentages).forEach((key) => {
55
- var x = Number(percentages[key]);
56
-
57
- if (ticket >= count && ticket < count + x) {
58
- winner = key;
59
- }
60
- count += x;
61
- });
62
-
63
- return winner;
64
- }
65
-
66
- /**
67
- * Determines if a probability map can return a positive result (true, or some string mode).
68
- * - Negative probability maps are used to remove transformations from running entirely.
69
- * @param map
70
- */
71
- export function isProbabilityMapProbable<T>(map: ProbabilityMap<T>): boolean {
72
- ok(!Number.isNaN(map), "Numbers cannot be NaN");
73
-
74
- if (!map || typeof map === "undefined") {
75
- return false;
76
- }
77
- if (typeof map === "function") {
78
- return true;
79
- }
80
- if (typeof map === "number") {
81
- if (map > 1 || map < 0) {
82
- throw new Error(`Numbers must be between 0 and 1 for 0% - 100%`);
83
- }
84
- }
85
- if (Array.isArray(map)) {
86
- ok(
87
- map.length != 0,
88
- "Empty arrays are not allowed for options. Use false instead."
89
- );
90
-
91
- if (map.length == 1) {
92
- return !!map[0];
93
- }
94
- }
95
- if (typeof map === "object") {
96
- if (map instanceof Date) return true;
97
- if (map instanceof RegExp) return true;
98
-
99
- var keys = Object.keys(map);
100
- ok(
101
- keys.length != 0,
102
- "Empty objects are not allowed for options. Use false instead."
103
- );
104
-
105
- if (keys.length == 1) {
106
- return !!keys[0];
107
- }
108
- }
109
- return true;
110
- }
@@ -2,12 +2,16 @@ import { NodePath } from "@babel/traverse";
2
2
  import { PluginInstance } from "../transforms/plugin";
3
3
  import Template from "./template";
4
4
  import { UNSAFE } from "../constants";
5
+ import { isStrictMode } from "../utils/ast-utils";
5
6
 
6
7
  export const createGetGlobalTemplate = (
7
8
  pluginInstance: PluginInstance,
8
9
  path: NodePath
9
10
  ) => {
10
- if (pluginInstance.options.lock?.tamperProtection) {
11
+ if (
12
+ pluginInstance.options.lock?.tamperProtection &&
13
+ !path.find((p) => isStrictMode(p))
14
+ ) {
11
15
  return new Template(`
12
16
  function {getGlobalFnName}(){
13
17
  var localVar = false;
@@ -5,28 +5,8 @@ export const StringCompressionTemplate = new Template(
5
5
  var {stringFn};
6
6
 
7
7
  (function (){
8
- {GetGlobalTemplate}
9
-
10
- var __globalObject = {getGlobalFnName}() || {};
11
-
12
- // Direct invocation of atob() is not allowed in some environments
13
- var _atob = (s) => __globalObject["atob"](s);
14
- var _Uint8Array = __globalObject["Uint8Array"];
15
-
16
- function convertBase64ToArrayBuffer(base64) {
17
- var binaryString = _atob(base64); // Decode Base64
18
- var len = binaryString.length;
19
- var uint8Array = new _Uint8Array(len);
20
-
21
- // Convert binary string back into Uint8Array
22
- for (var i = 0; i < len; i++) {
23
- uint8Array[i] = binaryString["charCodeAt"](i);
24
- }
25
- return uint8Array;
26
- }
27
-
28
- var compressedBuffer = convertBase64ToArrayBuffer({stringValue});
29
- var utf8String = {pakoName}["inflate"](compressedBuffer, { to: 'string' });
8
+ var compressedString = {stringValue};
9
+ var utf8String = {StringCompressionLibrary}["decompressFromUTF16"](compressedString);
30
10
  var stringArray = utf8String["split"]({stringDelimiter});
31
11
 
32
12
  {stringFn} = function(index){
@@ -36,9 +16,5 @@ var {stringFn};
36
16
  `
37
17
  );
38
18
 
39
- export const PakoInflateMin = `
40
- var {pako} = {};
41
-
42
- /*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
43
- !function(e,t){ t({pako}) }(this,(function(e){"use strict";var t=function(e,t,i,n){for(var a=65535&e|0,r=e>>>16&65535|0,o=0;0!==i;){i-=o=i>2e3?2e3:i;do{r=r+(a=a+t[n++]|0)|0}while(--o);a%=65521,r%=65521}return a|r<<16|0},i=new Uint32Array(function(){for(var e,t=[],i=0;i<256;i++){e=i;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[i]=e}return t}()),n=function(e,t,n,a){var r=i,o=a+n;e^=-1;for(var s=a;s<o;s++)e=e>>>8^r[255&(e^t[s])];return-1^e},a=16209,r=function(e,t){var i,n,r,o,s,l,f,d,h,c,u,w,b,m,k,_,v,g,p,y,x,E,R,A,Z=e.state;i=e.next_in,R=e.input,n=i+(e.avail_in-5),r=e.next_out,A=e.output,o=r-(t-e.avail_out),s=r+(e.avail_out-257),l=Z.dmax,f=Z.wsize,d=Z.whave,h=Z.wnext,c=Z.window,u=Z.hold,w=Z.bits,b=Z.lencode,m=Z.distcode,k=(1<<Z.lenbits)-1,_=(1<<Z.distbits)-1;e:do{w<15&&(u+=R[i++]<<w,w+=8,u+=R[i++]<<w,w+=8),v=b[u&k];t:for(;;){if(u>>>=g=v>>>24,w-=g,0===(g=v>>>16&255))A[r++]=65535&v;else{if(!(16&g)){if(0==(64&g)){v=b[(65535&v)+(u&(1<<g)-1)];continue t}if(32&g){Z.mode=16191;break e}e.msg="invalid literal/length code",Z.mode=a;break e}p=65535&v,(g&=15)&&(w<g&&(u+=R[i++]<<w,w+=8),p+=u&(1<<g)-1,u>>>=g,w-=g),w<15&&(u+=R[i++]<<w,w+=8,u+=R[i++]<<w,w+=8),v=m[u&_];i:for(;;){if(u>>>=g=v>>>24,w-=g,!(16&(g=v>>>16&255))){if(0==(64&g)){v=m[(65535&v)+(u&(1<<g)-1)];continue i}e.msg="invalid distance code",Z.mode=a;break e}if(y=65535&v,w<(g&=15)&&(u+=R[i++]<<w,(w+=8)<g&&(u+=R[i++]<<w,w+=8)),(y+=u&(1<<g)-1)>l){e.msg="invalid distance too far back",Z.mode=a;break e}if(u>>>=g,w-=g,y>(g=r-o)){if((g=y-g)>d&&Z.sane){e.msg="invalid distance too far back",Z.mode=a;break e}if(x=0,E=c,0===h){if(x+=f-g,g<p){p-=g;do{A[r++]=c[x++]}while(--g);x=r-y,E=A}}else if(h<g){if(x+=f+h-g,(g-=h)<p){p-=g;do{A[r++]=c[x++]}while(--g);if(x=0,h<p){p-=g=h;do{A[r++]=c[x++]}while(--g);x=r-y,E=A}}}else if(x+=h-g,g<p){p-=g;do{A[r++]=c[x++]}while(--g);x=r-y,E=A}for(;p>2;)A[r++]=E[x++],A[r++]=E[x++],A[r++]=E[x++],p-=3;p&&(A[r++]=E[x++],p>1&&(A[r++]=E[x++]))}else{x=r-y;do{A[r++]=A[x++],A[r++]=A[x++],A[r++]=A[x++],p-=3}while(p>2);p&&(A[r++]=A[x++],p>1&&(A[r++]=A[x++]))}break}}break}}while(i<n&&r<s);i-=p=w>>3,u&=(1<<(w-=p<<3))-1,e.next_in=i,e.next_out=r,e.avail_in=i<n?n-i+5:5-(i-n),e.avail_out=r<s?s-r+257:257-(r-s),Z.hold=u,Z.bits=w},o=15,s=new Uint16Array([3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0]),l=new Uint8Array([16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78]),f=new Uint16Array([1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0]),d=new Uint8Array([16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64]),h=function(e,t,i,n,a,r,h,c){var u,w,b,m,k,_,v,g,p,y=c.bits,x=0,E=0,R=0,A=0,Z=0,S=0,T=0,O=0,U=0,D=0,I=null,B=new Uint16Array(16),N=new Uint16Array(16),C=null;for(x=0;x<=o;x++)B[x]=0;for(E=0;E<n;E++)B[t[i+E]]++;for(Z=y,A=o;A>=1&&0===B[A];A--);if(Z>A&&(Z=A),0===A)return a[r++]=20971520,a[r++]=20971520,c.bits=1,0;for(R=1;R<A&&0===B[R];R++);for(Z<R&&(Z=R),O=1,x=1;x<=o;x++)if(O<<=1,(O-=B[x])<0)return-1;if(O>0&&(0===e||1!==A))return-1;for(N[1]=0,x=1;x<o;x++)N[x+1]=N[x]+B[x];for(E=0;E<n;E++)0!==t[i+E]&&(h[N[t[i+E]]++]=E);if(0===e?(I=C=h,_=20):1===e?(I=s,C=l,_=257):(I=f,C=d,_=0),D=0,E=0,x=R,k=r,S=Z,T=0,b=-1,m=(U=1<<Z)-1,1===e&&U>852||2===e&&U>592)return 1;for(;;){v=x-T,h[E]+1<_?(g=0,p=h[E]):h[E]>=_?(g=C[h[E]-_],p=I[h[E]-_]):(g=96,p=0),u=1<<x-T,R=w=1<<S;do{a[k+(D>>T)+(w-=u)]=v<<24|g<<16|p|0}while(0!==w);for(u=1<<x-1;D&u;)u>>=1;if(0!==u?(D&=u-1,D+=u):D=0,E++,0==--B[x]){if(x===A)break;x=t[i+h[E]]}if(x>Z&&(D&m)!==b){for(0===T&&(T=Z),k+=R,O=1<<(S=x-T);S+T<A&&!((O-=B[S+T])<=0);)S++,O<<=1;if(U+=1<<S,1===e&&U>852||2===e&&U>592)return 1;a[b=D&m]=Z<<24|S<<16|k-r|0}}return 0!==D&&(a[k+D]=x-T<<24|64<<16|0),c.bits=Z,0},c={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8},u=c.Z_FINISH,w=c.Z_BLOCK,b=c.Z_TREES,m=c.Z_OK,k=c.Z_STREAM_END,_=c.Z_NEED_DICT,v=c.Z_STREAM_ERROR,g=c.Z_DATA_ERROR,p=c.Z_MEM_ERROR,y=c.Z_BUF_ERROR,x=c.Z_DEFLATED,E=16180,R=16190,A=16191,Z=16192,S=16194,T=16199,O=16200,U=16206,D=16209,I=function(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)};function B(){this.strm=null,this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new Uint16Array(320),this.work=new Uint16Array(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}var N,C,z=function(e){if(!e)return 1;var t=e.state;return!t||t.strm!==e||t.mode<E||t.mode>16211?1:0},F=function(e){if(z(e))return v;var t=e.state;return e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=E,t.last=0,t.havedict=0,t.flags=-1,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new Int32Array(852),t.distcode=t.distdyn=new Int32Array(592),t.sane=1,t.back=-1,m},L=function(e){if(z(e))return v;var t=e.state;return t.wsize=0,t.whave=0,t.wnext=0,F(e)},M=function(e,t){var i;if(z(e))return v;var n=e.state;return t<0?(i=0,t=-t):(i=5+(t>>4),t<48&&(t&=15)),t&&(t<8||t>15)?v:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=i,n.wbits=t,L(e))},H=function(e,t){if(!e)return v;var i=new B;e.state=i,i.strm=e,i.window=null,i.mode=E;var n=M(e,t);return n!==m&&(e.state=null),n},j=!0,K=function(e){if(j){N=new Int32Array(512),C=new Int32Array(32);for(var t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(h(1,e.lens,0,288,N,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;h(2,e.lens,0,32,C,0,e.work,{bits:5}),j=!1}e.lencode=N,e.lenbits=9,e.distcode=C,e.distbits=5},P=function(e,t,i,n){var a,r=e.state;return null===r.window&&(r.wsize=1<<r.wbits,r.wnext=0,r.whave=0,r.window=new Uint8Array(r.wsize)),n>=r.wsize?(r.window.set(t.subarray(i-r.wsize,i),0),r.wnext=0,r.whave=r.wsize):((a=r.wsize-r.wnext)>n&&(a=n),r.window.set(t.subarray(i-n,i-n+a),r.wnext),(n-=a)?(r.window.set(t.subarray(i-n,i),0),r.wnext=n,r.whave=r.wsize):(r.wnext+=a,r.wnext===r.wsize&&(r.wnext=0),r.whave<r.wsize&&(r.whave+=a))),0},Y={inflateReset:L,inflateReset2:M,inflateResetKeep:F,inflateInit:function(e){return H(e,15)},inflateInit2:H,inflate:function(e,i){var a,o,s,l,f,d,c,B,N,C,F,L,M,H,j,Y,G,X,W,q,J,Q,V,$,ee=0,te=new Uint8Array(4),ie=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);if(z(e)||!e.output||!e.input&&0!==e.avail_in)return v;(a=e.state).mode===A&&(a.mode=Z),f=e.next_out,s=e.output,c=e.avail_out,l=e.next_in,o=e.input,d=e.avail_in,B=a.hold,N=a.bits,C=d,F=c,Q=m;e:for(;;)switch(a.mode){case E:if(0===a.wrap){a.mode=Z;break}for(;N<16;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(2&a.wrap&&35615===B){0===a.wbits&&(a.wbits=15),a.check=0,te[0]=255&B,te[1]=B>>>8&255,a.check=n(a.check,te,2,0),B=0,N=0,a.mode=16181;break}if(a.head&&(a.head.done=!1),!(1&a.wrap)||(((255&B)<<8)+(B>>8))%31){e.msg="incorrect header check",a.mode=D;break}if((15&B)!==x){e.msg="unknown compression method",a.mode=D;break}if(N-=4,J=8+(15&(B>>>=4)),0===a.wbits&&(a.wbits=J),J>15||J>a.wbits){e.msg="invalid window size",a.mode=D;break}a.dmax=1<<a.wbits,a.flags=0,e.adler=a.check=1,a.mode=512&B?16189:A,B=0,N=0;break;case 16181:for(;N<16;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(a.flags=B,(255&a.flags)!==x){e.msg="unknown compression method",a.mode=D;break}if(57344&a.flags){e.msg="unknown header flags set",a.mode=D;break}a.head&&(a.head.text=B>>8&1),512&a.flags&&4&a.wrap&&(te[0]=255&B,te[1]=B>>>8&255,a.check=n(a.check,te,2,0)),B=0,N=0,a.mode=16182;case 16182:for(;N<32;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}a.head&&(a.head.time=B),512&a.flags&&4&a.wrap&&(te[0]=255&B,te[1]=B>>>8&255,te[2]=B>>>16&255,te[3]=B>>>24&255,a.check=n(a.check,te,4,0)),B=0,N=0,a.mode=16183;case 16183:for(;N<16;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}a.head&&(a.head.xflags=255&B,a.head.os=B>>8),512&a.flags&&4&a.wrap&&(te[0]=255&B,te[1]=B>>>8&255,a.check=n(a.check,te,2,0)),B=0,N=0,a.mode=16184;case 16184:if(1024&a.flags){for(;N<16;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}a.length=B,a.head&&(a.head.extra_len=B),512&a.flags&&4&a.wrap&&(te[0]=255&B,te[1]=B>>>8&255,a.check=n(a.check,te,2,0)),B=0,N=0}else a.head&&(a.head.extra=null);a.mode=16185;case 16185:if(1024&a.flags&&((L=a.length)>d&&(L=d),L&&(a.head&&(J=a.head.extra_len-a.length,a.head.extra||(a.head.extra=new Uint8Array(a.head.extra_len)),a.head.extra.set(o.subarray(l,l+L),J)),512&a.flags&&4&a.wrap&&(a.check=n(a.check,o,L,l)),d-=L,l+=L,a.length-=L),a.length))break e;a.length=0,a.mode=16186;case 16186:if(2048&a.flags){if(0===d)break e;L=0;do{J=o[l+L++],a.head&&J&&a.length<65536&&(a.head.name+=String.fromCharCode(J))}while(J&&L<d);if(512&a.flags&&4&a.wrap&&(a.check=n(a.check,o,L,l)),d-=L,l+=L,J)break e}else a.head&&(a.head.name=null);a.length=0,a.mode=16187;case 16187:if(4096&a.flags){if(0===d)break e;L=0;do{J=o[l+L++],a.head&&J&&a.length<65536&&(a.head.comment+=String.fromCharCode(J))}while(J&&L<d);if(512&a.flags&&4&a.wrap&&(a.check=n(a.check,o,L,l)),d-=L,l+=L,J)break e}else a.head&&(a.head.comment=null);a.mode=16188;case 16188:if(512&a.flags){for(;N<16;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(4&a.wrap&&B!==(65535&a.check)){e.msg="header crc mismatch",a.mode=D;break}B=0,N=0}a.head&&(a.head.hcrc=a.flags>>9&1,a.head.done=!0),e.adler=a.check=0,a.mode=A;break;case 16189:for(;N<32;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}e.adler=a.check=I(B),B=0,N=0,a.mode=R;case R:if(0===a.havedict)return e.next_out=f,e.avail_out=c,e.next_in=l,e.avail_in=d,a.hold=B,a.bits=N,_;e.adler=a.check=1,a.mode=A;case A:if(i===w||i===b)break e;case Z:if(a.last){B>>>=7&N,N-=7&N,a.mode=U;break}for(;N<3;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}switch(a.last=1&B,N-=1,3&(B>>>=1)){case 0:a.mode=16193;break;case 1:if(K(a),a.mode=T,i===b){B>>>=2,N-=2;break e}break;case 2:a.mode=16196;break;case 3:e.msg="invalid block type",a.mode=D}B>>>=2,N-=2;break;case 16193:for(B>>>=7&N,N-=7&N;N<32;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if((65535&B)!=(B>>>16^65535)){e.msg="invalid stored block lengths",a.mode=D;break}if(a.length=65535&B,B=0,N=0,a.mode=S,i===b)break e;case S:a.mode=16195;case 16195:if(L=a.length){if(L>d&&(L=d),L>c&&(L=c),0===L)break e;s.set(o.subarray(l,l+L),f),d-=L,l+=L,c-=L,f+=L,a.length-=L;break}a.mode=A;break;case 16196:for(;N<14;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(a.nlen=257+(31&B),B>>>=5,N-=5,a.ndist=1+(31&B),B>>>=5,N-=5,a.ncode=4+(15&B),B>>>=4,N-=4,a.nlen>286||a.ndist>30){e.msg="too many length or distance symbols",a.mode=D;break}a.have=0,a.mode=16197;case 16197:for(;a.have<a.ncode;){for(;N<3;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}a.lens[ie[a.have++]]=7&B,B>>>=3,N-=3}for(;a.have<19;)a.lens[ie[a.have++]]=0;if(a.lencode=a.lendyn,a.lenbits=7,V={bits:a.lenbits},Q=h(0,a.lens,0,19,a.lencode,0,a.work,V),a.lenbits=V.bits,Q){e.msg="invalid code lengths set",a.mode=D;break}a.have=0,a.mode=16198;case 16198:for(;a.have<a.nlen+a.ndist;){for(;Y=(ee=a.lencode[B&(1<<a.lenbits)-1])>>>16&255,G=65535&ee,!((j=ee>>>24)<=N);){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(G<16)B>>>=j,N-=j,a.lens[a.have++]=G;else{if(16===G){for($=j+2;N<$;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(B>>>=j,N-=j,0===a.have){e.msg="invalid bit length repeat",a.mode=D;break}J=a.lens[a.have-1],L=3+(3&B),B>>>=2,N-=2}else if(17===G){for($=j+3;N<$;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}N-=j,J=0,L=3+(7&(B>>>=j)),B>>>=3,N-=3}else{for($=j+7;N<$;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}N-=j,J=0,L=11+(127&(B>>>=j)),B>>>=7,N-=7}if(a.have+L>a.nlen+a.ndist){e.msg="invalid bit length repeat",a.mode=D;break}for(;L--;)a.lens[a.have++]=J}}if(a.mode===D)break;if(0===a.lens[256]){e.msg="invalid code -- missing end-of-block",a.mode=D;break}if(a.lenbits=9,V={bits:a.lenbits},Q=h(1,a.lens,0,a.nlen,a.lencode,0,a.work,V),a.lenbits=V.bits,Q){e.msg="invalid literal/lengths set",a.mode=D;break}if(a.distbits=6,a.distcode=a.distdyn,V={bits:a.distbits},Q=h(2,a.lens,a.nlen,a.ndist,a.distcode,0,a.work,V),a.distbits=V.bits,Q){e.msg="invalid distances set",a.mode=D;break}if(a.mode=T,i===b)break e;case T:a.mode=O;case O:if(d>=6&&c>=258){e.next_out=f,e.avail_out=c,e.next_in=l,e.avail_in=d,a.hold=B,a.bits=N,r(e,F),f=e.next_out,s=e.output,c=e.avail_out,l=e.next_in,o=e.input,d=e.avail_in,B=a.hold,N=a.bits,a.mode===A&&(a.back=-1);break}for(a.back=0;Y=(ee=a.lencode[B&(1<<a.lenbits)-1])>>>16&255,G=65535&ee,!((j=ee>>>24)<=N);){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(Y&&0==(240&Y)){for(X=j,W=Y,q=G;Y=(ee=a.lencode[q+((B&(1<<X+W)-1)>>X)])>>>16&255,G=65535&ee,!(X+(j=ee>>>24)<=N);){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}B>>>=X,N-=X,a.back+=X}if(B>>>=j,N-=j,a.back+=j,a.length=G,0===Y){a.mode=16205;break}if(32&Y){a.back=-1,a.mode=A;break}if(64&Y){e.msg="invalid literal/length code",a.mode=D;break}a.extra=15&Y,a.mode=16201;case 16201:if(a.extra){for($=a.extra;N<$;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}a.length+=B&(1<<a.extra)-1,B>>>=a.extra,N-=a.extra,a.back+=a.extra}a.was=a.length,a.mode=16202;case 16202:for(;Y=(ee=a.distcode[B&(1<<a.distbits)-1])>>>16&255,G=65535&ee,!((j=ee>>>24)<=N);){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(0==(240&Y)){for(X=j,W=Y,q=G;Y=(ee=a.distcode[q+((B&(1<<X+W)-1)>>X)])>>>16&255,G=65535&ee,!(X+(j=ee>>>24)<=N);){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}B>>>=X,N-=X,a.back+=X}if(B>>>=j,N-=j,a.back+=j,64&Y){e.msg="invalid distance code",a.mode=D;break}a.offset=G,a.extra=15&Y,a.mode=16203;case 16203:if(a.extra){for($=a.extra;N<$;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}a.offset+=B&(1<<a.extra)-1,B>>>=a.extra,N-=a.extra,a.back+=a.extra}if(a.offset>a.dmax){e.msg="invalid distance too far back",a.mode=D;break}a.mode=16204;case 16204:if(0===c)break e;if(L=F-c,a.offset>L){if((L=a.offset-L)>a.whave&&a.sane){e.msg="invalid distance too far back",a.mode=D;break}L>a.wnext?(L-=a.wnext,M=a.wsize-L):M=a.wnext-L,L>a.length&&(L=a.length),H=a.window}else H=s,M=f-a.offset,L=a.length;L>c&&(L=c),c-=L,a.length-=L;do{s[f++]=H[M++]}while(--L);0===a.length&&(a.mode=O);break;case 16205:if(0===c)break e;s[f++]=a.length,c--,a.mode=O;break;case U:if(a.wrap){for(;N<32;){if(0===d)break e;d--,B|=o[l++]<<N,N+=8}if(F-=c,e.total_out+=F,a.total+=F,4&a.wrap&&F&&(e.adler=a.check=a.flags?n(a.check,s,F,f-F):t(a.check,s,F,f-F)),F=c,4&a.wrap&&(a.flags?B:I(B))!==a.check){e.msg="incorrect data check",a.mode=D;break}B=0,N=0}a.mode=16207;case 16207:if(a.wrap&&a.flags){for(;N<32;){if(0===d)break e;d--,B+=o[l++]<<N,N+=8}if(4&a.wrap&&B!==(4294967295&a.total)){e.msg="incorrect length check",a.mode=D;break}B=0,N=0}a.mode=16208;case 16208:Q=k;break e;case D:Q=g;break e;case 16210:return p;default:return v}return e.next_out=f,e.avail_out=c,e.next_in=l,e.avail_in=d,a.hold=B,a.bits=N,(a.wsize||F!==e.avail_out&&a.mode<D&&(a.mode<U||i!==u))&&P(e,e.output,e.next_out,F-e.avail_out),C-=e.avail_in,F-=e.avail_out,e.total_in+=C,e.total_out+=F,a.total+=F,4&a.wrap&&F&&(e.adler=a.check=a.flags?n(a.check,s,F,e.next_out-F):t(a.check,s,F,e.next_out-F)),e.data_type=a.bits+(a.last?64:0)+(a.mode===A?128:0)+(a.mode===T||a.mode===S?256:0),(0===C&&0===F||i===u)&&Q===m&&(Q=y),Q},inflateEnd:function(e){if(z(e))return v;var t=e.state;return t.window&&(t.window=null),e.state=null,m},inflateGetHeader:function(e,t){if(z(e))return v;var i=e.state;return 0==(2&i.wrap)?v:(i.head=t,t.done=!1,m)},inflateSetDictionary:function(e,i){var n,a=i.length;return z(e)||0!==(n=e.state).wrap&&n.mode!==R?v:n.mode===R&&t(1,i,a,0)!==n.check?g:P(e,i,a,a)?(n.mode=16210,p):(n.havedict=1,m)},inflateInfo:"pako inflate (from Nodeca project)"};function G(e){return G="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},G(e)}var X=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},W=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var i=t.shift();if(i){if("object"!==G(i))throw new TypeError(i+"must be non-object");for(var n in i)X(i,n)&&(e[n]=i[n])}}return e},q=function(e){for(var t=0,i=0,n=e.length;i<n;i++)t+=e[i].length;for(var a=new Uint8Array(t),r=0,o=0,s=e.length;r<s;r++){var l=e[r];a.set(l,o),o+=l.length}return a},J=!0;try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(e){J=!1}for(var Q=new Uint8Array(256),V=0;V<256;V++)Q[V]=V>=252?6:V>=248?5:V>=240?4:V>=224?3:V>=192?2:1;Q[254]=Q[254]=1;var $=function(e){if("function"==typeof TextEncoder&&TextEncoder.prototype.encode)return(new TextEncoder).encode(e);var t,i,n,a,r,o=e.length,s=0;for(a=0;a<o;a++)55296==(64512&(i=e.charCodeAt(a)))&&a+1<o&&56320==(64512&(n=e.charCodeAt(a+1)))&&(i=65536+(i-55296<<10)+(n-56320),a++),s+=i<128?1:i<2048?2:i<65536?3:4;for(t=new Uint8Array(s),r=0,a=0;r<s;a++)55296==(64512&(i=e.charCodeAt(a)))&&a+1<o&&56320==(64512&(n=e.charCodeAt(a+1)))&&(i=65536+(i-55296<<10)+(n-56320),a++),i<128?t[r++]=i:i<2048?(t[r++]=192|i>>>6,t[r++]=128|63&i):i<65536?(t[r++]=224|i>>>12,t[r++]=128|i>>>6&63,t[r++]=128|63&i):(t[r++]=240|i>>>18,t[r++]=128|i>>>12&63,t[r++]=128|i>>>6&63,t[r++]=128|63&i);return t},ee=function(e,t){var i,n,a=t||e.length;if("function"==typeof TextDecoder&&TextDecoder.prototype.decode)return(new TextDecoder).decode(e.subarray(0,t));var r=new Array(2*a);for(n=0,i=0;i<a;){var o=e[i++];if(o<128)r[n++]=o;else{var s=Q[o];if(s>4)r[n++]=65533,i+=s-1;else{for(o&=2===s?31:3===s?15:7;s>1&&i<a;)o=o<<6|63&e[i++],s--;s>1?r[n++]=65533:o<65536?r[n++]=o:(o-=65536,r[n++]=55296|o>>10&1023,r[n++]=56320|1023&o)}}}return function(e,t){if(t<65534&&e.subarray&&J)return String.fromCharCode.apply(null,e.length===t?e:e.subarray(0,t));for(var i="",n=0;n<t;n++)i+=String.fromCharCode(e[n]);return i}(r,n)},te=function(e,t){(t=t||e.length)>e.length&&(t=e.length);for(var i=t-1;i>=0&&128==(192&e[i]);)i--;return i<0||0===i?t:i+Q[e[i]]>t?i:t},ie={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"};var ne=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0};var ae=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1},re=Object.prototype.toString,oe=c.Z_NO_FLUSH,se=c.Z_FINISH,le=c.Z_OK,fe=c.Z_STREAM_END,de=c.Z_NEED_DICT,he=c.Z_STREAM_ERROR,ce=c.Z_DATA_ERROR,ue=c.Z_MEM_ERROR;function we(e){this.options=W({chunkSize:65536,windowBits:15,to:""},e||{});var t=this.options;t.raw&&t.windowBits>=0&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(t.windowBits>=0&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),t.windowBits>15&&t.windowBits<48&&0==(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new ne,this.strm.avail_out=0;var i=Y.inflateInit2(this.strm,t.windowBits);if(i!==le)throw new Error(ie[i]);if(this.header=new ae,Y.inflateGetHeader(this.strm,this.header),t.dictionary&&("string"==typeof t.dictionary?t.dictionary=$(t.dictionary):"[object ArrayBuffer]"===re.call(t.dictionary)&&(t.dictionary=new Uint8Array(t.dictionary)),t.raw&&(i=Y.inflateSetDictionary(this.strm,t.dictionary))!==le))throw new Error(ie[i])}function be(e,t){var i=new we(t);if(i.push(e),i.err)throw i.msg||ie[i.err];return i.result}we.prototype.push=function(e,t){var i,n,a,r=this.strm,o=this.options.chunkSize,s=this.options.dictionary;if(this.ended)return!1;for(n=t===~~t?t:!0===t?se:oe,"[object ArrayBuffer]"===re.call(e)?r.input=new Uint8Array(e):r.input=e,r.next_in=0,r.avail_in=r.input.length;;){for(0===r.avail_out&&(r.output=new Uint8Array(o),r.next_out=0,r.avail_out=o),(i=Y.inflate(r,n))===de&&s&&((i=Y.inflateSetDictionary(r,s))===le?i=Y.inflate(r,n):i===ce&&(i=de));r.avail_in>0&&i===fe&&r.state.wrap>0&&0!==e[r.next_in];)Y.inflateReset(r),i=Y.inflate(r,n);switch(i){case he:case ce:case de:case ue:return this.onEnd(i),this.ended=!0,!1}if(a=r.avail_out,r.next_out&&(0===r.avail_out||i===fe))if("string"===this.options.to){var l=te(r.output,r.next_out),f=r.next_out-l,d=ee(r.output,l);r.next_out=f,r.avail_out=o-f,f&&r.output.set(r.output.subarray(l,l+f),0),this.onData(d)}else this.onData(r.output.length===r.next_out?r.output:r.output.subarray(0,r.next_out));if(i!==le||0!==a){if(i===fe)return i=Y.inflateEnd(this.strm),this.onEnd(i),this.ended=!0,!0;if(0===r.avail_in)break}}return!0},we.prototype.onData=function(e){this.chunks.push(e)},we.prototype.onEnd=function(e){e===le&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=q(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg};var me=we,ke=be,_e=function(e,t){return(t=t||{}).raw=!0,be(e,t)},ve=be,ge=c,pe={Inflate:me,inflate:ke,inflateRaw:_e,ungzip:ve,constants:ge};e.Inflate=me,e.constants=ge,e.default=pe,e.inflate=ke,e.inflateRaw=_e,e.ungzip=ve,Object.defineProperty(e,"__esModule",{value:!0})}));
44
- `;
19
+ export const StringCompressionLibraryMinified = `
20
+ var {StringCompressionLibrary}=function(){var r=String.fromCharCode,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",e={};function t(r,o){if(!e[r]){e[r]={};for(var n=0;n<r.length;n++)e[r][r.charAt(n)]=n}return e[r][o]}var i={compressToBase64:function(r){if(null==r)return"";var n=i._compress(r,6,function(r){return o.charAt(r)});switch(n.length%4){default:case 0:return n;case 1:return n+"===";case 2:return n+"==";case 3:return n+"="}},decompressFromBase64:function(r){return null==r?"":""==r?null:i._decompress(r.length,32,function(n){return t(o,r.charAt(n))})},compressToUTF16:function(o){return null==o?"":i._compress(o,15,function(o){return r(o+32)})+" "},decompressFromUTF16:function(r){return null==r?"":""==r?null:i._decompress(r.length,16384,function(o){return r.charCodeAt(o)-32})},compressToUint8Array:function(r){for(var o=i.compress(r),n=new Uint8Array(2*o.length),e=0,t=o.length;e<t;e++){var s=o.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null==o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;e<t;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(r){return null==r?"":i._compress(r,6,function(r){return n.charAt(r)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(o){return t(n,r.charAt(o))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(r,o,n){if(null==r)return"";var e,t,i,s={},u={},a="",p="",c="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<r.length;i+=1)if(a=r.charAt(i),Object.prototype.hasOwnProperty.call(s,a)||(s[a]=f++,u[a]=!0),p=c+a,Object.prototype.hasOwnProperty.call(s,p))c=p;else{if(Object.prototype.hasOwnProperty.call(u,c)){if(c.charCodeAt(0)<256){for(e=0;e<h;e++)m<<=1,v==o-1?(v=0,d.push(n(m)),m=0):v++;for(t=c.charCodeAt(0),e=0;e<8;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;e<h;e++)m=m<<1|t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=c.charCodeAt(0),e=0;e<16;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;0==--l&&(l=Math.pow(2,h),h++),s[p]=f++,c=String(a)}if(""!==c){if(Object.prototype.hasOwnProperty.call(u,c)){if(c.charCodeAt(0)<256){for(e=0;e<h;e++)m<<=1,v==o-1?(v=0,d.push(n(m)),m=0):v++;for(t=c.charCodeAt(0),e=0;e<8;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;e<h;e++)m=m<<1|t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=c.charCodeAt(0),e=0;e<16;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;0==--l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==o-1){d.push(n(m));break}v++}return d.join("")},decompress:function(r){return null==r?"":""==r?null:i._decompress(r.length,32768,function(o){return r.charCodeAt(o)})},_decompress:function(o,n,e){var t,i,s,u,a,p,c,l=[],f=4,h=4,d=3,m="",v=[],g={val:e(0),position:n,index:1};for(t=0;t<3;t+=1)l[t]=t;for(s=0,a=Math.pow(2,2),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;switch(s){case 0:for(s=0,a=Math.pow(2,8),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;c=r(s);break;case 1:for(s=0,a=Math.pow(2,16),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;c=r(s);break;case 2:return""}for(l[3]=c,i=c,v.push(c);;){if(g.index>o)return"";for(s=0,a=Math.pow(2,d),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;switch(c=s){case 0:for(s=0,a=Math.pow(2,8),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;l[h++]=r(s),c=h-1,f--;break;case 1:for(s=0,a=Math.pow(2,16),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;l[h++]=r(s),c=h-1,f--;break;case 2:return v.join("")}if(0==f&&(f=Math.pow(2,d),d++),l[c])m=l[c];else{if(c!==h)return null;m=i+i.charAt(0)}v.push(m),l[h++]=i+m.charAt(0),i=m,0==--f&&(f=Math.pow(2,d),d++)}}};return i}();"function"==typeof define&&define.amd?define(function(){return {StringCompressionLibrary}}):"undefined"!=typeof module&&null!=module?module.exports={StringCompressionLibrary}:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return {StringCompressionLibrary}});`;
@@ -1,7 +1,11 @@
1
1
  import { NodePath } from "@babel/traverse";
2
2
  import { PluginInstance } from "../transforms/plugin";
3
3
  import Template from "./template";
4
- import { MULTI_TRANSFORM, UNSAFE } from "../constants";
4
+ import {
5
+ MULTI_TRANSFORM,
6
+ placeholderVariablePrefix,
7
+ UNSAFE,
8
+ } from "../constants";
5
9
 
6
10
  export const StrictModeTemplate = new Template(`
7
11
  (function(){
@@ -109,8 +113,8 @@ export const createEvalIntegrityTemplate = (
109
113
  }
110
114
 
111
115
  return new Template(`
112
- function {EvalIntegrityName}(a = true){
113
- return a;
116
+ function {EvalIntegrityName}(${placeholderVariablePrefix}_flag = true){
117
+ return ${placeholderVariablePrefix}_flag;
114
118
  }
115
119
  `);
116
120
  };
@@ -27,7 +27,7 @@ export default class Template {
27
27
  private requiredVariables: Set<string>;
28
28
  private astVariableMappings: Map<string, string>;
29
29
  private astIdentifierPrefix = "__t_" + getRandomString(6);
30
- private symbols: NodeSymbolKeys[] = [];
30
+ private symbols = new Set<NodeSymbolKeys>();
31
31
 
32
32
  constructor(...templates: string[]) {
33
33
  this.templates = templates;
@@ -38,7 +38,9 @@ export default class Template {
38
38
  }
39
39
 
40
40
  addSymbols(...symbols: NodeSymbolKeys[]): this {
41
- this.symbols.push(...symbols);
41
+ symbols.forEach((symbol) => {
42
+ this.symbols.add(symbol);
43
+ });
42
44
  return this;
43
45
  }
44
46
 
@@ -174,7 +176,7 @@ export default class Template {
174
176
 
175
177
  this.interpolateAST(file, variables);
176
178
 
177
- if (this.symbols.length > 0) {
179
+ if (this.symbols.size > 0) {
178
180
  file.program.body.forEach((node) => {
179
181
  for (const symbol of this.symbols) {
180
182
  node[symbol] = true;
@@ -1,7 +1,6 @@
1
1
  import traverse, { NodePath, Scope, Visitor } from "@babel/traverse";
2
2
  import { PluginArg, PluginObject } from "./plugin";
3
3
  import { Order } from "../order";
4
- import { computeProbabilityMap } from "../probability";
5
4
  import {
6
5
  ensureComputedExpression,
7
6
  getParentFunctionOrProgram,
@@ -30,7 +29,6 @@ import {
30
29
  PREDICTABLE,
31
30
  variableFunctionName,
32
31
  WITH_STATEMENT,
33
- CONTROL_OBJECTS,
34
32
  } from "../constants";
35
33
 
36
34
  /**
@@ -116,7 +114,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
116
114
  if (blockPath.node.body.length < 3) return;
117
115
 
118
116
  // Check user's threshold setting
119
- if (!computeProbabilityMap(me.options.controlFlowFlattening)) {
117
+ if (!me.computeProbabilityMap(me.options.controlFlowFlattening)) {
120
118
  return;
121
119
  }
122
120
 
@@ -1081,7 +1079,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
1081
1079
  const identifierName = path.node.name;
1082
1080
  if (identifierName === gotoFunctionName) return;
1083
1081
 
1084
- var binding = basicBlock.scope.getBinding(identifierName);
1082
+ var binding = path.scope.getBinding(identifierName);
1085
1083
  if (!binding) {
1086
1084
  return;
1087
1085
  }
@@ -1580,9 +1578,6 @@ export default ({ Plugin }: PluginArg): PluginObject => {
1580
1578
  // Reset all bindings here
1581
1579
  blockPath.scope.bindings = Object.create(null);
1582
1580
 
1583
- // Bindings changed - breaking control objects
1584
- delete (blockPath.node as NodeSymbol)[CONTROL_OBJECTS];
1585
-
1586
1581
  // Register new declarations
1587
1582
  for (var node of blockPath.get("body")) {
1588
1583
  blockPath.scope.registerDeclaration(node);
@@ -1,12 +1,11 @@
1
1
  import { PluginArg, PluginObject } from "./plugin";
2
2
  import { chance, choice } from "../utils/random-utils";
3
3
  import { deadCodeTemplates } from "../templates/deadCodeTemplates";
4
- import { computeProbabilityMap } from "../probability";
5
4
  import { Order } from "../order";
6
5
  import * as t from "@babel/types";
7
6
  import Template from "../templates/template";
8
- import { NameGen } from "../utils/NameGen";
9
7
  import { prepend } from "../utils/ast-utils";
8
+ import PredicateGen from "../utils/PredicateGen";
10
9
 
11
10
  export default ({ Plugin }: PluginArg): PluginObject => {
12
11
  const me = Plugin(Order.DeadCode, {
@@ -15,6 +14,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
15
14
  },
16
15
  });
17
16
  let created = 0;
17
+ let predicateGen = new PredicateGen(me);
18
18
 
19
19
  return {
20
20
  visitor: {
@@ -22,7 +22,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
22
22
  exit(blockPath) {
23
23
  if (blockPath.find((p) => me.isSkipped(p))) return;
24
24
 
25
- if (!computeProbabilityMap(me.options.deadCode)) {
25
+ if (!me.computeProbabilityMap(me.options.deadCode)) {
26
26
  return;
27
27
  }
28
28
 
@@ -43,8 +43,10 @@ export default ({ Plugin }: PluginArg): PluginObject => {
43
43
 
44
44
  var containingFnName = me.getPlaceholder("dead_" + created);
45
45
 
46
- var newPath = blockPath.unshiftContainer(
47
- "body",
46
+ // Insert dummy function
47
+ prepend(
48
+ blockPath,
49
+
48
50
  t.functionDeclaration(
49
51
  t.identifier(containingFnName),
50
52
  [],
@@ -52,29 +54,15 @@ export default ({ Plugin }: PluginArg): PluginObject => {
52
54
  )
53
55
  );
54
56
 
55
- // Overcomplicated way to get a random property name that doesn't exist on the Function
56
- var randomProperty: string;
57
- var nameGen = new NameGen("randomized");
58
-
59
- function PrototypeCollision() {}
60
- PrototypeCollision(); // Call it for code coverage :D
61
-
62
- do {
63
- randomProperty = nameGen.generate();
64
- } while (
65
- !randomProperty ||
66
- PrototypeCollision[randomProperty] !== undefined
67
- );
68
-
69
- me.changeData.deadCode++;
70
-
71
57
  prepend(
72
58
  blockPath,
73
59
  new Template(`
74
- if("${randomProperty}" in ${containingFnName}) {
60
+ if({falsePredicate}) {
75
61
  ${containingFnName}()
76
62
  }
77
- `).single()
63
+ `).single({
64
+ falsePredicate: predicateGen.generateFalseExpression(blockPath),
65
+ })
78
66
  );
79
67
 
80
68
  me.skip(blockPath);