保誠-保戶業務員媒合平台
HelenHuang
2022-06-09 23b60dc1975db38c280d8a123aff97544d1673e0
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/
 
"use strict";
 
var SourceNode = require("source-map").SourceNode;
var SourceMapConsumer = require("source-map").SourceMapConsumer;
 
var applySourceMap = function(
    sourceNode,
    sourceMapConsumer,
    sourceFile,
    removeGeneratedCodeForSourceFile
) {
    // The following notations are used to name stuff:
    // Left <------------> Middle <-------------------> Right
    // Input arguments:
    //        sourceNode                                       - Code mapping from Left to Middle
    //                   sourceFile                            - Name of a Middle file
    //                              sourceMapConsumer          - Code mapping from Middle to Right
    // Variables:
    //           l2m                      m2r
    // Left <-----------------------------------------> Right
    // Variables:
    //                       l2r
 
    var l2rResult = new SourceNode();
    var l2rOutput = [];
 
    var middleSourceContents = {};
 
    var m2rMappingsByLine = {};
 
    var rightSourceContentsSet = {};
    var rightSourceContentsLines = {};
 
    // Store all mappings by generated line
    sourceMapConsumer.eachMapping(
        function(mapping) {
            (m2rMappingsByLine[mapping.generatedLine] =
                m2rMappingsByLine[mapping.generatedLine] || []).push(mapping);
        },
        null,
        SourceMapConsumer.GENERATED_ORDER
    );
 
    // Store all source contents
    sourceNode.walkSourceContents(function(source, content) {
        middleSourceContents["$" + source] = content;
    });
 
    var middleSource = middleSourceContents["$" + sourceFile];
    var middleSourceLines = middleSource ? middleSource.split("\n") : undefined;
 
    // Walk all left to middle mappings
    sourceNode.walk(function(chunk, middleMapping) {
        var source;
 
        // Find a mapping from middle to right
        if(
            middleMapping.source === sourceFile &&
            middleMapping.line &&
            m2rMappingsByLine[middleMapping.line]
        ) {
            var m2rBestFit;
            var m2rMappings = m2rMappingsByLine[middleMapping.line];
            // Note: if this becomes a performance problem, use binary search
            for(var i = 0; i < m2rMappings.length; i++) {
                if(m2rMappings[i].generatedColumn <= middleMapping.column) {
                    m2rBestFit = m2rMappings[i];
                }
            }
            if(m2rBestFit) {
                var allowMiddleName = false;
                var middleLine;
                var rightSourceContent;
                var rightSourceContentLines;
                var rightSource = m2rBestFit.source;
                // Check if we have middle and right source for this mapping
                // Then we could have an "identify" mapping
                if(
                    middleSourceLines &&
                    rightSource &&
                    (middleLine = middleSourceLines[m2rBestFit.generatedLine - 1]) &&
                    ((rightSourceContentLines = rightSourceContentsLines[rightSource]) ||
                        (rightSourceContent = sourceMapConsumer.sourceContentFor(
                            rightSource,
                            true
                        )))
                ) {
                    if(!rightSourceContentLines) {
                        rightSourceContentLines = rightSourceContentsLines[
                            rightSource
                        ] = rightSourceContent.split("\n");
                    }
                    var rightLine = rightSourceContentLines[m2rBestFit.originalLine - 1];
                    if(rightLine) {
                        var offset = middleMapping.column - m2rBestFit.generatedColumn;
                        if(offset > 0) {
                            var middlePart = middleLine.slice(
                                m2rBestFit.generatedColumn,
                                middleMapping.column
                            );
                            var rightPart = rightLine.slice(
                                m2rBestFit.originalColumn,
                                m2rBestFit.originalColumn + offset
                            );
                            if(middlePart === rightPart) {
                                // When original and generated code is equal we assume we have an "identity" mapping
                                // In this case we can offset the original position
                                m2rBestFit = Object.assign({}, m2rBestFit, {
                                    originalColumn: m2rBestFit.originalColumn + offset,
                                    generatedColumn: middleMapping.column
                                });
                            }
                        }
                        if(!m2rBestFit.name && middleMapping.name) {
                            allowMiddleName =
                                rightLine.slice(
                                    m2rBestFit.originalColumn,
                                    m2rBestFit.originalColumn + middleMapping.name.length
                                ) === middleMapping.name;
                        }
                    }
                }
 
                // Construct a left to right node from the found middle to right mapping
                source = m2rBestFit.source;
                l2rOutput.push(
                    new SourceNode(
                        m2rBestFit.originalLine,
                        m2rBestFit.originalColumn,
                        source,
                        chunk,
                        allowMiddleName ? middleMapping.name : m2rBestFit.name
                    )
                );
 
                // Set the source contents once
                if(!("$" + source in rightSourceContentsSet)) {
                    rightSourceContentsSet["$" + source] = true;
                    var sourceContent = sourceMapConsumer.sourceContentFor(source, true);
                    if(sourceContent) {
                        l2rResult.setSourceContent(source, sourceContent);
                    }
                }
                return;
            }
        }
 
        if((removeGeneratedCodeForSourceFile && middleMapping.source === sourceFile) || !middleMapping.source) {
            // Construct a left to middle node with only generated code
            // Because user do not want mappings to middle sources
            // Or this chunk has no mapping
            l2rOutput.push(chunk);
            return;
        }
 
        // Construct a left to middle node
        source = middleMapping.source;
        l2rOutput.push(
            new SourceNode(
                middleMapping.line,
                middleMapping.column,
                source,
                chunk,
                middleMapping.name
            )
        );
        if("$" + source in middleSourceContents) {
            if(!("$" + source in rightSourceContentsSet)) {
                l2rResult.setSourceContent(source, middleSourceContents["$" + source]);
                delete middleSourceContents["$" + source];
            }
        }
    });
 
    // Put output into the resulting SourceNode
    l2rResult.add(l2rOutput);
    return l2rResult;
};
 
module.exports = applySourceMap;