1/***********************************************************************
2
3  A JavaScript tokenizer / parser / beautifier / compressor.
4  https://github.com/mishoo/UglifyJS
5
6  -------------------------------- (C) ---------------------------------
7
8                           Author: Mihai Bazon
9                         <mihai.bazon@gmail.com>
10                       http://mihai.bazon.net/blog
11
12  Distributed under the BSD license:
13
14    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
15
16    Redistribution and use in source and binary forms, with or without
17    modification, are permitted provided that the following conditions
18    are met:
19
20        * Redistributions of source code must retain the above
21          copyright notice, this list of conditions and the following
22          disclaimer.
23
24        * Redistributions in binary form must reproduce the above
25          copyright notice, this list of conditions and the following
26          disclaimer in the documentation and/or other materials
27          provided with the distribution.
28
29    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
30    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
33    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40    SUCH DAMAGE.
41
42 ***********************************************************************/
43
44"use strict";
45
46var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
47var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
48    map[ch] = bits;
49    return map;
50}, Object.create(null));
51
52function vlq_decode(indices, str) {
53    var value = 0;
54    var shift = 0;
55    for (var i = 0, j = 0; i < str.length; i++) {
56        var bits = vlq_bits[str[i]];
57        value += (bits & 31) << shift;
58        if (bits & 32) {
59            shift += 5;
60        } else {
61            indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
62            value = shift = 0;
63        }
64    }
65    return j;
66}
67
68function vlq_encode(num) {
69    var result = "";
70    num = Math.abs(num) << 1 | num >>> 31;
71    do {
72        var bits = num & 31;
73        if (num >>>= 5) bits |= 32;
74        result += vlq_char[bits];
75    } while (num);
76    return result;
77}
78
79function create_array_map() {
80    var map = new Dictionary();
81    var array = [];
82    array.index = function(name) {
83        var index = map.get(name);
84        if (!(index >= 0)) {
85            index = array.length;
86            array.push(name);
87            map.set(name, index);
88        }
89        return index;
90    };
91    return array;
92}
93
94function SourceMap(options) {
95    var sources = create_array_map();
96    var sources_content = options.includeSources && new Dictionary();
97    var names = create_array_map();
98    var mappings = "";
99    if (options.orig) Object.keys(options.orig).forEach(function(name) {
100        var map = options.orig[name];
101        var indices = [ 0, 0, 1, 0, 0 ];
102        options.orig[name] = {
103            names: map.names,
104            mappings: map.mappings.split(/;/).map(function(line) {
105                indices[0] = 0;
106                return line.split(/,/).map(function(segment) {
107                    return indices.slice(0, vlq_decode(indices, segment));
108                });
109            }),
110            sources: map.sources,
111        };
112        if (!sources_content || !map.sourcesContent) return;
113        for (var i = 0; i < map.sources.length; i++) {
114            var content = map.sourcesContent[i];
115            if (content) sources_content.set(map.sources[i], content);
116        }
117    });
118    var prev_source;
119    var generated_line = 1;
120    var generated_column = 0;
121    var source_index = 0;
122    var original_line = 1;
123    var original_column = 0;
124    var name_index = 0;
125    return {
126        add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
127            var map = options.orig[source];
128            if (map) {
129                var segments = map.mappings[orig_line - 1];
130                if (!segments) return;
131                var indices;
132                for (var i = 0; i < segments.length; i++) {
133                    var col = segments[i][0];
134                    if (orig_col >= col) indices = segments[i];
135                    if (orig_col <= col) break;
136                }
137                if (!indices || indices.length < 4) {
138                    source = null;
139                } else {
140                    source = map.sources[indices[1]];
141                    orig_line = indices[2];
142                    orig_col = indices[3];
143                    if (indices.length > 4) name = map.names[indices[4]];
144                }
145            }
146            add(source, gen_line, gen_col, orig_line, orig_col, name);
147        } : add,
148        setSourceContent: sources_content ? function(source, content) {
149            if (!sources_content.has(source)) {
150                sources_content.set(source, content);
151            }
152        } : noop,
153        toString: function() {
154            return JSON.stringify({
155                version: 3,
156                file: options.filename || undefined,
157                sourceRoot: options.root || undefined,
158                sources: sources,
159                sourcesContent: sources_content ? sources.map(function(source) {
160                    return sources_content.get(source) || null;
161                }) : undefined,
162                names: names,
163                mappings: mappings,
164            });
165        }
166    };
167
168    function add(source, gen_line, gen_col, orig_line, orig_col, name) {
169        if (prev_source == null && source == null) return;
170        prev_source = source;
171        if (generated_line < gen_line) {
172            generated_column = 0;
173            do {
174                mappings += ";";
175            } while (++generated_line < gen_line);
176        } else if (mappings) {
177            mappings += ",";
178        }
179        mappings += vlq_encode(gen_col - generated_column);
180        generated_column = gen_col;
181        if (source == null) return;
182        var src_idx = sources.index(source);
183        mappings += vlq_encode(src_idx - source_index);
184        source_index = src_idx;
185        mappings += vlq_encode(orig_line - original_line);
186        original_line = orig_line;
187        mappings += vlq_encode(orig_col - original_column);
188        original_column = orig_col;
189        if (options.names && name != null) {
190            var name_idx = names.index(name);
191            mappings += vlq_encode(name_idx - name_index);
192            name_index = name_idx;
193        }
194    }
195}
196