js-confuser 2.0.0-alpha.5 → 2.0.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.
Files changed (113) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +43 -43
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/workflows/node.js.yml +28 -28
  4. package/.prettierrc +4 -4
  5. package/CHANGELOG.md +1015 -989
  6. package/CODE_OF_CONDUCT.md +131 -131
  7. package/CONTRIBUTING.md +52 -52
  8. package/LICENSE +21 -21
  9. package/Migration.md +72 -71
  10. package/README.md +86 -78
  11. package/dist/constants.js +43 -43
  12. package/dist/index.js +14 -23
  13. package/dist/obfuscator.js +31 -25
  14. package/dist/order.js +4 -4
  15. package/dist/presets.js +31 -31
  16. package/dist/templates/integrityTemplate.js +4 -4
  17. package/dist/templates/template.js +1 -2
  18. package/dist/transforms/astScrambler.js +1 -2
  19. package/dist/transforms/calculator.js +1 -2
  20. package/dist/transforms/controlFlowFlattening.js +93 -63
  21. package/dist/transforms/deadCode.js +1 -2
  22. package/dist/transforms/dispatcher.js +4 -5
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +1 -2
  24. package/dist/transforms/extraction/objectExtraction.js +1 -2
  25. package/dist/transforms/finalizer.js +1 -2
  26. package/dist/transforms/flatten.js +1 -2
  27. package/dist/transforms/identifier/globalConcealing.js +15 -2
  28. package/dist/transforms/identifier/movedDeclarations.js +8 -7
  29. package/dist/transforms/identifier/renameVariables.js +7 -7
  30. package/dist/transforms/lock/integrity.js +11 -10
  31. package/dist/transforms/lock/lock.js +2 -3
  32. package/dist/transforms/minify.js +11 -29
  33. package/dist/transforms/opaquePredicates.js +1 -2
  34. package/dist/transforms/pack.js +5 -2
  35. package/dist/transforms/plugin.js +18 -19
  36. package/dist/transforms/preparation.js +16 -16
  37. package/dist/transforms/renameLabels.js +1 -2
  38. package/dist/transforms/rgf.js +8 -9
  39. package/dist/transforms/shuffle.js +1 -2
  40. package/dist/transforms/string/encoding.js +1 -2
  41. package/dist/transforms/string/stringCompression.js +3 -4
  42. package/dist/transforms/string/stringConcealing.js +8 -3
  43. package/dist/transforms/string/stringEncoding.js +1 -2
  44. package/dist/transforms/variableMasking.js +1 -2
  45. package/dist/utils/NameGen.js +2 -2
  46. package/dist/utils/PredicateGen.js +1 -2
  47. package/dist/utils/ast-utils.js +87 -88
  48. package/dist/utils/function-utils.js +8 -8
  49. package/dist/utils/node.js +5 -6
  50. package/dist/utils/object-utils.js +4 -4
  51. package/dist/utils/random-utils.js +20 -20
  52. package/dist/utils/static-utils.js +1 -2
  53. package/dist/validateOptions.js +4 -7
  54. package/index.d.ts +17 -17
  55. package/package.json +61 -59
  56. package/src/constants.ts +168 -168
  57. package/src/index.ts +118 -118
  58. package/src/obfuscationResult.ts +49 -49
  59. package/src/obfuscator.ts +501 -497
  60. package/src/options.ts +407 -407
  61. package/src/order.ts +54 -54
  62. package/src/presets.ts +125 -125
  63. package/src/templates/bufferToStringTemplate.ts +57 -57
  64. package/src/templates/deadCodeTemplates.ts +1185 -1185
  65. package/src/templates/getGlobalTemplate.ts +76 -76
  66. package/src/templates/integrityTemplate.ts +64 -64
  67. package/src/templates/setFunctionLengthTemplate.ts +11 -11
  68. package/src/templates/stringCompressionTemplate.ts +20 -20
  69. package/src/templates/tamperProtectionTemplates.ts +120 -120
  70. package/src/templates/template.ts +224 -224
  71. package/src/transforms/astScrambler.ts +99 -99
  72. package/src/transforms/calculator.ts +99 -99
  73. package/src/transforms/controlFlowFlattening.ts +1716 -1664
  74. package/src/transforms/deadCode.ts +82 -82
  75. package/src/transforms/dispatcher.ts +450 -450
  76. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +156 -158
  77. package/src/transforms/extraction/objectExtraction.ts +186 -186
  78. package/src/transforms/finalizer.ts +74 -74
  79. package/src/transforms/flatten.ts +421 -420
  80. package/src/transforms/identifier/globalConcealing.ts +315 -295
  81. package/src/transforms/identifier/movedDeclarations.ts +252 -251
  82. package/src/transforms/identifier/renameVariables.ts +328 -321
  83. package/src/transforms/lock/integrity.ts +117 -114
  84. package/src/transforms/lock/lock.ts +418 -425
  85. package/src/transforms/minify.ts +615 -629
  86. package/src/transforms/opaquePredicates.ts +100 -100
  87. package/src/transforms/pack.ts +239 -231
  88. package/src/transforms/plugin.ts +173 -173
  89. package/src/transforms/preparation.ts +349 -347
  90. package/src/transforms/renameLabels.ts +175 -175
  91. package/src/transforms/rgf.ts +322 -322
  92. package/src/transforms/shuffle.ts +82 -82
  93. package/src/transforms/string/encoding.ts +144 -144
  94. package/src/transforms/string/stringCompression.ts +128 -128
  95. package/src/transforms/string/stringConcealing.ts +312 -298
  96. package/src/transforms/string/stringEncoding.ts +80 -80
  97. package/src/transforms/string/stringSplitting.ts +77 -77
  98. package/src/transforms/variableMasking.ts +257 -257
  99. package/src/utils/IntGen.ts +33 -33
  100. package/src/utils/NameGen.ts +116 -116
  101. package/src/utils/PredicateGen.ts +61 -61
  102. package/src/utils/ast-utils.ts +663 -663
  103. package/src/utils/function-utils.ts +50 -50
  104. package/src/utils/gen-utils.ts +48 -48
  105. package/src/utils/node.ts +78 -78
  106. package/src/utils/object-utils.ts +21 -21
  107. package/src/utils/random-utils.ts +93 -93
  108. package/src/utils/static-utils.ts +66 -66
  109. package/src/validateOptions.ts +256 -259
  110. package/tsconfig.json +13 -14
  111. package/dist/probability.js +0 -1
  112. package/dist/transforms/functionOutlining.js +0 -230
  113. package/dist/utils/ControlObject.js +0 -125
