|
22 | 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 | 23 | */ |
24 | 24 |
|
25 | | -/*global exports:true*/ |
26 | | - |
27 | | -(function () { |
| 25 | +(() => { |
28 | 26 | 'use strict'; |
29 | 27 |
|
30 | | - var escope, |
31 | | - estraverse, |
32 | | - esutils, |
33 | | - utility, |
34 | | - version, |
35 | | - assert, |
36 | | - Syntax; |
| 28 | + let assert; |
37 | 29 |
|
38 | | - escope = require('escope'); |
39 | | - estraverse = require('estraverse'); |
40 | | - esutils = require('esutils'); |
41 | | - utility = require('./utility'); |
42 | | - version = require('../package.json').version; |
| 30 | + const escope = require('escope'); |
| 31 | + const estraverse = require('estraverse'); |
| 32 | + const esutils = require('esutils'); |
| 33 | + const utility = require('./utility'); |
| 34 | + const version = require('../package.json').version; |
43 | 35 |
|
44 | | - Syntax = estraverse.Syntax; |
| 36 | + const Syntax = estraverse.Syntax; |
45 | 37 |
|
46 | 38 | assert = function assert(cond, message) { |
47 | 39 | if (!cond) { |
48 | 40 | throw new Error(message); |
49 | 41 | } |
50 | 42 | }; |
51 | 43 |
|
52 | | - if (version.indexOf('-dev', version.length - 4) === -1) { |
53 | | - assert = function () { }; |
| 44 | + if (!version.endsWith('-dev')) { |
| 45 | + assert = () => { }; |
54 | 46 | } |
55 | 47 |
|
56 | | - function NameGenerator(scope, options) { |
57 | | - this._scope = scope; |
58 | | - this._functionName = ''; |
59 | | - if (!options.distinguishFunctionExpressionScope && |
60 | | - this._scope.upper && |
61 | | - this._scope.upper.functionExpressionScope) { |
62 | | - this._functionName = this._scope.upper.block.id.name; |
| 48 | + class NameGenerator { |
| 49 | + constructor(scope, options) { |
| 50 | + this._scope = scope; |
| 51 | + this._functionName = ''; |
| 52 | + if (!options.distinguishFunctionExpressionScope && |
| 53 | + this._scope.upper && |
| 54 | + this._scope.upper.functionExpressionScope) { |
| 55 | + this._functionName = this._scope.upper.block.id.name; |
| 56 | + } |
63 | 57 | } |
64 | | - } |
65 | 58 |
|
66 | | - NameGenerator.prototype.passAsUnique = function passAsUnique(name) { |
67 | | - var i, iz; |
68 | | - if (this._functionName === name) { |
69 | | - return false; |
70 | | - } |
71 | | - if (esutils.keyword.isKeywordES5(name, true) || esutils.keyword.isRestrictedWord(name)) { |
72 | | - return false; |
73 | | - } |
74 | | - if (this._scope.taints.has(name)) { |
75 | | - return false; |
76 | | - } |
77 | | - for (i = 0, iz = this._scope.through.length; i < iz; ++i) { |
78 | | - if (this._scope.through[i].identifier.name === name) { |
| 59 | + passAsUnique(name) { |
| 60 | + if (this._functionName === name) { |
79 | 61 | return false; |
80 | 62 | } |
| 63 | + if (esutils.keyword.isKeywordES5(name, true) || esutils.keyword.isRestrictedWord(name)) { |
| 64 | + return false; |
| 65 | + } |
| 66 | + if (this._scope.taints.has(name)) { |
| 67 | + return false; |
| 68 | + } |
| 69 | + for (let through of this._scope.through) { |
| 70 | + if (through.identifier.name === name) { |
| 71 | + return false; |
| 72 | + } |
| 73 | + } |
| 74 | + return true; |
81 | 75 | } |
82 | | - return true; |
83 | | - }; |
84 | | - |
85 | | - NameGenerator.prototype.generateName = function generateName(tip) { |
86 | | - do { |
87 | | - tip = utility.generateNextName(tip); |
88 | | - } while (!this.passAsUnique(tip)); |
89 | | - return tip; |
90 | | - }; |
91 | 76 |
|
92 | | - function run(scope, options) { |
93 | | - var i, iz, j, jz, variable, name, def, ref, generator; |
| 77 | + generateName(tip) { |
| 78 | + do { |
| 79 | + tip = utility.generateNextName(tip); |
| 80 | + } while (!this.passAsUnique(tip)); |
| 81 | + return tip; |
| 82 | + } |
| 83 | + } |
94 | 84 |
|
95 | | - generator = new NameGenerator(scope, options); |
| 85 | + const run = (scope, options) => { |
| 86 | + let generator = new NameGenerator(scope, options); |
96 | 87 |
|
97 | 88 | if (scope.isStatic()) { |
98 | | - name = '9'; |
| 89 | + let name = '9'; |
99 | 90 |
|
100 | | - scope.variables.sort(function (a, b) { |
| 91 | + scope.variables.sort((a, b) => { |
101 | 92 | if (a.tainted) { |
102 | 93 | return 1; |
103 | 94 | } |
|
107 | 98 | return (b.identifiers.length + b.references.length) - (a.identifiers.length + a.references.length); |
108 | 99 | }); |
109 | 100 |
|
110 | | - for (i = 0, iz = scope.variables.length; i < iz; ++i) { |
111 | | - variable = scope.variables[i]; |
| 101 | + for (let variable of scope.variables) { |
112 | 102 |
|
113 | 103 | if (variable.tainted) { |
114 | 104 | continue; |
|
124 | 114 |
|
125 | 115 | name = generator.generateName(name); |
126 | 116 |
|
127 | | - for (j = 0, jz = variable.identifiers.length; j < jz; ++j) { |
128 | | - def = variable.identifiers[j]; |
| 117 | + for (let def of variable.identifiers) { |
129 | 118 | // change definition's name |
130 | 119 | def.name = name; |
131 | 120 | } |
132 | 121 |
|
133 | | - for (j = 0, jz = variable.references.length; j < jz; ++j) { |
134 | | - ref = variable.references[j]; |
| 122 | + for (let ref of variable.references) { |
135 | 123 | // change reference's name |
136 | 124 | ref.identifier.name = name; |
137 | 125 | } |
138 | 126 | } |
139 | 127 | } |
140 | | - } |
| 128 | + }; |
141 | 129 |
|
142 | | - function Label(node, upper) { |
143 | | - this.node = node; |
144 | | - this.upper = upper; |
145 | | - this.users = []; |
146 | | - this.names = new Map(); |
147 | | - this.name = null; |
148 | | - } |
| 130 | + class Label { |
| 131 | + constructor(node, upper) { |
| 132 | + this.node = node; |
| 133 | + this.upper = upper; |
| 134 | + this.users = []; |
| 135 | + this.names = new Map(); |
| 136 | + this.name = null; |
| 137 | + } |
149 | 138 |
|
150 | | - Label.prototype.mangle = function () { |
151 | | - var tip, current, i, iz; |
152 | | - tip = '9'; |
| 139 | + mangle() { |
| 140 | + let tip = '9'; |
153 | 141 |
|
154 | | - // merge already used names |
155 | | - for (current = this.upper; current; current = current.upper) { |
156 | | - if (current.name !== null) { |
157 | | - this.names.set(current.name, true); |
| 142 | + // merge already used names |
| 143 | + for (let current = this.upper; current; current = current.upper) { |
| 144 | + if (current.name !== null) { |
| 145 | + this.names.set(current.name, true); |
| 146 | + } |
158 | 147 | } |
159 | | - } |
160 | 148 |
|
161 | | - do { |
162 | | - tip = utility.generateNextName(tip); |
163 | | - } while (this.names.has(tip)); |
| 149 | + do { |
| 150 | + tip = utility.generateNextName(tip); |
| 151 | + } while (this.names.has(tip)); |
164 | 152 |
|
165 | | - this.name = tip; |
| 153 | + this.name = tip; |
166 | 154 |
|
167 | | - for (current = this.upper; current; current = current.upper) { |
168 | | - current.names.set(tip, true); |
169 | | - } |
| 155 | + for (let current = this.upper; current; current = current.upper) { |
| 156 | + current.names.set(tip, true); |
| 157 | + } |
170 | 158 |
|
171 | | - this.node.label.name = tip; |
172 | | - for (i = 0, iz = this.users.length; i < iz; ++i) { |
173 | | - this.users[i].label.name = tip; |
| 159 | + this.node.label.name = tip; |
| 160 | + this.users.forEach(user => user.label.name = tip); |
174 | 161 | } |
175 | | - }; |
176 | | - |
177 | | - function LabelScope(upper) { |
178 | | - this.map = new Map(); |
179 | | - this.upper = upper; |
180 | | - this.label = null; |
181 | | - this.labels = []; |
182 | 162 | } |
183 | 163 |
|
184 | | - LabelScope.prototype.register = function register(node) { |
185 | | - var name; |
186 | 164 |
|
187 | | - assert(node.type === Syntax.LabeledStatement, 'node should be LabeledStatement'); |
| 165 | + class LabelScope { |
| 166 | + constructor (upper) { |
| 167 | + this.map = new Map(); |
| 168 | + this.upper = upper; |
| 169 | + this.label = null; |
| 170 | + this.labels = []; |
| 171 | + } |
188 | 172 |
|
189 | | - this.label = new Label(node, this.label); |
190 | | - this.labels.push(this.label); |
| 173 | + register(node) { |
| 174 | + let name; |
191 | 175 |
|
192 | | - name = node.label.name; |
193 | | - assert(!this.map.has(name), 'duplicate label is found'); |
194 | | - this.map.set(name, this.label); |
195 | | - }; |
| 176 | + assert(node.type === Syntax.LabeledStatement, 'node should be LabeledStatement'); |
196 | 177 |
|
197 | | - LabelScope.prototype.unregister = function unregister(node) { |
198 | | - var name, ref; |
199 | | - if (node.type !== Syntax.LabeledStatement) { |
200 | | - return; |
201 | | - } |
| 178 | + this.label = new Label(node, this.label); |
| 179 | + this.labels.push(this.label); |
202 | 180 |
|
203 | | - name = node.label.name; |
204 | | - ref = this.map.get(name); |
205 | | - this.map['delete'](name); |
| 181 | + name = node.label.name; |
| 182 | + assert(!this.map.has(name), 'duplicate label is found'); |
| 183 | + this.map.set(name, this.label); |
| 184 | + } |
206 | 185 |
|
207 | | - this.label = ref.upper; |
208 | | - }; |
| 186 | + unregister(node) { |
| 187 | + let name, ref; |
| 188 | + if (node.type !== Syntax.LabeledStatement) { |
| 189 | + return; |
| 190 | + } |
209 | 191 |
|
210 | | - LabelScope.prototype.resolve = function resolve(node) { |
211 | | - var name; |
212 | | - if (node.label) { |
213 | 192 | name = node.label.name; |
214 | | - assert(this.map.has(name), 'unresolved label'); |
215 | | - this.map.get(name).users.push(node); |
216 | | - } |
217 | | - }; |
| 193 | + ref = this.map.get(name); |
| 194 | + this.map.delete(name); |
218 | 195 |
|
219 | | - LabelScope.prototype.close = function close() { |
220 | | - var i, iz, label; |
221 | | - this.labels.sort(function (lhs, rhs) { |
222 | | - return rhs.users.length - lhs.users.length; |
223 | | - }); |
| 196 | + this.label = ref.upper; |
| 197 | + } |
224 | 198 |
|
225 | | - for (i = 0, iz = this.labels.length; i < iz; ++i) { |
226 | | - label = this.labels[i]; |
227 | | - label.mangle(); |
| 199 | + resolve(node) { |
| 200 | + if (node.label) { |
| 201 | + let name = node.label.name; |
| 202 | + assert(this.map.has(name), 'unresolved label'); |
| 203 | + this.map.get(name).users.push(node); |
| 204 | + } |
228 | 205 | } |
229 | 206 |
|
230 | | - return this.upper; |
231 | | - }; |
| 207 | + close() { |
| 208 | + this.labels.sort((lhs, rhs) => rhs.users.length - lhs.users.length); |
232 | 209 |
|
233 | | - function mangleLabels(tree) { |
234 | | - var labelScope; |
235 | | - var FuncOrProgram = [Syntax.Program, Syntax.FunctionExpression, Syntax.FunctionDeclaration]; |
| 210 | + this.labels.forEach(label => label.mangle()); |
| 211 | + |
| 212 | + return this.upper; |
| 213 | + } |
| 214 | + } |
| 215 | + |
| 216 | + const mangleLabels = tree => { |
| 217 | + let labelScope; |
| 218 | + const FuncOrProgram = [Syntax.Program, Syntax.FunctionExpression, Syntax.FunctionDeclaration]; |
236 | 219 | estraverse.traverse(tree, { |
237 | | - enter: function (node) { |
| 220 | + enter: node => { |
238 | 221 | if (FuncOrProgram.indexOf(node.type) >= 0) { |
239 | 222 | labelScope = new LabelScope(labelScope); |
240 | 223 | return; |
|
251 | 234 | break; |
252 | 235 | } |
253 | 236 | }, |
254 | | - leave: function (node) { |
| 237 | + leave: node => { |
255 | 238 | labelScope.unregister(node); |
256 | 239 | if (FuncOrProgram.indexOf(node.type) >= 0) { |
257 | 240 | labelScope = labelScope.close(); |
|
260 | 243 | }); |
261 | 244 |
|
262 | 245 | return tree; |
263 | | - } |
| 246 | + }; |
264 | 247 |
|
265 | | - function mangle(tree, options) { |
266 | | - var result, manager, i, iz; |
| 248 | + const mangle = (tree, options) => { |
| 249 | + let result, manager; |
267 | 250 |
|
268 | 251 | if (options == null) { |
269 | 252 | options = { destructive: true }; |
|
273 | 256 | manager = escope.analyze(result, { directive: true }); |
274 | 257 |
|
275 | 258 | // mangling names |
276 | | - for (i = 0, iz = manager.scopes.length; i < iz; ++i) { |
277 | | - run(manager.scopes[i], options); |
278 | | - } |
| 259 | + manager.scopes.forEach(scope => run(scope, options)); |
279 | 260 |
|
280 | 261 | // mangling labels |
281 | 262 | return mangleLabels(result); |
282 | | - } |
| 263 | + }; |
283 | 264 |
|
284 | | - exports.mangle = mangle; |
285 | | - exports.version = version; |
286 | | - exports.generateNextName = utility.generateNextName; |
287 | | -}()); |
| 265 | + module.exports = { |
| 266 | + mangle, |
| 267 | + version, |
| 268 | + generateNextName: utility.generateNextName |
| 269 | + }; |
| 270 | +})(); |
288 | 271 | /* vim: set sw=4 ts=4 et tw=80 : */ |
0 commit comments