monocart-coverage-reports 2.5.9 → 2.6.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.
- package/LICENSE +21 -21
- package/README.md +791 -778
- package/lib/cli.js +250 -215
- package/lib/converter/ast-visitor.js +675 -666
- package/lib/converter/ast.js +353 -353
- package/lib/converter/collect-source-maps.js +201 -201
- package/lib/converter/converter.js +1487 -1429
- package/lib/converter/find-original-range.js +737 -737
- package/lib/converter/ignore.js +163 -163
- package/lib/converter/info-branch.js +93 -93
- package/lib/converter/info-function.js +63 -63
- package/lib/converter/info-statement.js +43 -43
- package/lib/default/options.js +84 -84
- package/lib/default/template.html +47 -47
- package/lib/generate.js +720 -532
- package/lib/index.d.ts +360 -324
- package/lib/index.js +187 -180
- package/lib/index.mjs +5 -3
- package/lib/istanbul/istanbul-summary.js +70 -63
- package/lib/istanbul/istanbul.js +146 -146
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/platform/concurrency.js +74 -74
- package/lib/platform/share.js +484 -484
- package/lib/utils/dedupe.js +118 -118
- package/lib/utils/request.js +62 -62
- package/lib/utils/snapshot.js +381 -0
- package/lib/utils/source-path.js +179 -179
- package/lib/utils/util.js +526 -526
- package/lib/v8/v8-summary.js +138 -138
- package/lib/v8/v8.js +400 -630
- package/package.json +81 -80
|
@@ -1,737 +1,737 @@
|
|
|
1
|
-
const Util = require('../utils/util.js');
|
|
2
|
-
const EC = Util.EC;
|
|
3
|
-
|
|
4
|
-
const findMapping = (list, offset) => {
|
|
5
|
-
let start = 0;
|
|
6
|
-
let end = list.length - 1;
|
|
7
|
-
while (end - start > 1) {
|
|
8
|
-
const i = Math.floor((start + end) * 0.5);
|
|
9
|
-
const item = list[i];
|
|
10
|
-
if (offset < item.generatedOffset) {
|
|
11
|
-
end = i;
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
if (offset > item.generatedOffset) {
|
|
15
|
-
start = i;
|
|
16
|
-
continue;
|
|
17
|
-
}
|
|
18
|
-
return list[i];
|
|
19
|
-
}
|
|
20
|
-
// last two items, less is start
|
|
21
|
-
const startItem = list[start];
|
|
22
|
-
if (offset === startItem.generatedOffset) {
|
|
23
|
-
return startItem;
|
|
24
|
-
}
|
|
25
|
-
const endItem = list[end];
|
|
26
|
-
if (offset === endItem.generatedOffset) {
|
|
27
|
-
return endItem;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// between two mappings
|
|
31
|
-
if (offset > startItem.generatedOffset && offset < endItem.generatedOffset) {
|
|
32
|
-
return [startItem, endItem];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// not found the mappings
|
|
36
|
-
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// ========================================================================================================
|
|
40
|
-
|
|
41
|
-
const getBlockStartPosition = (originalLineText) => {
|
|
42
|
-
// originalText: 'argument) {',
|
|
43
|
-
// generatedLeft: 'o',
|
|
44
|
-
// generatedRight: '&&'
|
|
45
|
-
|
|
46
|
-
// function/block could be started with {(
|
|
47
|
-
const startBlockIndex = originalLineText.search(/[<{(]/);
|
|
48
|
-
if (startBlockIndex !== -1) {
|
|
49
|
-
return {
|
|
50
|
-
pos: startBlockIndex
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// end a block
|
|
55
|
-
const list = ['>', '}', ')'];
|
|
56
|
-
for (const s of list) {
|
|
57
|
-
const endBlockIndex = originalLineText.lastIndexOf(s);
|
|
58
|
-
if (endBlockIndex !== -1) {
|
|
59
|
-
return {
|
|
60
|
-
pos: endBlockIndex + 1
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ============================
|
|
66
|
-
// end characters
|
|
67
|
-
|
|
68
|
-
// ends with ">" in vue
|
|
69
|
-
// <span v-if="data.distFile">
|
|
70
|
-
|
|
71
|
-
// originalText: '">',
|
|
72
|
-
// generatedText: ' ? ((0,vue__.openBlock)(), '
|
|
73
|
-
|
|
74
|
-
// originalMethod?.apply
|
|
75
|
-
// originalText: '?.' no ?
|
|
76
|
-
|
|
77
|
-
const indexEndBlock = originalLineText.search(/(?<=[;,:"'\s])/);
|
|
78
|
-
if (indexEndBlock !== -1) {
|
|
79
|
-
return {
|
|
80
|
-
pos: indexEndBlock
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const getBlockEndPosition = (originalLineText) => {
|
|
87
|
-
|
|
88
|
-
// generatedText: 'e),',
|
|
89
|
-
// generatedPos: 2,
|
|
90
|
-
// originalText: 'prop))'
|
|
91
|
-
|
|
92
|
-
// generatedText: ' = false)',
|
|
93
|
-
// generatedPos: 8,
|
|
94
|
-
// originalText: '=false"'
|
|
95
|
-
|
|
96
|
-
// generatedText: '), 1 /* TEXT */)])])) : (0,vue__...)("v-if", true)], 6 /* CLASS, STYLE */);',
|
|
97
|
-
// generatedPos: 17,
|
|
98
|
-
// originalText: ' }}</slot>'
|
|
99
|
-
|
|
100
|
-
const list = ['>', '}', ')'];
|
|
101
|
-
for (const s of list) {
|
|
102
|
-
const endBlockIndex = originalLineText.lastIndexOf(s);
|
|
103
|
-
if (endBlockIndex !== -1) {
|
|
104
|
-
return {
|
|
105
|
-
pos: endBlockIndex + 1
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const startBlockIndex = originalLineText.search(/[<{(]/);
|
|
111
|
-
if (startBlockIndex !== -1) {
|
|
112
|
-
return {
|
|
113
|
-
pos: startBlockIndex
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const getComparedPosition = (gt, gp, ot, direction) => {
|
|
120
|
-
|
|
121
|
-
// before trim
|
|
122
|
-
const oLen = ot.length;
|
|
123
|
-
|
|
124
|
-
gt = gt.trimEnd();
|
|
125
|
-
ot = ot.trimEnd();
|
|
126
|
-
|
|
127
|
-
// no content after trim
|
|
128
|
-
if (!ot.length) {
|
|
129
|
-
return {
|
|
130
|
-
pos: direction === 'start' ? oLen : 0
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// same content
|
|
135
|
-
if (gt === ot) {
|
|
136
|
-
return {
|
|
137
|
-
pos: gp
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// =============================
|
|
142
|
-
|
|
143
|
-
// generatedText: '"false";\n',
|
|
144
|
-
// originalText: "'false';\r\n ",
|
|
145
|
-
// generatedPos: 7
|
|
146
|
-
|
|
147
|
-
// length not change, replace " to '
|
|
148
|
-
gt = gt.replace(/"/g, "'");
|
|
149
|
-
ot = ot.replace(/"/g, "'");
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// same content too
|
|
153
|
-
if (gt === ot) {
|
|
154
|
-
return {
|
|
155
|
-
pos: gp
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// ============================
|
|
160
|
-
// left matched
|
|
161
|
-
|
|
162
|
-
// originalText: '1;',
|
|
163
|
-
// generatedText: '1;else',
|
|
164
|
-
// generatedLeft: '1;'
|
|
165
|
-
|
|
166
|
-
// generatedText: ' var id = options.base ? item[0] + options.base : item[0];\r\n',
|
|
167
|
-
// originalText: ' var id = options.base ? item[0] + options.base : item[0];\n',
|
|
168
|
-
|
|
169
|
-
const left = gt.slice(0, gp);
|
|
170
|
-
if (ot.startsWith(left)) {
|
|
171
|
-
return {
|
|
172
|
-
pos: gp
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// ============================
|
|
177
|
-
// right matched
|
|
178
|
-
|
|
179
|
-
const right = gt.slice(gp);
|
|
180
|
-
if (ot.endsWith(right)) {
|
|
181
|
-
return {
|
|
182
|
-
pos: ot.length - right.length
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
const getSimilarPosition = (info, direction) => {
|
|
189
|
-
|
|
190
|
-
const {
|
|
191
|
-
generatedText, generatedPos, originalText
|
|
192
|
-
} = info;
|
|
193
|
-
|
|
194
|
-
const textPos = getComparedPosition(generatedText, generatedPos, originalText, direction);
|
|
195
|
-
if (textPos) {
|
|
196
|
-
return textPos;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// never cross line, using first line of original text
|
|
200
|
-
// trim end remove \r\n and \n
|
|
201
|
-
const originalLines = originalText.split(/\n/);
|
|
202
|
-
if (originalLines.length === 1) {
|
|
203
|
-
// already single line
|
|
204
|
-
info.originalLineText = originalText;
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const originalLineText = originalLines[0].trimEnd();
|
|
209
|
-
info.originalLineText = originalLineText;
|
|
210
|
-
|
|
211
|
-
// generatedPos not in first line
|
|
212
|
-
if (generatedPos > originalLineText.length) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const linePos = getComparedPosition(generatedText, generatedPos, originalLineText, direction);
|
|
217
|
-
if (linePos) {
|
|
218
|
-
return linePos;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// console.log('====================================================================');
|
|
222
|
-
// console.log(`${EC.magenta(direction)} similar position can NOT be fixed`);
|
|
223
|
-
// console.log({
|
|
224
|
-
// sourcePath: info.originalState.sourcePath,
|
|
225
|
-
// generatedText,
|
|
226
|
-
// generatedPos,
|
|
227
|
-
// originalText
|
|
228
|
-
// });
|
|
229
|
-
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
const getFixedPosition = (info, direction) => {
|
|
233
|
-
|
|
234
|
-
const similarPos = getSimilarPosition(info, direction);
|
|
235
|
-
if (similarPos) {
|
|
236
|
-
return similarPos.pos;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// generatedText: never cross lines
|
|
240
|
-
// originalText: could be multiple lines
|
|
241
|
-
// originalLineText: single line originalText
|
|
242
|
-
const { originalLineText } = info;
|
|
243
|
-
|
|
244
|
-
if (direction === 'start') {
|
|
245
|
-
const blockPos = getBlockStartPosition(originalLineText);
|
|
246
|
-
if (blockPos) {
|
|
247
|
-
return blockPos.pos;
|
|
248
|
-
}
|
|
249
|
-
return 0;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const blockPos = getBlockEndPosition(originalLineText);
|
|
253
|
-
if (blockPos) {
|
|
254
|
-
return blockPos.pos;
|
|
255
|
-
}
|
|
256
|
-
return originalLineText.length;
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
// ========================================================================================================
|
|
260
|
-
|
|
261
|
-
const getOriginalEndOffset = (m, rangeInfo) => {
|
|
262
|
-
if (!m.originalEndOffset) {
|
|
263
|
-
const line = rangeInfo.originalState.locator.getLine(m.originalLine + 1);
|
|
264
|
-
m.originalEndOffset = line ? line.end : m.originalOffset;
|
|
265
|
-
}
|
|
266
|
-
return m.originalEndOffset;
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
const getOriginalText = (m1, m2, rangeInfo, direction) => {
|
|
270
|
-
const originalLocator = rangeInfo.originalState.locator;
|
|
271
|
-
|
|
272
|
-
const o1 = m1.originalOffset;
|
|
273
|
-
const o2 = m2.originalOffset;
|
|
274
|
-
|
|
275
|
-
// o1 < o2: most of time
|
|
276
|
-
if (o1 < o2) {
|
|
277
|
-
// could be multiple lines for original text
|
|
278
|
-
return {
|
|
279
|
-
originalOffset: o1,
|
|
280
|
-
originalText: originalLocator.getSlice(o1, o2)
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// esbuild fixing two mapping have same original
|
|
285
|
-
// m1 to end line
|
|
286
|
-
if (o1 === o2) {
|
|
287
|
-
const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
|
|
288
|
-
return {
|
|
289
|
-
originalOffset: o1,
|
|
290
|
-
originalText: originalLocator.getSlice(o1, originalEndOffset)
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// o1 > o2: should be wrong sourcemap
|
|
295
|
-
|
|
296
|
-
// just reverse offsets if few cross lines
|
|
297
|
-
const crossLines = m1.originalLine - m2.originalLine;
|
|
298
|
-
if (crossLines < 2) {
|
|
299
|
-
return {
|
|
300
|
-
originalOffset: o2,
|
|
301
|
-
originalText: originalLocator.getSlice(o2, o1)
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// if (direction === 'start') {
|
|
306
|
-
// should be m2 ?
|
|
307
|
-
// console.log(direction, rangeInfo.originalState.sourcePath);
|
|
308
|
-
// console.log(m1, m2);
|
|
309
|
-
// }
|
|
310
|
-
|
|
311
|
-
// should be wrong, ignore m2
|
|
312
|
-
const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
|
|
313
|
-
return {
|
|
314
|
-
originalOffset: o1,
|
|
315
|
-
originalText: originalLocator.getSlice(o1, originalEndOffset)
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const getGeneratedText = (m1, m2, state, offset) => {
|
|
321
|
-
const generatedLocator = state.locator;
|
|
322
|
-
|
|
323
|
-
const o1 = m1.generatedOffset;
|
|
324
|
-
const o2 = m2.generatedOffset;
|
|
325
|
-
|
|
326
|
-
// same line
|
|
327
|
-
if (m1.generatedLine === m2.generatedLine) {
|
|
328
|
-
return {
|
|
329
|
-
generatedText: generatedLocator.getSlice(o1, o2),
|
|
330
|
-
generatedPos: offset - o1
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// =======================================
|
|
335
|
-
// different lines
|
|
336
|
-
// never cross lines
|
|
337
|
-
|
|
338
|
-
// 1-base
|
|
339
|
-
const lineInfo = generatedLocator.offsetToLocation(offset);
|
|
340
|
-
// 0-base
|
|
341
|
-
const targetLine = lineInfo.line - 1;
|
|
342
|
-
|
|
343
|
-
// m1 p (case 1, right to end)
|
|
344
|
-
// p (case 2, mid line)
|
|
345
|
-
// p (case 3) m2
|
|
346
|
-
|
|
347
|
-
// case 1
|
|
348
|
-
if (targetLine === m1.generatedLine) {
|
|
349
|
-
return {
|
|
350
|
-
generatedText: generatedLocator.getSlice(o1, lineInfo.end),
|
|
351
|
-
generatedPos: offset - o1
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// case 3
|
|
356
|
-
if (targetLine === m2.generatedLine) {
|
|
357
|
-
return {
|
|
358
|
-
generatedText: generatedLocator.getSlice(lineInfo.start, o2),
|
|
359
|
-
generatedPos: offset - lineInfo.start
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// case 2
|
|
364
|
-
return {
|
|
365
|
-
generatedText: lineInfo.text,
|
|
366
|
-
generatedPos: offset - lineInfo.start
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
// ========================================================================================================
|
|
372
|
-
|
|
373
|
-
const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
374
|
-
|
|
375
|
-
const [m1, m2] = mappings;
|
|
376
|
-
const { originalState, crossStart } = rangeInfo;
|
|
377
|
-
|
|
378
|
-
// cross file from start of line
|
|
379
|
-
if (crossStart) {
|
|
380
|
-
return {
|
|
381
|
-
originalStart: m2.originalOffset
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const direction = 'start';
|
|
386
|
-
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo, direction);
|
|
387
|
-
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, start);
|
|
388
|
-
|
|
389
|
-
const originalPos = getFixedPosition({
|
|
390
|
-
generatedText,
|
|
391
|
-
generatedPos,
|
|
392
|
-
originalText,
|
|
393
|
-
originalState
|
|
394
|
-
}, direction);
|
|
395
|
-
|
|
396
|
-
// if (start === 2660) {
|
|
397
|
-
// console.log('=====================================================');
|
|
398
|
-
// console.log('fixed start', originalState.sourcePath);
|
|
399
|
-
// console.log({
|
|
400
|
-
// generatedText,
|
|
401
|
-
// generatedPos,
|
|
402
|
-
// originalText,
|
|
403
|
-
// originalPos
|
|
404
|
-
// });
|
|
405
|
-
// }
|
|
406
|
-
|
|
407
|
-
return {
|
|
408
|
-
originalStart: originalOffset + originalPos
|
|
409
|
-
};
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
413
|
-
|
|
414
|
-
const [m1, m2] = mappings;
|
|
415
|
-
const { originalState, crossEnd } = rangeInfo;
|
|
416
|
-
|
|
417
|
-
// cross file until e1 line end (not file end)
|
|
418
|
-
if (crossEnd) {
|
|
419
|
-
const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
|
|
420
|
-
return {
|
|
421
|
-
originalEnd: originalEndOffset
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// end is exclusive
|
|
426
|
-
// quick check previous one if exact match
|
|
427
|
-
// most of case is matching "}"
|
|
428
|
-
if (m1.generatedOffset === end - 1) {
|
|
429
|
-
return {
|
|
430
|
-
originalEnd: m1.originalOffset + 1
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// quick check next one if exact match
|
|
435
|
-
// most of case is same string
|
|
436
|
-
if (m2.generatedOffset === end + 1) {
|
|
437
|
-
const gt = state.locator.source[end];
|
|
438
|
-
const oi = m2.originalOffset - 1;
|
|
439
|
-
const ot = originalState.locator.source[oi];
|
|
440
|
-
if (gt === ot) {
|
|
441
|
-
return {
|
|
442
|
-
originalEnd: oi
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Not applicable
|
|
447
|
-
// console.log('==================================');
|
|
448
|
-
// console.log({
|
|
449
|
-
// gp: state.sourcePath,
|
|
450
|
-
// g: end,
|
|
451
|
-
// gt,
|
|
452
|
-
// op: originalState.sourcePath,
|
|
453
|
-
// o: oi,
|
|
454
|
-
// ot
|
|
455
|
-
// });
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
const direction = 'end';
|
|
459
|
-
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo, direction);
|
|
460
|
-
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end);
|
|
461
|
-
|
|
462
|
-
const originalPos = getFixedPosition({
|
|
463
|
-
generatedText,
|
|
464
|
-
generatedPos,
|
|
465
|
-
originalText,
|
|
466
|
-
originalState
|
|
467
|
-
}, direction);
|
|
468
|
-
|
|
469
|
-
// if (end === 2858) {
|
|
470
|
-
// console.log('=====================================================');
|
|
471
|
-
// console.log('fixed end', originalState.sourcePath);
|
|
472
|
-
// console.log({
|
|
473
|
-
// generatedText,
|
|
474
|
-
// generatedPos,
|
|
475
|
-
// originalText,
|
|
476
|
-
// originalPos
|
|
477
|
-
// });
|
|
478
|
-
// }
|
|
479
|
-
|
|
480
|
-
return {
|
|
481
|
-
originalEnd: originalOffset + originalPos
|
|
482
|
-
};
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
// ========================================================================================================
|
|
486
|
-
|
|
487
|
-
const getOriginalStart = (start, startMapping, state, rangeInfo) => {
|
|
488
|
-
if (Array.isArray(startMapping)) {
|
|
489
|
-
return getFixedOriginalStart(start, startMapping, state, rangeInfo);
|
|
490
|
-
}
|
|
491
|
-
// Exact match
|
|
492
|
-
return {
|
|
493
|
-
originalStart: startMapping.originalOffset
|
|
494
|
-
};
|
|
495
|
-
};
|
|
496
|
-
|
|
497
|
-
const getOriginalEnd = (end, endMapping, state, rangeInfo) => {
|
|
498
|
-
if (Array.isArray(endMapping)) {
|
|
499
|
-
return getFixedOriginalEnd(end, endMapping, state, rangeInfo);
|
|
500
|
-
}
|
|
501
|
-
// Exact match
|
|
502
|
-
return {
|
|
503
|
-
originalEnd: endMapping.originalOffset
|
|
504
|
-
};
|
|
505
|
-
};
|
|
506
|
-
|
|
507
|
-
// ========================================================================================================
|
|
508
|
-
|
|
509
|
-
const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
510
|
-
|
|
511
|
-
const checkIndex11 = (s1, e1) => {
|
|
512
|
-
if (s1 === e1) {
|
|
513
|
-
return {
|
|
514
|
-
sourceIndex: s1
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
return {
|
|
518
|
-
error: true
|
|
519
|
-
};
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
const checkIndex21 = (s1, s2, e1) => {
|
|
523
|
-
if (s1 === e1 || s2 === e1) {
|
|
524
|
-
if (s1 === s2) {
|
|
525
|
-
return {
|
|
526
|
-
sourceIndex: e1
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
return {
|
|
530
|
-
crossStart: true,
|
|
531
|
-
sourceIndex: e1
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
return {
|
|
535
|
-
error: true
|
|
536
|
-
};
|
|
537
|
-
};
|
|
538
|
-
|
|
539
|
-
const checkIndex12 = (s1, e1, e2) => {
|
|
540
|
-
if (s1 === e1 || s1 === e2) {
|
|
541
|
-
if (e1 === e2) {
|
|
542
|
-
return {
|
|
543
|
-
sourceIndex: s1
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
return {
|
|
547
|
-
crossEnd: true,
|
|
548
|
-
sourceIndex: s1
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
return {
|
|
552
|
-
error: true
|
|
553
|
-
};
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
const checkIndex22 = (s1, s2, e1, e2) => {
|
|
557
|
-
// 4 same
|
|
558
|
-
if (s1 === s2 && e1 === e2 && s1 === e1) {
|
|
559
|
-
return {
|
|
560
|
-
sourceIndex: s1
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
if (e1 === e2) {
|
|
565
|
-
return checkIndex21(s1, s2, e1);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
if (s1 === s2) {
|
|
569
|
-
return checkIndex12(s1, e1, e2);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
if (s2 === e1) {
|
|
573
|
-
return {
|
|
574
|
-
crossStart: true,
|
|
575
|
-
crossEnd: true,
|
|
576
|
-
sourceIndex: s2
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// both between two mappings: 38,39 ~ 38,39
|
|
581
|
-
// if (s1 === e1 && s2 === e2) {
|
|
582
|
-
// }
|
|
583
|
-
|
|
584
|
-
return {
|
|
585
|
-
error: true
|
|
586
|
-
};
|
|
587
|
-
};
|
|
588
|
-
|
|
589
|
-
// both exact matched
|
|
590
|
-
if (startIndexes.length === 1 && endIndexes.length === 1) {
|
|
591
|
-
return checkIndex11(startIndexes[0], endIndexes[0]);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if (startIndexes.length === 2 && endIndexes.length === 1) {
|
|
595
|
-
return checkIndex21(startIndexes[0], startIndexes[1], endIndexes[0]);
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
if (startIndexes.length === 1 && endIndexes.length === 2) {
|
|
599
|
-
return checkIndex12(startIndexes[0], endIndexes[0], endIndexes[1]);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// both 2 mappings
|
|
603
|
-
return checkIndex22(startIndexes[0], startIndexes[1], endIndexes[0], endIndexes[1]);
|
|
604
|
-
|
|
605
|
-
};
|
|
606
|
-
|
|
607
|
-
const getOriginalState = (startMappings, endMappings, originalMap) => {
|
|
608
|
-
|
|
609
|
-
// check source file indexes
|
|
610
|
-
const startIndexes = [].concat(startMappings).map((it) => it.sourceIndex);
|
|
611
|
-
const endIndexes = [].concat(endMappings).map((it) => it.sourceIndex);
|
|
612
|
-
const rangeInfo = checkSourceFileIndexes(startIndexes, endIndexes);
|
|
613
|
-
if (rangeInfo.error) {
|
|
614
|
-
return {
|
|
615
|
-
error: true,
|
|
616
|
-
errors: [`invalid source indexes: ${EC.yellow(`${startIndexes} ~ ${endIndexes}`)}`]
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
const {
|
|
621
|
-
sourceIndex, crossStart, crossEnd
|
|
622
|
-
} = rangeInfo;
|
|
623
|
-
|
|
624
|
-
// if (crossStart || crossEnd) {
|
|
625
|
-
// console.log(EC.magenta('cross file'), EC.yellow(`${startIndexes} ~ ${endIndexes}`));
|
|
626
|
-
// }
|
|
627
|
-
|
|
628
|
-
const originalState = originalMap.get(sourceIndex);
|
|
629
|
-
if (!originalState) {
|
|
630
|
-
return {
|
|
631
|
-
error: true,
|
|
632
|
-
errors: [`not found original file: ${EC.yellow(sourceIndex)}`]
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
return {
|
|
637
|
-
// for debug
|
|
638
|
-
// startIndexes,
|
|
639
|
-
// endIndexes,
|
|
640
|
-
|
|
641
|
-
sourceIndex,
|
|
642
|
-
crossStart,
|
|
643
|
-
crossEnd,
|
|
644
|
-
originalState
|
|
645
|
-
};
|
|
646
|
-
};
|
|
647
|
-
|
|
648
|
-
const getMappingInfo = (decodedMappings, start, end) => {
|
|
649
|
-
// possible no length
|
|
650
|
-
if (decodedMappings.length < 2) {
|
|
651
|
-
return {
|
|
652
|
-
error: true,
|
|
653
|
-
errors: ['invalid decoded mappings (length < 2)']
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// start: inclusive
|
|
658
|
-
// end: exclusive
|
|
659
|
-
// could be 4 mappings found
|
|
660
|
-
|
|
661
|
-
const startMappings = findMapping(decodedMappings, start);
|
|
662
|
-
if (!startMappings) {
|
|
663
|
-
return {
|
|
664
|
-
error: true,
|
|
665
|
-
errors: ['not found start mappings']
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
const endMappings = findMapping(decodedMappings, end);
|
|
670
|
-
if (!endMappings) {
|
|
671
|
-
return {
|
|
672
|
-
error: true,
|
|
673
|
-
errors: ['not found end mappings']
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
return {
|
|
678
|
-
startMappings,
|
|
679
|
-
endMappings
|
|
680
|
-
};
|
|
681
|
-
};
|
|
682
|
-
|
|
683
|
-
const findOriginalRange = (start, end, state, originalMap) => {
|
|
684
|
-
|
|
685
|
-
const { sourcePath, decodedMappings } = state;
|
|
686
|
-
|
|
687
|
-
const createMappingError = (errors) => {
|
|
688
|
-
return {
|
|
689
|
-
error: true,
|
|
690
|
-
start,
|
|
691
|
-
end,
|
|
692
|
-
sourcePath,
|
|
693
|
-
errors
|
|
694
|
-
};
|
|
695
|
-
};
|
|
696
|
-
|
|
697
|
-
const mappingInfo = getMappingInfo(decodedMappings, start, end);
|
|
698
|
-
if (mappingInfo.error) {
|
|
699
|
-
return createMappingError(mappingInfo.errors);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
const { startMappings, endMappings } = mappingInfo;
|
|
703
|
-
|
|
704
|
-
const rangeInfo = getOriginalState(startMappings, endMappings, originalMap);
|
|
705
|
-
if (rangeInfo.error) {
|
|
706
|
-
return createMappingError(rangeInfo.errors);
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
const originalStartResult = getOriginalStart(start, startMappings, state, rangeInfo);
|
|
710
|
-
if (originalStartResult.error) {
|
|
711
|
-
return createMappingError(originalStartResult.errors);
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
const originalEndResult = getOriginalEnd(end, endMappings, state, rangeInfo);
|
|
715
|
-
if (originalEndResult.error) {
|
|
716
|
-
return createMappingError(originalEndResult.errors);
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
const { originalStart } = originalStartResult;
|
|
720
|
-
const { originalEnd } = originalEndResult;
|
|
721
|
-
|
|
722
|
-
// range start > end
|
|
723
|
-
if (originalStart > originalEnd) {
|
|
724
|
-
return createMappingError([`invalid original start > end: ${EC.yellow(originalStart)} > ${EC.yellow(originalEnd)}`]);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
const { originalState } = rangeInfo;
|
|
728
|
-
|
|
729
|
-
return {
|
|
730
|
-
start: originalStart,
|
|
731
|
-
end: originalEnd,
|
|
732
|
-
originalState
|
|
733
|
-
};
|
|
734
|
-
|
|
735
|
-
};
|
|
736
|
-
|
|
737
|
-
module.exports = findOriginalRange;
|
|
1
|
+
const Util = require('../utils/util.js');
|
|
2
|
+
const EC = Util.EC;
|
|
3
|
+
|
|
4
|
+
const findMapping = (list, offset) => {
|
|
5
|
+
let start = 0;
|
|
6
|
+
let end = list.length - 1;
|
|
7
|
+
while (end - start > 1) {
|
|
8
|
+
const i = Math.floor((start + end) * 0.5);
|
|
9
|
+
const item = list[i];
|
|
10
|
+
if (offset < item.generatedOffset) {
|
|
11
|
+
end = i;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (offset > item.generatedOffset) {
|
|
15
|
+
start = i;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
return list[i];
|
|
19
|
+
}
|
|
20
|
+
// last two items, less is start
|
|
21
|
+
const startItem = list[start];
|
|
22
|
+
if (offset === startItem.generatedOffset) {
|
|
23
|
+
return startItem;
|
|
24
|
+
}
|
|
25
|
+
const endItem = list[end];
|
|
26
|
+
if (offset === endItem.generatedOffset) {
|
|
27
|
+
return endItem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// between two mappings
|
|
31
|
+
if (offset > startItem.generatedOffset && offset < endItem.generatedOffset) {
|
|
32
|
+
return [startItem, endItem];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// not found the mappings
|
|
36
|
+
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// ========================================================================================================
|
|
40
|
+
|
|
41
|
+
const getBlockStartPosition = (originalLineText) => {
|
|
42
|
+
// originalText: 'argument) {',
|
|
43
|
+
// generatedLeft: 'o',
|
|
44
|
+
// generatedRight: '&&'
|
|
45
|
+
|
|
46
|
+
// function/block could be started with {(
|
|
47
|
+
const startBlockIndex = originalLineText.search(/[<{(]/);
|
|
48
|
+
if (startBlockIndex !== -1) {
|
|
49
|
+
return {
|
|
50
|
+
pos: startBlockIndex
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// end a block
|
|
55
|
+
const list = ['>', '}', ')'];
|
|
56
|
+
for (const s of list) {
|
|
57
|
+
const endBlockIndex = originalLineText.lastIndexOf(s);
|
|
58
|
+
if (endBlockIndex !== -1) {
|
|
59
|
+
return {
|
|
60
|
+
pos: endBlockIndex + 1
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ============================
|
|
66
|
+
// end characters
|
|
67
|
+
|
|
68
|
+
// ends with ">" in vue
|
|
69
|
+
// <span v-if="data.distFile">
|
|
70
|
+
|
|
71
|
+
// originalText: '">',
|
|
72
|
+
// generatedText: ' ? ((0,vue__.openBlock)(), '
|
|
73
|
+
|
|
74
|
+
// originalMethod?.apply
|
|
75
|
+
// originalText: '?.' no ?
|
|
76
|
+
|
|
77
|
+
const indexEndBlock = originalLineText.search(/(?<=[;,:"'\s])/);
|
|
78
|
+
if (indexEndBlock !== -1) {
|
|
79
|
+
return {
|
|
80
|
+
pos: indexEndBlock
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const getBlockEndPosition = (originalLineText) => {
|
|
87
|
+
|
|
88
|
+
// generatedText: 'e),',
|
|
89
|
+
// generatedPos: 2,
|
|
90
|
+
// originalText: 'prop))'
|
|
91
|
+
|
|
92
|
+
// generatedText: ' = false)',
|
|
93
|
+
// generatedPos: 8,
|
|
94
|
+
// originalText: '=false"'
|
|
95
|
+
|
|
96
|
+
// generatedText: '), 1 /* TEXT */)])])) : (0,vue__...)("v-if", true)], 6 /* CLASS, STYLE */);',
|
|
97
|
+
// generatedPos: 17,
|
|
98
|
+
// originalText: ' }}</slot>'
|
|
99
|
+
|
|
100
|
+
const list = ['>', '}', ')'];
|
|
101
|
+
for (const s of list) {
|
|
102
|
+
const endBlockIndex = originalLineText.lastIndexOf(s);
|
|
103
|
+
if (endBlockIndex !== -1) {
|
|
104
|
+
return {
|
|
105
|
+
pos: endBlockIndex + 1
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const startBlockIndex = originalLineText.search(/[<{(]/);
|
|
111
|
+
if (startBlockIndex !== -1) {
|
|
112
|
+
return {
|
|
113
|
+
pos: startBlockIndex
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const getComparedPosition = (gt, gp, ot, direction) => {
|
|
120
|
+
|
|
121
|
+
// before trim
|
|
122
|
+
const oLen = ot.length;
|
|
123
|
+
|
|
124
|
+
gt = gt.trimEnd();
|
|
125
|
+
ot = ot.trimEnd();
|
|
126
|
+
|
|
127
|
+
// no content after trim
|
|
128
|
+
if (!ot.length) {
|
|
129
|
+
return {
|
|
130
|
+
pos: direction === 'start' ? oLen : 0
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// same content
|
|
135
|
+
if (gt === ot) {
|
|
136
|
+
return {
|
|
137
|
+
pos: gp
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// =============================
|
|
142
|
+
|
|
143
|
+
// generatedText: '"false";\n',
|
|
144
|
+
// originalText: "'false';\r\n ",
|
|
145
|
+
// generatedPos: 7
|
|
146
|
+
|
|
147
|
+
// length not change, replace " to '
|
|
148
|
+
gt = gt.replace(/"/g, "'");
|
|
149
|
+
ot = ot.replace(/"/g, "'");
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
// same content too
|
|
153
|
+
if (gt === ot) {
|
|
154
|
+
return {
|
|
155
|
+
pos: gp
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ============================
|
|
160
|
+
// left matched
|
|
161
|
+
|
|
162
|
+
// originalText: '1;',
|
|
163
|
+
// generatedText: '1;else',
|
|
164
|
+
// generatedLeft: '1;'
|
|
165
|
+
|
|
166
|
+
// generatedText: ' var id = options.base ? item[0] + options.base : item[0];\r\n',
|
|
167
|
+
// originalText: ' var id = options.base ? item[0] + options.base : item[0];\n',
|
|
168
|
+
|
|
169
|
+
const left = gt.slice(0, gp);
|
|
170
|
+
if (ot.startsWith(left)) {
|
|
171
|
+
return {
|
|
172
|
+
pos: gp
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ============================
|
|
177
|
+
// right matched
|
|
178
|
+
|
|
179
|
+
const right = gt.slice(gp);
|
|
180
|
+
if (ot.endsWith(right)) {
|
|
181
|
+
return {
|
|
182
|
+
pos: ot.length - right.length
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const getSimilarPosition = (info, direction) => {
|
|
189
|
+
|
|
190
|
+
const {
|
|
191
|
+
generatedText, generatedPos, originalText
|
|
192
|
+
} = info;
|
|
193
|
+
|
|
194
|
+
const textPos = getComparedPosition(generatedText, generatedPos, originalText, direction);
|
|
195
|
+
if (textPos) {
|
|
196
|
+
return textPos;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// never cross line, using first line of original text
|
|
200
|
+
// trim end remove \r\n and \n
|
|
201
|
+
const originalLines = originalText.split(/\n/);
|
|
202
|
+
if (originalLines.length === 1) {
|
|
203
|
+
// already single line
|
|
204
|
+
info.originalLineText = originalText;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const originalLineText = originalLines[0].trimEnd();
|
|
209
|
+
info.originalLineText = originalLineText;
|
|
210
|
+
|
|
211
|
+
// generatedPos not in first line
|
|
212
|
+
if (generatedPos > originalLineText.length) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const linePos = getComparedPosition(generatedText, generatedPos, originalLineText, direction);
|
|
217
|
+
if (linePos) {
|
|
218
|
+
return linePos;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// console.log('====================================================================');
|
|
222
|
+
// console.log(`${EC.magenta(direction)} similar position can NOT be fixed`);
|
|
223
|
+
// console.log({
|
|
224
|
+
// sourcePath: info.originalState.sourcePath,
|
|
225
|
+
// generatedText,
|
|
226
|
+
// generatedPos,
|
|
227
|
+
// originalText
|
|
228
|
+
// });
|
|
229
|
+
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const getFixedPosition = (info, direction) => {
|
|
233
|
+
|
|
234
|
+
const similarPos = getSimilarPosition(info, direction);
|
|
235
|
+
if (similarPos) {
|
|
236
|
+
return similarPos.pos;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// generatedText: never cross lines
|
|
240
|
+
// originalText: could be multiple lines
|
|
241
|
+
// originalLineText: single line originalText
|
|
242
|
+
const { originalLineText } = info;
|
|
243
|
+
|
|
244
|
+
if (direction === 'start') {
|
|
245
|
+
const blockPos = getBlockStartPosition(originalLineText);
|
|
246
|
+
if (blockPos) {
|
|
247
|
+
return blockPos.pos;
|
|
248
|
+
}
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const blockPos = getBlockEndPosition(originalLineText);
|
|
253
|
+
if (blockPos) {
|
|
254
|
+
return blockPos.pos;
|
|
255
|
+
}
|
|
256
|
+
return originalLineText.length;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// ========================================================================================================
|
|
260
|
+
|
|
261
|
+
const getOriginalEndOffset = (m, rangeInfo) => {
|
|
262
|
+
if (!m.originalEndOffset) {
|
|
263
|
+
const line = rangeInfo.originalState.locator.getLine(m.originalLine + 1);
|
|
264
|
+
m.originalEndOffset = line ? line.end : m.originalOffset;
|
|
265
|
+
}
|
|
266
|
+
return m.originalEndOffset;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const getOriginalText = (m1, m2, rangeInfo, direction) => {
|
|
270
|
+
const originalLocator = rangeInfo.originalState.locator;
|
|
271
|
+
|
|
272
|
+
const o1 = m1.originalOffset;
|
|
273
|
+
const o2 = m2.originalOffset;
|
|
274
|
+
|
|
275
|
+
// o1 < o2: most of time
|
|
276
|
+
if (o1 < o2) {
|
|
277
|
+
// could be multiple lines for original text
|
|
278
|
+
return {
|
|
279
|
+
originalOffset: o1,
|
|
280
|
+
originalText: originalLocator.getSlice(o1, o2)
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// esbuild fixing two mapping have same original
|
|
285
|
+
// m1 to end line
|
|
286
|
+
if (o1 === o2) {
|
|
287
|
+
const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
|
|
288
|
+
return {
|
|
289
|
+
originalOffset: o1,
|
|
290
|
+
originalText: originalLocator.getSlice(o1, originalEndOffset)
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// o1 > o2: should be wrong sourcemap
|
|
295
|
+
|
|
296
|
+
// just reverse offsets if few cross lines
|
|
297
|
+
const crossLines = m1.originalLine - m2.originalLine;
|
|
298
|
+
if (crossLines < 2) {
|
|
299
|
+
return {
|
|
300
|
+
originalOffset: o2,
|
|
301
|
+
originalText: originalLocator.getSlice(o2, o1)
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// if (direction === 'start') {
|
|
306
|
+
// should be m2 ?
|
|
307
|
+
// console.log(direction, rangeInfo.originalState.sourcePath);
|
|
308
|
+
// console.log(m1, m2);
|
|
309
|
+
// }
|
|
310
|
+
|
|
311
|
+
// should be wrong, ignore m2
|
|
312
|
+
const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
|
|
313
|
+
return {
|
|
314
|
+
originalOffset: o1,
|
|
315
|
+
originalText: originalLocator.getSlice(o1, originalEndOffset)
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const getGeneratedText = (m1, m2, state, offset) => {
|
|
321
|
+
const generatedLocator = state.locator;
|
|
322
|
+
|
|
323
|
+
const o1 = m1.generatedOffset;
|
|
324
|
+
const o2 = m2.generatedOffset;
|
|
325
|
+
|
|
326
|
+
// same line
|
|
327
|
+
if (m1.generatedLine === m2.generatedLine) {
|
|
328
|
+
return {
|
|
329
|
+
generatedText: generatedLocator.getSlice(o1, o2),
|
|
330
|
+
generatedPos: offset - o1
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// =======================================
|
|
335
|
+
// different lines
|
|
336
|
+
// never cross lines
|
|
337
|
+
|
|
338
|
+
// 1-base
|
|
339
|
+
const lineInfo = generatedLocator.offsetToLocation(offset);
|
|
340
|
+
// 0-base
|
|
341
|
+
const targetLine = lineInfo.line - 1;
|
|
342
|
+
|
|
343
|
+
// m1 p (case 1, right to end)
|
|
344
|
+
// p (case 2, mid line)
|
|
345
|
+
// p (case 3) m2
|
|
346
|
+
|
|
347
|
+
// case 1
|
|
348
|
+
if (targetLine === m1.generatedLine) {
|
|
349
|
+
return {
|
|
350
|
+
generatedText: generatedLocator.getSlice(o1, lineInfo.end),
|
|
351
|
+
generatedPos: offset - o1
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// case 3
|
|
356
|
+
if (targetLine === m2.generatedLine) {
|
|
357
|
+
return {
|
|
358
|
+
generatedText: generatedLocator.getSlice(lineInfo.start, o2),
|
|
359
|
+
generatedPos: offset - lineInfo.start
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// case 2
|
|
364
|
+
return {
|
|
365
|
+
generatedText: lineInfo.text,
|
|
366
|
+
generatedPos: offset - lineInfo.start
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
// ========================================================================================================
|
|
372
|
+
|
|
373
|
+
const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
374
|
+
|
|
375
|
+
const [m1, m2] = mappings;
|
|
376
|
+
const { originalState, crossStart } = rangeInfo;
|
|
377
|
+
|
|
378
|
+
// cross file from start of line
|
|
379
|
+
if (crossStart) {
|
|
380
|
+
return {
|
|
381
|
+
originalStart: m2.originalOffset
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const direction = 'start';
|
|
386
|
+
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo, direction);
|
|
387
|
+
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, start);
|
|
388
|
+
|
|
389
|
+
const originalPos = getFixedPosition({
|
|
390
|
+
generatedText,
|
|
391
|
+
generatedPos,
|
|
392
|
+
originalText,
|
|
393
|
+
originalState
|
|
394
|
+
}, direction);
|
|
395
|
+
|
|
396
|
+
// if (start === 2660) {
|
|
397
|
+
// console.log('=====================================================');
|
|
398
|
+
// console.log('fixed start', originalState.sourcePath);
|
|
399
|
+
// console.log({
|
|
400
|
+
// generatedText,
|
|
401
|
+
// generatedPos,
|
|
402
|
+
// originalText,
|
|
403
|
+
// originalPos
|
|
404
|
+
// });
|
|
405
|
+
// }
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
originalStart: originalOffset + originalPos
|
|
409
|
+
};
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
413
|
+
|
|
414
|
+
const [m1, m2] = mappings;
|
|
415
|
+
const { originalState, crossEnd } = rangeInfo;
|
|
416
|
+
|
|
417
|
+
// cross file until e1 line end (not file end)
|
|
418
|
+
if (crossEnd) {
|
|
419
|
+
const originalEndOffset = getOriginalEndOffset(m1, rangeInfo);
|
|
420
|
+
return {
|
|
421
|
+
originalEnd: originalEndOffset
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// end is exclusive
|
|
426
|
+
// quick check previous one if exact match
|
|
427
|
+
// most of case is matching "}"
|
|
428
|
+
if (m1.generatedOffset === end - 1) {
|
|
429
|
+
return {
|
|
430
|
+
originalEnd: m1.originalOffset + 1
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// quick check next one if exact match
|
|
435
|
+
// most of case is same string
|
|
436
|
+
if (m2.generatedOffset === end + 1) {
|
|
437
|
+
const gt = state.locator.source[end];
|
|
438
|
+
const oi = m2.originalOffset - 1;
|
|
439
|
+
const ot = originalState.locator.source[oi];
|
|
440
|
+
if (gt === ot) {
|
|
441
|
+
return {
|
|
442
|
+
originalEnd: oi
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Not applicable
|
|
447
|
+
// console.log('==================================');
|
|
448
|
+
// console.log({
|
|
449
|
+
// gp: state.sourcePath,
|
|
450
|
+
// g: end,
|
|
451
|
+
// gt,
|
|
452
|
+
// op: originalState.sourcePath,
|
|
453
|
+
// o: oi,
|
|
454
|
+
// ot
|
|
455
|
+
// });
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const direction = 'end';
|
|
459
|
+
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo, direction);
|
|
460
|
+
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end);
|
|
461
|
+
|
|
462
|
+
const originalPos = getFixedPosition({
|
|
463
|
+
generatedText,
|
|
464
|
+
generatedPos,
|
|
465
|
+
originalText,
|
|
466
|
+
originalState
|
|
467
|
+
}, direction);
|
|
468
|
+
|
|
469
|
+
// if (end === 2858) {
|
|
470
|
+
// console.log('=====================================================');
|
|
471
|
+
// console.log('fixed end', originalState.sourcePath);
|
|
472
|
+
// console.log({
|
|
473
|
+
// generatedText,
|
|
474
|
+
// generatedPos,
|
|
475
|
+
// originalText,
|
|
476
|
+
// originalPos
|
|
477
|
+
// });
|
|
478
|
+
// }
|
|
479
|
+
|
|
480
|
+
return {
|
|
481
|
+
originalEnd: originalOffset + originalPos
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// ========================================================================================================
|
|
486
|
+
|
|
487
|
+
const getOriginalStart = (start, startMapping, state, rangeInfo) => {
|
|
488
|
+
if (Array.isArray(startMapping)) {
|
|
489
|
+
return getFixedOriginalStart(start, startMapping, state, rangeInfo);
|
|
490
|
+
}
|
|
491
|
+
// Exact match
|
|
492
|
+
return {
|
|
493
|
+
originalStart: startMapping.originalOffset
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
const getOriginalEnd = (end, endMapping, state, rangeInfo) => {
|
|
498
|
+
if (Array.isArray(endMapping)) {
|
|
499
|
+
return getFixedOriginalEnd(end, endMapping, state, rangeInfo);
|
|
500
|
+
}
|
|
501
|
+
// Exact match
|
|
502
|
+
return {
|
|
503
|
+
originalEnd: endMapping.originalOffset
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// ========================================================================================================
|
|
508
|
+
|
|
509
|
+
const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
510
|
+
|
|
511
|
+
const checkIndex11 = (s1, e1) => {
|
|
512
|
+
if (s1 === e1) {
|
|
513
|
+
return {
|
|
514
|
+
sourceIndex: s1
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
error: true
|
|
519
|
+
};
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const checkIndex21 = (s1, s2, e1) => {
|
|
523
|
+
if (s1 === e1 || s2 === e1) {
|
|
524
|
+
if (s1 === s2) {
|
|
525
|
+
return {
|
|
526
|
+
sourceIndex: e1
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
crossStart: true,
|
|
531
|
+
sourceIndex: e1
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
error: true
|
|
536
|
+
};
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
const checkIndex12 = (s1, e1, e2) => {
|
|
540
|
+
if (s1 === e1 || s1 === e2) {
|
|
541
|
+
if (e1 === e2) {
|
|
542
|
+
return {
|
|
543
|
+
sourceIndex: s1
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
return {
|
|
547
|
+
crossEnd: true,
|
|
548
|
+
sourceIndex: s1
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
error: true
|
|
553
|
+
};
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
const checkIndex22 = (s1, s2, e1, e2) => {
|
|
557
|
+
// 4 same
|
|
558
|
+
if (s1 === s2 && e1 === e2 && s1 === e1) {
|
|
559
|
+
return {
|
|
560
|
+
sourceIndex: s1
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (e1 === e2) {
|
|
565
|
+
return checkIndex21(s1, s2, e1);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if (s1 === s2) {
|
|
569
|
+
return checkIndex12(s1, e1, e2);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (s2 === e1) {
|
|
573
|
+
return {
|
|
574
|
+
crossStart: true,
|
|
575
|
+
crossEnd: true,
|
|
576
|
+
sourceIndex: s2
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// both between two mappings: 38,39 ~ 38,39
|
|
581
|
+
// if (s1 === e1 && s2 === e2) {
|
|
582
|
+
// }
|
|
583
|
+
|
|
584
|
+
return {
|
|
585
|
+
error: true
|
|
586
|
+
};
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
// both exact matched
|
|
590
|
+
if (startIndexes.length === 1 && endIndexes.length === 1) {
|
|
591
|
+
return checkIndex11(startIndexes[0], endIndexes[0]);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (startIndexes.length === 2 && endIndexes.length === 1) {
|
|
595
|
+
return checkIndex21(startIndexes[0], startIndexes[1], endIndexes[0]);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (startIndexes.length === 1 && endIndexes.length === 2) {
|
|
599
|
+
return checkIndex12(startIndexes[0], endIndexes[0], endIndexes[1]);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// both 2 mappings
|
|
603
|
+
return checkIndex22(startIndexes[0], startIndexes[1], endIndexes[0], endIndexes[1]);
|
|
604
|
+
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
const getOriginalState = (startMappings, endMappings, originalMap) => {
|
|
608
|
+
|
|
609
|
+
// check source file indexes
|
|
610
|
+
const startIndexes = [].concat(startMappings).map((it) => it.sourceIndex);
|
|
611
|
+
const endIndexes = [].concat(endMappings).map((it) => it.sourceIndex);
|
|
612
|
+
const rangeInfo = checkSourceFileIndexes(startIndexes, endIndexes);
|
|
613
|
+
if (rangeInfo.error) {
|
|
614
|
+
return {
|
|
615
|
+
error: true,
|
|
616
|
+
errors: [`invalid source indexes: ${EC.yellow(`${startIndexes} ~ ${endIndexes}`)}`]
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const {
|
|
621
|
+
sourceIndex, crossStart, crossEnd
|
|
622
|
+
} = rangeInfo;
|
|
623
|
+
|
|
624
|
+
// if (crossStart || crossEnd) {
|
|
625
|
+
// console.log(EC.magenta('cross file'), EC.yellow(`${startIndexes} ~ ${endIndexes}`));
|
|
626
|
+
// }
|
|
627
|
+
|
|
628
|
+
const originalState = originalMap.get(sourceIndex);
|
|
629
|
+
if (!originalState) {
|
|
630
|
+
return {
|
|
631
|
+
error: true,
|
|
632
|
+
errors: [`not found original file: ${EC.yellow(sourceIndex)}`]
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return {
|
|
637
|
+
// for debug
|
|
638
|
+
// startIndexes,
|
|
639
|
+
// endIndexes,
|
|
640
|
+
|
|
641
|
+
sourceIndex,
|
|
642
|
+
crossStart,
|
|
643
|
+
crossEnd,
|
|
644
|
+
originalState
|
|
645
|
+
};
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
const getMappingInfo = (decodedMappings, start, end) => {
|
|
649
|
+
// possible no length
|
|
650
|
+
if (decodedMappings.length < 2) {
|
|
651
|
+
return {
|
|
652
|
+
error: true,
|
|
653
|
+
errors: ['invalid decoded mappings (length < 2)']
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// start: inclusive
|
|
658
|
+
// end: exclusive
|
|
659
|
+
// could be 4 mappings found
|
|
660
|
+
|
|
661
|
+
const startMappings = findMapping(decodedMappings, start);
|
|
662
|
+
if (!startMappings) {
|
|
663
|
+
return {
|
|
664
|
+
error: true,
|
|
665
|
+
errors: ['not found start mappings']
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const endMappings = findMapping(decodedMappings, end);
|
|
670
|
+
if (!endMappings) {
|
|
671
|
+
return {
|
|
672
|
+
error: true,
|
|
673
|
+
errors: ['not found end mappings']
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
return {
|
|
678
|
+
startMappings,
|
|
679
|
+
endMappings
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
const findOriginalRange = (start, end, state, originalMap) => {
|
|
684
|
+
|
|
685
|
+
const { sourcePath, decodedMappings } = state;
|
|
686
|
+
|
|
687
|
+
const createMappingError = (errors) => {
|
|
688
|
+
return {
|
|
689
|
+
error: true,
|
|
690
|
+
start,
|
|
691
|
+
end,
|
|
692
|
+
sourcePath,
|
|
693
|
+
errors
|
|
694
|
+
};
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
const mappingInfo = getMappingInfo(decodedMappings, start, end);
|
|
698
|
+
if (mappingInfo.error) {
|
|
699
|
+
return createMappingError(mappingInfo.errors);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const { startMappings, endMappings } = mappingInfo;
|
|
703
|
+
|
|
704
|
+
const rangeInfo = getOriginalState(startMappings, endMappings, originalMap);
|
|
705
|
+
if (rangeInfo.error) {
|
|
706
|
+
return createMappingError(rangeInfo.errors);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const originalStartResult = getOriginalStart(start, startMappings, state, rangeInfo);
|
|
710
|
+
if (originalStartResult.error) {
|
|
711
|
+
return createMappingError(originalStartResult.errors);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const originalEndResult = getOriginalEnd(end, endMappings, state, rangeInfo);
|
|
715
|
+
if (originalEndResult.error) {
|
|
716
|
+
return createMappingError(originalEndResult.errors);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const { originalStart } = originalStartResult;
|
|
720
|
+
const { originalEnd } = originalEndResult;
|
|
721
|
+
|
|
722
|
+
// range start > end
|
|
723
|
+
if (originalStart > originalEnd) {
|
|
724
|
+
return createMappingError([`invalid original start > end: ${EC.yellow(originalStart)} > ${EC.yellow(originalEnd)}`]);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const { originalState } = rangeInfo;
|
|
728
|
+
|
|
729
|
+
return {
|
|
730
|
+
start: originalStart,
|
|
731
|
+
end: originalEnd,
|
|
732
|
+
originalState
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
module.exports = findOriginalRange;
|