@@ -1,295 +1,315 @@
1
- import * as t from "@babel/types";
2
- import { NodePath } from "@babel/traverse";
3
- import { NameGen } from "../../utils/NameGen";
4
- import Template from "../../templates/template";
5
- import { PluginArg, PluginObject } from "../plugin";
6
- import { Order } from "../../order";
7
- import {
8
- MULTI_TRANSFORM,
9
- reservedIdentifiers,
10
- reservedNodeModuleIdentifiers,
11
- variableFunctionName,
12
- } from "../../constants";
13
- import {
14
- getMemberExpressionPropertyAsString,
15
- isVariableIdentifier,
16
- prepend,
17
- } from "../../utils/ast-utils";
18
- import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
19
- import {
20
- getRandomInteger,
21
- getRandomString,
22
- shuffle,
23
- } from "../../utils/random-utils";
24
- import { ok } from "assert";
25
-
26
- const ignoreGlobals = new Set([
27
- ...reservedNodeModuleIdentifiers,
28
- "__dirname",
29
- "eval",
30
- "arguments",
31
- variableFunctionName,
32
- ...reservedIdentifiers,
33
- ]);
34
-
35
- export default ({ Plugin }: PluginArg): PluginObject => {
36
- const me = Plugin(Order.GlobalConcealing, {
37
- changeData: {
38
- globals: 0,
39
- nativeFunctions: 0,
40
- },
41
- });
42
-
43
- var globalMapping = new Map<string, string>(),
44
- globalFnName = me.getPlaceholder() + "_getGlobal",
45
- globalVarName = me.getPlaceholder() + "_globalVar",
46
- gen = new NameGen();
47
-
48
- // Create the getGlobal function using a template
49
- function createGlobalConcealingFunction(): t.FunctionDeclaration {
50
- // Create fake global mappings
51
-
52
- var fakeCount = getRandomInteger(20, 40);
53
- for (var i = 0; i < fakeCount; i++) {
54
- var fakeName = getRandomString(getRandomInteger(6, 8));
55
- globalMapping.set(gen.generate(), fakeName);
56
- }
57
-
58
- const createSwitchStatement = () => {
59
- const cases = shuffle(Array.from(globalMapping.keys())).map(
60
- (originalName) => {
61
- var mappedKey = globalMapping.get(originalName);
62
-
63
- return t.switchCase(t.stringLiteral(mappedKey), [
64
- t.returnStatement(
65
- t.memberExpression(
66
- t.identifier(globalVarName),
67
- t.stringLiteral(originalName),
68
- true
69
- )
70
- ),
71
- ]);
72
- }
73
- );
74
-
75
- return t.switchStatement(t.identifier("mapping"), cases);
76
- };
77
-
78
- return t.functionDeclaration(
79
- t.identifier(globalFnName),
80
- [t.identifier("mapping")],
81
- t.blockStatement([createSwitchStatement()])
82
- );
83
- }
84
-
85
- return {
86
- visitor: {
87
- Program: {
88
- exit(programPath: NodePath<t.Program>) {
89
- var illegalGlobals = new Set<string>();
90
- var pendingReplacements = new Map<string, NodePath[]>();
91
-
92
- programPath.traverse({
93
- Identifier(identifierPath) {
94
- if (!isVariableIdentifier(identifierPath)) return;
95
-
96
- var identifierName = identifierPath.node.name;
97
-
98
- if (ignoreGlobals.has(identifierName)) return;
99
-
100
- const binding = identifierPath.scope.getBinding(identifierName);
101
- if (binding) {
102
- illegalGlobals.add(identifierName);
103
- return;
104
- }
105
-
106
- if (!identifierPath.scope.hasGlobal(identifierName)) {
107
- return;
108
- }
109
-
110
- var assignmentChild = identifierPath.find((p) =>
111
- p.parentPath?.isAssignmentExpression()
112
- );
113
- if (
114
- assignmentChild &&
115
- t.isAssignmentExpression(assignmentChild.parent) &&
116
- assignmentChild.parent.left === assignmentChild.node &&
117
- !t.isMemberExpression(identifierPath.parent)
118
- ) {
119
- illegalGlobals.add(identifierName);
120
- return;
121
- }
122
-
123
- if (!pendingReplacements.has(identifierName)) {
124
- pendingReplacements.set(identifierName, [identifierPath]);
125
- } else {
126
- pendingReplacements.get(identifierName).push(identifierPath);
127
- }
128
- },
129
- });
130
-
131
- // Remove illegal globals
132
- illegalGlobals.forEach((globalName) => {
133
- pendingReplacements.delete(globalName);
134
- });
135
-
136
- for (var [globalName, paths] of pendingReplacements) {
137
- var mapping = globalMapping.get(globalName);
138
- if (!mapping) {
139
- // Allow user to disable custom global variables
140
- if (
141
- !me.computeProbabilityMap(
142
- me.options.globalConcealing,
143
- globalName
144
- )
145
- )
146
- continue;
147
-
148
- mapping = gen.generate();
149
- globalMapping.set(globalName, mapping);
150
- }
151
-
152
- // Replace global reference with getGlobal("name")
153
- const callExpression = t.callExpression(
154
- t.identifier(globalFnName),
155
- [t.stringLiteral(mapping)]
156
- );
157
-
158
- const { nativeFunctionName } = me.globalState.internals;
159
-
160
- for (let path of paths) {
161
- const replaceExpression = t.cloneNode(callExpression);
162
- me.skip(replaceExpression);
163
-
164
- if (
165
- // Native Function will only be populated if tamper protection is enabled
166
- nativeFunctionName &&
167
- // Avoid maximum call stack error
168
- !path.find((p) => p.node[MULTI_TRANSFORM] || me.isSkipped(p))
169
- ) {
170
- // First extract the member expression chain
171
- let nameAndPropertyPath = [globalName];
172
- let cursorPath = path;
173
- let callExpressionPath: NodePath<t.CallExpression> | null =
174
- null;
175
-
176
- const checkForCallExpression = () => {
177
- if (
178
- cursorPath.parentPath?.isCallExpression() &&
179
- cursorPath.key === "callee"
180
- ) {
181
- callExpressionPath = cursorPath.parentPath;
182
- return true;
183
- }
184
- };
185
-
186
- if (!checkForCallExpression()) {
187
- cursorPath = cursorPath?.parentPath;
188
- while (cursorPath?.isMemberExpression()) {
189
- let propertyString = getMemberExpressionPropertyAsString(
190
- cursorPath.node
191
- );
192
- if (!propertyString || typeof propertyString !== "string") {
193
- break;
194
- }
195
-
196
- nameAndPropertyPath.push(propertyString);
197
-
198
- if (checkForCallExpression()) break;
199
- cursorPath = cursorPath.parentPath;
200
- }
201
- }
202
-
203
- // Eligible member-expression/identifier
204
- if (callExpressionPath) {
205
- // Check user's custom implementation
206
- var shouldTransform =
207
- me.obfuscator.shouldTransformNativeFunction(
208
- nameAndPropertyPath
209
- );
210
- if (shouldTransform) {
211
- path.replaceWith(replaceExpression);
212
-
213
- // console.log("Hello World") ->
214
- // checkNative(getGlobal("console")["log"])("Hello World")
215
-
216
- // Parent-most member expression must be wrapped
217
- // This to preserve proper 'this' binding in member expression invocations
218
- let callee = callExpressionPath.get(
219
- "callee"
220
- ) as NodePath<t.Expression>;
221
- let callArgs: t.Expression[] = [callee.node];
222
-
223
- if (callee.isMemberExpression()) {
224
- const additionalPropertyString =
225
- getMemberExpressionPropertyAsString(callee.node);
226
- ok(
227
- additionalPropertyString,
228
- "Expected additional property to be a string"
229
- );
230
- callee = callee.get("object");
231
- callArgs = [
232
- callee.node,
233
- t.stringLiteral(additionalPropertyString),
234
- ];
235
- }
236
-
237
- // Method supports two signatures:
238
- // checkNative(fetch)(...)
239
- // checkNative(console, "log")(...)
240
-
241
- callExpressionPath
242
- .get("callee")
243
- .replaceWith(
244
- me.skip(
245
- t.callExpression(
246
- t.identifier(nativeFunctionName),
247
- callArgs
248
- )
249
- )
250
- );
251
-
252
- me.changeData.nativeFunctions++;
253
- continue;
254
- }
255
- }
256
- }
257
-
258
- me.changeData.globals++;
259
-
260
- // Regular replacement
261
- // console -> getGlobal("console")
262
- path.replaceWith(replaceExpression);
263
- }
264
- }
265
-
266
- // No globals changed, no need to insert the getGlobal function
267
- if (globalMapping.size === 0) return;
268
-
269
- // The Global Concealing function returns the global variable from the specified parameter
270
- const globalConcealingFunction = createGlobalConcealingFunction();
271
-
272
- prepend(programPath, globalConcealingFunction);
273
-
274
- const getGlobalVarFnName = me.getPlaceholder() + "_getGlobalVarFn";
275
-
276
- // Insert the get global function
277
- prepend(
278
- programPath,
279
- createGetGlobalTemplate(me, programPath).compile({
280
- getGlobalFnName: getGlobalVarFnName,
281
- })
282
- );
283
-
284
- // Call the get global function and store result in 'globalVarName'
285
- prepend(
286
- programPath,
287
- new Template(
288
- `var ${globalVarName} = ${getGlobalVarFnName}()`
289
- ).single<t.Statement>()
290
- );
291
- },
292
- },
293
- },
294
- };
295
- };
1
+ import * as t from "@babel/types";
2
+ import { NodePath } from "@babel/traverse";
3
+ import { NameGen } from "../../utils/NameGen";
4
+ import Template from "../../templates/template";
5
+ import { PluginArg, PluginObject } from "../plugin";
6
+ import { Order } from "../../order";
7
+ import {
8
+ MULTI_TRANSFORM,
9
+ reservedIdentifiers,
10
+ reservedNodeModuleIdentifiers,
11
+ variableFunctionName,
12
+ } from "../../constants";
13
+ import {
14
+ getMemberExpressionPropertyAsString,
15
+ isVariableIdentifier,
16
+ prepend,
17
+ } from "../../utils/ast-utils";
18
+ import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
19
+ import {
20
+ getRandomInteger,
21
+ getRandomString,
22
+ shuffle,
23
+ } from "../../utils/random-utils";
24
+ import { ok } from "assert";
25
+
26
+ const ignoreGlobals = new Set([
27
+ ...reservedNodeModuleIdentifiers,
28
+ "__dirname",
29
+ "eval",
30
+ "arguments",
31
+ variableFunctionName,
32
+ ...reservedIdentifiers,
33
+ ]);
34
+
35
+ export default ({ Plugin }: PluginArg): PluginObject => {
36
+ const me = Plugin(Order.GlobalConcealing, {
37
+ changeData: {
38
+ globals: 0,
39
+ nativeFunctions: 0,
40
+ },
41
+ });
42
+
43
+ var globalMapping = new Map<string, string>(),
44
+ globalFnName = me.getPlaceholder() + "_getGlobal",
45
+ globalVarName = me.getPlaceholder() + "_globalVar",
46
+ gen = new NameGen();
47
+
48
+ // Create the getGlobal function using a template
49
+ function createGlobalConcealingFunction(): t.FunctionDeclaration {
50
+ // Create fake global mappings
51
+
52
+ var fakeCount = getRandomInteger(20, 40);
53
+ for (var i = 0; i < fakeCount; i++) {
54
+ var fakeName = getRandomString(getRandomInteger(6, 8));
55
+ globalMapping.set(gen.generate(), fakeName);
56
+ }
57
+
58
+ const createSwitchStatement = () => {
59
+ const cases = shuffle(Array.from(globalMapping.keys())).map(
60
+ (originalName) => {
61
+ var mappedKey = globalMapping.get(originalName);
62
+
63
+ return t.switchCase(t.stringLiteral(mappedKey), [
64
+ t.returnStatement(
65
+ t.memberExpression(
66
+ t.identifier(globalVarName),
67
+ t.stringLiteral(originalName),
68
+ true
69
+ )
70
+ ),
71
+ ]);
72
+ }
73
+ );
74
+
75
+ return t.switchStatement(t.identifier("mapping"), cases);
76
+ };
77
+
78
+ return t.functionDeclaration(
79
+ t.identifier(globalFnName),
80
+ [t.identifier("mapping")],
81
+ t.blockStatement([createSwitchStatement()])
82
+ );
83
+ }
84
+
85
+ return {
86
+ visitor: {
87
+ Program: {
88
+ exit(programPath: NodePath<t.Program>) {
89
+ var illegalGlobals = new Set<string>();
90
+ var pendingReplacements = new Map<string, NodePath[]>();
91
+
92
+ programPath.traverse({
93
+ Identifier(identifierPath) {
94
+ if (!isVariableIdentifier(identifierPath)) return;
95
+
96
+ var identifierName = identifierPath.node.name;
97
+
98
+ if (ignoreGlobals.has(identifierName)) return;
99
+
100
+ const binding = identifierPath.scope.getBinding(identifierName);
101
+ if (binding) {
102
+ illegalGlobals.add(identifierName);
103
+ return;
104
+ }
105
+
106
+ if (!identifierPath.scope.hasGlobal(identifierName)) {
107
+ return;
108
+ }
109
+
110
+ // Do not transform:
111
+ // identifier = "value"
112
+ var assignmentChild = identifierPath.find((p) =>
113
+ p.parentPath?.isAssignmentExpression()
114
+ );
115
+ if (
116
+ assignmentChild &&
117
+ t.isAssignmentExpression(assignmentChild.parent) &&
118
+ assignmentChild.parent.left === assignmentChild.node &&
119
+ !t.isMemberExpression(identifierPath.parent)
120
+ ) {
121
+ illegalGlobals.add(identifierName);
122
+ return;
123
+ }
124
+
125
+ // Do not transform:
126
+ // for(identifier in object) or for(identifier of object)
127
+ var forInOfChild = identifierPath.find(
128
+ (p) =>
129
+ p.key === "left" &&
130
+ (p.parentPath?.isForInStatement() ||
131
+ p.parentPath?.isForOfStatement())
132
+ );
133
+ if (
134
+ forInOfChild &&
135
+ (t.isForInStatement(forInOfChild.parent) ||
136
+ t.isForOfStatement(forInOfChild.parent)) &&
137
+ forInOfChild.parent.left === forInOfChild.node
138
+ ) {
139
+ illegalGlobals.add(identifierName);
140
+ return;
141
+ }
142
+
143
+ if (!pendingReplacements.has(identifierName)) {
144
+ pendingReplacements.set(identifierName, [identifierPath]);
145
+ } else {
146
+ pendingReplacements.get(identifierName).push(identifierPath);
147
+ }
148
+ },
149
+ });
150
+
151
+ // Remove illegal globals
152
+ illegalGlobals.forEach((globalName) => {
153
+ pendingReplacements.delete(globalName);
154
+ });
155
+
156
+ for (var [globalName, paths] of pendingReplacements) {
157
+ var mapping = globalMapping.get(globalName);
158
+ if (!mapping) {
159
+ // Allow user to disable custom global variables
160
+ if (
161
+ !me.computeProbabilityMap(
162
+ me.options.globalConcealing,
163
+ globalName
164
+ )
165
+ )
166
+ continue;
167
+
168
+ mapping = gen.generate();
169
+ globalMapping.set(globalName, mapping);
170
+ }
171
+
172
+ // Replace global reference with getGlobal("name")
173
+ const callExpression = t.callExpression(
174
+ t.identifier(globalFnName),
175
+ [t.stringLiteral(mapping)]
176
+ );
177
+
178
+ const { nativeFunctionName } = me.globalState.internals;
179
+
180
+ for (let path of paths) {
181
+ const replaceExpression = t.cloneNode(callExpression);
182
+ me.skip(replaceExpression);
183
+
184
+ if (
185
+ // Native Function will only be populated if tamper protection is enabled
186
+ nativeFunctionName &&
187
+ // Avoid maximum call stack error
188
+ !path.find((p) => p.node[MULTI_TRANSFORM] || me.isSkipped(p))
189
+ ) {
190
+ // First extract the member expression chain
191
+ let nameAndPropertyPath = [globalName];
192
+ let cursorPath = path;
193
+ let callExpressionPath: NodePath<t.CallExpression> | null =
194
+ null;
195
+
196
+ const checkForCallExpression = () => {
197
+ if (
198
+ cursorPath.parentPath?.isCallExpression() &&
199
+ cursorPath.key === "callee"
200
+ ) {
201
+ callExpressionPath = cursorPath.parentPath;
202
+ return true;
203
+ }
204
+ };
205
+
206
+ if (!checkForCallExpression()) {
207
+ cursorPath = cursorPath?.parentPath;
208
+ while (cursorPath?.isMemberExpression()) {
209
+ let propertyString = getMemberExpressionPropertyAsString(
210
+ cursorPath.node
211
+ );
212
+ if (!propertyString || typeof propertyString !== "string") {
213
+ break;
214
+ }
215
+
216
+ nameAndPropertyPath.push(propertyString);
217
+
218
+ if (checkForCallExpression()) break;
219
+ cursorPath = cursorPath.parentPath;
220
+ }
221
+ }
222
+
223
+ // Eligible member-expression/identifier
224
+ if (callExpressionPath) {
225
+ // Check user's custom implementation
226
+ var shouldTransform =
227
+ me.obfuscator.shouldTransformNativeFunction(
228
+ nameAndPropertyPath
229
+ );
230
+ if (shouldTransform) {
231
+ path.replaceWith(replaceExpression);
232
+
233
+ // console.log("Hello World") ->
234
+ // checkNative(getGlobal("console")["log"])("Hello World")
235
+
236
+ // Parent-most member expression must be wrapped
237
+ // This to preserve proper 'this' binding in member expression invocations
238
+ let callee = callExpressionPath.get(
239
+ "callee"
240
+ ) as NodePath<t.Expression>;
241
+ let callArgs: t.Expression[] = [callee.node];
242
+
243
+ if (callee.isMemberExpression()) {
244
+ const additionalPropertyString =
245
+ getMemberExpressionPropertyAsString(callee.node);
246
+ ok(
247
+ additionalPropertyString,
248
+ "Expected additional property to be a string"
249
+ );
250
+ callee = callee.get("object");
251
+ callArgs = [
252
+ callee.node,
253
+ t.stringLiteral(additionalPropertyString),
254
+ ];
255
+ }
256
+
257
+ // Method supports two signatures:
258
+ // checkNative(fetch)(...)
259
+ // checkNative(console, "log")(...)
260
+
261
+ callExpressionPath
262
+ .get("callee")
263
+ .replaceWith(
264
+ me.skip(
265
+ t.callExpression(
266
+ t.identifier(nativeFunctionName),
267
+ callArgs
268
+ )
269
+ )
270
+ );
271
+
272
+ me.changeData.nativeFunctions++;
273
+ continue;
274
+ }
275
+ }
276
+ }
277
+
278
+ me.changeData.globals++;
279
+
280
+ // Regular replacement
281
+ // console -> getGlobal("console")
282
+ path.replaceWith(replaceExpression);
283
+ }
284
+ }
285
+
286
+ // No globals changed, no need to insert the getGlobal function
287
+ if (globalMapping.size === 0) return;
288
+
289
+ // The Global Concealing function returns the global variable from the specified parameter
290
+ const globalConcealingFunction = createGlobalConcealingFunction();
291
+
292
+ prepend(programPath, globalConcealingFunction);
293
+
294
+ const getGlobalVarFnName = me.getPlaceholder() + "_getGlobalVarFn";
295
+
296
+ // Insert the get global function
297
+ prepend(
298
+ programPath,
299
+ createGetGlobalTemplate(me, programPath).compile({
300
+ getGlobalFnName: getGlobalVarFnName,
301
+ })
302
+ );
303
+
304
+ // Call the get global function and store result in 'globalVarName'
305
+ prepend(
306
+ programPath,
307
+ new Template(
308
+ `var ${globalVarName} = ${getGlobalVarFnName}()`
309
+ ).single<t.Statement>()
310
+ );
311
+ },
312
+ },
313
+ },
314
+ };
315
+ };