-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVarSet.js
91 lines (75 loc) · 2.21 KB
/
VarSet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
'use strict';
var isId = /^[a-zA-Z_]\w*$/;
function VarSet () {
this.root = {};
}
VarSet.prototype = {
add: function (path) {
toParts(path).reduce(function (root, part, index) {
if (!index && part.charAt(0) === '!') {
part = part.slice(1);
}
if (!root.hasOwnProperty(part)) {
root[part] = {};
}
return root[part];
}, this.root);
},
buildGetter: function (path) {
return toParts(path).reduce(function (acc, part, index) {
if (!index && part.charAt(0) === '!') {
part = part.slice(1);
}
return acc + (isId.test(part) ? '.' + part : '[' + JSON.stringify(part) + ']');
}, '');
},
buildSetter: function (path) {
var parts = toParts(path);
// no assignment for '!' variables
if (parts[0].charAt(0) === '!') {
return '';
}
// simple case: all paths are already created
var prefixSize = this.getPrefixSize(parts);
if (prefixSize + 1 >= parts.length) {
if (prefixSize == parts.length) {
console.warn('WARNING: about to assign to already assigned variable -', parts.join('.'));
}
return 'window' + this.buildGetter(parts) + '=';
}
// assign a common prefix (no need to create intermediate objects)
var s = 'g=window' + this.buildGetter(parts.slice(0, prefixSize)) + ';';
// create objects for the rest but the last one
s += parts.slice(prefixSize, parts.length - 1).reduce(function (acc, part) {
var accessor = this.buildGetter(part);
return acc + 'g=g' + accessor + '||(g' + accessor + '={});';
}.bind(this), '');
// assign to the last one
return s + 'g' + this.buildGetter(parts[parts.length - 1]) + '=';
},
getPrefixSize: function (path) {
var parts = toParts(path);
for (var i = 0, root = this.root; i < parts.length; ++i) {
var part = parts[i];
if (!root.hasOwnProperty(part)) {
return i;
}
root = root[part];
}
return parts.length;
}
};
VarSet.getPrefixSize = function getPrefixSize (path1, path2) {
var parts1 = toParts(path1), parts2 = toParts(path2),
size = Math.min(parts1.length, parts2.length);
for (var i = 0; i < size; ++i) {
if (parts1[i] !== parts2[i]) {
return i;
}
}
return size;
};
function toParts (path) {
return path instanceof Array ? path : path.split('.');
}
module.exports = VarSet;