-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathindex.js
162 lines (137 loc) · 5.25 KB
/
index.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
var validate
, validateMapping
, toAscii
, assert = require('assert')
, SMConsumer = require('source-map').SourceMapConsumer
, each = require('lodash.foreach')
, template = require('lodash.template')
, jsesc = require('jsesc')
, fancyArrow = String.fromCharCode(parseInt(2192,16));
// Lifted from UglifyJS
toAscii = function (str, identifier) {
return str.replace(/[\u0080-\uffff]/g, function(ch) {
var code = ch.charCodeAt(0).toString(16);
if (code.length <= 2 && !identifier) {
while (code.length < 2) code = "0" + code;
return "\\x" + code;
} else {
while (code.length < 4) code = "0" + code;
return "\\u" + code;
}
}).replace(/\x0B/g, "\\x0B");
};
// Performs simple validation of a mapping
validateMapping = function (mapping) {
var prettyMapping = JSON.stringify(mapping, null, 2);
assert.ok(mapping.generatedColumn!=null, 'missing generated column, mapping: ' + prettyMapping);
assert.ok(mapping.generatedLine!=null, 'missing generated line, mapping: ' + prettyMapping);
assert.ok(mapping.generatedColumn >= 0, 'generated column must be greater or equal to zero, mapping: ' + prettyMapping);
assert.ok(mapping.generatedLine >= 0, 'generated line must be greater or equal to zero: ' + prettyMapping);
// If the source is null, the original location data has been explicitly
// omitted from the map to clear the mapped state of a line.
if (typeof mapping.source === "string") {
assert.ok(mapping.originalColumn!=null, 'missing original column, mapping: ' + prettyMapping);
assert.ok(mapping.originalLine!=null, 'missing original line, mapping: ' + prettyMapping);
assert.ok(mapping.originalColumn >= 0, 'original column must be greater or equal to zero, mapping: ' + prettyMapping);
assert.ok(mapping.originalLine >= 0, 'original line must be greater or equal to zero, mapping: ' + prettyMapping);
}
};
createBuffer = function (str, encoding) {
// [DEP0005] Buffer() is deprecated due to security and usability issues
// https://nodejs.org/api/buffer.html#buffer_new_buffer_array
// Preserving backward compatibility until dropping Node version prior to v5.10.0
return Buffer.hasOwnProperty('from') ? Buffer.from(str, encoding) : new Buffer(str, encoding);
};
// Validates an entire sourcemap
validate = function (min, map, srcs) {
var consumer
, mappingCount = 0
, splitSrcs = {};
srcs = srcs || {};
// If no map was given, try to extract it from min
if(map == null) {
try {
var re = /\s*\/\/(?:@|#) sourceMappingURL=data:application\/json;(?:charset=utf-?8;)?base64,(\S*)$/m
, map = min.match(re);
map = createBuffer(map[1], 'base64').toString();
min = min.replace(re, '');
}
catch (e) {
throw new Error('No map argument provided, and no inline sourcemap found');
}
}
try {
consumer = new SMConsumer(map);
}
catch (e) {
throw new Error('The map is not valid JSON');
}
each(consumer.sources, function (src) {
var content = consumer.sourceContentFor(src);
if(content)
srcs[src] = content;
});
each(srcs, function (src, file) {
return splitSrcs[file] = src.split('\n'); // Split sources by line
});
consumer.eachMapping(function (mapping) {
mappingCount++;
validateMapping(mapping);
// These validations can't be performed with just the mapping
var originalLine
, errMsg
, mapRef
, expected
, actuals = []
, success = false;
if(mapping.name) {
if(!splitSrcs[mapping.source]) {
throw new Error(mapping.source + ' not found in ' + Object.keys(splitSrcs).join(', '));
}
originalLine = splitSrcs[mapping.source][mapping.originalLine - 1];
expected = [
mapping.name
, '\'' + jsesc(mapping.name) + '\''
, '\'' + toAscii(mapping.name) + '\''
, '"' + jsesc(mapping.name, {quotes: 'double'}) + '"'
, '"' + toAscii(mapping.name) + '"'
];
// An exact match
for(var i=0, ii=expected.length; i<ii; i++) {
// It's possible to go out of bounds on some stupid cases
try {
var actual = originalLine.split('').splice(mapping.originalColumn, expected[i].length).join('');
}
catch (e) {
return;
}
actuals.push(actual);
if(expected[i] === actual) {
success = true;
break;
}
};
if(!success) {
mapRef = template('<%=generatedLine%>:<%=generatedColumn%>'
+ fancyArrow
+ '<%=originalLine%>:<%=originalColumn%> "<%=name%>" in <%=source%>')(mapping);
errMsg = template(''
+ 'Warning: mismatched names\n'
+ 'Expected: <%=expected%>\n'
+ 'Got: <%=actual%>\n'
+ 'Original Line: <%=original%>\n'
+ 'Mapping: <%=mapRef%>'
)({
expected: expected.join(' || ')
, actual: actuals.join(' || ')
, original: originalLine
, mapRef: mapRef
});
throw new Error(errMsg);
}
}
});
assert.ok(JSON.parse(map).sources && JSON.parse(map).sources.length, 'There were no sources in the file');
assert.ok(mappingCount > 0, 'There were no mappings in the file');
};
module.exports = validate;