UNPKG

2.45 kBJavaScriptView Raw
1"use strict";
2
3const rename = require('./renamer');
4
5const t = require('@babel/types');
6
7const CHARSET = ('abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ$_').split('');
8/**
9 * This is a very specialized mangler designer to mangle only names in the top-level scope.
10 * Mangling of names in other scopes happens at a file level inside workers, but we can't
11 * mangle the top-level scope until scope hoisting is complete in the packager.
12 *
13 * Based on code from babel-minify!
14 * https://github.com/babel/minify/blob/master/packages/babel-plugin-minify-mangle-names/src/charset.js
15 */
16
17function mangleScope(scope) {
18 let newNames = new Set(); // Sort bindings so that more frequently referenced bindings get shorter names.
19
20 let sortedBindings = Object.keys(scope.bindings).sort((a, b) => scope.bindings[b].referencePaths.length - scope.bindings[a].referencePaths.length);
21 var _iteratorNormalCompletion = true;
22 var _didIteratorError = false;
23 var _iteratorError = undefined;
24
25 try {
26 for (var _iterator = sortedBindings[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
27 let oldName = _step.value;
28 let i = 0;
29 let newName = '';
30
31 do {
32 newName = getIdentifier(i++);
33 } while (newNames.has(newName) || !canRename(scope, scope.bindings[oldName], newName));
34
35 rename(scope, oldName, newName);
36 newNames.add(newName);
37 }
38 } catch (err) {
39 _didIteratorError = true;
40 _iteratorError = err;
41 } finally {
42 try {
43 if (!_iteratorNormalCompletion && _iterator.return != null) {
44 _iterator.return();
45 }
46 } finally {
47 if (_didIteratorError) {
48 throw _iteratorError;
49 }
50 }
51 }
52}
53
54function getIdentifier(num) {
55 let ret = '';
56 num++;
57
58 do {
59 num--;
60 ret += CHARSET[num % CHARSET.length];
61 num = Math.floor(num / CHARSET.length);
62 } while (num > 0);
63
64 return ret;
65}
66
67function canRename(scope, binding, newName) {
68 if (!t.isValidIdentifier(newName)) {
69 return false;
70 } // If there are any references where the parent scope has a binding
71 // for the new name, we cannot rename to this name.
72
73
74 for (let i = 0; i < binding.referencePaths.length; i++) {
75 const ref = binding.referencePaths[i];
76
77 if (ref.scope.hasBinding(newName) || ref.scope.hasReference(newName)) {
78 return false;
79 }
80 }
81
82 return true;
83}
84
85module.exports = mangleScope;
\No newline at end of file