윤준현

Test promise

dd
Showing 219 changed files with 147 additions and 26383 deletions
...@@ -6,6 +6,7 @@ var bodyParser = require('body-parser'); ...@@ -6,6 +6,7 @@ var bodyParser = require('body-parser');
6 var singer = require('./content') 6 var singer = require('./content')
7 var app = express(); // express 객체 저장 7 var app = express(); // express 객체 저장
8 8
9 +
9 //body-parser 미들웨어 사용 10 //body-parser 미들웨어 사용
10 app.use(bodyParser.urlencoded({extended: false})); 11 app.use(bodyParser.urlencoded({extended: false}));
11 app.use(bodyParser.json()); 12 app.use(bodyParser.json());
...@@ -32,7 +33,7 @@ app.post('/message', function(req,res){ ...@@ -32,7 +33,7 @@ app.post('/message', function(req,res){
32 console.log('전달받은 메시지 : ' + msg); 33 console.log('전달받은 메시지 : ' + msg);
33 34
34 var send = {}; 35 var send = {};
35 - function hell_callback(msg, callback){ 36 + function delay(){
36 switch(msg){ 37 switch(msg){
37 case '일본' : 38 case '일본' :
38 send = { 39 send = {
...@@ -58,23 +59,17 @@ app.post('/message', function(req,res){ ...@@ -58,23 +59,17 @@ app.post('/message', function(req,res){
58 }; 59 };
59 break; 60 break;
60 default: 61 default:
61 - send = singer.jpSinger(msg) 62 + singer.jpSinger(msg).then(function(result){
62 - var album_info = []; 63 + send = result;
63 - var album; 64 + })
64 - console.log(discography[0].json_album[1]);
65 - for (var i = 0; i < discography[0].json_album.lenth; i++) {
66 - album = discography[0].json_album[i] + ' 발매일 : ' + discography[0].json_year[i];
67 - console.log(album);
68 - }
69 - });
70 if(send == '') 65 if(send == '')
71 send = singer.krSinger(msg); 66 send = singer.krSinger(msg);
72 break; 67 break;
73 } 68 }
74 - callback(send);
75 } 69 }
76 - console.log(send); 70 + delay().then(function(){
77 - hell_callback(msg,function(hell_send){ 71 + console.log(send);
78 - res.json(hell_send); 72 +
73 + res.json(send);
79 }) 74 })
80 }) 75 })
...\ No newline at end of file ...\ No newline at end of file
......
1 var webcrawl = require('./crawling/Reol') 1 var webcrawl = require('./crawling/Reol')
2 2
3 -function jpSinger(msg,callback){
4 - var send = {};
5 - switch(msg){
6 - case 'Reol' :
7 - send = {
8 - 'message' : {
9 - 'text' : '이름 : Reol(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
10 - 'photo' : {
11 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
12 - 'width' : 1000,
13 - 'height' : 667
14 - },
15 - 'message_button' : {
16 - 'label' : '공식 홈페이지',
17 - 'url' : "https://www.reol.jp/"
18 - }
19 - },
20 - keyboard : {
21 - 'type' : 'buttons',
22 - 'buttons' : ['Reol-Discography']
23 - }
24 - };
25 - break;
26 - case 'Reol-Discography' :
27 - webcrawl.crawl_Reol('https://namu.wiki/w/%EB%A0%88%EC%98%A4%EB%A3%A8/%EC%9D%8C%EB%B0%98#toc', function(discography){
28 - callback(discography)
29 - });
30 - break;
31 - case '米津玄師' :
32 - send = {
33 - 'message' : {
34 - 'text' : '이름 : 米津玄師(Yonezu Kenshi) \n 성별 : 남성 \n생년월일 : 1991년 3월 10일 \n혈액형 : O형',
35 - 'photo' : {
36 - 'url' : 'http://reissuerecords.net/rr/wp-content/uploads/flamingo_photo2.jpg',
37 - 'width' : 1000,
38 - 'height' : 667
39 - },
40 - 'message_button' : {
41 - 'label' : '공식 홈페이지',
42 - 'url' : "http://reissuerecords.net/"
43 - }
44 - },
45 - keyboard : {
46 - 'type' : 'buttons',
47 - 'buttons' : ['米津玄師-Discography']
48 - }
49 - };
50 - break;
51 - case '米津玄師-Discography' :
52 - send = {
53 - 'message' : {
54 - 'text' : 'Album List'
55 - },
56 - keyboard : {
57 - 'type' : 'buttons',
58 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
59 - }
60 -
61 - };
62 - break;
63 - case 'Reol' :
64 - send = {
65 - 'message' : {
66 - 'text' : '이름 : Reol(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
67 - 'photo' : {
68 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
69 - 'width' : 1000,
70 - 'height' : 667
71 - },
72 - 'message_button' : {
73 - 'label' : '공식 홈페이지',
74 - 'url' : "https://www.reol.jp/"
75 - }
76 - },
77 - keyboard : {
78 - 'type' : 'buttons',
79 - 'buttons' : ['Reol-Discography']
80 - }
81 - };
82 - break;
83 - case 'Reol-Discography' :
84 - send = {
85 - 'message' : {
86 - 'text' : 'Album List'
87 - },
88 - keyboard : {
89 - 'type' : 'buttons',
90 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
91 - }
92 -
93 - };
94 - break;
95 - case '米津玄師' :
96 - send = {
97 - 'message' : {
98 - 'text' : '이름 : 米津玄師(Yonezu Kenshi) \n 성별 : 남성 \n생년월일 : 1991년 3월 10일 \n혈액형 : O형',
99 - 'photo' : {
100 - 'url' : 'http://reissuerecords.net/rr/wp-content/uploads/flamingo_photo2.jpg',
101 - 'width' : 1000,
102 - 'height' : 667
103 - },
104 - 'message_button' : {
105 - 'label' : '공식 홈페이지',
106 - 'url' : "http://reissuerecords.net/"
107 - }
108 - },
109 - keyboard : {
110 - 'type' : 'buttons',
111 - 'buttons' : ['米津玄師-Discography']
112 - }
113 - };
114 - break;
115 - case '米津玄師-Discography' :
116 - send = {
117 - 'message' : {
118 - 'text' : 'Album List'
119 - },
120 - keyboard : {
121 - 'type' : 'buttons',
122 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
123 - }
124 -
125 - };
126 - break;
127 -
128 - case 'yanaginagi' :
129 - send = {
130 - 'message' : {
131 - 'text' : '이름 : yanaginagi(やなぎなぎ) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
132 - 'photo' : {
133 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
134 - 'width' : 1000,
135 - 'height' : 667
136 - },
137 - 'message_button' : {
138 - 'label' : '공식 홈페이지',
139 - 'url' : "https://www.reol.jp/"
140 - }
141 - },
142 - keyboard : {
143 - 'type' : 'buttons',
144 - 'buttons' : ['Reol-Discography']
145 - }
146 - };
147 - break;
148 - case 'yanaginagi-Discography' :
149 - send = {
150 - 'message' : {
151 - 'text' : 'Album List'
152 - },
153 - keyboard : {
154 - 'type' : 'buttons',
155 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
156 - }
157 -
158 - };
159 - break;
160 - case 'ヨルシカ' :
161 - send = {
162 - 'message' : {
163 - 'text' : '이름 : ヨルシカ(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
164 - 'photo' : {
165 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
166 - 'width' : 1000,
167 - 'height' : 667
168 - },
169 - 'message_button' : {
170 - 'label' : '공식 홈페이지',
171 - 'url' : "https://www.reol.jp/"
172 - }
173 - },
174 - keyboard : {
175 - 'type' : 'buttons',
176 - 'buttons' : ['Reol-Discography']
177 - }
178 - };
179 - break;
180 - case 'ヨルシカ-Discography' :
181 - send = {
182 - 'message' : {
183 - 'text' : 'Album List'
184 - },
185 - keyboard : {
186 - 'type' : 'buttons',
187 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
188 - }
189 -
190 - };
191 - break;
192 - case 'ダズビ' :
193 - send = {
194 - 'message' : {
195 - 'text' : '이름 : ダズビ(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
196 - 'photo' : {
197 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
198 - 'width' : 1000,
199 - 'height' : 667
200 - },
201 - 'message_button' : {
202 - 'label' : '공식 홈페이지',
203 - 'url' : "https://www.reol.jp/"
204 - }
205 - },
206 - keyboard : {
207 - 'type' : 'buttons',
208 - 'buttons' : ['Reol-Discography']
209 - }
210 - };
211 - break;
212 - case 'ダズビ-Discography' :
213 - send = {
214 - 'message' : {
215 - 'text' : 'Album List'
216 - },
217 - keyboard : {
218 - 'type' : 'buttons',
219 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
220 - }
221 3
222 - }; 4 +function jpSinger(msg, discography){
223 - break; 5 + var test;
224 - case 'Polkadot Stingray' : 6 + var discography;
225 - send = { 7 + var send = {};
226 - 'message' : { 8 + return new Promise(function(resolve, reject){
227 - 'text' : '이름 : Polkadot Stingray(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형', 9 + function delay(discography) {
228 - 'photo' : { 10 + switch (msg) {
229 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png', 11 + case 'Reol':
230 - 'width' : 1000, 12 + send = {
231 - 'height' : 667 13 + 'message': {
232 - }, 14 + 'text': '이름 : Reol(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
233 - 'message_button' : { 15 + 'photo': {
234 - 'label' : '공식 홈페이지', 16 + 'url': 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
235 - 'url' : "https://www.reol.jp/" 17 + 'width': 1000,
18 + 'height': 667
19 + },
20 + 'message_button': {
21 + 'label': '공식 홈페이지',
22 + 'url': "https://www.reol.jp/"
23 + }
24 + },
25 + keyboard: {
26 + 'type': 'buttons',
27 + 'buttons': ['Reol-Discography']
28 + }
29 + };
30 + break;
31 + case 'Reol-Discography':
32 + console.log(discography);
33 + send = {
34 + 'message': {
35 + 'text': '앨범 목록입니다.'
36 + },
37 + keyboard: {
38 + 'type': 'buttons',
39 + 'buttons': ['a']
40 + }
236 } 41 }
237 - }, 42 + break;
238 - keyboard : { 43 + case '米津玄師':
239 - 'type' : 'buttons', 44 + send = {
240 - 'buttons' : ['Reol-Discography'] 45 + 'message': {
241 - } 46 + 'text': '이름 : 米津玄師(Yonezu Kenshi) \n 성별 : 남성 \n생년월일 : 1991년 3월 10일 \n혈액형 : O형',
242 - }; 47 + 'photo': {
243 - break; 48 + 'url': 'http://reissuerecords.net/rr/wp-content/uploads/flamingo_photo2.jpg',
244 - case 'Polkadot Stingray-Discography' : 49 + 'width': 1000,
245 - send = { 50 + 'height': 667
246 - 'message' : { 51 + },
247 - 'text' : 'Album List' 52 + 'message_button': {
248 - }, 53 + 'label': '공식 홈페이지',
249 - keyboard : { 54 + 'url': "http://reissuerecords.net/"
250 - 'type' : 'buttons', 55 + }
251 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong'] 56 + },
252 - } 57 + keyboard: {
58 + 'type': 'buttons',
59 + 'buttons': ['米津玄師-Discography']
60 + }
61 + };
62 + break;
63 + case '米津玄師-Discography':
64 + send = {
65 + 'message': {
66 + 'text': 'Album List'
67 + },
68 + keyboard: {
69 + 'type': 'buttons',
70 + 'buttons': ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
71 + }
253 72
254 - }; 73 + };
255 - break; 74 + break;
256 - case 'Aimyong' :
257 - send = {
258 - 'message' : {
259 - 'text' : '이름 : Aimyong(れをる) \n성별 : 여성 \n생년월일 : 1993년 11월 9일 \n혈액형 : AB형',
260 - 'photo' : {
261 - 'url' : 'https://www.reol.jp/images/profile/reol_Aphoto_2.png',
262 - 'width' : 1000,
263 - 'height' : 667
264 - },
265 - 'message_button' : {
266 - 'label' : '공식 홈페이지',
267 - 'url' : "https://www.reol.jp/"
268 - }
269 - },
270 - keyboard : {
271 - 'type' : 'buttons',
272 - 'buttons' : ['Reol-Discography']
273 - }
274 - };
275 - break;
276 - case 'Aimyong-Discography' :
277 - send = {
278 - 'message' : {
279 - 'text' : 'Album List'
280 - },
281 - keyboard : {
282 - 'type' : 'buttons',
283 - 'buttons' : ['Reol', '米津玄師', 'yanaginagi', 'ヨルシカ', 'ダズビ', 'Polkadot Stingray', 'Aimyong']
284 - }
285 75
286 - }; 76 + default:
287 - break; 77 + break;
78 + }
79 + return send;
80 + }
81 + webcrawl.crawl_Reol('https://namu.wiki/w/%EB%A0%88%EC%98%A4%EB%A3%A8/%EC%9D%8C%EB%B0%98#toc').then(function (Result) {
82 + discography = Result;
83 + return function () {
84 + return Result;
85 + }
86 + }).catch(function (err) {
87 + console.error(err);
88 + }).then(function () {
89 + delay(discography)
90 + })
91 + if(send)
92 + resolve(send)
93 + reject(new Error("Request is failed"));
94 + })
288 95
289 - default:
290 - break;
291 - }
292 -
293 - return send;
294 } 96 }
295 97
296 function krSinger(msg){ 98 function krSinger(msg){
......
1 //Reol 나무위키 앨범 발매년도 트랙 크롤링 1 //Reol 나무위키 앨범 발매년도 트랙 크롤링
2 var request = require('request'); 2 var request = require('request');
3 var cheerio = require('cheerio'); 3 var cheerio = require('cheerio');
4 -function crawl_Reol(url, callBack){ 4 +function crawl_Reol(url){
5 - request(url, function(err, res, body){ 5 + return new Promise(function(resolve, reject){
6 - const $ = cheerio.load(body); 6 + request(url, function (err, res, body) {
7 + const $ = cheerio.load(body);
7 8
8 - var Reol = new Array(); 9 + var Reol = new Array();
9 - var album, year 10 + var album, year
10 - var album_track = new Array(); 11 + var album_track = new Array();
11 - var json_album = new Array(), json_year = new Array(), json_track = new Array(); 12 + var json_album = new Array(), json_year = new Array(), json_track = new Array();
13 + $('body > div.content-wrapper > article > div.wiki-content.clearfix > div').each(function (index, ele) {
14 + for (var i = 1; i <= $('.toc-item').length; i++) {
15 + album = $(this).find('#toc > div > div:nth-child(2) > span:nth-child(' + i + ')').text() //앨범 정보 가져오기
16 + if (album != '') {
17 + json_album.push(album.substr(2));
18 + }
12 19
13 - $('body > div.content-wrapper > article > div.wiki-content.clearfix > div').each(function(index, ele){ 20 + var index = 7 + (i * 2); //트랙, 연도 가져오기 인덱스 변수
14 - for(var i = 1; i <= $('.toc-item').length; i++){
15 - album = $(this).find('#toc > div > div:nth-child(2) > span:nth-child('+i+')').text() //앨범 정보 가져오기
16 - if(album != ''){
17 - json_album.push(album.substr(2));
18 - }
19 -
20 - var index = 7 + (i*2); //트랙, 연도 가져오기 인덱스 변수
21 21
22 - if(index != 25){ //규칙성이 어긋나는 부분을 예외처리를 위해 if문 22 + if (index != 25) { //규칙성이 어긋나는 부분을 예외처리를 위해 if문
23 - //year 가져오기 23 + //year 가져오기
24 - year = $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child('+index+') > div:nth-child(3) > table > tbody > tr:nth-child(1) > td:nth-child(2)').text(); 24 + year = $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child(' + index + ') > div:nth-child(3) > table > tbody > tr:nth-child(1) > td:nth-child(2)').text();
25 - //track 가져오기 25 + //track 가져오기
26 - $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child('+index+') > div:nth-child(3) > table > tbody').find('tr').each(function(index, ele){ 26 + $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child(' + index + ') > div:nth-child(3) > table > tbody').find('tr').each(function (index, ele) {
27 - var track = $(this).children().eq(1).text(); 27 + var track = $(this).children().eq(1).text();
28 - if(track != '1' && track != '곡명' && track[4] != '년') 28 + if (track != '1' && track != '곡명' && track[4] != '년')
29 - album_track.push(track) 29 + album_track.push(track)
30 - }); 30 + });
31 - } 31 + }
32 - else{ 32 + else {
33 - year = $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child('+index+') > div:nth-child(4) > table > tbody > tr:nth-child(1) > td:nth-child(2)').text(); 33 + year = $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child(' + index + ') > div:nth-child(4) > table > tbody > tr:nth-child(1) > td:nth-child(2)').text();
34 - $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child('+index+') > div:nth-child(4) > table > tbody').find('tr').each(function(index, ele){ 34 + $('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div:nth-child(' + index + ') > div:nth-child(4) > table > tbody').find('tr').each(function (index, ele) {
35 - var track = $(this).children().eq(1).text(); 35 + var track = $(this).children().eq(1).text();
36 - if(track != '1' && track != '곡명' && track[4] != '년') 36 + if (track != '1' && track != '곡명' && track[4] != '년')
37 - album_track.push(track) 37 + album_track.push(track)
38 - }); 38 + });
39 - } 39 + }
40 - if(year != ''){ 40 + if (year != '') {
41 - json_year.push(year); 41 + json_year.push(year);
42 - json_track.push(album_track); 42 + json_track.push(album_track);
43 + }
44 + album_track = [];
43 } 45 }
44 - album_track = []; 46 + });
47 + Reol.push({ json_album, json_year, json_track });
48 + if (Reol) {
49 + resolve(Reol);
45 } 50 }
51 + reject(new Error("Request is failed"));
46 }); 52 });
47 - Reol.push({json_album,json_year,json_track});
48 - callBack(Reol);
49 }); 53 });
50 } 54 }
51 55
......
1 -#!/bin/sh
2 -basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3 -
4 -case `uname` in
5 - *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6 -esac
7 -
8 -if [ -x "$basedir/node" ]; then
9 - "$basedir/node" "$basedir/../require/bin/require-command.js" "$@"
10 - ret=$?
11 -else
12 - node "$basedir/../require/bin/require-command.js" "$@"
13 - ret=$?
14 -fi
15 -exit $ret
1 -@IF EXIST "%~dp0\node.exe" (
2 - "%~dp0\node.exe" "%~dp0\..\require\bin\require-command.js" %*
3 -) ELSE (
4 - @SETLOCAL
5 - @SET PATHEXT=%PATHEXT:;.JS;=;%
6 - node "%~dp0\..\require\bin\require-command.js" %*
7 -)
...\ No newline at end of file ...\ No newline at end of file
1 -#!/bin/sh
2 -basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3 -
4 -case `uname` in
5 - *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6 -esac
7 -
8 -if [ -x "$basedir/node" ]; then
9 - "$basedir/node" "$basedir/../uglify-js/bin/uglifyjs" "$@"
10 - ret=$?
11 -else
12 - node "$basedir/../uglify-js/bin/uglifyjs" "$@"
13 - ret=$?
14 -fi
15 -exit $ret
1 -@IF EXIST "%~dp0\node.exe" (
2 - "%~dp0\node.exe" "%~dp0\..\uglify-js\bin\uglifyjs" %*
3 -) ELSE (
4 - @SETLOCAL
5 - @SET PATHEXT=%PATHEXT:;.JS;=;%
6 - node "%~dp0\..\uglify-js\bin\uglifyjs" %*
7 -)
...\ No newline at end of file ...\ No newline at end of file
1 -amdefine is released under two licenses: new BSD, and MIT. You may pick the
2 -license that best suits your development needs. The text of both licenses are
3 -provided below.
4 -
5 -
6 -The "New" BSD License:
7 -----------------------
8 -
9 -Copyright (c) 2011-2016, The Dojo Foundation
10 -All rights reserved.
11 -
12 -Redistribution and use in source and binary forms, with or without
13 -modification, are permitted provided that the following conditions are met:
14 -
15 - * Redistributions of source code must retain the above copyright notice, this
16 - list of conditions and the following disclaimer.
17 - * Redistributions in binary form must reproduce the above copyright notice,
18 - this list of conditions and the following disclaimer in the documentation
19 - and/or other materials provided with the distribution.
20 - * Neither the name of the Dojo Foundation nor the names of its contributors
21 - may be used to endorse or promote products derived from this software
22 - without specific prior written permission.
23 -
24 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28 -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 -
35 -
36 -
37 -MIT License
38 ------------
39 -
40 -Copyright (c) 2011-2016, The Dojo Foundation
41 -
42 -Permission is hereby granted, free of charge, to any person obtaining a copy
43 -of this software and associated documentation files (the "Software"), to deal
44 -in the Software without restriction, including without limitation the rights
45 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46 -copies of the Software, and to permit persons to whom the Software is
47 -furnished to do so, subject to the following conditions:
48 -
49 -The above copyright notice and this permission notice shall be included in
50 -all copies or substantial portions of the Software.
51 -
52 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58 -THE SOFTWARE.
1 -# amdefine
2 -
3 -A module that can be used to implement AMD's define() in Node. This allows you
4 -to code to the AMD API and have the module work in node programs without
5 -requiring those other programs to use AMD.
6 -
7 -## Usage
8 -
9 -**1)** Update your package.json to indicate amdefine as a dependency:
10 -
11 -```javascript
12 - "dependencies": {
13 - "amdefine": ">=0.1.0"
14 - }
15 -```
16 -
17 -Then run `npm install` to get amdefine into your project.
18 -
19 -**2)** At the top of each module that uses define(), place this code:
20 -
21 -```javascript
22 -if (typeof define !== 'function') { var define = require('amdefine')(module) }
23 -```
24 -
25 -**Only use these snippets** when loading amdefine. If you preserve the basic structure,
26 -with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).
27 -
28 -You can add spaces, line breaks and even require amdefine with a local path, but
29 -keep the rest of the structure to get the stripping behavior.
30 -
31 -As you may know, because `if` statements in JavaScript don't have their own scope, the var
32 -declaration in the above snippet is made whether the `if` expression is truthy or not. If
33 -RequireJS is loaded then the declaration is superfluous because `define` is already already
34 -declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`
35 -declarations of the same variable in the same scope gracefully.
36 -
37 -If you want to deliver amdefine.js with your code rather than specifying it as a dependency
38 -with npm, then just download the latest release and refer to it using a relative path:
39 -
40 -[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)
41 -
42 -### amdefine/intercept
43 -
44 -Consider this very experimental.
45 -
46 -Instead of pasting the piece of text for the amdefine setup of a `define`
47 -variable in each module you create or consume, you can use `amdefine/intercept`
48 -instead. It will automatically insert the above snippet in each .js file loaded
49 -by Node.
50 -
51 -**Warning**: you should only use this if you are creating an application that
52 -is consuming AMD style defined()'d modules that are distributed via npm and want
53 -to run that code in Node.
54 -
55 -For library code where you are not sure if it will be used by others in Node or
56 -in the browser, then explicitly depending on amdefine and placing the code
57 -snippet above is suggested path, instead of using `amdefine/intercept`. The
58 -intercept module affects all .js files loaded in the Node app, and it is
59 -inconsiderate to modify global state like that unless you are also controlling
60 -the top level app.
61 -
62 -#### Why distribute AMD-style modules via npm?
63 -
64 -npm has a lot of weaknesses for front-end use (installed layout is not great,
65 -should have better support for the `baseUrl + moduleID + '.js' style of loading,
66 -single file JS installs), but some people want a JS package manager and are
67 -willing to live with those constraints. If that is you, but still want to author
68 -in AMD style modules to get dynamic require([]), better direct source usage and
69 -powerful loader plugin support in the browser, then this tool can help.
70 -
71 -#### amdefine/intercept usage
72 -
73 -Just require it in your top level app module (for example index.js, server.js):
74 -
75 -```javascript
76 -require('amdefine/intercept');
77 -```
78 -
79 -The module does not return a value, so no need to assign the result to a local
80 -variable.
81 -
82 -Then just require() code as you normally would with Node's require(). Any .js
83 -loaded after the intercept require will have the amdefine check injected in
84 -the .js source as it is loaded. It does not modify the source on disk, just
85 -prepends some content to the text of the module as it is loaded by Node.
86 -
87 -#### How amdefine/intercept works
88 -
89 -It overrides the `Module._extensions['.js']` in Node to automatically prepend
90 -the amdefine snippet above. So, it will affect any .js file loaded by your
91 -app.
92 -
93 -## define() usage
94 -
95 -It is best if you use the anonymous forms of define() in your module:
96 -
97 -```javascript
98 -define(function (require) {
99 - var dependency = require('dependency');
100 -});
101 -```
102 -
103 -or
104 -
105 -```javascript
106 -define(['dependency'], function (dependency) {
107 -
108 -});
109 -```
110 -
111 -## RequireJS optimizer integration. <a name="optimizer"></name>
112 -
113 -Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)
114 -will have support for stripping the `if (typeof define !== 'function')` check
115 -mentioned above, so you can include this snippet for code that runs in the
116 -browser, but avoid taking the cost of the if() statement once the code is
117 -optimized for deployment.
118 -
119 -## Node 0.4 Support
120 -
121 -If you want to support Node 0.4, then add `require` as the second parameter to amdefine:
122 -
123 -```javascript
124 -//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.
125 -if (typeof define !== 'function') { var define = require('amdefine')(module, require) }
126 -```
127 -
128 -## Limitations
129 -
130 -### Synchronous vs Asynchronous
131 -
132 -amdefine creates a define() function that is callable by your code. It will
133 -execute and trace dependencies and call the factory function *synchronously*,
134 -to keep the behavior in line with Node's synchronous dependency tracing.
135 -
136 -The exception: calling AMD's callback-style require() from inside a factory
137 -function. The require callback is called on process.nextTick():
138 -
139 -```javascript
140 -define(function (require) {
141 - require(['a'], function(a) {
142 - //'a' is loaded synchronously, but
143 - //this callback is called on process.nextTick().
144 - });
145 -});
146 -```
147 -
148 -### Loader Plugins
149 -
150 -Loader plugins are supported as long as they call their load() callbacks
151 -synchronously. So ones that do network requests will not work. However plugins
152 -like [text](http://requirejs.org/docs/api.html#text) can load text files locally.
153 -
154 -The plugin API's `load.fromText()` is **not supported** in amdefine, so this means
155 -transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)
156 -will not work. This may be fixable, but it is a bit complex, and I do not have
157 -enough node-fu to figure it out yet. See the source for amdefine.js if you want
158 -to get an idea of the issues involved.
159 -
160 -## Tests
161 -
162 -To run the tests, cd to **tests** and run:
163 -
164 -```
165 -node all.js
166 -node all-intercept.js
167 -```
168 -
169 -## License
170 -
171 -New BSD and MIT. Check the LICENSE file for all the details.
1 -/** vim: et:ts=4:sw=4:sts=4
2 - * @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved.
3 - * Available via the MIT or new BSD license.
4 - * see: http://github.com/jrburke/amdefine for details
5 - */
6 -
7 -/*jslint node: true */
8 -/*global module, process */
9 -'use strict';
10 -
11 -/**
12 - * Creates a define for node.
13 - * @param {Object} module the "module" object that is defined by Node for the
14 - * current module.
15 - * @param {Function} [requireFn]. Node's require function for the current module.
16 - * It only needs to be passed in Node versions before 0.5, when module.require
17 - * did not exist.
18 - * @returns {Function} a define function that is usable for the current node
19 - * module.
20 - */
21 -function amdefine(module, requireFn) {
22 - 'use strict';
23 - var defineCache = {},
24 - loaderCache = {},
25 - alreadyCalled = false,
26 - path = require('path'),
27 - makeRequire, stringRequire;
28 -
29 - /**
30 - * Trims the . and .. from an array of path segments.
31 - * It will keep a leading path segment if a .. will become
32 - * the first path segment, to help with module name lookups,
33 - * which act like paths, but can be remapped. But the end result,
34 - * all paths that use this function should look normalized.
35 - * NOTE: this method MODIFIES the input array.
36 - * @param {Array} ary the array of path segments.
37 - */
38 - function trimDots(ary) {
39 - var i, part;
40 - for (i = 0; ary[i]; i+= 1) {
41 - part = ary[i];
42 - if (part === '.') {
43 - ary.splice(i, 1);
44 - i -= 1;
45 - } else if (part === '..') {
46 - if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
47 - //End of the line. Keep at least one non-dot
48 - //path segment at the front so it can be mapped
49 - //correctly to disk. Otherwise, there is likely
50 - //no path mapping for a path starting with '..'.
51 - //This can still fail, but catches the most reasonable
52 - //uses of ..
53 - break;
54 - } else if (i > 0) {
55 - ary.splice(i - 1, 2);
56 - i -= 2;
57 - }
58 - }
59 - }
60 - }
61 -
62 - function normalize(name, baseName) {
63 - var baseParts;
64 -
65 - //Adjust any relative paths.
66 - if (name && name.charAt(0) === '.') {
67 - //If have a base name, try to normalize against it,
68 - //otherwise, assume it is a top-level require that will
69 - //be relative to baseUrl in the end.
70 - if (baseName) {
71 - baseParts = baseName.split('/');
72 - baseParts = baseParts.slice(0, baseParts.length - 1);
73 - baseParts = baseParts.concat(name.split('/'));
74 - trimDots(baseParts);
75 - name = baseParts.join('/');
76 - }
77 - }
78 -
79 - return name;
80 - }
81 -
82 - /**
83 - * Create the normalize() function passed to a loader plugin's
84 - * normalize method.
85 - */
86 - function makeNormalize(relName) {
87 - return function (name) {
88 - return normalize(name, relName);
89 - };
90 - }
91 -
92 - function makeLoad(id) {
93 - function load(value) {
94 - loaderCache[id] = value;
95 - }
96 -
97 - load.fromText = function (id, text) {
98 - //This one is difficult because the text can/probably uses
99 - //define, and any relative paths and requires should be relative
100 - //to that id was it would be found on disk. But this would require
101 - //bootstrapping a module/require fairly deeply from node core.
102 - //Not sure how best to go about that yet.
103 - throw new Error('amdefine does not implement load.fromText');
104 - };
105 -
106 - return load;
107 - }
108 -
109 - makeRequire = function (systemRequire, exports, module, relId) {
110 - function amdRequire(deps, callback) {
111 - if (typeof deps === 'string') {
112 - //Synchronous, single module require('')
113 - return stringRequire(systemRequire, exports, module, deps, relId);
114 - } else {
115 - //Array of dependencies with a callback.
116 -
117 - //Convert the dependencies to modules.
118 - deps = deps.map(function (depName) {
119 - return stringRequire(systemRequire, exports, module, depName, relId);
120 - });
121 -
122 - //Wait for next tick to call back the require call.
123 - if (callback) {
124 - process.nextTick(function () {
125 - callback.apply(null, deps);
126 - });
127 - }
128 - }
129 - }
130 -
131 - amdRequire.toUrl = function (filePath) {
132 - if (filePath.indexOf('.') === 0) {
133 - return normalize(filePath, path.dirname(module.filename));
134 - } else {
135 - return filePath;
136 - }
137 - };
138 -
139 - return amdRequire;
140 - };
141 -
142 - //Favor explicit value, passed in if the module wants to support Node 0.4.
143 - requireFn = requireFn || function req() {
144 - return module.require.apply(module, arguments);
145 - };
146 -
147 - function runFactory(id, deps, factory) {
148 - var r, e, m, result;
149 -
150 - if (id) {
151 - e = loaderCache[id] = {};
152 - m = {
153 - id: id,
154 - uri: __filename,
155 - exports: e
156 - };
157 - r = makeRequire(requireFn, e, m, id);
158 - } else {
159 - //Only support one define call per file
160 - if (alreadyCalled) {
161 - throw new Error('amdefine with no module ID cannot be called more than once per file.');
162 - }
163 - alreadyCalled = true;
164 -
165 - //Use the real variables from node
166 - //Use module.exports for exports, since
167 - //the exports in here is amdefine exports.
168 - e = module.exports;
169 - m = module;
170 - r = makeRequire(requireFn, e, m, module.id);
171 - }
172 -
173 - //If there are dependencies, they are strings, so need
174 - //to convert them to dependency values.
175 - if (deps) {
176 - deps = deps.map(function (depName) {
177 - return r(depName);
178 - });
179 - }
180 -
181 - //Call the factory with the right dependencies.
182 - if (typeof factory === 'function') {
183 - result = factory.apply(m.exports, deps);
184 - } else {
185 - result = factory;
186 - }
187 -
188 - if (result !== undefined) {
189 - m.exports = result;
190 - if (id) {
191 - loaderCache[id] = m.exports;
192 - }
193 - }
194 - }
195 -
196 - stringRequire = function (systemRequire, exports, module, id, relId) {
197 - //Split the ID by a ! so that
198 - var index = id.indexOf('!'),
199 - originalId = id,
200 - prefix, plugin;
201 -
202 - if (index === -1) {
203 - id = normalize(id, relId);
204 -
205 - //Straight module lookup. If it is one of the special dependencies,
206 - //deal with it, otherwise, delegate to node.
207 - if (id === 'require') {
208 - return makeRequire(systemRequire, exports, module, relId);
209 - } else if (id === 'exports') {
210 - return exports;
211 - } else if (id === 'module') {
212 - return module;
213 - } else if (loaderCache.hasOwnProperty(id)) {
214 - return loaderCache[id];
215 - } else if (defineCache[id]) {
216 - runFactory.apply(null, defineCache[id]);
217 - return loaderCache[id];
218 - } else {
219 - if(systemRequire) {
220 - return systemRequire(originalId);
221 - } else {
222 - throw new Error('No module with ID: ' + id);
223 - }
224 - }
225 - } else {
226 - //There is a plugin in play.
227 - prefix = id.substring(0, index);
228 - id = id.substring(index + 1, id.length);
229 -
230 - plugin = stringRequire(systemRequire, exports, module, prefix, relId);
231 -
232 - if (plugin.normalize) {
233 - id = plugin.normalize(id, makeNormalize(relId));
234 - } else {
235 - //Normalize the ID normally.
236 - id = normalize(id, relId);
237 - }
238 -
239 - if (loaderCache[id]) {
240 - return loaderCache[id];
241 - } else {
242 - plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {});
243 -
244 - return loaderCache[id];
245 - }
246 - }
247 - };
248 -
249 - //Create a define function specific to the module asking for amdefine.
250 - function define(id, deps, factory) {
251 - if (Array.isArray(id)) {
252 - factory = deps;
253 - deps = id;
254 - id = undefined;
255 - } else if (typeof id !== 'string') {
256 - factory = id;
257 - id = deps = undefined;
258 - }
259 -
260 - if (deps && !Array.isArray(deps)) {
261 - factory = deps;
262 - deps = undefined;
263 - }
264 -
265 - if (!deps) {
266 - deps = ['require', 'exports', 'module'];
267 - }
268 -
269 - //Set up properties for this module. If an ID, then use
270 - //internal cache. If no ID, then use the external variables
271 - //for this node module.
272 - if (id) {
273 - //Put the module in deep freeze until there is a
274 - //require call for it.
275 - defineCache[id] = [id, deps, factory];
276 - } else {
277 - runFactory(id, deps, factory);
278 - }
279 - }
280 -
281 - //define.require, which has access to all the values in the
282 - //cache. Useful for AMD modules that all have IDs in the file,
283 - //but need to finally export a value to node based on one of those
284 - //IDs.
285 - define.require = function (id) {
286 - if (loaderCache[id]) {
287 - return loaderCache[id];
288 - }
289 -
290 - if (defineCache[id]) {
291 - runFactory.apply(null, defineCache[id]);
292 - return loaderCache[id];
293 - }
294 - };
295 -
296 - define.amd = {};
297 -
298 - return define;
299 -}
300 -
301 -module.exports = amdefine;
1 -/*jshint node: true */
2 -var inserted,
3 - Module = require('module'),
4 - fs = require('fs'),
5 - existingExtFn = Module._extensions['.js'],
6 - amdefineRegExp = /amdefine\.js/;
7 -
8 -inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}";
9 -
10 -//From the node/lib/module.js source:
11 -function stripBOM(content) {
12 - // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
13 - // because the buffer-to-string conversion in `fs.readFileSync()`
14 - // translates it to FEFF, the UTF-16 BOM.
15 - if (content.charCodeAt(0) === 0xFEFF) {
16 - content = content.slice(1);
17 - }
18 - return content;
19 -}
20 -
21 -//Also adapted from the node/lib/module.js source:
22 -function intercept(module, filename) {
23 - var content = stripBOM(fs.readFileSync(filename, 'utf8'));
24 -
25 - if (!amdefineRegExp.test(module.id)) {
26 - content = inserted + content;
27 - }
28 -
29 - module._compile(content, filename);
30 -}
31 -
32 -intercept._id = 'amdefine/intercept';
33 -
34 -if (!existingExtFn._id || existingExtFn._id !== intercept._id) {
35 - Module._extensions['.js'] = intercept;
36 -}
1 -{
2 - "_from": "amdefine@>=0.0.4",
3 - "_id": "amdefine@1.0.1",
4 - "_inBundle": false,
5 - "_integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
6 - "_location": "/amdefine",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "range",
10 - "registry": true,
11 - "raw": "amdefine@>=0.0.4",
12 - "name": "amdefine",
13 - "escapedName": "amdefine",
14 - "rawSpec": ">=0.0.4",
15 - "saveSpec": null,
16 - "fetchSpec": ">=0.0.4"
17 - },
18 - "_requiredBy": [
19 - "/source-map"
20 - ],
21 - "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
22 - "_shasum": "4a5282ac164729e93619bcfd3ad151f817ce91f5",
23 - "_spec": "amdefine@>=0.0.4",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\source-map",
25 - "author": {
26 - "name": "James Burke",
27 - "email": "jrburke@gmail.com",
28 - "url": "http://github.com/jrburke"
29 - },
30 - "bugs": {
31 - "url": "https://github.com/jrburke/amdefine/issues"
32 - },
33 - "bundleDependencies": false,
34 - "deprecated": false,
35 - "description": "Provide AMD's define() API for declaring modules in the AMD format",
36 - "engines": {
37 - "node": ">=0.4.2"
38 - },
39 - "homepage": "http://github.com/jrburke/amdefine",
40 - "license": "BSD-3-Clause OR MIT",
41 - "main": "./amdefine.js",
42 - "name": "amdefine",
43 - "repository": {
44 - "type": "git",
45 - "url": "git+https://github.com/jrburke/amdefine.git"
46 - },
47 - "version": "1.0.1"
48 -}
1 -Copyright (c) 2010 Caolan McMahon
2 -
3 -Permission is hereby granted, free of charge, to any person obtaining a copy
4 -of this software and associated documentation files (the "Software"), to deal
5 -in the Software without restriction, including without limitation the rights
6 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 -copies of the Software, and to permit persons to whom the Software is
8 -furnished to do so, subject to the following conditions:
9 -
10 -The above copyright notice and this permission notice shall be included in
11 -all copies or substantial portions of the Software.
12 -
13 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 -THE SOFTWARE.
1 -# Async.js
2 -
3 -Async is a utility module which provides straight-forward, powerful functions
4 -for working with asynchronous JavaScript. Although originally designed for
5 -use with [node.js](http://nodejs.org), it can also be used directly in the
6 -browser. Also supports [component](https://github.com/component/component).
7 -
8 -Async provides around 20 functions that include the usual 'functional'
9 -suspects (map, reduce, filter, each…) as well as some common patterns
10 -for asynchronous control flow (parallel, series, waterfall…). All these
11 -functions assume you follow the node.js convention of providing a single
12 -callback as the last argument of your async function.
13 -
14 -
15 -## Quick Examples
16 -
17 -```javascript
18 -async.map(['file1','file2','file3'], fs.stat, function(err, results){
19 - // results is now an array of stats for each file
20 -});
21 -
22 -async.filter(['file1','file2','file3'], fs.exists, function(results){
23 - // results now equals an array of the existing files
24 -});
25 -
26 -async.parallel([
27 - function(){ ... },
28 - function(){ ... }
29 -], callback);
30 -
31 -async.series([
32 - function(){ ... },
33 - function(){ ... }
34 -]);
35 -```
36 -
37 -There are many more functions available so take a look at the docs below for a
38 -full list. This module aims to be comprehensive, so if you feel anything is
39 -missing please create a GitHub issue for it.
40 -
41 -## Common Pitfalls
42 -
43 -### Binding a context to an iterator
44 -
45 -This section is really about bind, not about async. If you are wondering how to
46 -make async execute your iterators in a given context, or are confused as to why
47 -a method of another library isn't working as an iterator, study this example:
48 -
49 -```js
50 -// Here is a simple object with an (unnecessarily roundabout) squaring method
51 -var AsyncSquaringLibrary = {
52 - squareExponent: 2,
53 - square: function(number, callback){
54 - var result = Math.pow(number, this.squareExponent);
55 - setTimeout(function(){
56 - callback(null, result);
57 - }, 200);
58 - }
59 -};
60 -
61 -async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){
62 - // result is [NaN, NaN, NaN]
63 - // This fails because the `this.squareExponent` expression in the square
64 - // function is not evaluated in the context of AsyncSquaringLibrary, and is
65 - // therefore undefined.
66 -});
67 -
68 -async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){
69 - // result is [1, 4, 9]
70 - // With the help of bind we can attach a context to the iterator before
71 - // passing it to async. Now the square function will be executed in its
72 - // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`
73 - // will be as expected.
74 -});
75 -```
76 -
77 -## Download
78 -
79 -The source is available for download from
80 -[GitHub](http://github.com/caolan/async).
81 -Alternatively, you can install using Node Package Manager (npm):
82 -
83 - npm install async
84 -
85 -__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed
86 -
87 -## In the Browser
88 -
89 -So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
90 -
91 -```html
92 -<script type="text/javascript" src="async.js"></script>
93 -<script type="text/javascript">
94 -
95 - async.map(data, asyncProcess, function(err, results){
96 - alert(results);
97 - });
98 -
99 -</script>
100 -```
101 -
102 -## Documentation
103 -
104 -### Collections
105 -
106 -* [each](#each)
107 -* [eachSeries](#eachSeries)
108 -* [eachLimit](#eachLimit)
109 -* [map](#map)
110 -* [mapSeries](#mapSeries)
111 -* [mapLimit](#mapLimit)
112 -* [filter](#filter)
113 -* [filterSeries](#filterSeries)
114 -* [reject](#reject)
115 -* [rejectSeries](#rejectSeries)
116 -* [reduce](#reduce)
117 -* [reduceRight](#reduceRight)
118 -* [detect](#detect)
119 -* [detectSeries](#detectSeries)
120 -* [sortBy](#sortBy)
121 -* [some](#some)
122 -* [every](#every)
123 -* [concat](#concat)
124 -* [concatSeries](#concatSeries)
125 -
126 -### Control Flow
127 -
128 -* [series](#series)
129 -* [parallel](#parallel)
130 -* [parallelLimit](#parallellimittasks-limit-callback)
131 -* [whilst](#whilst)
132 -* [doWhilst](#doWhilst)
133 -* [until](#until)
134 -* [doUntil](#doUntil)
135 -* [forever](#forever)
136 -* [waterfall](#waterfall)
137 -* [compose](#compose)
138 -* [applyEach](#applyEach)
139 -* [applyEachSeries](#applyEachSeries)
140 -* [queue](#queue)
141 -* [cargo](#cargo)
142 -* [auto](#auto)
143 -* [iterator](#iterator)
144 -* [apply](#apply)
145 -* [nextTick](#nextTick)
146 -* [times](#times)
147 -* [timesSeries](#timesSeries)
148 -
149 -### Utils
150 -
151 -* [memoize](#memoize)
152 -* [unmemoize](#unmemoize)
153 -* [log](#log)
154 -* [dir](#dir)
155 -* [noConflict](#noConflict)
156 -
157 -
158 -## Collections
159 -
160 -<a name="forEach" />
161 -<a name="each" />
162 -### each(arr, iterator, callback)
163 -
164 -Applies an iterator function to each item in an array, in parallel.
165 -The iterator is called with an item from the list and a callback for when it
166 -has finished. If the iterator passes an error to this callback, the main
167 -callback for the each function is immediately called with the error.
168 -
169 -Note, that since this function applies the iterator to each item in parallel
170 -there is no guarantee that the iterator functions will complete in order.
171 -
172 -__Arguments__
173 -
174 -* arr - An array to iterate over.
175 -* iterator(item, callback) - A function to apply to each item in the array.
176 - The iterator is passed a callback(err) which must be called once it has
177 - completed. If no error has occured, the callback should be run without
178 - arguments or with an explicit null argument.
179 -* callback(err) - A callback which is called after all the iterator functions
180 - have finished, or an error has occurred.
181 -
182 -__Example__
183 -
184 -```js
185 -// assuming openFiles is an array of file names and saveFile is a function
186 -// to save the modified contents of that file:
187 -
188 -async.each(openFiles, saveFile, function(err){
189 - // if any of the saves produced an error, err would equal that error
190 -});
191 -```
192 -
193 ----------------------------------------
194 -
195 -<a name="forEachSeries" />
196 -<a name="eachSeries" />
197 -### eachSeries(arr, iterator, callback)
198 -
199 -The same as each only the iterator is applied to each item in the array in
200 -series. The next iterator is only called once the current one has completed
201 -processing. This means the iterator functions will complete in order.
202 -
203 -
204 ----------------------------------------
205 -
206 -<a name="forEachLimit" />
207 -<a name="eachLimit" />
208 -### eachLimit(arr, limit, iterator, callback)
209 -
210 -The same as each only no more than "limit" iterators will be simultaneously
211 -running at any time.
212 -
213 -Note that the items are not processed in batches, so there is no guarantee that
214 - the first "limit" iterator functions will complete before any others are
215 -started.
216 -
217 -__Arguments__
218 -
219 -* arr - An array to iterate over.
220 -* limit - The maximum number of iterators to run at any time.
221 -* iterator(item, callback) - A function to apply to each item in the array.
222 - The iterator is passed a callback(err) which must be called once it has
223 - completed. If no error has occured, the callback should be run without
224 - arguments or with an explicit null argument.
225 -* callback(err) - A callback which is called after all the iterator functions
226 - have finished, or an error has occurred.
227 -
228 -__Example__
229 -
230 -```js
231 -// Assume documents is an array of JSON objects and requestApi is a
232 -// function that interacts with a rate-limited REST api.
233 -
234 -async.eachLimit(documents, 20, requestApi, function(err){
235 - // if any of the saves produced an error, err would equal that error
236 -});
237 -```
238 -
239 ----------------------------------------
240 -
241 -<a name="map" />
242 -### map(arr, iterator, callback)
243 -
244 -Produces a new array of values by mapping each value in the given array through
245 -the iterator function. The iterator is called with an item from the array and a
246 -callback for when it has finished processing. The callback takes 2 arguments,
247 -an error and the transformed item from the array. If the iterator passes an
248 -error to this callback, the main callback for the map function is immediately
249 -called with the error.
250 -
251 -Note, that since this function applies the iterator to each item in parallel
252 -there is no guarantee that the iterator functions will complete in order, however
253 -the results array will be in the same order as the original array.
254 -
255 -__Arguments__
256 -
257 -* arr - An array to iterate over.
258 -* iterator(item, callback) - A function to apply to each item in the array.
259 - The iterator is passed a callback(err, transformed) which must be called once
260 - it has completed with an error (which can be null) and a transformed item.
261 -* callback(err, results) - A callback which is called after all the iterator
262 - functions have finished, or an error has occurred. Results is an array of the
263 - transformed items from the original array.
264 -
265 -__Example__
266 -
267 -```js
268 -async.map(['file1','file2','file3'], fs.stat, function(err, results){
269 - // results is now an array of stats for each file
270 -});
271 -```
272 -
273 ----------------------------------------
274 -
275 -<a name="mapSeries" />
276 -### mapSeries(arr, iterator, callback)
277 -
278 -The same as map only the iterator is applied to each item in the array in
279 -series. The next iterator is only called once the current one has completed
280 -processing. The results array will be in the same order as the original.
281 -
282 -
283 ----------------------------------------
284 -
285 -<a name="mapLimit" />
286 -### mapLimit(arr, limit, iterator, callback)
287 -
288 -The same as map only no more than "limit" iterators will be simultaneously
289 -running at any time.
290 -
291 -Note that the items are not processed in batches, so there is no guarantee that
292 - the first "limit" iterator functions will complete before any others are
293 -started.
294 -
295 -__Arguments__
296 -
297 -* arr - An array to iterate over.
298 -* limit - The maximum number of iterators to run at any time.
299 -* iterator(item, callback) - A function to apply to each item in the array.
300 - The iterator is passed a callback(err, transformed) which must be called once
301 - it has completed with an error (which can be null) and a transformed item.
302 -* callback(err, results) - A callback which is called after all the iterator
303 - functions have finished, or an error has occurred. Results is an array of the
304 - transformed items from the original array.
305 -
306 -__Example__
307 -
308 -```js
309 -async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){
310 - // results is now an array of stats for each file
311 -});
312 -```
313 -
314 ----------------------------------------
315 -
316 -<a name="filter" />
317 -### filter(arr, iterator, callback)
318 -
319 -__Alias:__ select
320 -
321 -Returns a new array of all the values which pass an async truth test.
322 -_The callback for each iterator call only accepts a single argument of true or
323 -false, it does not accept an error argument first!_ This is in-line with the
324 -way node libraries work with truth tests like fs.exists. This operation is
325 -performed in parallel, but the results array will be in the same order as the
326 -original.
327 -
328 -__Arguments__
329 -
330 -* arr - An array to iterate over.
331 -* iterator(item, callback) - A truth test to apply to each item in the array.
332 - The iterator is passed a callback(truthValue) which must be called with a
333 - boolean argument once it has completed.
334 -* callback(results) - A callback which is called after all the iterator
335 - functions have finished.
336 -
337 -__Example__
338 -
339 -```js
340 -async.filter(['file1','file2','file3'], fs.exists, function(results){
341 - // results now equals an array of the existing files
342 -});
343 -```
344 -
345 ----------------------------------------
346 -
347 -<a name="filterSeries" />
348 -### filterSeries(arr, iterator, callback)
349 -
350 -__alias:__ selectSeries
351 -
352 -The same as filter only the iterator is applied to each item in the array in
353 -series. The next iterator is only called once the current one has completed
354 -processing. The results array will be in the same order as the original.
355 -
356 ----------------------------------------
357 -
358 -<a name="reject" />
359 -### reject(arr, iterator, callback)
360 -
361 -The opposite of filter. Removes values that pass an async truth test.
362 -
363 ----------------------------------------
364 -
365 -<a name="rejectSeries" />
366 -### rejectSeries(arr, iterator, callback)
367 -
368 -The same as reject, only the iterator is applied to each item in the array
369 -in series.
370 -
371 -
372 ----------------------------------------
373 -
374 -<a name="reduce" />
375 -### reduce(arr, memo, iterator, callback)
376 -
377 -__aliases:__ inject, foldl
378 -
379 -Reduces a list of values into a single value using an async iterator to return
380 -each successive step. Memo is the initial state of the reduction. This
381 -function only operates in series. For performance reasons, it may make sense to
382 -split a call to this function into a parallel map, then use the normal
383 -Array.prototype.reduce on the results. This function is for situations where
384 -each step in the reduction needs to be async, if you can get the data before
385 -reducing it then it's probably a good idea to do so.
386 -
387 -__Arguments__
388 -
389 -* arr - An array to iterate over.
390 -* memo - The initial state of the reduction.
391 -* iterator(memo, item, callback) - A function applied to each item in the
392 - array to produce the next step in the reduction. The iterator is passed a
393 - callback(err, reduction) which accepts an optional error as its first
394 - argument, and the state of the reduction as the second. If an error is
395 - passed to the callback, the reduction is stopped and the main callback is
396 - immediately called with the error.
397 -* callback(err, result) - A callback which is called after all the iterator
398 - functions have finished. Result is the reduced value.
399 -
400 -__Example__
401 -
402 -```js
403 -async.reduce([1,2,3], 0, function(memo, item, callback){
404 - // pointless async:
405 - process.nextTick(function(){
406 - callback(null, memo + item)
407 - });
408 -}, function(err, result){
409 - // result is now equal to the last value of memo, which is 6
410 -});
411 -```
412 -
413 ----------------------------------------
414 -
415 -<a name="reduceRight" />
416 -### reduceRight(arr, memo, iterator, callback)
417 -
418 -__Alias:__ foldr
419 -
420 -Same as reduce, only operates on the items in the array in reverse order.
421 -
422 -
423 ----------------------------------------
424 -
425 -<a name="detect" />
426 -### detect(arr, iterator, callback)
427 -
428 -Returns the first value in a list that passes an async truth test. The
429 -iterator is applied in parallel, meaning the first iterator to return true will
430 -fire the detect callback with that result. That means the result might not be
431 -the first item in the original array (in terms of order) that passes the test.
432 -
433 -If order within the original array is important then look at detectSeries.
434 -
435 -__Arguments__
436 -
437 -* arr - An array to iterate over.
438 -* iterator(item, callback) - A truth test to apply to each item in the array.
439 - The iterator is passed a callback(truthValue) which must be called with a
440 - boolean argument once it has completed.
441 -* callback(result) - A callback which is called as soon as any iterator returns
442 - true, or after all the iterator functions have finished. Result will be
443 - the first item in the array that passes the truth test (iterator) or the
444 - value undefined if none passed.
445 -
446 -__Example__
447 -
448 -```js
449 -async.detect(['file1','file2','file3'], fs.exists, function(result){
450 - // result now equals the first file in the list that exists
451 -});
452 -```
453 -
454 ----------------------------------------
455 -
456 -<a name="detectSeries" />
457 -### detectSeries(arr, iterator, callback)
458 -
459 -The same as detect, only the iterator is applied to each item in the array
460 -in series. This means the result is always the first in the original array (in
461 -terms of array order) that passes the truth test.
462 -
463 -
464 ----------------------------------------
465 -
466 -<a name="sortBy" />
467 -### sortBy(arr, iterator, callback)
468 -
469 -Sorts a list by the results of running each value through an async iterator.
470 -
471 -__Arguments__
472 -
473 -* arr - An array to iterate over.
474 -* iterator(item, callback) - A function to apply to each item in the array.
475 - The iterator is passed a callback(err, sortValue) which must be called once it
476 - has completed with an error (which can be null) and a value to use as the sort
477 - criteria.
478 -* callback(err, results) - A callback which is called after all the iterator
479 - functions have finished, or an error has occurred. Results is the items from
480 - the original array sorted by the values returned by the iterator calls.
481 -
482 -__Example__
483 -
484 -```js
485 -async.sortBy(['file1','file2','file3'], function(file, callback){
486 - fs.stat(file, function(err, stats){
487 - callback(err, stats.mtime);
488 - });
489 -}, function(err, results){
490 - // results is now the original array of files sorted by
491 - // modified date
492 -});
493 -```
494 -
495 ----------------------------------------
496 -
497 -<a name="some" />
498 -### some(arr, iterator, callback)
499 -
500 -__Alias:__ any
501 -
502 -Returns true if at least one element in the array satisfies an async test.
503 -_The callback for each iterator call only accepts a single argument of true or
504 -false, it does not accept an error argument first!_ This is in-line with the
505 -way node libraries work with truth tests like fs.exists. Once any iterator
506 -call returns true, the main callback is immediately called.
507 -
508 -__Arguments__
509 -
510 -* arr - An array to iterate over.
511 -* iterator(item, callback) - A truth test to apply to each item in the array.
512 - The iterator is passed a callback(truthValue) which must be called with a
513 - boolean argument once it has completed.
514 -* callback(result) - A callback which is called as soon as any iterator returns
515 - true, or after all the iterator functions have finished. Result will be
516 - either true or false depending on the values of the async tests.
517 -
518 -__Example__
519 -
520 -```js
521 -async.some(['file1','file2','file3'], fs.exists, function(result){
522 - // if result is true then at least one of the files exists
523 -});
524 -```
525 -
526 ----------------------------------------
527 -
528 -<a name="every" />
529 -### every(arr, iterator, callback)
530 -
531 -__Alias:__ all
532 -
533 -Returns true if every element in the array satisfies an async test.
534 -_The callback for each iterator call only accepts a single argument of true or
535 -false, it does not accept an error argument first!_ This is in-line with the
536 -way node libraries work with truth tests like fs.exists.
537 -
538 -__Arguments__
539 -
540 -* arr - An array to iterate over.
541 -* iterator(item, callback) - A truth test to apply to each item in the array.
542 - The iterator is passed a callback(truthValue) which must be called with a
543 - boolean argument once it has completed.
544 -* callback(result) - A callback which is called after all the iterator
545 - functions have finished. Result will be either true or false depending on
546 - the values of the async tests.
547 -
548 -__Example__
549 -
550 -```js
551 -async.every(['file1','file2','file3'], fs.exists, function(result){
552 - // if result is true then every file exists
553 -});
554 -```
555 -
556 ----------------------------------------
557 -
558 -<a name="concat" />
559 -### concat(arr, iterator, callback)
560 -
561 -Applies an iterator to each item in a list, concatenating the results. Returns the
562 -concatenated list. The iterators are called in parallel, and the results are
563 -concatenated as they return. There is no guarantee that the results array will
564 -be returned in the original order of the arguments passed to the iterator function.
565 -
566 -__Arguments__
567 -
568 -* arr - An array to iterate over
569 -* iterator(item, callback) - A function to apply to each item in the array.
570 - The iterator is passed a callback(err, results) which must be called once it
571 - has completed with an error (which can be null) and an array of results.
572 -* callback(err, results) - A callback which is called after all the iterator
573 - functions have finished, or an error has occurred. Results is an array containing
574 - the concatenated results of the iterator function.
575 -
576 -__Example__
577 -
578 -```js
579 -async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
580 - // files is now a list of filenames that exist in the 3 directories
581 -});
582 -```
583 -
584 ----------------------------------------
585 -
586 -<a name="concatSeries" />
587 -### concatSeries(arr, iterator, callback)
588 -
589 -Same as async.concat, but executes in series instead of parallel.
590 -
591 -
592 -## Control Flow
593 -
594 -<a name="series" />
595 -### series(tasks, [callback])
596 -
597 -Run an array of functions in series, each one running once the previous
598 -function has completed. If any functions in the series pass an error to its
599 -callback, no more functions are run and the callback for the series is
600 -immediately called with the value of the error. Once the tasks have completed,
601 -the results are passed to the final callback as an array.
602 -
603 -It is also possible to use an object instead of an array. Each property will be
604 -run as a function and the results will be passed to the final callback as an object
605 -instead of an array. This can be a more readable way of handling results from
606 -async.series.
607 -
608 -
609 -__Arguments__
610 -
611 -* tasks - An array or object containing functions to run, each function is passed
612 - a callback(err, result) it must call on completion with an error (which can
613 - be null) and an optional result value.
614 -* callback(err, results) - An optional callback to run once all the functions
615 - have completed. This function gets a results array (or object) containing all
616 - the result arguments passed to the task callbacks.
617 -
618 -__Example__
619 -
620 -```js
621 -async.series([
622 - function(callback){
623 - // do some stuff ...
624 - callback(null, 'one');
625 - },
626 - function(callback){
627 - // do some more stuff ...
628 - callback(null, 'two');
629 - }
630 -],
631 -// optional callback
632 -function(err, results){
633 - // results is now equal to ['one', 'two']
634 -});
635 -
636 -
637 -// an example using an object instead of an array
638 -async.series({
639 - one: function(callback){
640 - setTimeout(function(){
641 - callback(null, 1);
642 - }, 200);
643 - },
644 - two: function(callback){
645 - setTimeout(function(){
646 - callback(null, 2);
647 - }, 100);
648 - }
649 -},
650 -function(err, results) {
651 - // results is now equal to: {one: 1, two: 2}
652 -});
653 -```
654 -
655 ----------------------------------------
656 -
657 -<a name="parallel" />
658 -### parallel(tasks, [callback])
659 -
660 -Run an array of functions in parallel, without waiting until the previous
661 -function has completed. If any of the functions pass an error to its
662 -callback, the main callback is immediately called with the value of the error.
663 -Once the tasks have completed, the results are passed to the final callback as an
664 -array.
665 -
666 -It is also possible to use an object instead of an array. Each property will be
667 -run as a function and the results will be passed to the final callback as an object
668 -instead of an array. This can be a more readable way of handling results from
669 -async.parallel.
670 -
671 -
672 -__Arguments__
673 -
674 -* tasks - An array or object containing functions to run, each function is passed
675 - a callback(err, result) it must call on completion with an error (which can
676 - be null) and an optional result value.
677 -* callback(err, results) - An optional callback to run once all the functions
678 - have completed. This function gets a results array (or object) containing all
679 - the result arguments passed to the task callbacks.
680 -
681 -__Example__
682 -
683 -```js
684 -async.parallel([
685 - function(callback){
686 - setTimeout(function(){
687 - callback(null, 'one');
688 - }, 200);
689 - },
690 - function(callback){
691 - setTimeout(function(){
692 - callback(null, 'two');
693 - }, 100);
694 - }
695 -],
696 -// optional callback
697 -function(err, results){
698 - // the results array will equal ['one','two'] even though
699 - // the second function had a shorter timeout.
700 -});
701 -
702 -
703 -// an example using an object instead of an array
704 -async.parallel({
705 - one: function(callback){
706 - setTimeout(function(){
707 - callback(null, 1);
708 - }, 200);
709 - },
710 - two: function(callback){
711 - setTimeout(function(){
712 - callback(null, 2);
713 - }, 100);
714 - }
715 -},
716 -function(err, results) {
717 - // results is now equals to: {one: 1, two: 2}
718 -});
719 -```
720 -
721 ----------------------------------------
722 -
723 -<a name="parallel" />
724 -### parallelLimit(tasks, limit, [callback])
725 -
726 -The same as parallel only the tasks are executed in parallel with a maximum of "limit"
727 -tasks executing at any time.
728 -
729 -Note that the tasks are not executed in batches, so there is no guarantee that
730 -the first "limit" tasks will complete before any others are started.
731 -
732 -__Arguments__
733 -
734 -* tasks - An array or object containing functions to run, each function is passed
735 - a callback(err, result) it must call on completion with an error (which can
736 - be null) and an optional result value.
737 -* limit - The maximum number of tasks to run at any time.
738 -* callback(err, results) - An optional callback to run once all the functions
739 - have completed. This function gets a results array (or object) containing all
740 - the result arguments passed to the task callbacks.
741 -
742 ----------------------------------------
743 -
744 -<a name="whilst" />
745 -### whilst(test, fn, callback)
746 -
747 -Repeatedly call fn, while test returns true. Calls the callback when stopped,
748 -or an error occurs.
749 -
750 -__Arguments__
751 -
752 -* test() - synchronous truth test to perform before each execution of fn.
753 -* fn(callback) - A function to call each time the test passes. The function is
754 - passed a callback(err) which must be called once it has completed with an
755 - optional error argument.
756 -* callback(err) - A callback which is called after the test fails and repeated
757 - execution of fn has stopped.
758 -
759 -__Example__
760 -
761 -```js
762 -var count = 0;
763 -
764 -async.whilst(
765 - function () { return count < 5; },
766 - function (callback) {
767 - count++;
768 - setTimeout(callback, 1000);
769 - },
770 - function (err) {
771 - // 5 seconds have passed
772 - }
773 -);
774 -```
775 -
776 ----------------------------------------
777 -
778 -<a name="doWhilst" />
779 -### doWhilst(fn, test, callback)
780 -
781 -The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
782 -
783 ----------------------------------------
784 -
785 -<a name="until" />
786 -### until(test, fn, callback)
787 -
788 -Repeatedly call fn, until test returns true. Calls the callback when stopped,
789 -or an error occurs.
790 -
791 -The inverse of async.whilst.
792 -
793 ----------------------------------------
794 -
795 -<a name="doUntil" />
796 -### doUntil(fn, test, callback)
797 -
798 -Like doWhilst except the test is inverted. Note the argument ordering differs from `until`.
799 -
800 ----------------------------------------
801 -
802 -<a name="forever" />
803 -### forever(fn, callback)
804 -
805 -Calls the asynchronous function 'fn' repeatedly, in series, indefinitely.
806 -If an error is passed to fn's callback then 'callback' is called with the
807 -error, otherwise it will never be called.
808 -
809 ----------------------------------------
810 -
811 -<a name="waterfall" />
812 -### waterfall(tasks, [callback])
813 -
814 -Runs an array of functions in series, each passing their results to the next in
815 -the array. However, if any of the functions pass an error to the callback, the
816 -next function is not executed and the main callback is immediately called with
817 -the error.
818 -
819 -__Arguments__
820 -
821 -* tasks - An array of functions to run, each function is passed a
822 - callback(err, result1, result2, ...) it must call on completion. The first
823 - argument is an error (which can be null) and any further arguments will be
824 - passed as arguments in order to the next task.
825 -* callback(err, [results]) - An optional callback to run once all the functions
826 - have completed. This will be passed the results of the last task's callback.
827 -
828 -
829 -
830 -__Example__
831 -
832 -```js
833 -async.waterfall([
834 - function(callback){
835 - callback(null, 'one', 'two');
836 - },
837 - function(arg1, arg2, callback){
838 - callback(null, 'three');
839 - },
840 - function(arg1, callback){
841 - // arg1 now equals 'three'
842 - callback(null, 'done');
843 - }
844 -], function (err, result) {
845 - // result now equals 'done'
846 -});
847 -```
848 -
849 ----------------------------------------
850 -<a name="compose" />
851 -### compose(fn1, fn2...)
852 -
853 -Creates a function which is a composition of the passed asynchronous
854 -functions. Each function consumes the return value of the function that
855 -follows. Composing functions f(), g() and h() would produce the result of
856 -f(g(h())), only this version uses callbacks to obtain the return values.
857 -
858 -Each function is executed with the `this` binding of the composed function.
859 -
860 -__Arguments__
861 -
862 -* functions... - the asynchronous functions to compose
863 -
864 -
865 -__Example__
866 -
867 -```js
868 -function add1(n, callback) {
869 - setTimeout(function () {
870 - callback(null, n + 1);
871 - }, 10);
872 -}
873 -
874 -function mul3(n, callback) {
875 - setTimeout(function () {
876 - callback(null, n * 3);
877 - }, 10);
878 -}
879 -
880 -var add1mul3 = async.compose(mul3, add1);
881 -
882 -add1mul3(4, function (err, result) {
883 - // result now equals 15
884 -});
885 -```
886 -
887 ----------------------------------------
888 -<a name="applyEach" />
889 -### applyEach(fns, args..., callback)
890 -
891 -Applies the provided arguments to each function in the array, calling the
892 -callback after all functions have completed. If you only provide the first
893 -argument then it will return a function which lets you pass in the
894 -arguments as if it were a single function call.
895 -
896 -__Arguments__
897 -
898 -* fns - the asynchronous functions to all call with the same arguments
899 -* args... - any number of separate arguments to pass to the function
900 -* callback - the final argument should be the callback, called when all
901 - functions have completed processing
902 -
903 -
904 -__Example__
905 -
906 -```js
907 -async.applyEach([enableSearch, updateSchema], 'bucket', callback);
908 -
909 -// partial application example:
910 -async.each(
911 - buckets,
912 - async.applyEach([enableSearch, updateSchema]),
913 - callback
914 -);
915 -```
916 -
917 ----------------------------------------
918 -
919 -<a name="applyEachSeries" />
920 -### applyEachSeries(arr, iterator, callback)
921 -
922 -The same as applyEach only the functions are applied in series.
923 -
924 ----------------------------------------
925 -
926 -<a name="queue" />
927 -### queue(worker, concurrency)
928 -
929 -Creates a queue object with the specified concurrency. Tasks added to the
930 -queue will be processed in parallel (up to the concurrency limit). If all
931 -workers are in progress, the task is queued until one is available. Once
932 -a worker has completed a task, the task's callback is called.
933 -
934 -__Arguments__
935 -
936 -* worker(task, callback) - An asynchronous function for processing a queued
937 - task, which must call its callback(err) argument when finished, with an
938 - optional error as an argument.
939 -* concurrency - An integer for determining how many worker functions should be
940 - run in parallel.
941 -
942 -__Queue objects__
943 -
944 -The queue object returned by this function has the following properties and
945 -methods:
946 -
947 -* length() - a function returning the number of items waiting to be processed.
948 -* concurrency - an integer for determining how many worker functions should be
949 - run in parallel. This property can be changed after a queue is created to
950 - alter the concurrency on-the-fly.
951 -* push(task, [callback]) - add a new task to the queue, the callback is called
952 - once the worker has finished processing the task.
953 - instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
954 -* unshift(task, [callback]) - add a new task to the front of the queue.
955 -* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
956 -* empty - a callback that is called when the last item from the queue is given to a worker
957 -* drain - a callback that is called when the last item from the queue has returned from the worker
958 -
959 -__Example__
960 -
961 -```js
962 -// create a queue object with concurrency 2
963 -
964 -var q = async.queue(function (task, callback) {
965 - console.log('hello ' + task.name);
966 - callback();
967 -}, 2);
968 -
969 -
970 -// assign a callback
971 -q.drain = function() {
972 - console.log('all items have been processed');
973 -}
974 -
975 -// add some items to the queue
976 -
977 -q.push({name: 'foo'}, function (err) {
978 - console.log('finished processing foo');
979 -});
980 -q.push({name: 'bar'}, function (err) {
981 - console.log('finished processing bar');
982 -});
983 -
984 -// add some items to the queue (batch-wise)
985 -
986 -q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
987 - console.log('finished processing bar');
988 -});
989 -
990 -// add some items to the front of the queue
991 -
992 -q.unshift({name: 'bar'}, function (err) {
993 - console.log('finished processing bar');
994 -});
995 -```
996 -
997 ----------------------------------------
998 -
999 -<a name="cargo" />
1000 -### cargo(worker, [payload])
1001 -
1002 -Creates a cargo object with the specified payload. Tasks added to the
1003 -cargo will be processed altogether (up to the payload limit). If the
1004 -worker is in progress, the task is queued until it is available. Once
1005 -the worker has completed some tasks, each callback of those tasks is called.
1006 -
1007 -__Arguments__
1008 -
1009 -* worker(tasks, callback) - An asynchronous function for processing an array of
1010 - queued tasks, which must call its callback(err) argument when finished, with
1011 - an optional error as an argument.
1012 -* payload - An optional integer for determining how many tasks should be
1013 - processed per round; if omitted, the default is unlimited.
1014 -
1015 -__Cargo objects__
1016 -
1017 -The cargo object returned by this function has the following properties and
1018 -methods:
1019 -
1020 -* length() - a function returning the number of items waiting to be processed.
1021 -* payload - an integer for determining how many tasks should be
1022 - process per round. This property can be changed after a cargo is created to
1023 - alter the payload on-the-fly.
1024 -* push(task, [callback]) - add a new task to the queue, the callback is called
1025 - once the worker has finished processing the task.
1026 - instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
1027 -* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
1028 -* empty - a callback that is called when the last item from the queue is given to a worker
1029 -* drain - a callback that is called when the last item from the queue has returned from the worker
1030 -
1031 -__Example__
1032 -
1033 -```js
1034 -// create a cargo object with payload 2
1035 -
1036 -var cargo = async.cargo(function (tasks, callback) {
1037 - for(var i=0; i<tasks.length; i++){
1038 - console.log('hello ' + tasks[i].name);
1039 - }
1040 - callback();
1041 -}, 2);
1042 -
1043 -
1044 -// add some items
1045 -
1046 -cargo.push({name: 'foo'}, function (err) {
1047 - console.log('finished processing foo');
1048 -});
1049 -cargo.push({name: 'bar'}, function (err) {
1050 - console.log('finished processing bar');
1051 -});
1052 -cargo.push({name: 'baz'}, function (err) {
1053 - console.log('finished processing baz');
1054 -});
1055 -```
1056 -
1057 ----------------------------------------
1058 -
1059 -<a name="auto" />
1060 -### auto(tasks, [callback])
1061 -
1062 -Determines the best order for running functions based on their requirements.
1063 -Each function can optionally depend on other functions being completed first,
1064 -and each function is run as soon as its requirements are satisfied. If any of
1065 -the functions pass an error to their callback, that function will not complete
1066 -(so any other functions depending on it will not run) and the main callback
1067 -will be called immediately with the error. Functions also receive an object
1068 -containing the results of functions which have completed so far.
1069 -
1070 -Note, all functions are called with a results object as a second argument,
1071 -so it is unsafe to pass functions in the tasks object which cannot handle the
1072 -extra argument. For example, this snippet of code:
1073 -
1074 -```js
1075 -async.auto({
1076 - readData: async.apply(fs.readFile, 'data.txt', 'utf-8')
1077 -}, callback);
1078 -```
1079 -
1080 -will have the effect of calling readFile with the results object as the last
1081 -argument, which will fail:
1082 -
1083 -```js
1084 -fs.readFile('data.txt', 'utf-8', cb, {});
1085 -```
1086 -
1087 -Instead, wrap the call to readFile in a function which does not forward the
1088 -results object:
1089 -
1090 -```js
1091 -async.auto({
1092 - readData: function(cb, results){
1093 - fs.readFile('data.txt', 'utf-8', cb);
1094 - }
1095 -}, callback);
1096 -```
1097 -
1098 -__Arguments__
1099 -
1100 -* tasks - An object literal containing named functions or an array of
1101 - requirements, with the function itself the last item in the array. The key
1102 - used for each function or array is used when specifying requirements. The
1103 - function receives two arguments: (1) a callback(err, result) which must be
1104 - called when finished, passing an error (which can be null) and the result of
1105 - the function's execution, and (2) a results object, containing the results of
1106 - the previously executed functions.
1107 -* callback(err, results) - An optional callback which is called when all the
1108 - tasks have been completed. The callback will receive an error as an argument
1109 - if any tasks pass an error to their callback. Results will always be passed
1110 - but if an error occurred, no other tasks will be performed, and the results
1111 - object will only contain partial results.
1112 -
1113 -
1114 -__Example__
1115 -
1116 -```js
1117 -async.auto({
1118 - get_data: function(callback){
1119 - // async code to get some data
1120 - },
1121 - make_folder: function(callback){
1122 - // async code to create a directory to store a file in
1123 - // this is run at the same time as getting the data
1124 - },
1125 - write_file: ['get_data', 'make_folder', function(callback){
1126 - // once there is some data and the directory exists,
1127 - // write the data to a file in the directory
1128 - callback(null, filename);
1129 - }],
1130 - email_link: ['write_file', function(callback, results){
1131 - // once the file is written let's email a link to it...
1132 - // results.write_file contains the filename returned by write_file.
1133 - }]
1134 -});
1135 -```
1136 -
1137 -This is a fairly trivial example, but to do this using the basic parallel and
1138 -series functions would look like this:
1139 -
1140 -```js
1141 -async.parallel([
1142 - function(callback){
1143 - // async code to get some data
1144 - },
1145 - function(callback){
1146 - // async code to create a directory to store a file in
1147 - // this is run at the same time as getting the data
1148 - }
1149 -],
1150 -function(err, results){
1151 - async.series([
1152 - function(callback){
1153 - // once there is some data and the directory exists,
1154 - // write the data to a file in the directory
1155 - },
1156 - function(callback){
1157 - // once the file is written let's email a link to it...
1158 - }
1159 - ]);
1160 -});
1161 -```
1162 -
1163 -For a complicated series of async tasks using the auto function makes adding
1164 -new tasks much easier and makes the code more readable.
1165 -
1166 -
1167 ----------------------------------------
1168 -
1169 -<a name="iterator" />
1170 -### iterator(tasks)
1171 -
1172 -Creates an iterator function which calls the next function in the array,
1173 -returning a continuation to call the next one after that. It's also possible to
1174 -'peek' the next iterator by doing iterator.next().
1175 -
1176 -This function is used internally by the async module but can be useful when
1177 -you want to manually control the flow of functions in series.
1178 -
1179 -__Arguments__
1180 -
1181 -* tasks - An array of functions to run.
1182 -
1183 -__Example__
1184 -
1185 -```js
1186 -var iterator = async.iterator([
1187 - function(){ sys.p('one'); },
1188 - function(){ sys.p('two'); },
1189 - function(){ sys.p('three'); }
1190 -]);
1191 -
1192 -node> var iterator2 = iterator();
1193 -'one'
1194 -node> var iterator3 = iterator2();
1195 -'two'
1196 -node> iterator3();
1197 -'three'
1198 -node> var nextfn = iterator2.next();
1199 -node> nextfn();
1200 -'three'
1201 -```
1202 -
1203 ----------------------------------------
1204 -
1205 -<a name="apply" />
1206 -### apply(function, arguments..)
1207 -
1208 -Creates a continuation function with some arguments already applied, a useful
1209 -shorthand when combined with other control flow functions. Any arguments
1210 -passed to the returned function are added to the arguments originally passed
1211 -to apply.
1212 -
1213 -__Arguments__
1214 -
1215 -* function - The function you want to eventually apply all arguments to.
1216 -* arguments... - Any number of arguments to automatically apply when the
1217 - continuation is called.
1218 -
1219 -__Example__
1220 -
1221 -```js
1222 -// using apply
1223 -
1224 -async.parallel([
1225 - async.apply(fs.writeFile, 'testfile1', 'test1'),
1226 - async.apply(fs.writeFile, 'testfile2', 'test2'),
1227 -]);
1228 -
1229 -
1230 -// the same process without using apply
1231 -
1232 -async.parallel([
1233 - function(callback){
1234 - fs.writeFile('testfile1', 'test1', callback);
1235 - },
1236 - function(callback){
1237 - fs.writeFile('testfile2', 'test2', callback);
1238 - }
1239 -]);
1240 -```
1241 -
1242 -It's possible to pass any number of additional arguments when calling the
1243 -continuation:
1244 -
1245 -```js
1246 -node> var fn = async.apply(sys.puts, 'one');
1247 -node> fn('two', 'three');
1248 -one
1249 -two
1250 -three
1251 -```
1252 -
1253 ----------------------------------------
1254 -
1255 -<a name="nextTick" />
1256 -### nextTick(callback)
1257 -
1258 -Calls the callback on a later loop around the event loop. In node.js this just
1259 -calls process.nextTick, in the browser it falls back to setImmediate(callback)
1260 -if available, otherwise setTimeout(callback, 0), which means other higher priority
1261 -events may precede the execution of the callback.
1262 -
1263 -This is used internally for browser-compatibility purposes.
1264 -
1265 -__Arguments__
1266 -
1267 -* callback - The function to call on a later loop around the event loop.
1268 -
1269 -__Example__
1270 -
1271 -```js
1272 -var call_order = [];
1273 -async.nextTick(function(){
1274 - call_order.push('two');
1275 - // call_order now equals ['one','two']
1276 -});
1277 -call_order.push('one')
1278 -```
1279 -
1280 -<a name="times" />
1281 -### times(n, callback)
1282 -
1283 -Calls the callback n times and accumulates results in the same manner
1284 -you would use with async.map.
1285 -
1286 -__Arguments__
1287 -
1288 -* n - The number of times to run the function.
1289 -* callback - The function to call n times.
1290 -
1291 -__Example__
1292 -
1293 -```js
1294 -// Pretend this is some complicated async factory
1295 -var createUser = function(id, callback) {
1296 - callback(null, {
1297 - id: 'user' + id
1298 - })
1299 -}
1300 -// generate 5 users
1301 -async.times(5, function(n, next){
1302 - createUser(n, function(err, user) {
1303 - next(err, user)
1304 - })
1305 -}, function(err, users) {
1306 - // we should now have 5 users
1307 -});
1308 -```
1309 -
1310 -<a name="timesSeries" />
1311 -### timesSeries(n, callback)
1312 -
1313 -The same as times only the iterator is applied to each item in the array in
1314 -series. The next iterator is only called once the current one has completed
1315 -processing. The results array will be in the same order as the original.
1316 -
1317 -
1318 -## Utils
1319 -
1320 -<a name="memoize" />
1321 -### memoize(fn, [hasher])
1322 -
1323 -Caches the results of an async function. When creating a hash to store function
1324 -results against, the callback is omitted from the hash and an optional hash
1325 -function can be used.
1326 -
1327 -The cache of results is exposed as the `memo` property of the function returned
1328 -by `memoize`.
1329 -
1330 -__Arguments__
1331 -
1332 -* fn - the function you to proxy and cache results from.
1333 -* hasher - an optional function for generating a custom hash for storing
1334 - results, it has all the arguments applied to it apart from the callback, and
1335 - must be synchronous.
1336 -
1337 -__Example__
1338 -
1339 -```js
1340 -var slow_fn = function (name, callback) {
1341 - // do something
1342 - callback(null, result);
1343 -};
1344 -var fn = async.memoize(slow_fn);
1345 -
1346 -// fn can now be used as if it were slow_fn
1347 -fn('some name', function () {
1348 - // callback
1349 -});
1350 -```
1351 -
1352 -<a name="unmemoize" />
1353 -### unmemoize(fn)
1354 -
1355 -Undoes a memoized function, reverting it to the original, unmemoized
1356 -form. Comes handy in tests.
1357 -
1358 -__Arguments__
1359 -
1360 -* fn - the memoized function
1361 -
1362 -<a name="log" />
1363 -### log(function, arguments)
1364 -
1365 -Logs the result of an async function to the console. Only works in node.js or
1366 -in browsers that support console.log and console.error (such as FF and Chrome).
1367 -If multiple arguments are returned from the async function, console.log is
1368 -called on each argument in order.
1369 -
1370 -__Arguments__
1371 -
1372 -* function - The function you want to eventually apply all arguments to.
1373 -* arguments... - Any number of arguments to apply to the function.
1374 -
1375 -__Example__
1376 -
1377 -```js
1378 -var hello = function(name, callback){
1379 - setTimeout(function(){
1380 - callback(null, 'hello ' + name);
1381 - }, 1000);
1382 -};
1383 -```
1384 -```js
1385 -node> async.log(hello, 'world');
1386 -'hello world'
1387 -```
1388 -
1389 ----------------------------------------
1390 -
1391 -<a name="dir" />
1392 -### dir(function, arguments)
1393 -
1394 -Logs the result of an async function to the console using console.dir to
1395 -display the properties of the resulting object. Only works in node.js or
1396 -in browsers that support console.dir and console.error (such as FF and Chrome).
1397 -If multiple arguments are returned from the async function, console.dir is
1398 -called on each argument in order.
1399 -
1400 -__Arguments__
1401 -
1402 -* function - The function you want to eventually apply all arguments to.
1403 -* arguments... - Any number of arguments to apply to the function.
1404 -
1405 -__Example__
1406 -
1407 -```js
1408 -var hello = function(name, callback){
1409 - setTimeout(function(){
1410 - callback(null, {hello: name});
1411 - }, 1000);
1412 -};
1413 -```
1414 -```js
1415 -node> async.dir(hello, 'world');
1416 -{hello: 'world'}
1417 -```
1418 -
1419 ----------------------------------------
1420 -
1421 -<a name="noConflict" />
1422 -### noConflict()
1423 -
1424 -Changes the value of async back to its original value, returning a reference to the
1425 -async object.
1 -{
2 - "name": "async",
3 - "repo": "caolan/async",
4 - "description": "Higher-order functions and common patterns for asynchronous code",
5 - "version": "0.1.23",
6 - "keywords": [],
7 - "dependencies": {},
8 - "development": {},
9 - "main": "lib/async.js",
10 - "scripts": [ "lib/async.js" ]
11 -}
1 -/*global setImmediate: false, setTimeout: false, console: false */
2 -(function () {
3 -
4 - var async = {};
5 -
6 - // global on the server, window in the browser
7 - var root, previous_async;
8 -
9 - root = this;
10 - if (root != null) {
11 - previous_async = root.async;
12 - }
13 -
14 - async.noConflict = function () {
15 - root.async = previous_async;
16 - return async;
17 - };
18 -
19 - function only_once(fn) {
20 - var called = false;
21 - return function() {
22 - if (called) throw new Error("Callback was already called.");
23 - called = true;
24 - fn.apply(root, arguments);
25 - }
26 - }
27 -
28 - //// cross-browser compatiblity functions ////
29 -
30 - var _each = function (arr, iterator) {
31 - if (arr.forEach) {
32 - return arr.forEach(iterator);
33 - }
34 - for (var i = 0; i < arr.length; i += 1) {
35 - iterator(arr[i], i, arr);
36 - }
37 - };
38 -
39 - var _map = function (arr, iterator) {
40 - if (arr.map) {
41 - return arr.map(iterator);
42 - }
43 - var results = [];
44 - _each(arr, function (x, i, a) {
45 - results.push(iterator(x, i, a));
46 - });
47 - return results;
48 - };
49 -
50 - var _reduce = function (arr, iterator, memo) {
51 - if (arr.reduce) {
52 - return arr.reduce(iterator, memo);
53 - }
54 - _each(arr, function (x, i, a) {
55 - memo = iterator(memo, x, i, a);
56 - });
57 - return memo;
58 - };
59 -
60 - var _keys = function (obj) {
61 - if (Object.keys) {
62 - return Object.keys(obj);
63 - }
64 - var keys = [];
65 - for (var k in obj) {
66 - if (obj.hasOwnProperty(k)) {
67 - keys.push(k);
68 - }
69 - }
70 - return keys;
71 - };
72 -
73 - //// exported async module functions ////
74 -
75 - //// nextTick implementation with browser-compatible fallback ////
76 - if (typeof process === 'undefined' || !(process.nextTick)) {
77 - if (typeof setImmediate === 'function') {
78 - async.nextTick = function (fn) {
79 - // not a direct alias for IE10 compatibility
80 - setImmediate(fn);
81 - };
82 - async.setImmediate = async.nextTick;
83 - }
84 - else {
85 - async.nextTick = function (fn) {
86 - setTimeout(fn, 0);
87 - };
88 - async.setImmediate = async.nextTick;
89 - }
90 - }
91 - else {
92 - async.nextTick = process.nextTick;
93 - if (typeof setImmediate !== 'undefined') {
94 - async.setImmediate = function (fn) {
95 - // not a direct alias for IE10 compatibility
96 - setImmediate(fn);
97 - };
98 - }
99 - else {
100 - async.setImmediate = async.nextTick;
101 - }
102 - }
103 -
104 - async.each = function (arr, iterator, callback) {
105 - callback = callback || function () {};
106 - if (!arr.length) {
107 - return callback();
108 - }
109 - var completed = 0;
110 - _each(arr, function (x) {
111 - iterator(x, only_once(function (err) {
112 - if (err) {
113 - callback(err);
114 - callback = function () {};
115 - }
116 - else {
117 - completed += 1;
118 - if (completed >= arr.length) {
119 - callback(null);
120 - }
121 - }
122 - }));
123 - });
124 - };
125 - async.forEach = async.each;
126 -
127 - async.eachSeries = function (arr, iterator, callback) {
128 - callback = callback || function () {};
129 - if (!arr.length) {
130 - return callback();
131 - }
132 - var completed = 0;
133 - var iterate = function () {
134 - iterator(arr[completed], function (err) {
135 - if (err) {
136 - callback(err);
137 - callback = function () {};
138 - }
139 - else {
140 - completed += 1;
141 - if (completed >= arr.length) {
142 - callback(null);
143 - }
144 - else {
145 - iterate();
146 - }
147 - }
148 - });
149 - };
150 - iterate();
151 - };
152 - async.forEachSeries = async.eachSeries;
153 -
154 - async.eachLimit = function (arr, limit, iterator, callback) {
155 - var fn = _eachLimit(limit);
156 - fn.apply(null, [arr, iterator, callback]);
157 - };
158 - async.forEachLimit = async.eachLimit;
159 -
160 - var _eachLimit = function (limit) {
161 -
162 - return function (arr, iterator, callback) {
163 - callback = callback || function () {};
164 - if (!arr.length || limit <= 0) {
165 - return callback();
166 - }
167 - var completed = 0;
168 - var started = 0;
169 - var running = 0;
170 -
171 - (function replenish () {
172 - if (completed >= arr.length) {
173 - return callback();
174 - }
175 -
176 - while (running < limit && started < arr.length) {
177 - started += 1;
178 - running += 1;
179 - iterator(arr[started - 1], function (err) {
180 - if (err) {
181 - callback(err);
182 - callback = function () {};
183 - }
184 - else {
185 - completed += 1;
186 - running -= 1;
187 - if (completed >= arr.length) {
188 - callback();
189 - }
190 - else {
191 - replenish();
192 - }
193 - }
194 - });
195 - }
196 - })();
197 - };
198 - };
199 -
200 -
201 - var doParallel = function (fn) {
202 - return function () {
203 - var args = Array.prototype.slice.call(arguments);
204 - return fn.apply(null, [async.each].concat(args));
205 - };
206 - };
207 - var doParallelLimit = function(limit, fn) {
208 - return function () {
209 - var args = Array.prototype.slice.call(arguments);
210 - return fn.apply(null, [_eachLimit(limit)].concat(args));
211 - };
212 - };
213 - var doSeries = function (fn) {
214 - return function () {
215 - var args = Array.prototype.slice.call(arguments);
216 - return fn.apply(null, [async.eachSeries].concat(args));
217 - };
218 - };
219 -
220 -
221 - var _asyncMap = function (eachfn, arr, iterator, callback) {
222 - var results = [];
223 - arr = _map(arr, function (x, i) {
224 - return {index: i, value: x};
225 - });
226 - eachfn(arr, function (x, callback) {
227 - iterator(x.value, function (err, v) {
228 - results[x.index] = v;
229 - callback(err);
230 - });
231 - }, function (err) {
232 - callback(err, results);
233 - });
234 - };
235 - async.map = doParallel(_asyncMap);
236 - async.mapSeries = doSeries(_asyncMap);
237 - async.mapLimit = function (arr, limit, iterator, callback) {
238 - return _mapLimit(limit)(arr, iterator, callback);
239 - };
240 -
241 - var _mapLimit = function(limit) {
242 - return doParallelLimit(limit, _asyncMap);
243 - };
244 -
245 - // reduce only has a series version, as doing reduce in parallel won't
246 - // work in many situations.
247 - async.reduce = function (arr, memo, iterator, callback) {
248 - async.eachSeries(arr, function (x, callback) {
249 - iterator(memo, x, function (err, v) {
250 - memo = v;
251 - callback(err);
252 - });
253 - }, function (err) {
254 - callback(err, memo);
255 - });
256 - };
257 - // inject alias
258 - async.inject = async.reduce;
259 - // foldl alias
260 - async.foldl = async.reduce;
261 -
262 - async.reduceRight = function (arr, memo, iterator, callback) {
263 - var reversed = _map(arr, function (x) {
264 - return x;
265 - }).reverse();
266 - async.reduce(reversed, memo, iterator, callback);
267 - };
268 - // foldr alias
269 - async.foldr = async.reduceRight;
270 -
271 - var _filter = function (eachfn, arr, iterator, callback) {
272 - var results = [];
273 - arr = _map(arr, function (x, i) {
274 - return {index: i, value: x};
275 - });
276 - eachfn(arr, function (x, callback) {
277 - iterator(x.value, function (v) {
278 - if (v) {
279 - results.push(x);
280 - }
281 - callback();
282 - });
283 - }, function (err) {
284 - callback(_map(results.sort(function (a, b) {
285 - return a.index - b.index;
286 - }), function (x) {
287 - return x.value;
288 - }));
289 - });
290 - };
291 - async.filter = doParallel(_filter);
292 - async.filterSeries = doSeries(_filter);
293 - // select alias
294 - async.select = async.filter;
295 - async.selectSeries = async.filterSeries;
296 -
297 - var _reject = function (eachfn, arr, iterator, callback) {
298 - var results = [];
299 - arr = _map(arr, function (x, i) {
300 - return {index: i, value: x};
301 - });
302 - eachfn(arr, function (x, callback) {
303 - iterator(x.value, function (v) {
304 - if (!v) {
305 - results.push(x);
306 - }
307 - callback();
308 - });
309 - }, function (err) {
310 - callback(_map(results.sort(function (a, b) {
311 - return a.index - b.index;
312 - }), function (x) {
313 - return x.value;
314 - }));
315 - });
316 - };
317 - async.reject = doParallel(_reject);
318 - async.rejectSeries = doSeries(_reject);
319 -
320 - var _detect = function (eachfn, arr, iterator, main_callback) {
321 - eachfn(arr, function (x, callback) {
322 - iterator(x, function (result) {
323 - if (result) {
324 - main_callback(x);
325 - main_callback = function () {};
326 - }
327 - else {
328 - callback();
329 - }
330 - });
331 - }, function (err) {
332 - main_callback();
333 - });
334 - };
335 - async.detect = doParallel(_detect);
336 - async.detectSeries = doSeries(_detect);
337 -
338 - async.some = function (arr, iterator, main_callback) {
339 - async.each(arr, function (x, callback) {
340 - iterator(x, function (v) {
341 - if (v) {
342 - main_callback(true);
343 - main_callback = function () {};
344 - }
345 - callback();
346 - });
347 - }, function (err) {
348 - main_callback(false);
349 - });
350 - };
351 - // any alias
352 - async.any = async.some;
353 -
354 - async.every = function (arr, iterator, main_callback) {
355 - async.each(arr, function (x, callback) {
356 - iterator(x, function (v) {
357 - if (!v) {
358 - main_callback(false);
359 - main_callback = function () {};
360 - }
361 - callback();
362 - });
363 - }, function (err) {
364 - main_callback(true);
365 - });
366 - };
367 - // all alias
368 - async.all = async.every;
369 -
370 - async.sortBy = function (arr, iterator, callback) {
371 - async.map(arr, function (x, callback) {
372 - iterator(x, function (err, criteria) {
373 - if (err) {
374 - callback(err);
375 - }
376 - else {
377 - callback(null, {value: x, criteria: criteria});
378 - }
379 - });
380 - }, function (err, results) {
381 - if (err) {
382 - return callback(err);
383 - }
384 - else {
385 - var fn = function (left, right) {
386 - var a = left.criteria, b = right.criteria;
387 - return a < b ? -1 : a > b ? 1 : 0;
388 - };
389 - callback(null, _map(results.sort(fn), function (x) {
390 - return x.value;
391 - }));
392 - }
393 - });
394 - };
395 -
396 - async.auto = function (tasks, callback) {
397 - callback = callback || function () {};
398 - var keys = _keys(tasks);
399 - if (!keys.length) {
400 - return callback(null);
401 - }
402 -
403 - var results = {};
404 -
405 - var listeners = [];
406 - var addListener = function (fn) {
407 - listeners.unshift(fn);
408 - };
409 - var removeListener = function (fn) {
410 - for (var i = 0; i < listeners.length; i += 1) {
411 - if (listeners[i] === fn) {
412 - listeners.splice(i, 1);
413 - return;
414 - }
415 - }
416 - };
417 - var taskComplete = function () {
418 - _each(listeners.slice(0), function (fn) {
419 - fn();
420 - });
421 - };
422 -
423 - addListener(function () {
424 - if (_keys(results).length === keys.length) {
425 - callback(null, results);
426 - callback = function () {};
427 - }
428 - });
429 -
430 - _each(keys, function (k) {
431 - var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
432 - var taskCallback = function (err) {
433 - var args = Array.prototype.slice.call(arguments, 1);
434 - if (args.length <= 1) {
435 - args = args[0];
436 - }
437 - if (err) {
438 - var safeResults = {};
439 - _each(_keys(results), function(rkey) {
440 - safeResults[rkey] = results[rkey];
441 - });
442 - safeResults[k] = args;
443 - callback(err, safeResults);
444 - // stop subsequent errors hitting callback multiple times
445 - callback = function () {};
446 - }
447 - else {
448 - results[k] = args;
449 - async.setImmediate(taskComplete);
450 - }
451 - };
452 - var requires = task.slice(0, Math.abs(task.length - 1)) || [];
453 - var ready = function () {
454 - return _reduce(requires, function (a, x) {
455 - return (a && results.hasOwnProperty(x));
456 - }, true) && !results.hasOwnProperty(k);
457 - };
458 - if (ready()) {
459 - task[task.length - 1](taskCallback, results);
460 - }
461 - else {
462 - var listener = function () {
463 - if (ready()) {
464 - removeListener(listener);
465 - task[task.length - 1](taskCallback, results);
466 - }
467 - };
468 - addListener(listener);
469 - }
470 - });
471 - };
472 -
473 - async.waterfall = function (tasks, callback) {
474 - callback = callback || function () {};
475 - if (tasks.constructor !== Array) {
476 - var err = new Error('First argument to waterfall must be an array of functions');
477 - return callback(err);
478 - }
479 - if (!tasks.length) {
480 - return callback();
481 - }
482 - var wrapIterator = function (iterator) {
483 - return function (err) {
484 - if (err) {
485 - callback.apply(null, arguments);
486 - callback = function () {};
487 - }
488 - else {
489 - var args = Array.prototype.slice.call(arguments, 1);
490 - var next = iterator.next();
491 - if (next) {
492 - args.push(wrapIterator(next));
493 - }
494 - else {
495 - args.push(callback);
496 - }
497 - async.setImmediate(function () {
498 - iterator.apply(null, args);
499 - });
500 - }
501 - };
502 - };
503 - wrapIterator(async.iterator(tasks))();
504 - };
505 -
506 - var _parallel = function(eachfn, tasks, callback) {
507 - callback = callback || function () {};
508 - if (tasks.constructor === Array) {
509 - eachfn.map(tasks, function (fn, callback) {
510 - if (fn) {
511 - fn(function (err) {
512 - var args = Array.prototype.slice.call(arguments, 1);
513 - if (args.length <= 1) {
514 - args = args[0];
515 - }
516 - callback.call(null, err, args);
517 - });
518 - }
519 - }, callback);
520 - }
521 - else {
522 - var results = {};
523 - eachfn.each(_keys(tasks), function (k, callback) {
524 - tasks[k](function (err) {
525 - var args = Array.prototype.slice.call(arguments, 1);
526 - if (args.length <= 1) {
527 - args = args[0];
528 - }
529 - results[k] = args;
530 - callback(err);
531 - });
532 - }, function (err) {
533 - callback(err, results);
534 - });
535 - }
536 - };
537 -
538 - async.parallel = function (tasks, callback) {
539 - _parallel({ map: async.map, each: async.each }, tasks, callback);
540 - };
541 -
542 - async.parallelLimit = function(tasks, limit, callback) {
543 - _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
544 - };
545 -
546 - async.series = function (tasks, callback) {
547 - callback = callback || function () {};
548 - if (tasks.constructor === Array) {
549 - async.mapSeries(tasks, function (fn, callback) {
550 - if (fn) {
551 - fn(function (err) {
552 - var args = Array.prototype.slice.call(arguments, 1);
553 - if (args.length <= 1) {
554 - args = args[0];
555 - }
556 - callback.call(null, err, args);
557 - });
558 - }
559 - }, callback);
560 - }
561 - else {
562 - var results = {};
563 - async.eachSeries(_keys(tasks), function (k, callback) {
564 - tasks[k](function (err) {
565 - var args = Array.prototype.slice.call(arguments, 1);
566 - if (args.length <= 1) {
567 - args = args[0];
568 - }
569 - results[k] = args;
570 - callback(err);
571 - });
572 - }, function (err) {
573 - callback(err, results);
574 - });
575 - }
576 - };
577 -
578 - async.iterator = function (tasks) {
579 - var makeCallback = function (index) {
580 - var fn = function () {
581 - if (tasks.length) {
582 - tasks[index].apply(null, arguments);
583 - }
584 - return fn.next();
585 - };
586 - fn.next = function () {
587 - return (index < tasks.length - 1) ? makeCallback(index + 1): null;
588 - };
589 - return fn;
590 - };
591 - return makeCallback(0);
592 - };
593 -
594 - async.apply = function (fn) {
595 - var args = Array.prototype.slice.call(arguments, 1);
596 - return function () {
597 - return fn.apply(
598 - null, args.concat(Array.prototype.slice.call(arguments))
599 - );
600 - };
601 - };
602 -
603 - var _concat = function (eachfn, arr, fn, callback) {
604 - var r = [];
605 - eachfn(arr, function (x, cb) {
606 - fn(x, function (err, y) {
607 - r = r.concat(y || []);
608 - cb(err);
609 - });
610 - }, function (err) {
611 - callback(err, r);
612 - });
613 - };
614 - async.concat = doParallel(_concat);
615 - async.concatSeries = doSeries(_concat);
616 -
617 - async.whilst = function (test, iterator, callback) {
618 - if (test()) {
619 - iterator(function (err) {
620 - if (err) {
621 - return callback(err);
622 - }
623 - async.whilst(test, iterator, callback);
624 - });
625 - }
626 - else {
627 - callback();
628 - }
629 - };
630 -
631 - async.doWhilst = function (iterator, test, callback) {
632 - iterator(function (err) {
633 - if (err) {
634 - return callback(err);
635 - }
636 - if (test()) {
637 - async.doWhilst(iterator, test, callback);
638 - }
639 - else {
640 - callback();
641 - }
642 - });
643 - };
644 -
645 - async.until = function (test, iterator, callback) {
646 - if (!test()) {
647 - iterator(function (err) {
648 - if (err) {
649 - return callback(err);
650 - }
651 - async.until(test, iterator, callback);
652 - });
653 - }
654 - else {
655 - callback();
656 - }
657 - };
658 -
659 - async.doUntil = function (iterator, test, callback) {
660 - iterator(function (err) {
661 - if (err) {
662 - return callback(err);
663 - }
664 - if (!test()) {
665 - async.doUntil(iterator, test, callback);
666 - }
667 - else {
668 - callback();
669 - }
670 - });
671 - };
672 -
673 - async.queue = function (worker, concurrency) {
674 - if (concurrency === undefined) {
675 - concurrency = 1;
676 - }
677 - function _insert(q, data, pos, callback) {
678 - if(data.constructor !== Array) {
679 - data = [data];
680 - }
681 - _each(data, function(task) {
682 - var item = {
683 - data: task,
684 - callback: typeof callback === 'function' ? callback : null
685 - };
686 -
687 - if (pos) {
688 - q.tasks.unshift(item);
689 - } else {
690 - q.tasks.push(item);
691 - }
692 -
693 - if (q.saturated && q.tasks.length === concurrency) {
694 - q.saturated();
695 - }
696 - async.setImmediate(q.process);
697 - });
698 - }
699 -
700 - var workers = 0;
701 - var q = {
702 - tasks: [],
703 - concurrency: concurrency,
704 - saturated: null,
705 - empty: null,
706 - drain: null,
707 - push: function (data, callback) {
708 - _insert(q, data, false, callback);
709 - },
710 - unshift: function (data, callback) {
711 - _insert(q, data, true, callback);
712 - },
713 - process: function () {
714 - if (workers < q.concurrency && q.tasks.length) {
715 - var task = q.tasks.shift();
716 - if (q.empty && q.tasks.length === 0) {
717 - q.empty();
718 - }
719 - workers += 1;
720 - var next = function () {
721 - workers -= 1;
722 - if (task.callback) {
723 - task.callback.apply(task, arguments);
724 - }
725 - if (q.drain && q.tasks.length + workers === 0) {
726 - q.drain();
727 - }
728 - q.process();
729 - };
730 - var cb = only_once(next);
731 - worker(task.data, cb);
732 - }
733 - },
734 - length: function () {
735 - return q.tasks.length;
736 - },
737 - running: function () {
738 - return workers;
739 - }
740 - };
741 - return q;
742 - };
743 -
744 - async.cargo = function (worker, payload) {
745 - var working = false,
746 - tasks = [];
747 -
748 - var cargo = {
749 - tasks: tasks,
750 - payload: payload,
751 - saturated: null,
752 - empty: null,
753 - drain: null,
754 - push: function (data, callback) {
755 - if(data.constructor !== Array) {
756 - data = [data];
757 - }
758 - _each(data, function(task) {
759 - tasks.push({
760 - data: task,
761 - callback: typeof callback === 'function' ? callback : null
762 - });
763 - if (cargo.saturated && tasks.length === payload) {
764 - cargo.saturated();
765 - }
766 - });
767 - async.setImmediate(cargo.process);
768 - },
769 - process: function process() {
770 - if (working) return;
771 - if (tasks.length === 0) {
772 - if(cargo.drain) cargo.drain();
773 - return;
774 - }
775 -
776 - var ts = typeof payload === 'number'
777 - ? tasks.splice(0, payload)
778 - : tasks.splice(0);
779 -
780 - var ds = _map(ts, function (task) {
781 - return task.data;
782 - });
783 -
784 - if(cargo.empty) cargo.empty();
785 - working = true;
786 - worker(ds, function () {
787 - working = false;
788 -
789 - var args = arguments;
790 - _each(ts, function (data) {
791 - if (data.callback) {
792 - data.callback.apply(null, args);
793 - }
794 - });
795 -
796 - process();
797 - });
798 - },
799 - length: function () {
800 - return tasks.length;
801 - },
802 - running: function () {
803 - return working;
804 - }
805 - };
806 - return cargo;
807 - };
808 -
809 - var _console_fn = function (name) {
810 - return function (fn) {
811 - var args = Array.prototype.slice.call(arguments, 1);
812 - fn.apply(null, args.concat([function (err) {
813 - var args = Array.prototype.slice.call(arguments, 1);
814 - if (typeof console !== 'undefined') {
815 - if (err) {
816 - if (console.error) {
817 - console.error(err);
818 - }
819 - }
820 - else if (console[name]) {
821 - _each(args, function (x) {
822 - console[name](x);
823 - });
824 - }
825 - }
826 - }]));
827 - };
828 - };
829 - async.log = _console_fn('log');
830 - async.dir = _console_fn('dir');
831 - /*async.info = _console_fn('info');
832 - async.warn = _console_fn('warn');
833 - async.error = _console_fn('error');*/
834 -
835 - async.memoize = function (fn, hasher) {
836 - var memo = {};
837 - var queues = {};
838 - hasher = hasher || function (x) {
839 - return x;
840 - };
841 - var memoized = function () {
842 - var args = Array.prototype.slice.call(arguments);
843 - var callback = args.pop();
844 - var key = hasher.apply(null, args);
845 - if (key in memo) {
846 - callback.apply(null, memo[key]);
847 - }
848 - else if (key in queues) {
849 - queues[key].push(callback);
850 - }
851 - else {
852 - queues[key] = [callback];
853 - fn.apply(null, args.concat([function () {
854 - memo[key] = arguments;
855 - var q = queues[key];
856 - delete queues[key];
857 - for (var i = 0, l = q.length; i < l; i++) {
858 - q[i].apply(null, arguments);
859 - }
860 - }]));
861 - }
862 - };
863 - memoized.memo = memo;
864 - memoized.unmemoized = fn;
865 - return memoized;
866 - };
867 -
868 - async.unmemoize = function (fn) {
869 - return function () {
870 - return (fn.unmemoized || fn).apply(null, arguments);
871 - };
872 - };
873 -
874 - async.times = function (count, iterator, callback) {
875 - var counter = [];
876 - for (var i = 0; i < count; i++) {
877 - counter.push(i);
878 - }
879 - return async.map(counter, iterator, callback);
880 - };
881 -
882 - async.timesSeries = function (count, iterator, callback) {
883 - var counter = [];
884 - for (var i = 0; i < count; i++) {
885 - counter.push(i);
886 - }
887 - return async.mapSeries(counter, iterator, callback);
888 - };
889 -
890 - async.compose = function (/* functions... */) {
891 - var fns = Array.prototype.reverse.call(arguments);
892 - return function () {
893 - var that = this;
894 - var args = Array.prototype.slice.call(arguments);
895 - var callback = args.pop();
896 - async.reduce(fns, args, function (newargs, fn, cb) {
897 - fn.apply(that, newargs.concat([function () {
898 - var err = arguments[0];
899 - var nextargs = Array.prototype.slice.call(arguments, 1);
900 - cb(err, nextargs);
901 - }]))
902 - },
903 - function (err, results) {
904 - callback.apply(that, [err].concat(results));
905 - });
906 - };
907 - };
908 -
909 - var _applyEach = function (eachfn, fns /*args...*/) {
910 - var go = function () {
911 - var that = this;
912 - var args = Array.prototype.slice.call(arguments);
913 - var callback = args.pop();
914 - return eachfn(fns, function (fn, cb) {
915 - fn.apply(that, args.concat([cb]));
916 - },
917 - callback);
918 - };
919 - if (arguments.length > 2) {
920 - var args = Array.prototype.slice.call(arguments, 2);
921 - return go.apply(this, args);
922 - }
923 - else {
924 - return go;
925 - }
926 - };
927 - async.applyEach = doParallel(_applyEach);
928 - async.applyEachSeries = doSeries(_applyEach);
929 -
930 - async.forever = function (fn, callback) {
931 - function next(err) {
932 - if (err) {
933 - if (callback) {
934 - return callback(err);
935 - }
936 - throw err;
937 - }
938 - fn(next);
939 - }
940 - next();
941 - };
942 -
943 - // AMD / RequireJS
944 - if (typeof define !== 'undefined' && define.amd) {
945 - define([], function () {
946 - return async;
947 - });
948 - }
949 - // Node.js
950 - else if (typeof module !== 'undefined' && module.exports) {
951 - module.exports = async;
952 - }
953 - // included directly via <script> tag
954 - else {
955 - root.async = async;
956 - }
957 -
958 -}());
1 -{
2 - "_from": "async@~0.2.6",
3 - "_id": "async@0.2.10",
4 - "_inBundle": false,
5 - "_integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
6 - "_location": "/async",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "range",
10 - "registry": true,
11 - "raw": "async@~0.2.6",
12 - "name": "async",
13 - "escapedName": "async",
14 - "rawSpec": "~0.2.6",
15 - "saveSpec": null,
16 - "fetchSpec": "~0.2.6"
17 - },
18 - "_requiredBy": [
19 - "/uglify-js"
20 - ],
21 - "_resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz",
22 - "_shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1",
23 - "_spec": "async@~0.2.6",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\uglify-js",
25 - "author": {
26 - "name": "Caolan McMahon"
27 - },
28 - "bugs": {
29 - "url": "https://github.com/caolan/async/issues"
30 - },
31 - "bundleDependencies": false,
32 - "deprecated": false,
33 - "description": "Higher-order functions and common patterns for asynchronous code",
34 - "devDependencies": {
35 - "nodelint": ">0.0.0",
36 - "nodeunit": ">0.0.0",
37 - "uglify-js": "1.2.x"
38 - },
39 - "homepage": "https://github.com/caolan/async#readme",
40 - "jam": {
41 - "main": "lib/async.js",
42 - "include": [
43 - "lib/async.js",
44 - "README.md",
45 - "LICENSE"
46 - ]
47 - },
48 - "licenses": [
49 - {
50 - "type": "MIT",
51 - "url": "https://github.com/caolan/async/raw/master/LICENSE"
52 - }
53 - ],
54 - "main": "./lib/async",
55 - "name": "async",
56 - "repository": {
57 - "type": "git",
58 - "url": "git+https://github.com/caolan/async.git"
59 - },
60 - "scripts": {
61 - "test": "nodeunit test/test-async.js"
62 - },
63 - "version": "0.2.10"
64 -}
1 { 1 {
2 - "_from": "cheerio@^1.0.0-rc.2", 2 + "_from": "cheerio",
3 "_id": "cheerio@1.0.0-rc.2", 3 "_id": "cheerio@1.0.0-rc.2",
4 "_inBundle": false, 4 "_inBundle": false,
5 "_integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", 5 "_integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=",
6 "_location": "/cheerio", 6 "_location": "/cheerio",
7 "_phantomChildren": {}, 7 "_phantomChildren": {},
8 "_requested": { 8 "_requested": {
9 - "type": "range", 9 + "type": "tag",
10 "registry": true, 10 "registry": true,
11 - "raw": "cheerio@^1.0.0-rc.2", 11 + "raw": "cheerio",
12 "name": "cheerio", 12 "name": "cheerio",
13 "escapedName": "cheerio", 13 "escapedName": "cheerio",
14 - "rawSpec": "^1.0.0-rc.2", 14 + "rawSpec": "",
15 "saveSpec": null, 15 "saveSpec": null,
16 - "fetchSpec": "^1.0.0-rc.2" 16 + "fetchSpec": "latest"
17 }, 17 },
18 "_requiredBy": [ 18 "_requiredBy": [
19 "#USER", 19 "#USER",
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
21 ], 21 ],
22 "_resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", 22 "_resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
23 "_shasum": "4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db", 23 "_shasum": "4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db",
24 - "_spec": "cheerio@^1.0.0-rc.2", 24 + "_spec": "cheerio",
25 "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot", 25 "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot",
26 "author": { 26 "author": {
27 "name": "Matt Mueller", 27 "name": "Matt Mueller",
......
1 -language: node_js
2 -node_js:
3 - - "0.8"
4 - - "0.10"
1 -Copyright 2010 James Halliday (mail@substack.net)
2 -
3 -This project is free software released under the MIT/X11 license:
4 -
5 -Permission is hereby granted, free of charge, to any person obtaining a copy
6 -of this software and associated documentation files (the "Software"), to deal
7 -in the Software without restriction, including without limitation the rights
8 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 -copies of the Software, and to permit persons to whom the Software is
10 -furnished to do so, subject to the following conditions:
11 -
12 -The above copyright notice and this permission notice shall be included in
13 -all copies or substantial portions of the Software.
14 -
15 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 -THE SOFTWARE.
1 -#!/usr/bin/env node
2 -var util = require('util');
3 -var argv = require('optimist').argv;
4 -
5 -if (argv.s) {
6 - util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');
7 -}
8 -console.log(
9 - (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')
10 -);
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .boolean(['x','y','z'])
4 - .argv
5 -;
6 -console.dir([ argv.x, argv.y, argv.z ]);
7 -console.dir(argv._);
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .boolean('v')
4 - .argv
5 -;
6 -console.dir(argv.v);
7 -console.dir(argv._);
1 -#!/usr/bin/env node
2 -
3 -var argv = require('optimist')
4 - .default({ x : 10, y : 10 })
5 - .argv
6 -;
7 -
8 -console.log(argv.x + argv.y);
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .default('x', 10)
4 - .default('y', 10)
5 - .argv
6 -;
7 -console.log(argv.x + argv.y);
1 -#!/usr/bin/env node
2 -
3 -var argv = require('optimist')
4 - .usage('Usage: $0 -x [num] -y [num]')
5 - .demand(['x','y'])
6 - .argv;
7 -
8 -console.log(argv.x / argv.y);
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .usage('Count the lines in a file.\nUsage: $0')
4 - .demand('f')
5 - .alias('f', 'file')
6 - .describe('f', 'Load a file')
7 - .argv
8 -;
9 -
10 -var fs = require('fs');
11 -var s = fs.createReadStream(argv.file);
12 -
13 -var lines = 0;
14 -s.on('data', function (buf) {
15 - lines += buf.toString().match(/\n/g).length;
16 -});
17 -
18 -s.on('end', function () {
19 - console.log(lines);
20 -});
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .usage('Count the lines in a file.\nUsage: $0')
4 - .options({
5 - file : {
6 - demand : true,
7 - alias : 'f',
8 - description : 'Load a file'
9 - },
10 - base : {
11 - alias : 'b',
12 - description : 'Numeric base to use for output',
13 - default : 10,
14 - },
15 - })
16 - .argv
17 -;
18 -
19 -var fs = require('fs');
20 -var s = fs.createReadStream(argv.file);
21 -
22 -var lines = 0;
23 -s.on('data', function (buf) {
24 - lines += buf.toString().match(/\n/g).length;
25 -});
26 -
27 -s.on('end', function () {
28 - console.log(lines.toString(argv.base));
29 -});
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .usage('Count the lines in a file.\nUsage: $0')
4 - .wrap(80)
5 - .demand('f')
6 - .alias('f', [ 'file', 'filename' ])
7 - .describe('f',
8 - "Load a file. It's pretty important."
9 - + " Required even. So you'd better specify it."
10 - )
11 - .alias('b', 'base')
12 - .describe('b', 'Numeric base to display the number of lines in')
13 - .default('b', 10)
14 - .describe('x', 'Super-secret optional parameter which is secret')
15 - .default('x', '')
16 - .argv
17 -;
18 -
19 -var fs = require('fs');
20 -var s = fs.createReadStream(argv.file);
21 -
22 -var lines = 0;
23 -s.on('data', function (buf) {
24 - lines += buf.toString().match(/\n/g).length;
25 -});
26 -
27 -s.on('end', function () {
28 - console.log(lines.toString(argv.base));
29 -});
1 -#!/usr/bin/env node
2 -var argv = require('optimist').argv;
3 -console.log('(%d,%d)', argv.x, argv.y);
4 -console.log(argv._);
1 -#!/usr/bin/env node
2 -console.dir(require('optimist').argv);
1 -#!/usr/bin/env node
2 -var argv = require('optimist').argv;
3 -console.log('(%d,%d)', argv.x, argv.y);
1 -#!/usr/bin/env node
2 -var argv = require('optimist')
3 - .string('x', 'y')
4 - .argv
5 -;
6 -console.dir([ argv.x, argv.y ]);
7 -
8 -/* Turns off numeric coercion:
9 - ./node string.js -x 000123 -y 9876
10 - [ '000123', '9876' ]
11 -*/
1 -var optimist = require('./../index');
2 -
3 -var argv = optimist.usage('This is my awesome program', {
4 - 'about': {
5 - description: 'Provide some details about the author of this program',
6 - required: true,
7 - short: 'a',
8 - },
9 - 'info': {
10 - description: 'Provide some information about the node.js agains!!!!!!',
11 - boolean: true,
12 - short: 'i'
13 - }
14 -}).argv;
15 -
16 -optimist.showHelp();
17 -
18 -console.log('\n\nInspecting options');
19 -console.dir(argv);
...\ No newline at end of file ...\ No newline at end of file
1 -#!/usr/bin/env node
2 -var argv = require('optimist').argv;
3 -
4 -if (argv.rif - 5 * argv.xup > 7.138) {
5 - console.log('Buy more riffiwobbles');
6 -}
7 -else {
8 - console.log('Sell the xupptumblers');
9 -}
10 -
1 -var path = require('path');
2 -var wordwrap = require('wordwrap');
3 -
4 -/* Hack an instance of Argv with process.argv into Argv
5 - so people can do
6 - require('optimist')(['--beeble=1','-z','zizzle']).argv
7 - to parse a list of args and
8 - require('optimist').argv
9 - to get a parsed version of process.argv.
10 -*/
11 -
12 -var inst = Argv(process.argv.slice(2));
13 -Object.keys(inst).forEach(function (key) {
14 - Argv[key] = typeof inst[key] == 'function'
15 - ? inst[key].bind(inst)
16 - : inst[key];
17 -});
18 -
19 -var exports = module.exports = Argv;
20 -function Argv (args, cwd) {
21 - var self = {};
22 - if (!cwd) cwd = process.cwd();
23 -
24 - self.$0 = process.argv
25 - .slice(0,2)
26 - .map(function (x) {
27 - var b = rebase(cwd, x);
28 - return x.match(/^\//) && b.length < x.length
29 - ? b : x
30 - })
31 - .join(' ')
32 - ;
33 -
34 - if (process.env._ != undefined && process.argv[1] == process.env._) {
35 - self.$0 = process.env._.replace(
36 - path.dirname(process.execPath) + '/', ''
37 - );
38 - }
39 -
40 - var flags = { bools : {}, strings : {} };
41 -
42 - self.boolean = function (bools) {
43 - if (!Array.isArray(bools)) {
44 - bools = [].slice.call(arguments);
45 - }
46 -
47 - bools.forEach(function (name) {
48 - flags.bools[name] = true;
49 - });
50 -
51 - return self;
52 - };
53 -
54 - self.string = function (strings) {
55 - if (!Array.isArray(strings)) {
56 - strings = [].slice.call(arguments);
57 - }
58 -
59 - strings.forEach(function (name) {
60 - flags.strings[name] = true;
61 - });
62 -
63 - return self;
64 - };
65 -
66 - var aliases = {};
67 - self.alias = function (x, y) {
68 - if (typeof x === 'object') {
69 - Object.keys(x).forEach(function (key) {
70 - self.alias(key, x[key]);
71 - });
72 - }
73 - else if (Array.isArray(y)) {
74 - y.forEach(function (yy) {
75 - self.alias(x, yy);
76 - });
77 - }
78 - else {
79 - var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y);
80 - aliases[x] = zs.filter(function (z) { return z != x });
81 - aliases[y] = zs.filter(function (z) { return z != y });
82 - }
83 -
84 - return self;
85 - };
86 -
87 - var demanded = {};
88 - self.demand = function (keys) {
89 - if (typeof keys == 'number') {
90 - if (!demanded._) demanded._ = 0;
91 - demanded._ += keys;
92 - }
93 - else if (Array.isArray(keys)) {
94 - keys.forEach(function (key) {
95 - self.demand(key);
96 - });
97 - }
98 - else {
99 - demanded[keys] = true;
100 - }
101 -
102 - return self;
103 - };
104 -
105 - var usage;
106 - self.usage = function (msg, opts) {
107 - if (!opts && typeof msg === 'object') {
108 - opts = msg;
109 - msg = null;
110 - }
111 -
112 - usage = msg;
113 -
114 - if (opts) self.options(opts);
115 -
116 - return self;
117 - };
118 -
119 - function fail (msg) {
120 - self.showHelp();
121 - if (msg) console.error(msg);
122 - process.exit(1);
123 - }
124 -
125 - var checks = [];
126 - self.check = function (f) {
127 - checks.push(f);
128 - return self;
129 - };
130 -
131 - var defaults = {};
132 - self.default = function (key, value) {
133 - if (typeof key === 'object') {
134 - Object.keys(key).forEach(function (k) {
135 - self.default(k, key[k]);
136 - });
137 - }
138 - else {
139 - defaults[key] = value;
140 - }
141 -
142 - return self;
143 - };
144 -
145 - var descriptions = {};
146 - self.describe = function (key, desc) {
147 - if (typeof key === 'object') {
148 - Object.keys(key).forEach(function (k) {
149 - self.describe(k, key[k]);
150 - });
151 - }
152 - else {
153 - descriptions[key] = desc;
154 - }
155 - return self;
156 - };
157 -
158 - self.parse = function (args) {
159 - return Argv(args).argv;
160 - };
161 -
162 - self.option = self.options = function (key, opt) {
163 - if (typeof key === 'object') {
164 - Object.keys(key).forEach(function (k) {
165 - self.options(k, key[k]);
166 - });
167 - }
168 - else {
169 - if (opt.alias) self.alias(key, opt.alias);
170 - if (opt.demand) self.demand(key);
171 - if (typeof opt.default !== 'undefined') {
172 - self.default(key, opt.default);
173 - }
174 -
175 - if (opt.boolean || opt.type === 'boolean') {
176 - self.boolean(key);
177 - }
178 - if (opt.string || opt.type === 'string') {
179 - self.string(key);
180 - }
181 -
182 - var desc = opt.describe || opt.description || opt.desc;
183 - if (desc) {
184 - self.describe(key, desc);
185 - }
186 - }
187 -
188 - return self;
189 - };
190 -
191 - var wrap = null;
192 - self.wrap = function (cols) {
193 - wrap = cols;
194 - return self;
195 - };
196 -
197 - self.showHelp = function (fn) {
198 - if (!fn) fn = console.error;
199 - fn(self.help());
200 - };
201 -
202 - self.help = function () {
203 - var keys = Object.keys(
204 - Object.keys(descriptions)
205 - .concat(Object.keys(demanded))
206 - .concat(Object.keys(defaults))
207 - .reduce(function (acc, key) {
208 - if (key !== '_') acc[key] = true;
209 - return acc;
210 - }, {})
211 - );
212 -
213 - var help = keys.length ? [ 'Options:' ] : [];
214 -
215 - if (usage) {
216 - help.unshift(usage.replace(/\$0/g, self.$0), '');
217 - }
218 -
219 - var switches = keys.reduce(function (acc, key) {
220 - acc[key] = [ key ].concat(aliases[key] || [])
221 - .map(function (sw) {
222 - return (sw.length > 1 ? '--' : '-') + sw
223 - })
224 - .join(', ')
225 - ;
226 - return acc;
227 - }, {});
228 -
229 - var switchlen = longest(Object.keys(switches).map(function (s) {
230 - return switches[s] || '';
231 - }));
232 -
233 - var desclen = longest(Object.keys(descriptions).map(function (d) {
234 - return descriptions[d] || '';
235 - }));
236 -
237 - keys.forEach(function (key) {
238 - var kswitch = switches[key];
239 - var desc = descriptions[key] || '';
240 -
241 - if (wrap) {
242 - desc = wordwrap(switchlen + 4, wrap)(desc)
243 - .slice(switchlen + 4)
244 - ;
245 - }
246 -
247 - var spadding = new Array(
248 - Math.max(switchlen - kswitch.length + 3, 0)
249 - ).join(' ');
250 -
251 - var dpadding = new Array(
252 - Math.max(desclen - desc.length + 1, 0)
253 - ).join(' ');
254 -
255 - var type = null;
256 -
257 - if (flags.bools[key]) type = '[boolean]';
258 - if (flags.strings[key]) type = '[string]';
259 -
260 - if (!wrap && dpadding.length > 0) {
261 - desc += dpadding;
262 - }
263 -
264 - var prelude = ' ' + kswitch + spadding;
265 - var extra = [
266 - type,
267 - demanded[key]
268 - ? '[required]'
269 - : null
270 - ,
271 - defaults[key] !== undefined
272 - ? '[default: ' + JSON.stringify(defaults[key]) + ']'
273 - : null
274 - ,
275 - ].filter(Boolean).join(' ');
276 -
277 - var body = [ desc, extra ].filter(Boolean).join(' ');
278 -
279 - if (wrap) {
280 - var dlines = desc.split('\n');
281 - var dlen = dlines.slice(-1)[0].length
282 - + (dlines.length === 1 ? prelude.length : 0)
283 -
284 - body = desc + (dlen + extra.length > wrap - 2
285 - ? '\n'
286 - + new Array(wrap - extra.length + 1).join(' ')
287 - + extra
288 - : new Array(wrap - extra.length - dlen + 1).join(' ')
289 - + extra
290 - );
291 - }
292 -
293 - help.push(prelude + body);
294 - });
295 -
296 - help.push('');
297 - return help.join('\n');
298 - };
299 -
300 - Object.defineProperty(self, 'argv', {
301 - get : parseArgs,
302 - enumerable : true,
303 - });
304 -
305 - function parseArgs () {
306 - var argv = { _ : [], $0 : self.$0 };
307 - Object.keys(flags.bools).forEach(function (key) {
308 - setArg(key, defaults[key] || false);
309 - });
310 -
311 - function setArg (key, val) {
312 - var num = Number(val);
313 - var value = typeof val !== 'string' || isNaN(num) ? val : num;
314 - if (flags.strings[key]) value = val;
315 -
316 - setKey(argv, key.split('.'), value);
317 -
318 - (aliases[key] || []).forEach(function (x) {
319 - argv[x] = argv[key];
320 - });
321 - }
322 -
323 - for (var i = 0; i < args.length; i++) {
324 - var arg = args[i];
325 -
326 - if (arg === '--') {
327 - argv._.push.apply(argv._, args.slice(i + 1));
328 - break;
329 - }
330 - else if (arg.match(/^--.+=/)) {
331 - // Using [\s\S] instead of . because js doesn't support the
332 - // 'dotall' regex modifier. See:
333 - // http://stackoverflow.com/a/1068308/13216
334 - var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
335 - setArg(m[1], m[2]);
336 - }
337 - else if (arg.match(/^--no-.+/)) {
338 - var key = arg.match(/^--no-(.+)/)[1];
339 - setArg(key, false);
340 - }
341 - else if (arg.match(/^--.+/)) {
342 - var key = arg.match(/^--(.+)/)[1];
343 - var next = args[i + 1];
344 - if (next !== undefined && !next.match(/^-/)
345 - && !flags.bools[key]
346 - && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
347 - setArg(key, next);
348 - i++;
349 - }
350 - else if (/^(true|false)$/.test(next)) {
351 - setArg(key, next === 'true');
352 - i++;
353 - }
354 - else {
355 - setArg(key, true);
356 - }
357 - }
358 - else if (arg.match(/^-[^-]+/)) {
359 - var letters = arg.slice(1,-1).split('');
360 -
361 - var broken = false;
362 - for (var j = 0; j < letters.length; j++) {
363 - if (letters[j+1] && letters[j+1].match(/\W/)) {
364 - setArg(letters[j], arg.slice(j+2));
365 - broken = true;
366 - break;
367 - }
368 - else {
369 - setArg(letters[j], true);
370 - }
371 - }
372 -
373 - if (!broken) {
374 - var key = arg.slice(-1)[0];
375 -
376 - if (args[i+1] && !args[i+1].match(/^-/)
377 - && !flags.bools[key]
378 - && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
379 - setArg(key, args[i+1]);
380 - i++;
381 - }
382 - else if (args[i+1] && /true|false/.test(args[i+1])) {
383 - setArg(key, args[i+1] === 'true');
384 - i++;
385 - }
386 - else {
387 - setArg(key, true);
388 - }
389 - }
390 - }
391 - else {
392 - var n = Number(arg);
393 - argv._.push(flags.strings['_'] || isNaN(n) ? arg : n);
394 - }
395 - }
396 -
397 - Object.keys(defaults).forEach(function (key) {
398 - if (!(key in argv)) {
399 - argv[key] = defaults[key];
400 - if (key in aliases) {
401 - argv[aliases[key]] = defaults[key];
402 - }
403 - }
404 - });
405 -
406 - if (demanded._ && argv._.length < demanded._) {
407 - fail('Not enough non-option arguments: got '
408 - + argv._.length + ', need at least ' + demanded._
409 - );
410 - }
411 -
412 - var missing = [];
413 - Object.keys(demanded).forEach(function (key) {
414 - if (!argv[key]) missing.push(key);
415 - });
416 -
417 - if (missing.length) {
418 - fail('Missing required arguments: ' + missing.join(', '));
419 - }
420 -
421 - checks.forEach(function (f) {
422 - try {
423 - if (f(argv) === false) {
424 - fail('Argument check failed: ' + f.toString());
425 - }
426 - }
427 - catch (err) {
428 - fail(err)
429 - }
430 - });
431 -
432 - return argv;
433 - }
434 -
435 - function longest (xs) {
436 - return Math.max.apply(
437 - null,
438 - xs.map(function (x) { return x.length })
439 - );
440 - }
441 -
442 - return self;
443 -};
444 -
445 -// rebase an absolute path to a relative one with respect to a base directory
446 -// exported for tests
447 -exports.rebase = rebase;
448 -function rebase (base, dir) {
449 - var ds = path.normalize(dir).split('/').slice(1);
450 - var bs = path.normalize(base).split('/').slice(1);
451 -
452 - for (var i = 0; ds[i] && ds[i] == bs[i]; i++);
453 - ds.splice(0, i); bs.splice(0, i);
454 -
455 - var p = path.normalize(
456 - bs.map(function () { return '..' }).concat(ds).join('/')
457 - ).replace(/\/$/,'').replace(/^$/, '.');
458 - return p.match(/^[.\/]/) ? p : './' + p;
459 -};
460 -
461 -function setKey (obj, keys, value) {
462 - var o = obj;
463 - keys.slice(0,-1).forEach(function (key) {
464 - if (o[key] === undefined) o[key] = {};
465 - o = o[key];
466 - });
467 -
468 - var key = keys[keys.length - 1];
469 - if (o[key] === undefined || typeof o[key] === 'boolean') {
470 - o[key] = value;
471 - }
472 - else if (Array.isArray(o[key])) {
473 - o[key].push(value);
474 - }
475 - else {
476 - o[key] = [ o[key], value ];
477 - }
478 -}
1 -{
2 - "_from": "optimist@~0.3.5",
3 - "_id": "optimist@0.3.7",
4 - "_inBundle": false,
5 - "_integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=",
6 - "_location": "/optimist",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "range",
10 - "registry": true,
11 - "raw": "optimist@~0.3.5",
12 - "name": "optimist",
13 - "escapedName": "optimist",
14 - "rawSpec": "~0.3.5",
15 - "saveSpec": null,
16 - "fetchSpec": "~0.3.5"
17 - },
18 - "_requiredBy": [
19 - "/uglify-js"
20 - ],
21 - "_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
22 - "_shasum": "c90941ad59e4273328923074d2cf2e7cbc6ec0d9",
23 - "_spec": "optimist@~0.3.5",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\uglify-js",
25 - "author": {
26 - "name": "James Halliday",
27 - "email": "mail@substack.net",
28 - "url": "http://substack.net"
29 - },
30 - "bugs": {
31 - "url": "https://github.com/substack/node-optimist/issues"
32 - },
33 - "bundleDependencies": false,
34 - "dependencies": {
35 - "wordwrap": "~0.0.2"
36 - },
37 - "deprecated": false,
38 - "description": "Light-weight option parsing with an argv hash. No optstrings attached.",
39 - "devDependencies": {
40 - "hashish": "~0.0.4",
41 - "tap": "~0.4.0"
42 - },
43 - "engine": {
44 - "node": ">=0.4"
45 - },
46 - "homepage": "https://github.com/substack/node-optimist#readme",
47 - "keywords": [
48 - "argument",
49 - "args",
50 - "option",
51 - "parser",
52 - "parsing",
53 - "cli",
54 - "command"
55 - ],
56 - "license": "MIT/X11",
57 - "main": "./index.js",
58 - "name": "optimist",
59 - "repository": {
60 - "type": "git",
61 - "url": "git+ssh://git@github.com/substack/node-optimist.git"
62 - },
63 - "scripts": {
64 - "test": "tap ./test/*.js"
65 - },
66 - "version": "0.3.7"
67 -}
1 -optimist
2 -========
3 -
4 -Optimist is a node.js library for option parsing for people who hate option
5 -parsing. More specifically, this module is for people who like all the --bells
6 -and -whistlz of program usage but think optstrings are a waste of time.
7 -
8 -With optimist, option parsing doesn't have to suck (as much).
9 -
10 -[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)
11 -
12 -examples
13 -========
14 -
15 -With Optimist, the options are just a hash! No optstrings attached.
16 --------------------------------------------------------------------
17 -
18 -xup.js:
19 -
20 -````javascript
21 -#!/usr/bin/env node
22 -var argv = require('optimist').argv;
23 -
24 -if (argv.rif - 5 * argv.xup > 7.138) {
25 - console.log('Buy more riffiwobbles');
26 -}
27 -else {
28 - console.log('Sell the xupptumblers');
29 -}
30 -````
31 -
32 -***
33 -
34 - $ ./xup.js --rif=55 --xup=9.52
35 - Buy more riffiwobbles
36 -
37 - $ ./xup.js --rif 12 --xup 8.1
38 - Sell the xupptumblers
39 -
40 -![This one's optimistic.](http://substack.net/images/optimistic.png)
41 -
42 -But wait! There's more! You can do short options:
43 --------------------------------------------------
44 -
45 -short.js:
46 -
47 -````javascript
48 -#!/usr/bin/env node
49 -var argv = require('optimist').argv;
50 -console.log('(%d,%d)', argv.x, argv.y);
51 -````
52 -
53 -***
54 -
55 - $ ./short.js -x 10 -y 21
56 - (10,21)
57 -
58 -And booleans, both long and short (and grouped):
59 -----------------------------------
60 -
61 -bool.js:
62 -
63 -````javascript
64 -#!/usr/bin/env node
65 -var util = require('util');
66 -var argv = require('optimist').argv;
67 -
68 -if (argv.s) {
69 - util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');
70 -}
71 -console.log(
72 - (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')
73 -);
74 -````
75 -
76 -***
77 -
78 - $ ./bool.js -s
79 - The cat says: meow
80 -
81 - $ ./bool.js -sp
82 - The cat says: meow.
83 -
84 - $ ./bool.js -sp --fr
85 - Le chat dit: miaou.
86 -
87 -And non-hypenated options too! Just use `argv._`!
88 --------------------------------------------------
89 -
90 -nonopt.js:
91 -
92 -````javascript
93 -#!/usr/bin/env node
94 -var argv = require('optimist').argv;
95 -console.log('(%d,%d)', argv.x, argv.y);
96 -console.log(argv._);
97 -````
98 -
99 -***
100 -
101 - $ ./nonopt.js -x 6.82 -y 3.35 moo
102 - (6.82,3.35)
103 - [ 'moo' ]
104 -
105 - $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz
106 - (0.54,1.12)
107 - [ 'foo', 'bar', 'baz' ]
108 -
109 -Plus, Optimist comes with .usage() and .demand()!
110 --------------------------------------------------
111 -
112 -divide.js:
113 -
114 -````javascript
115 -#!/usr/bin/env node
116 -var argv = require('optimist')
117 - .usage('Usage: $0 -x [num] -y [num]')
118 - .demand(['x','y'])
119 - .argv;
120 -
121 -console.log(argv.x / argv.y);
122 -````
123 -
124 -***
125 -
126 - $ ./divide.js -x 55 -y 11
127 - 5
128 -
129 - $ node ./divide.js -x 4.91 -z 2.51
130 - Usage: node ./divide.js -x [num] -y [num]
131 -
132 - Options:
133 - -x [required]
134 - -y [required]
135 -
136 - Missing required arguments: y
137 -
138 -EVEN MORE HOLY COW
139 -------------------
140 -
141 -default_singles.js:
142 -
143 -````javascript
144 -#!/usr/bin/env node
145 -var argv = require('optimist')
146 - .default('x', 10)
147 - .default('y', 10)
148 - .argv
149 -;
150 -console.log(argv.x + argv.y);
151 -````
152 -
153 -***
154 -
155 - $ ./default_singles.js -x 5
156 - 15
157 -
158 -default_hash.js:
159 -
160 -````javascript
161 -#!/usr/bin/env node
162 -var argv = require('optimist')
163 - .default({ x : 10, y : 10 })
164 - .argv
165 -;
166 -console.log(argv.x + argv.y);
167 -````
168 -
169 -***
170 -
171 - $ ./default_hash.js -y 7
172 - 17
173 -
174 -And if you really want to get all descriptive about it...
175 ----------------------------------------------------------
176 -
177 -boolean_single.js
178 -
179 -````javascript
180 -#!/usr/bin/env node
181 -var argv = require('optimist')
182 - .boolean('v')
183 - .argv
184 -;
185 -console.dir(argv);
186 -````
187 -
188 -***
189 -
190 - $ ./boolean_single.js -v foo bar baz
191 - true
192 - [ 'bar', 'baz', 'foo' ]
193 -
194 -boolean_double.js
195 -
196 -````javascript
197 -#!/usr/bin/env node
198 -var argv = require('optimist')
199 - .boolean(['x','y','z'])
200 - .argv
201 -;
202 -console.dir([ argv.x, argv.y, argv.z ]);
203 -console.dir(argv._);
204 -````
205 -
206 -***
207 -
208 - $ ./boolean_double.js -x -z one two three
209 - [ true, false, true ]
210 - [ 'one', 'two', 'three' ]
211 -
212 -Optimist is here to help...
213 ----------------------------
214 -
215 -You can describe parameters for help messages and set aliases. Optimist figures
216 -out how to format a handy help string automatically.
217 -
218 -line_count.js
219 -
220 -````javascript
221 -#!/usr/bin/env node
222 -var argv = require('optimist')
223 - .usage('Count the lines in a file.\nUsage: $0')
224 - .demand('f')
225 - .alias('f', 'file')
226 - .describe('f', 'Load a file')
227 - .argv
228 -;
229 -
230 -var fs = require('fs');
231 -var s = fs.createReadStream(argv.file);
232 -
233 -var lines = 0;
234 -s.on('data', function (buf) {
235 - lines += buf.toString().match(/\n/g).length;
236 -});
237 -
238 -s.on('end', function () {
239 - console.log(lines);
240 -});
241 -````
242 -
243 -***
244 -
245 - $ node line_count.js
246 - Count the lines in a file.
247 - Usage: node ./line_count.js
248 -
249 - Options:
250 - -f, --file Load a file [required]
251 -
252 - Missing required arguments: f
253 -
254 - $ node line_count.js --file line_count.js
255 - 20
256 -
257 - $ node line_count.js -f line_count.js
258 - 20
259 -
260 -methods
261 -=======
262 -
263 -By itself,
264 -
265 -````javascript
266 -require('optimist').argv
267 -`````
268 -
269 -will use `process.argv` array to construct the `argv` object.
270 -
271 -You can pass in the `process.argv` yourself:
272 -
273 -````javascript
274 -require('optimist')([ '-x', '1', '-y', '2' ]).argv
275 -````
276 -
277 -or use .parse() to do the same thing:
278 -
279 -````javascript
280 -require('optimist').parse([ '-x', '1', '-y', '2' ])
281 -````
282 -
283 -The rest of these methods below come in just before the terminating `.argv`.
284 -
285 -.alias(key, alias)
286 -------------------
287 -
288 -Set key names as equivalent such that updates to a key will propagate to aliases
289 -and vice-versa.
290 -
291 -Optionally `.alias()` can take an object that maps keys to aliases.
292 -
293 -.default(key, value)
294 ---------------------
295 -
296 -Set `argv[key]` to `value` if no option was specified on `process.argv`.
297 -
298 -Optionally `.default()` can take an object that maps keys to default values.
299 -
300 -.demand(key)
301 -------------
302 -
303 -If `key` is a string, show the usage information and exit if `key` wasn't
304 -specified in `process.argv`.
305 -
306 -If `key` is a number, demand at least as many non-option arguments, which show
307 -up in `argv._`.
308 -
309 -If `key` is an Array, demand each element.
310 -
311 -.describe(key, desc)
312 ---------------------
313 -
314 -Describe a `key` for the generated usage information.
315 -
316 -Optionally `.describe()` can take an object that maps keys to descriptions.
317 -
318 -.options(key, opt)
319 -------------------
320 -
321 -Instead of chaining together `.alias().demand().default()`, you can specify
322 -keys in `opt` for each of the chainable methods.
323 -
324 -For example:
325 -
326 -````javascript
327 -var argv = require('optimist')
328 - .options('f', {
329 - alias : 'file',
330 - default : '/etc/passwd',
331 - })
332 - .argv
333 -;
334 -````
335 -
336 -is the same as
337 -
338 -````javascript
339 -var argv = require('optimist')
340 - .alias('f', 'file')
341 - .default('f', '/etc/passwd')
342 - .argv
343 -;
344 -````
345 -
346 -Optionally `.options()` can take an object that maps keys to `opt` parameters.
347 -
348 -.usage(message)
349 ----------------
350 -
351 -Set a usage message to show which commands to use. Inside `message`, the string
352 -`$0` will get interpolated to the current script name or node command for the
353 -present script similar to how `$0` works in bash or perl.
354 -
355 -.check(fn)
356 -----------
357 -
358 -Check that certain conditions are met in the provided arguments.
359 -
360 -If `fn` throws or returns `false`, show the thrown error, usage information, and
361 -exit.
362 -
363 -.boolean(key)
364 --------------
365 -
366 -Interpret `key` as a boolean. If a non-flag option follows `key` in
367 -`process.argv`, that string won't get set as the value of `key`.
368 -
369 -If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be
370 -`false`.
371 -
372 -If `key` is an Array, interpret all the elements as booleans.
373 -
374 -.string(key)
375 -------------
376 -
377 -Tell the parser logic not to interpret `key` as a number or boolean.
378 -This can be useful if you need to preserve leading zeros in an input.
379 -
380 -If `key` is an Array, interpret all the elements as strings.
381 -
382 -.wrap(columns)
383 ---------------
384 -
385 -Format usage output to wrap at `columns` many columns.
386 -
387 -.help()
388 --------
389 -
390 -Return the generated usage string.
391 -
392 -.showHelp(fn=console.error)
393 ----------------------------
394 -
395 -Print the usage data using `fn` for printing.
396 -
397 -.parse(args)
398 -------------
399 -
400 -Parse `args` instead of `process.argv`. Returns the `argv` object.
401 -
402 -.argv
403 ------
404 -
405 -Get the arguments as a plain old object.
406 -
407 -Arguments without a corresponding flag show up in the `argv._` array.
408 -
409 -The script name or node command is available at `argv.$0` similarly to how `$0`
410 -works in bash or perl.
411 -
412 -parsing tricks
413 -==============
414 -
415 -stop parsing
416 -------------
417 -
418 -Use `--` to stop parsing flags and stuff the remainder into `argv._`.
419 -
420 - $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4
421 - { _: [ '-c', '3', '-d', '4' ],
422 - '$0': 'node ./examples/reflect.js',
423 - a: 1,
424 - b: 2 }
425 -
426 -negate fields
427 --------------
428 -
429 -If you want to explicity set a field to false instead of just leaving it
430 -undefined or to override a default you can do `--no-key`.
431 -
432 - $ node examples/reflect.js -a --no-b
433 - { _: [],
434 - '$0': 'node ./examples/reflect.js',
435 - a: true,
436 - b: false }
437 -
438 -numbers
439 --------
440 -
441 -Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to
442 -one. This way you can just `net.createConnection(argv.port)` and you can add
443 -numbers out of `argv` with `+` without having that mean concatenation,
444 -which is super frustrating.
445 -
446 -duplicates
447 -----------
448 -
449 -If you specify a flag multiple times it will get turned into an array containing
450 -all the values in order.
451 -
452 - $ node examples/reflect.js -x 5 -x 8 -x 0
453 - { _: [],
454 - '$0': 'node ./examples/reflect.js',
455 - x: [ 5, 8, 0 ] }
456 -
457 -dot notation
458 -------------
459 -
460 -When you use dots (`.`s) in argument names, an implicit object path is assumed.
461 -This lets you organize arguments into nested objects.
462 -
463 - $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5
464 - { _: [],
465 - '$0': 'node ./examples/reflect.js',
466 - foo: { bar: { baz: 33 }, quux: 5 } }
467 -
468 -installation
469 -============
470 -
471 -With [npm](http://github.com/isaacs/npm), just do:
472 - npm install optimist
473 -
474 -or clone this project on github:
475 -
476 - git clone http://github.com/substack/node-optimist.git
477 -
478 -To run the tests with [expresso](http://github.com/visionmedia/expresso),
479 -just do:
480 -
481 - expresso
482 -
483 -inspired By
484 -===========
485 -
486 -This module is loosely inspired by Perl's
487 -[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).
1 -var spawn = require('child_process').spawn;
2 -var test = require('tap').test;
3 -
4 -test('dotSlashEmpty', testCmd('./bin.js', []));
5 -
6 -test('dotSlashArgs', testCmd('./bin.js', [ 'a', 'b', 'c' ]));
7 -
8 -test('nodeEmpty', testCmd('node bin.js', []));
9 -
10 -test('nodeArgs', testCmd('node bin.js', [ 'x', 'y', 'z' ]));
11 -
12 -test('whichNodeEmpty', function (t) {
13 - var which = spawn('which', ['node']);
14 -
15 - which.stdout.on('data', function (buf) {
16 - t.test(
17 - testCmd(buf.toString().trim() + ' bin.js', [])
18 - );
19 - t.end();
20 - });
21 -
22 - which.stderr.on('data', function (err) {
23 - assert.error(err);
24 - t.end();
25 - });
26 -});
27 -
28 -test('whichNodeArgs', function (t) {
29 - var which = spawn('which', ['node']);
30 -
31 - which.stdout.on('data', function (buf) {
32 - t.test(
33 - testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ])
34 - );
35 - t.end();
36 - });
37 -
38 - which.stderr.on('data', function (err) {
39 - t.error(err);
40 - t.end();
41 - });
42 -});
43 -
44 -function testCmd (cmd, args) {
45 -
46 - return function (t) {
47 - var to = setTimeout(function () {
48 - assert.fail('Never got stdout data.')
49 - }, 5000);
50 -
51 - var oldDir = process.cwd();
52 - process.chdir(__dirname + '/_');
53 -
54 - var cmds = cmd.split(' ');
55 -
56 - var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String)));
57 - process.chdir(oldDir);
58 -
59 - bin.stderr.on('data', function (err) {
60 - t.error(err);
61 - t.end();
62 - });
63 -
64 - bin.stdout.on('data', function (buf) {
65 - clearTimeout(to);
66 - var _ = JSON.parse(buf.toString());
67 - t.same(_.map(String), args.map(String));
68 - t.end();
69 - });
70 - };
71 -}
1 -#!/usr/bin/env node
2 -console.log(JSON.stringify(process.argv));
1 -#!/usr/bin/env node
2 -var argv = require('../../index').argv
3 -console.log(JSON.stringify(argv._));
1 -var optimist = require('../index');
2 -var path = require('path');
3 -var test = require('tap').test;
4 -
5 -var $0 = 'node ./' + path.relative(process.cwd(), __filename);
6 -
7 -test('short boolean', function (t) {
8 - var parse = optimist.parse([ '-b' ]);
9 - t.same(parse, { b : true, _ : [], $0 : $0 });
10 - t.same(typeof parse.b, 'boolean');
11 - t.end();
12 -});
13 -
14 -test('long boolean', function (t) {
15 - t.same(
16 - optimist.parse([ '--bool' ]),
17 - { bool : true, _ : [], $0 : $0 }
18 - );
19 - t.end();
20 -});
21 -
22 -test('bare', function (t) {
23 - t.same(
24 - optimist.parse([ 'foo', 'bar', 'baz' ]),
25 - { _ : [ 'foo', 'bar', 'baz' ], $0 : $0 }
26 - );
27 - t.end();
28 -});
29 -
30 -test('short group', function (t) {
31 - t.same(
32 - optimist.parse([ '-cats' ]),
33 - { c : true, a : true, t : true, s : true, _ : [], $0 : $0 }
34 - );
35 - t.end();
36 -});
37 -
38 -test('short group next', function (t) {
39 - t.same(
40 - optimist.parse([ '-cats', 'meow' ]),
41 - { c : true, a : true, t : true, s : 'meow', _ : [], $0 : $0 }
42 - );
43 - t.end();
44 -});
45 -
46 -test('short capture', function (t) {
47 - t.same(
48 - optimist.parse([ '-h', 'localhost' ]),
49 - { h : 'localhost', _ : [], $0 : $0 }
50 - );
51 - t.end();
52 -});
53 -
54 -test('short captures', function (t) {
55 - t.same(
56 - optimist.parse([ '-h', 'localhost', '-p', '555' ]),
57 - { h : 'localhost', p : 555, _ : [], $0 : $0 }
58 - );
59 - t.end();
60 -});
61 -
62 -test('long capture sp', function (t) {
63 - t.same(
64 - optimist.parse([ '--pow', 'xixxle' ]),
65 - { pow : 'xixxle', _ : [], $0 : $0 }
66 - );
67 - t.end();
68 -});
69 -
70 -test('long capture eq', function (t) {
71 - t.same(
72 - optimist.parse([ '--pow=xixxle' ]),
73 - { pow : 'xixxle', _ : [], $0 : $0 }
74 - );
75 - t.end()
76 -});
77 -
78 -test('long captures sp', function (t) {
79 - t.same(
80 - optimist.parse([ '--host', 'localhost', '--port', '555' ]),
81 - { host : 'localhost', port : 555, _ : [], $0 : $0 }
82 - );
83 - t.end();
84 -});
85 -
86 -test('long captures eq', function (t) {
87 - t.same(
88 - optimist.parse([ '--host=localhost', '--port=555' ]),
89 - { host : 'localhost', port : 555, _ : [], $0 : $0 }
90 - );
91 - t.end();
92 -});
93 -
94 -test('mixed short bool and capture', function (t) {
95 - t.same(
96 - optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
97 - {
98 - f : true, p : 555, h : 'localhost',
99 - _ : [ 'script.js' ], $0 : $0,
100 - }
101 - );
102 - t.end();
103 -});
104 -
105 -test('short and long', function (t) {
106 - t.same(
107 - optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
108 - {
109 - f : true, p : 555, h : 'localhost',
110 - _ : [ 'script.js' ], $0 : $0,
111 - }
112 - );
113 - t.end();
114 -});
115 -
116 -test('no', function (t) {
117 - t.same(
118 - optimist.parse([ '--no-moo' ]),
119 - { moo : false, _ : [], $0 : $0 }
120 - );
121 - t.end();
122 -});
123 -
124 -test('multi', function (t) {
125 - t.same(
126 - optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
127 - { v : ['a','b','c'], _ : [], $0 : $0 }
128 - );
129 - t.end();
130 -});
131 -
132 -test('comprehensive', function (t) {
133 - t.same(
134 - optimist.parse([
135 - '--name=meowmers', 'bare', '-cats', 'woo',
136 - '-h', 'awesome', '--multi=quux',
137 - '--key', 'value',
138 - '-b', '--bool', '--no-meep', '--multi=baz',
139 - '--', '--not-a-flag', 'eek'
140 - ]),
141 - {
142 - c : true,
143 - a : true,
144 - t : true,
145 - s : 'woo',
146 - h : 'awesome',
147 - b : true,
148 - bool : true,
149 - key : 'value',
150 - multi : [ 'quux', 'baz' ],
151 - meep : false,
152 - name : 'meowmers',
153 - _ : [ 'bare', '--not-a-flag', 'eek' ],
154 - $0 : $0
155 - }
156 - );
157 - t.end();
158 -});
159 -
160 -test('nums', function (t) {
161 - var argv = optimist.parse([
162 - '-x', '1234',
163 - '-y', '5.67',
164 - '-z', '1e7',
165 - '-w', '10f',
166 - '--hex', '0xdeadbeef',
167 - '789',
168 - ]);
169 - t.same(argv, {
170 - x : 1234,
171 - y : 5.67,
172 - z : 1e7,
173 - w : '10f',
174 - hex : 0xdeadbeef,
175 - _ : [ 789 ],
176 - $0 : $0
177 - });
178 - t.same(typeof argv.x, 'number');
179 - t.same(typeof argv.y, 'number');
180 - t.same(typeof argv.z, 'number');
181 - t.same(typeof argv.w, 'string');
182 - t.same(typeof argv.hex, 'number');
183 - t.same(typeof argv._[0], 'number');
184 - t.end();
185 -});
186 -
187 -test('flag boolean', function (t) {
188 - var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv;
189 - t.same(parse, { t : true, _ : [ 'moo' ], $0 : $0 });
190 - t.same(typeof parse.t, 'boolean');
191 - t.end();
192 -});
193 -
194 -test('flag boolean value', function (t) {
195 - var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true'])
196 - .boolean(['t', 'verbose']).default('verbose', true).argv;
197 -
198 - t.same(parse, {
199 - verbose: false,
200 - t: true,
201 - _: ['moo'],
202 - $0 : $0
203 - });
204 -
205 - t.same(typeof parse.verbose, 'boolean');
206 - t.same(typeof parse.t, 'boolean');
207 - t.end();
208 -});
209 -
210 -test('flag boolean default false', function (t) {
211 - var parse = optimist(['moo'])
212 - .boolean(['t', 'verbose'])
213 - .default('verbose', false)
214 - .default('t', false).argv;
215 -
216 - t.same(parse, {
217 - verbose: false,
218 - t: false,
219 - _: ['moo'],
220 - $0 : $0
221 - });
222 -
223 - t.same(typeof parse.verbose, 'boolean');
224 - t.same(typeof parse.t, 'boolean');
225 - t.end();
226 -
227 -});
228 -
229 -test('boolean groups', function (t) {
230 - var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ])
231 - .boolean(['x','y','z']).argv;
232 -
233 - t.same(parse, {
234 - x : true,
235 - y : false,
236 - z : true,
237 - _ : [ 'one', 'two', 'three' ],
238 - $0 : $0
239 - });
240 -
241 - t.same(typeof parse.x, 'boolean');
242 - t.same(typeof parse.y, 'boolean');
243 - t.same(typeof parse.z, 'boolean');
244 - t.end();
245 -});
246 -
247 -test('newlines in params' , function (t) {
248 - var args = optimist.parse([ '-s', "X\nX" ])
249 - t.same(args, { _ : [], s : "X\nX", $0 : $0 });
250 -
251 - // reproduce in bash:
252 - // VALUE="new
253 - // line"
254 - // node program.js --s="$VALUE"
255 - args = optimist.parse([ "--s=X\nX" ])
256 - t.same(args, { _ : [], s : "X\nX", $0 : $0 });
257 - t.end();
258 -});
259 -
260 -test('strings' , function (t) {
261 - var s = optimist([ '-s', '0001234' ]).string('s').argv.s;
262 - t.same(s, '0001234');
263 - t.same(typeof s, 'string');
264 -
265 - var x = optimist([ '-x', '56' ]).string('x').argv.x;
266 - t.same(x, '56');
267 - t.same(typeof x, 'string');
268 - t.end();
269 -});
270 -
271 -test('stringArgs', function (t) {
272 - var s = optimist([ ' ', ' ' ]).string('_').argv._;
273 - t.same(s.length, 2);
274 - t.same(typeof s[0], 'string');
275 - t.same(s[0], ' ');
276 - t.same(typeof s[1], 'string');
277 - t.same(s[1], ' ');
278 - t.end();
279 -});
280 -
281 -test('slashBreak', function (t) {
282 - t.same(
283 - optimist.parse([ '-I/foo/bar/baz' ]),
284 - { I : '/foo/bar/baz', _ : [], $0 : $0 }
285 - );
286 - t.same(
287 - optimist.parse([ '-xyz/foo/bar/baz' ]),
288 - { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : $0 }
289 - );
290 - t.end();
291 -});
292 -
293 -test('alias', function (t) {
294 - var argv = optimist([ '-f', '11', '--zoom', '55' ])
295 - .alias('z', 'zoom')
296 - .argv
297 - ;
298 - t.equal(argv.zoom, 55);
299 - t.equal(argv.z, argv.zoom);
300 - t.equal(argv.f, 11);
301 - t.end();
302 -});
303 -
304 -test('multiAlias', function (t) {
305 - var argv = optimist([ '-f', '11', '--zoom', '55' ])
306 - .alias('z', [ 'zm', 'zoom' ])
307 - .argv
308 - ;
309 - t.equal(argv.zoom, 55);
310 - t.equal(argv.z, argv.zoom);
311 - t.equal(argv.z, argv.zm);
312 - t.equal(argv.f, 11);
313 - t.end();
314 -});
315 -
316 -test('boolean default true', function (t) {
317 - var argv = optimist.options({
318 - sometrue: {
319 - boolean: true,
320 - default: true
321 - }
322 - }).argv;
323 -
324 - t.equal(argv.sometrue, true);
325 - t.end();
326 -});
327 -
328 -test('boolean default false', function (t) {
329 - var argv = optimist.options({
330 - somefalse: {
331 - boolean: true,
332 - default: false
333 - }
334 - }).argv;
335 -
336 - t.equal(argv.somefalse, false);
337 - t.end();
338 -});
339 -
340 -test('nested dotted objects', function (t) {
341 - var argv = optimist([
342 - '--foo.bar', '3', '--foo.baz', '4',
343 - '--foo.quux.quibble', '5', '--foo.quux.o_O',
344 - '--beep.boop'
345 - ]).argv;
346 -
347 - t.same(argv.foo, {
348 - bar : 3,
349 - baz : 4,
350 - quux : {
351 - quibble : 5,
352 - o_O : true
353 - },
354 - });
355 - t.same(argv.beep, { boop : true });
356 - t.end();
357 -});
358 -
359 -test('boolean and alias with chainable api', function (t) {
360 - var aliased = [ '-h', 'derp' ];
361 - var regular = [ '--herp', 'derp' ];
362 - var opts = {
363 - herp: { alias: 'h', boolean: true }
364 - };
365 - var aliasedArgv = optimist(aliased)
366 - .boolean('herp')
367 - .alias('h', 'herp')
368 - .argv;
369 - var propertyArgv = optimist(regular)
370 - .boolean('herp')
371 - .alias('h', 'herp')
372 - .argv;
373 - var expected = {
374 - herp: true,
375 - h: true,
376 - '_': [ 'derp' ],
377 - '$0': $0,
378 - };
379 -
380 - t.same(aliasedArgv, expected);
381 - t.same(propertyArgv, expected);
382 - t.end();
383 -});
384 -
385 -test('boolean and alias with options hash', function (t) {
386 - var aliased = [ '-h', 'derp' ];
387 - var regular = [ '--herp', 'derp' ];
388 - var opts = {
389 - herp: { alias: 'h', boolean: true }
390 - };
391 - var aliasedArgv = optimist(aliased)
392 - .options(opts)
393 - .argv;
394 - var propertyArgv = optimist(regular).options(opts).argv;
395 - var expected = {
396 - herp: true,
397 - h: true,
398 - '_': [ 'derp' ],
399 - '$0': $0,
400 - };
401 -
402 - t.same(aliasedArgv, expected);
403 - t.same(propertyArgv, expected);
404 -
405 - t.end();
406 -});
407 -
408 -test('boolean and alias using explicit true', function (t) {
409 - var aliased = [ '-h', 'true' ];
410 - var regular = [ '--herp', 'true' ];
411 - var opts = {
412 - herp: { alias: 'h', boolean: true }
413 - };
414 - var aliasedArgv = optimist(aliased)
415 - .boolean('h')
416 - .alias('h', 'herp')
417 - .argv;
418 - var propertyArgv = optimist(regular)
419 - .boolean('h')
420 - .alias('h', 'herp')
421 - .argv;
422 - var expected = {
423 - herp: true,
424 - h: true,
425 - '_': [ ],
426 - '$0': $0,
427 - };
428 -
429 - t.same(aliasedArgv, expected);
430 - t.same(propertyArgv, expected);
431 - t.end();
432 -});
433 -
434 -// regression, see https://github.com/substack/node-optimist/issues/71
435 -test('boolean and --x=true', function(t) {
436 - var parsed = optimist(['--boool', '--other=true']).boolean('boool').argv;
437 -
438 - t.same(parsed.boool, true);
439 - t.same(parsed.other, 'true');
440 -
441 - parsed = optimist(['--boool', '--other=false']).boolean('boool').argv;
442 -
443 - t.same(parsed.boool, true);
444 - t.same(parsed.other, 'false');
445 - t.end();
446 -});
1 -var Hash = require('hashish');
2 -var optimist = require('../index');
3 -var test = require('tap').test;
4 -
5 -test('usageFail', function (t) {
6 - var r = checkUsage(function () {
7 - return optimist('-x 10 -z 20'.split(' '))
8 - .usage('Usage: $0 -x NUM -y NUM')
9 - .demand(['x','y'])
10 - .argv;
11 - });
12 - t.same(
13 - r.result,
14 - { x : 10, z : 20, _ : [], $0 : './usage' }
15 - );
16 -
17 - t.same(
18 - r.errors.join('\n').split(/\n+/),
19 - [
20 - 'Usage: ./usage -x NUM -y NUM',
21 - 'Options:',
22 - ' -x [required]',
23 - ' -y [required]',
24 - 'Missing required arguments: y',
25 - ]
26 - );
27 - t.same(r.logs, []);
28 - t.ok(r.exit);
29 - t.end();
30 -});
31 -
32 -
33 -test('usagePass', function (t) {
34 - var r = checkUsage(function () {
35 - return optimist('-x 10 -y 20'.split(' '))
36 - .usage('Usage: $0 -x NUM -y NUM')
37 - .demand(['x','y'])
38 - .argv;
39 - });
40 - t.same(r, {
41 - result : { x : 10, y : 20, _ : [], $0 : './usage' },
42 - errors : [],
43 - logs : [],
44 - exit : false,
45 - });
46 - t.end();
47 -});
48 -
49 -test('checkPass', function (t) {
50 - var r = checkUsage(function () {
51 - return optimist('-x 10 -y 20'.split(' '))
52 - .usage('Usage: $0 -x NUM -y NUM')
53 - .check(function (argv) {
54 - if (!('x' in argv)) throw 'You forgot about -x';
55 - if (!('y' in argv)) throw 'You forgot about -y';
56 - })
57 - .argv;
58 - });
59 - t.same(r, {
60 - result : { x : 10, y : 20, _ : [], $0 : './usage' },
61 - errors : [],
62 - logs : [],
63 - exit : false,
64 - });
65 - t.end();
66 -});
67 -
68 -test('checkFail', function (t) {
69 - var r = checkUsage(function () {
70 - return optimist('-x 10 -z 20'.split(' '))
71 - .usage('Usage: $0 -x NUM -y NUM')
72 - .check(function (argv) {
73 - if (!('x' in argv)) throw 'You forgot about -x';
74 - if (!('y' in argv)) throw 'You forgot about -y';
75 - })
76 - .argv;
77 - });
78 -
79 - t.same(
80 - r.result,
81 - { x : 10, z : 20, _ : [], $0 : './usage' }
82 - );
83 -
84 - t.same(
85 - r.errors.join('\n').split(/\n+/),
86 - [
87 - 'Usage: ./usage -x NUM -y NUM',
88 - 'You forgot about -y'
89 - ]
90 - );
91 -
92 - t.same(r.logs, []);
93 - t.ok(r.exit);
94 - t.end();
95 -});
96 -
97 -test('checkCondPass', function (t) {
98 - function checker (argv) {
99 - return 'x' in argv && 'y' in argv;
100 - }
101 -
102 - var r = checkUsage(function () {
103 - return optimist('-x 10 -y 20'.split(' '))
104 - .usage('Usage: $0 -x NUM -y NUM')
105 - .check(checker)
106 - .argv;
107 - });
108 - t.same(r, {
109 - result : { x : 10, y : 20, _ : [], $0 : './usage' },
110 - errors : [],
111 - logs : [],
112 - exit : false,
113 - });
114 - t.end();
115 -});
116 -
117 -test('checkCondFail', function (t) {
118 - function checker (argv) {
119 - return 'x' in argv && 'y' in argv;
120 - }
121 -
122 - var r = checkUsage(function () {
123 - return optimist('-x 10 -z 20'.split(' '))
124 - .usage('Usage: $0 -x NUM -y NUM')
125 - .check(checker)
126 - .argv;
127 - });
128 -
129 - t.same(
130 - r.result,
131 - { x : 10, z : 20, _ : [], $0 : './usage' }
132 - );
133 -
134 - t.same(
135 - r.errors.join('\n').split(/\n+/).join('\n'),
136 - 'Usage: ./usage -x NUM -y NUM\n'
137 - + 'Argument check failed: ' + checker.toString()
138 - );
139 -
140 - t.same(r.logs, []);
141 - t.ok(r.exit);
142 - t.end();
143 -});
144 -
145 -test('countPass', function (t) {
146 - var r = checkUsage(function () {
147 - return optimist('1 2 3 --moo'.split(' '))
148 - .usage('Usage: $0 [x] [y] [z] {OPTIONS}')
149 - .demand(3)
150 - .argv;
151 - });
152 - t.same(r, {
153 - result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' },
154 - errors : [],
155 - logs : [],
156 - exit : false,
157 - });
158 - t.end();
159 -});
160 -
161 -test('countFail', function (t) {
162 - var r = checkUsage(function () {
163 - return optimist('1 2 --moo'.split(' '))
164 - .usage('Usage: $0 [x] [y] [z] {OPTIONS}')
165 - .demand(3)
166 - .argv;
167 - });
168 - t.same(
169 - r.result,
170 - { _ : [ '1', '2' ], moo : true, $0 : './usage' }
171 - );
172 -
173 - t.same(
174 - r.errors.join('\n').split(/\n+/),
175 - [
176 - 'Usage: ./usage [x] [y] [z] {OPTIONS}',
177 - 'Not enough non-option arguments: got 2, need at least 3',
178 - ]
179 - );
180 -
181 - t.same(r.logs, []);
182 - t.ok(r.exit);
183 - t.end();
184 -});
185 -
186 -test('defaultSingles', function (t) {
187 - var r = checkUsage(function () {
188 - return optimist('--foo 50 --baz 70 --powsy'.split(' '))
189 - .default('foo', 5)
190 - .default('bar', 6)
191 - .default('baz', 7)
192 - .argv
193 - ;
194 - });
195 - t.same(r.result, {
196 - foo : '50',
197 - bar : 6,
198 - baz : '70',
199 - powsy : true,
200 - _ : [],
201 - $0 : './usage',
202 - });
203 - t.end();
204 -});
205 -
206 -test('defaultAliases', function (t) {
207 - var r = checkUsage(function () {
208 - return optimist('')
209 - .alias('f', 'foo')
210 - .default('f', 5)
211 - .argv
212 - ;
213 - });
214 - t.same(r.result, {
215 - f : '5',
216 - foo : '5',
217 - _ : [],
218 - $0 : './usage',
219 - });
220 - t.end();
221 -});
222 -
223 -test('defaultHash', function (t) {
224 - var r = checkUsage(function () {
225 - return optimist('--foo 50 --baz 70'.split(' '))
226 - .default({ foo : 10, bar : 20, quux : 30 })
227 - .argv
228 - ;
229 - });
230 - t.same(r.result, {
231 - _ : [],
232 - $0 : './usage',
233 - foo : 50,
234 - baz : 70,
235 - bar : 20,
236 - quux : 30,
237 - });
238 - t.end();
239 -});
240 -
241 -test('rebase', function (t) {
242 - t.equal(
243 - optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'),
244 - './foo/bar/baz'
245 - );
246 - t.equal(
247 - optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'),
248 - '../../..'
249 - );
250 - t.equal(
251 - optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'),
252 - '../pow/zoom.txt'
253 - );
254 - t.end();
255 -});
256 -
257 -function checkUsage (f) {
258 -
259 - var exit = false;
260 -
261 - process._exit = process.exit;
262 - process._env = process.env;
263 - process._argv = process.argv;
264 -
265 - process.exit = function (t) { exit = true };
266 - process.env = Hash.merge(process.env, { _ : 'node' });
267 - process.argv = [ './usage' ];
268 -
269 - var errors = [];
270 - var logs = [];
271 -
272 - console._error = console.error;
273 - console.error = function (msg) { errors.push(msg) };
274 - console._log = console.log;
275 - console.log = function (msg) { logs.push(msg) };
276 -
277 - var result = f();
278 -
279 - process.exit = process._exit;
280 - process.env = process._env;
281 - process.argv = process._argv;
282 -
283 - console.error = console._error;
284 - console.log = console._log;
285 -
286 - return {
287 - errors : errors,
288 - logs : logs,
289 - exit : exit,
290 - result : result,
291 - };
292 -};
1 -TODO
2 -
3 -v0.5.0
4 -+ Major cleanup
5 -+ Remove old unused functionality
6 -+ Load modules in parallel (faster dev mode)
7 -
8 -v0.4.9
9 -+ Make the max length of lines an option and make it quite short by default for easier debugging
10 -
11 -v0.4.7
12 -+ Remove default port and host - just use what the current page uses by default
13 -+ Treat Android devices as mobile, with regards to loading resources in one big response rather than individual requests
14 -+ Now works if script include put in head
15 -
16 -v0.4.6
17 -+ Add server.setOpts and server.handleRequest
18 -
19 -v0.4.5
20 -+ Set the mimetype of script files correctly
21 -+ Remove node_modules directory - use dependencies in package.json instead
22 -+ Implement addPath and addFile for specifying custom path resolutions
23 -+ Implement addReplacement for replacing code during dev serving or compilation
24 -+ Implement dontAddClosureForModule and dontIncludeModule for compiler
25 -+ Remove dependency on std.js
26 -+ Add usePagePort option to make module requests go to the host/port of the page it's served on, rather than the host/port passed in to listen(port, ...)
27 -
28 -v0.4.4
29 -+ Import js files directly under node_modules correctly, e.g. ./node_modules/foo.js
30 -
31 -v0.4.3
32 -+ Fix import of socket.io browser npm module
33 -+ Enable nested npm module imports by reimplementing node's require.resolve algorithm
34 -
35 -v0.4.2
36 -+ Use uglifyjs to compress JS
37 -+ Synchronous compilation API
38 -+ Remove --paths option. Search for modules exactly like require.resolve does
39 -+ Greatle simplify Readme instructions
40 -+ Use util.resolve in compiler, minimizing repeated code
41 -+ Implement require.mount(server, opts) - mounts itself onto an existing http server
42 -+ Implement require.connect(opts) - connect middleware
43 -+ Implement require.isRequireRequest - checks if an http request is for the require server
44 -
45 -v0.4.1
46 -+ Consult package.json's "main" field when resolving modules in the compiler
47 -+ Fix bug where modules starting with (function() { ... }) would throw in their compiled form
48 -+ Clearer compiler usage example in example/compile.js
49 -+ Better error messages when a module cannot be found during compilation
50 -
51 -v0.4.0
52 -+ New API
53 -+ New command line utility
54 -+ New documentation
55 -
56 -v0.3.2
57 -+ Improved command line tool
58 -+ new API: single method require('require/compiler').compile(<code | file path>, <compilation level 0 | 1 | 2 | 3>, <callback>)
59 -+ allow chaining of methods on the require server
60 -+ alert an error message client-side when a module is not found (rather than crash the process :)
61 -
62 -v0.3.1
63 -+ Fix context bug in delay
64 -+ Change compiled instances of require._[PATH] to require[PATH]. require is simply a hash of module paths.
65 -+ Add setRoot API
66 -+ Improved docs in README
67 -+ Binary request-dev --port 1234 --host localhost ./path
68 -
69 -v0.3.0
70 -+ Make a standalone server for dev mode
71 -
72 -v0.2.8
73 -+ Don't leave require.paths modified after require.resolve. Add paths right before they're needed, and remove paths after.
74 -
75 -v0.2.7
76 -+ Improve path resolution
77 -
78 -v0.2.6
79 -+ Improve the order in which we try to load modules
80 -
81 -v0.2.5
82 -+ Fix compilation order for __main__
83 -
84 -v0.2.1
85 -+ A development server that serves requires files in dev mode
86 -
87 -v0.2.0
88 -+ latest version published on npm
89 -
90 -v0.1.13
91 -+ better file layout - bin/ lib/
92 -+ created bin/compile to compile files
93 -+ created bin/compress to compile and compress files
94 -+ improved readability of compiled files by flattening the require hierarchy
95 -+ replace module names with short names, e.g. "_1", "_2", etc
96 -
97 -v0.1.12
98 -+ Support module path names in the compiler, e.g. require('require/compiler')
99 -
100 -v0.1.11
101 -+ Fix: compiler now resolves module/index.js paths correctly
102 -
103 -v0.1.10
104 -+ Allow for a node server to server require using require('require').toString()
105 -
106 -v0.1.9
107 -+ It's no longer required to add id="browser-require" to a script tag in order to load the main module automatically
108 -
109 -v0.1.8
110 -+ Rename to require
111 -
112 -v0.1.7
113 -+ Publish with npm
114 -
115 -v0.1.6
116 -+ Fix: Variables declared inside of require.js are no longer visible to imported modules
117 -+ Remove the "root" configuration parameter added in v0.1.1. You cannot modify the root in node.
118 -
119 -v0.1.5
120 -+ Allow for a file inside of a folder to import the folder's index file with require('./')
121 -
122 -v0.1.4
123 -+ Allow modules with circular dependencies to reference each other
124 -
125 -v0.1.3
126 -+ Don't get stuck loading circular dependencies
127 -
128 -v0.1.2
129 -+ Support index.js - if a module is not found at location, look for it at location/index.js
130 -
131 -v0.1.1
132 -+ Support the "root" configuration parameter
133 -+ Fix: consecutive slashes get replaced with a single slash as opposed to no slash
134 -
135 -v0.1.0
136 -First version, implements node's require() statement for the browser
1 -Copyright (c) 2011 Marcus Westin
2 -
3 -Permission is hereby granted, free of charge, to any person obtaining a copy
4 -of this software and associated documentation files (the "Software"), to deal
5 -in the Software without restriction, including without limitation the rights
6 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 -copies of the Software, and to permit persons to whom the Software is
8 -furnished to do so, subject to the following conditions:
9 -
10 -The above copyright notice and this permission notice shall be included in
11 -all copies or substantial portions of the Software.
12 -
13 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 -THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 -require brings `require` to the browser
2 -=======================================
3 -
4 -Node's `require()` is the de facto javascript dependency statement.
5 -
6 -`npm` is the de facto javascript module manager.
7 -
8 -require brings both of them to the browser.
9 -
10 -tl;dr
11 -=====
12 -"Just give me some code that runs"
13 -
14 - mkdir app; cd app
15 - echo '{ "name":"app" }' > package.json
16 - sudo npm install require
17 - sudo npm install raphael
18 - curl -O https://raw.github.com/gist/975866/little_server.js
19 - curl -O https://raw.github.com/gist/975868/little_client.js
20 - node little_server.js
21 -
22 -Now go to http://localhost:8080
23 -
24 -Install
25 -=======
26 -
27 - sudo npm install -g require
28 -
29 -Run
30 -===
31 -Start dev server
32 -
33 - require serve ./example --port 1234 --host localhost
34 -
35 -In your HTML:
36 -
37 - <script src="//localhost:1234/require/client"></script>
38 -
39 -This is like calling require('client') from inside ./example.
40 -[Read more on node's require path resolution](http://nodejs.org/api/modules.html)
41 -
42 -Compile
43 -=======
44 -(You'll want to do this before you deploy to production)
45 -
46 - require compile ./example/client.js > client.min.js
47 -
48 -Use programmatically
49 -====================
50 -In node:
51 -
52 - require('require/server').listen(1234)
53 -
54 -or mount it on an http server you're already running
55 -
56 - var server = http.createServer(function(req, res) { })
57 - require('require/server').mount(server)
58 - server.listen(8080, 'localhost')
59 -
60 -or, as connect middleware
61 -
62 - connect.createServer(
63 - connect.static(__dirname + '/example'),
64 - require('require/server').connect()
65 - )
66 -
67 -Compile programmatically:
68 -
69 - var compiler = require('require/compiler')
70 - console.log(compiler.compile('./example/client.js'))
71 - console.log(compiler.compileCode('require("./example/client")'))
72 -
73 -The compiler supports all the options of https://github.com/mishoo/UglifyJS, e.g.
74 -
75 - compiler.compile('./example/client.js', { beautify:true, ascii_only:true })
1 -#!/usr/bin/env node
2 -
3 -var path = require('path'),
4 - server = require('../server'),
5 - compiler = require('../compiler')
6 -
7 -var opts = {
8 - port: 1234,
9 - host: 'localhost',
10 - command: null,
11 - path: null
12 -}
13 -
14 -var args = [].slice.call(process.argv, 2)
15 -
16 -opts.command = args.shift()
17 -opts.path = path.resolve(args.shift())
18 -
19 -while (args.length) {
20 - var arg = args.shift()
21 - switch(arg) {
22 - case '--port':
23 - opts.port = args.shift()
24 - break
25 - case '--host':
26 - opts.host = args.shift()
27 - break
28 - case '--root':
29 - opts.root = args.shift()
30 - break
31 - case '--usePagePort':
32 - if (args[0] && args[0][0] != '-') {
33 - console.log('Unexpected value for --usePagePort flag', args[0])
34 - process.exit(1)
35 - }
36 - opts.usePagePort = true
37 - break
38 - default:
39 - console.log('Unknown option', arg)
40 - process.exit(1)
41 - break
42 - }
43 -}
44 -
45 -switch (opts.command) {
46 - case 'serve':
47 - if (!opts.path) {
48 - console.log('Specify a path to serve from, e.g. require serve ./example')
49 - process.exit(1)
50 - }
51 - server.listen(opts)
52 - console.log('serving from', opts.path, 'on', 'http://'+opts.host+':'+opts.port)
53 - break
54 - case 'compile':
55 - if (!opts.path) {
56 - console.log('Specify a single file to compile, e.g. require compile ./path/to/file.js')
57 - process.exit(1)
58 - }
59 - console.log(compiler.compile(opts.path))
60 - break
61 - default:
62 - if (opts.command) {
63 - console.log('Unknown command', '"' + opts.command + '".', 'Try "require serve" or "require compile"')
64 - } else {
65 - console.log('You need to give a command, e.g. "require serve" or "require compile"')
66 - }
67 - process.exit(1)
68 -}
69 -
1 -var fs = require('fs')
2 -var path = require('path')
3 -var extend = require('std/extend')
4 -var each = require('std/each')
5 -var getCode = require('./lib/getCode')
6 -var resolve = require('./lib/resolve')
7 -var getRequireStatements = require('./lib/getRequireStatements')
8 -
9 -module.exports = {
10 - compile: compileFile,
11 - compileHTML: compileHTMLFile,
12 - compileCode: compileCode
13 -}
14 -
15 -/* api
16 - *****/
17 -function compileFile(filePath, opts) {
18 - filePath = path.resolve(filePath)
19 - opts = extend(opts, { basePath:path.dirname(filePath), toplevel:true })
20 - var code = getCode(filePath)
21 - return _compile(code, opts, filePath)
22 -}
23 -
24 -function compileCode(code, opts) {
25 - opts = extend(opts, { basePath:process.cwd(), toplevel:true })
26 - return _compile(code, opts, '<code passed into compiler.compile()>')
27 -}
28 -
29 -function compileHTMLFile(filePath, opts) {
30 - var html = fs.readFileSync(filePath).toString()
31 - while (match = html.match(/<script src="\/require\/([\/\w\.]+)"><\/script>/)) {
32 - var js = compileFile(match[1].toString(), opts)
33 -
34 - var BACKREFERENCE_WORKAROUND = '____________backreference_workaround________'
35 - js = js.replace('\$\&', BACKREFERENCE_WORKAROUND)
36 - html = html.replace(match[0], '<script>'+js+'</script>')
37 - html = html.replace(BACKREFERENCE_WORKAROUND, '\$\&')
38 - }
39 - return html
40 -}
41 -
42 -
43 -var _compile = function(code, opts, mainModule) {
44 - var code = 'var __require__ = {}, require=function(){}\n' + _compileModule(code, opts.basePath, mainModule)
45 - if (opts.minify === false) { return code } // TODO use uglifyjs' beautifier?
46 -
47 - var UglifyJS = require('uglify-js')
48 - var result = UglifyJS.minify(code, {
49 - fromString:true,
50 - mangle:true,
51 - output: {
52 - // http://lisperator.net/uglifyjs/codegen
53 - indent_start : 0, // start indentation on every line (only when `beautify`)
54 - indent_level : 4, // indentation level (only when `beautify`)
55 - quote_keys : false, // quote all keys in object literals?
56 - space_colon : true, // add a space after colon signs?
57 - ascii_only : false, // output ASCII-safe? (encodes Unicode characters as ASCII)
58 - inline_script : false, // escape "</script"?
59 - width : 80, // informative maximum line width (for beautified output)
60 - max_line_len : 200, // maximum line length (for non-beautified output)
61 - ie_proof : true, // output IE-safe code?
62 - beautify : false, // beautify output?
63 - source_map : null, // output a source map
64 - bracketize : false, // use brackets every time?
65 - comments : false, // output comments?
66 - semicolons : true // use semicolons to separate statements? (otherwise, newlines)
67 - },
68 - compress: {
69 - // http://lisperator.net/uglifyjs/compress
70 - sequences : true, // join consecutive statemets with the “comma operator”
71 - properties : true, // optimize property access: a["foo"] → a.foo
72 - dead_code : true, // discard unreachable code
73 - drop_debugger : true, // discard “debugger” statements
74 - unsafe : false, // some unsafe optimizations (see below)
75 - conditionals : true, // optimize if-s and conditional expressions
76 - comparisons : true, // optimize comparisons
77 - evaluate : true, // evaluate constant expressions
78 - booleans : true, // optimize boolean expressions
79 - loops : true, // optimize loops
80 - unused : true, // drop unused variables/functions
81 - hoist_funs : true, // hoist function declarations
82 - hoist_vars : false, // hoist variable declarations
83 - if_return : true, // optimize if-s followed by return/continue
84 - join_vars : true, // join var declarations
85 - cascade : true, // try to cascade `right` into `left` in sequences
86 - side_effects : true, // drop side-effect-free statements
87 - warnings : false, // warn about potentially dangerous optimizations/code
88 - global_defs : {} // global definitions
89 - }
90 - })
91 - // also see result.map
92 - return result.code
93 -}
94 -
95 -/* util
96 - ******/
97 -var _compileModule = function(code, pathBase, mainModule) {
98 - var modules = [mainModule]
99 - _replaceRequireStatements(mainModule, code, modules, pathBase)
100 - code = _concatModules(modules)
101 - code = _minifyRequireStatements(code, modules)
102 - return code
103 -}
104 -
105 -var _minifyRequireStatements = function(code, modules) {
106 - each(modules, function(modulePath, i) {
107 - var escapedPath = modulePath.replace(/\//g, '\\/').replace('(','\\(').replace(')','\\)')
108 - var regex = new RegExp('__require__\\["'+ escapedPath +'"\\]', 'g')
109 -
110 - code = code.replace(regex, '__require__["_'+ i +'"]')
111 - })
112 - return code
113 -}
114 -
115 -var _replaceRequireStatements = function(modulePath, code, modules, pathBase) {
116 - var requireStatements = getRequireStatements(code)
117 -
118 - if (!requireStatements.length) {
119 - modules[modulePath] = code
120 - return
121 - }
122 -
123 - each(requireStatements, function(requireStatement) {
124 - var subModulePath = resolve.requireStatement(requireStatement, modulePath)
125 -
126 - if (!subModulePath) {
127 - throw new Error("Require Compiler Error: Cannot find module '"+ rawModulePath +"' (in '"+ modulePath +"')")
128 - }
129 -
130 - code = code.replace(requireStatement, '__require__["' + subModulePath + '"].exports')
131 -
132 - if (!modules[subModulePath]) {
133 - modules[subModulePath] = true
134 - var newPathBase = path.dirname(subModulePath)
135 - var newModuleCode = getCode(subModulePath)
136 - _replaceRequireStatements(subModulePath, newModuleCode, modules, newPathBase)
137 - modules.push(subModulePath)
138 - }
139 - })
140 -
141 - modules[modulePath] = code
142 -}
143 -
144 -var _concatModules = function(modules) {
145 - var getClosuredModule = function(modulePath) {
146 - return [
147 - ';(function() {',
148 - ' // ' + modulePath,
149 - ' var module = __require__["'+modulePath+'"] = {exports:{}}, exports = module.exports;',
150 - modules[modulePath],
151 - '})()'
152 - ].join('\n')
153 - }
154 -
155 - var moduleDefinitions = []
156 - for (var i=1, modulePath; modulePath = modules[i]; i++) {
157 - moduleDefinitions.push(getClosuredModule(modulePath))
158 - }
159 - moduleDefinitions.push(getClosuredModule(modules[0])) // __main__
160 -
161 - return moduleDefinitions.join('\n\n')
162 -}
1 -var dependency = require('./shared/dependency')
2 -
3 -var el = document.body.appendChild(document.createElement('div'))
4 -el.innerHTML = 'shared dependency:' + JSON.stringify(dependency)
1 -var fs = require('fs'),
2 - compiler = require('../compiler')
3 -
4 -var file = __dirname + '/client.js',
5 - basePath = __dirname,
6 - code = fs.readFileSync(file).toString()
7 -
8 -console.log(compiler.compileCode(code, { basePath:__dirname }))
1 -var connect = require('connect'),
2 - requireServer = require('require/server')
3 -
4 -connect.createServer(
5 - connect.static(__dirname),
6 - requireServer.connect(__dirname)
7 -).listen(8080)
1 -<!doctype html>
2 -<html>
3 -<head>
4 - <title>test</title>
5 -</head>
6 -<body>
7 - <script src="/require/client"></script>
8 -</body>
1 -{
2 - "author": "",
3 - "name": "testApp",
4 - "version": "0.0.0",
5 - "repository": {
6 - "url": ""
7 - },
8 - "directories": {
9 - "lib": "."
10 - },
11 - "engines": {
12 - "node": "*"
13 - },
14 - "dependencies": {},
15 - "devDependencies": {}
16 -}
...\ No newline at end of file ...\ No newline at end of file
1 -<body>
2 - <script src="//localhost:1234/raphael_circle"></script>
3 -</body>
4 -
1 -var raphael = require('raphael'),
2 - canvas = document.body.appendChild(document.createElement('div')),
3 - paper = raphael(canvas)
4 -
5 -paper.circle(50, 50, 40)
1 -var http = require('http'),
2 - fs = require('fs'),
3 - dependency = require('./shared/dependency'),
4 - requireServer = require('../server') // this would be require('require/server') in most applications
5 -
6 -var base = __dirname + '/',
7 - root = 'require'
8 -var server = http.createServer(function(req, res) {
9 - if (requireServer.isRequireRequest(req)) { return }
10 - fs.readFile(base + (req.url.substr(1) || 'index.html'), function(err, content) {
11 - if (err) { return res.end(err.stack) }
12 - res.end(content)
13 - })
14 -})
15 -
16 -requireServer.mount(server, __dirname)
17 -
18 -server.listen(8080)
19 -
20 -console.log('shared dependency:', dependency)
1 -module.exports = {
2 - foo: 'bar',
3 - cat: 'qwe'
4 -}
1 -var fs = require('fs')
2 -
3 -module.exports = function readCode(filePath) {
4 - if (!filePath.match(/\.js$/)) { filePath += '.js' }
5 - return fs.readFileSync(filePath).toString()
6 -}
...\ No newline at end of file ...\ No newline at end of file
1 -var each = require('std/each')
2 -var getCode = require('./getCode')
3 -var getRequireStatements = require('./getRequireStatements')
4 -var resolve = require('./resolve')
5 -
6 -module.exports = getDependencyLevels
7 -
8 -function getDependencyLevels(mainModulePath) {
9 - var leaves = []
10 - var root = []
11 - root.isRoot = true
12 - root.path = mainModulePath
13 - _buildDependencyTreeOf(root)
14 -
15 - var levels = []
16 - var seenPaths = {}
17 - _buildLevel(leaves)
18 -
19 - return levels
20 -
21 - // builds full dependency tree, noting every dependency of every node
22 - function _buildDependencyTreeOf(node) {
23 - var requireStatements = getRequireStatements(getCode(node.path))
24 - if (requireStatements.length == 0) {
25 - return leaves.push(node)
26 - }
27 - each(requireStatements, function(requireStatement) {
28 - var childNode = []
29 - childNode.path = resolve.requireStatement(requireStatement, node.path)
30 - childNode.parent = node
31 - node.push(childNode)
32 - _buildDependencyTreeOf(childNode)
33 - })
34 - node.waitingForNumChildren = node.length
35 - }
36 -
37 - // builds a list of dependency levels, where nodes in each level is dependent only on nodes in levels below it
38 - // the dependency levels allow for parallel loading of every file in any given level
39 - function _buildLevel(nodes) {
40 - var level = []
41 - levels.push(level)
42 - var parents = []
43 - each(nodes, function(node) {
44 - if (!seenPaths[node.path]) {
45 - seenPaths[node.path] = true
46 - level.push(node.path)
47 - }
48 - if (node.isRoot) { return }
49 -
50 - node.parent.waitingForNumChildren -= 1
51 -
52 - if (node.parent.waitingForNumChildren == 0) {
53 - parents.push(node.parent)
54 - }
55 - })
56 - if (!parents.length) { return }
57 - _buildLevel(parents)
58 - }
59 -}
1 -module.exports = getRequireStatements
2 -
3 -var _globalRequireRegex = /require\s*\(['"][\w\/\.-]*['"]\)/g
4 -function getRequireStatements(code) {
5 - return code.match(_globalRequireRegex) || []
6 -}
1 -var path = require('path')
2 -var fs = require('fs')
3 -var existsSync = fs.existsSync || path.existsSync
4 -
5 -var _nodePaths = (process.env.NODE_PATH ? process.env.NODE_PATH.split(':') : [])
6 -_nodePaths.push(process.cwd())
7 -
8 -module.exports = {
9 - path: resolvePath,
10 - _nodePaths:_nodePaths,
11 - requireStatement: resolveRequireStatement
12 -}
13 -
14 -function resolvePath(searchPath, pathBase) {
15 - if (searchPath[0] == '.') {
16 - // relative path, e.g. require("./foo")
17 - return _findModuleMain(path.resolve(pathBase, searchPath))
18 - }
19 -
20 - var searchParts = searchPath.split('/')
21 - var componentName = searchParts[searchParts.length - 1]
22 - var name = searchParts.shift()
23 - var rest = searchParts.join('/')
24 -
25 - // npm-style path, e.g. require("npm").
26 - // Climb parent directories in search for "node_modules"
27 - var modulePath = _findModuleMain(path.resolve(pathBase, 'node_modules', searchPath))
28 - if (modulePath) { return modulePath }
29 -
30 - if (pathBase != '/') {
31 - // not yet at the root - keep climbing!
32 - return resolvePath(searchPath, path.resolve(pathBase, '..'))
33 - }
34 -
35 - return ''
36 -}
37 -
38 -var _pathnameGroupingRegex = /require\s*\(['"]([\w\/\.-]*)['"]\)/
39 -function resolveRequireStatement(requireStmnt, currentPath) {
40 - var rawPath = requireStmnt.match(_pathnameGroupingRegex)[1]
41 - var resolvedPath = resolvePath(rawPath, path.dirname(currentPath))
42 -
43 - if (!resolvedPath && rawPath[0] != '.' && rawPath[0] != '/') {
44 - for (var i=0; i<_nodePaths.length; i++) {
45 - resolvedPath = _findModuleMain(path.resolve(_nodePaths[i], rawPath))
46 - if (resolvedPath) { break }
47 - }
48 - }
49 -
50 - if (!resolvedPath) { throw 'Could not resolve "'+rawPath+'" in "'+currentPath+'"' }
51 - return resolvedPath
52 -}
53 -
54 -function _findModuleMain(absModulePath, tryFileName) {
55 - var foundPath = ''
56 - function attempt(aPath) {
57 - if (foundPath) { return }
58 - if (existsSync(aPath)) { foundPath = aPath }
59 - }
60 - attempt(absModulePath + '.js')
61 - try {
62 - var package = JSON.parse(fs.readFileSync(absModulePath + '/package.json').toString())
63 - attempt(path.resolve(absModulePath, package.main+'.js'))
64 - attempt(path.resolve(absModulePath, package.main))
65 - } catch(e) {}
66 - attempt(absModulePath + '/index.js')
67 -
68 - if (tryFileName) { attempt(absModulePath + '/' + tryFileName + '.js') }
69 - return foundPath
70 -}
71 -
72 -
1 -{
2 - "_from": "require",
3 - "_id": "require@2.4.20",
4 - "_inBundle": false,
5 - "_integrity": "sha1-Zstrqqu2XeinHXk/XGX9GE83mLY=",
6 - "_location": "/require",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "tag",
10 - "registry": true,
11 - "raw": "require",
12 - "name": "require",
13 - "escapedName": "require",
14 - "rawSpec": "",
15 - "saveSpec": null,
16 - "fetchSpec": "latest"
17 - },
18 - "_requiredBy": [
19 - "#USER",
20 - "/"
21 - ],
22 - "_resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz",
23 - "_shasum": "66cb6baaabb65de8a71d793f5c65fd184f3798b6",
24 - "_spec": "require",
25 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot",
26 - "author": {
27 - "name": "Marcus Westin",
28 - "email": "narcvs@gmail.com",
29 - "url": "http://marcuswest.in"
30 - },
31 - "bin": {
32 - "require": "./bin/require-command.js"
33 - },
34 - "bugs": {
35 - "url": "https://github.com/marcuswestin/require/issues"
36 - },
37 - "bundleDependencies": false,
38 - "dependencies": {
39 - "std": "0.1.40",
40 - "uglify-js": "2.3.0"
41 - },
42 - "deprecated": false,
43 - "description": "javascript module management! brings node's require statement to the browser",
44 - "devDependencies": {},
45 - "directories": {},
46 - "engines": {
47 - "browsers": "*",
48 - "node": "*"
49 - },
50 - "homepage": "https://github.com/marcuswestin/require",
51 - "main": "./require",
52 - "name": "require",
53 - "repository": {
54 - "type": "git",
55 - "url": "git://github.com/marcuswestin/require.git"
56 - },
57 - "scripts": {
58 - "start": "node server.js"
59 - },
60 - "version": "2.4.20"
61 -}
1 -var http = require('http')
2 -var fs = require('fs')
3 -var path = require('path')
4 -var extend = require('std/extend')
5 -var isObject = require('std/isObject')
6 -var map = require('std/map')
7 -var each = require('std/each')
8 -var getDependencyLevels = require('./lib/getDependencyLevels')
9 -var getRequireStatements = require('./lib/getRequireStatements')
10 -var getCode = require('./lib/getCode')
11 -var resolve = require('./lib/resolve')
12 -
13 -module.exports = {
14 - listen: listen,
15 - mount: mount,
16 - connect: connect,
17 - isRequireRequest: isRequireRequest,
18 - handleRequest: handleRequest
19 -}
20 -
21 -function listen(portOrOpts) {
22 - var _opts = (isObject(portOrOpts) ? portOrOpts : { port:portOrOpts || 1234 })
23 - opts.handleAllRequests = true
24 - mount(http.createServer(), _opts).listen(opts.port, opts.host)
25 -}
26 -
27 -function mount(server, _opts) {
28 - setOpts(_opts)
29 - return server.on('request', _checkRequest)
30 -}
31 -
32 -function connect(opts) {
33 - setOpts(opts)
34 - return _checkRequest
35 -}
36 -
37 -function _checkRequest(req, res, next) {
38 - if (isRequireRequest(req) || opts.handleAllRequests) {
39 - handleRequest(req, res)
40 - } else {
41 - next && next()
42 - }
43 -}
44 -
45 -function isRequireRequest(req) {
46 - return req.url.substr(1, opts.root.length) == opts.root
47 -}
48 -
49 -/* options
50 - *********/
51 -var opts = {
52 - path: process.cwd(),
53 - root: 'require',
54 - port: null,
55 - host: null
56 -}
57 -function setOpts(_opts) {
58 - opts = extend(_opts, opts)
59 - if (opts.path) {
60 - resolve._nodePaths.push(opts.path)
61 - }
62 -}
63 -function getUrlBase() {
64 - var basePort = (!opts.usePagePort && opts.port)
65 - if (opts.host && basePort) {
66 - return '//' + opts.host + ':' + basePort + '/' + opts.root + '/'
67 - } else {
68 - return '/' + opts.root + '/'
69 - }
70 -}
71 -
72 -/* request handlers
73 - ******************/
74 -function handleRequest(req, res) {
75 - var reqPath = _normalizeURL(req.url).substr(opts.root.length + 2)
76 - if (reqPath.match(/\.js$/)) {
77 - _handleModuleRequest(reqPath, res)
78 - } else {
79 - _handleMainModuleRequest(reqPath, req, res)
80 - }
81 -
82 - function _normalizeURL(url) {
83 - return url.replace(/\?.*/g, '').replace(/\/js$/, '.js')
84 - }
85 -}
86 -
87 -function _handleMainModuleRequest(reqPath, req, res) {
88 - var mainModulePath = resolve.path('./' + reqPath, opts.path)
89 - if (!mainModulePath) { return _sendError(res, 'Could not find module "'+reqPath+'" from "'+opts.path+'"') }
90 -
91 - try { var dependencyTree = getDependencyLevels(mainModulePath) }
92 - catch(err) { return _sendError(res, 'in getDependencyLevels: ' + (err.message || err)) }
93 -
94 - var userAgent = req.headers['user-agent']
95 - var isMobile = userAgent.match('iPad') || userAgent.match('iPod') || userAgent.match('iPhone') || userAgent.match('Android')
96 -
97 - var response = isMobile ? _getMobilePayload() : _getNormalPayload()
98 -
99 - res.writeHead(200, { 'Cache-Control':'no-cache', 'Expires':'Fri, 31 Dec 1998 12:00:00 GMT', 'Content-Length':response.length, 'Content-Type':'text/javascript' })
100 - res.end(response)
101 -
102 - function _getMobilePayload() {
103 - var result = ['__require__={loadNextModule:function(){},onModuleLoaded:function(){}}']
104 - each(dependencyTree, function(level) {
105 - each(level, function(dependency) {
106 - result.push(';(function(){ '+_getModuleCode(res, dependency)+' }());')
107 - })
108 - })
109 - return new Buffer(result.join('\n'))
110 - }
111 -
112 - function _getNormalPayload() {
113 - var paramsString = map([getUrlBase(), dependencyTree], JSON.stringify).join(',\n\t\t')
114 - return new Buffer('\t('+clientBootstrapFn.toString()+')(\n\t\t'+paramsString+'\n\t)')
115 -
116 - function clientBootstrapFn(urlBase, levels) {
117 - // This function gets sent to the client as toString
118 - __require__ = {
119 - loadNextLevel: loadNextLevel,
120 - onModuleLoaded: onModuleLoaded
121 - }
122 -
123 - var currentLevel = null
124 - loadNextLevel()
125 -
126 - function loadNextLevel() {
127 - if (!levels.length) { return } // all done!
128 - currentLevel = levels.shift()
129 - var head = document.getElementsByTagName('head')[0]
130 - for (var i=0; i<currentLevel.length; i++) {
131 - // var url = location.protocol + '//' + location.host + urlBase + currentLevel[i]
132 - var url = urlBase + currentLevel[i]
133 - head.appendChild(document.createElement('script')).src = url
134 - }
135 - }
136 -
137 - function onModuleLoaded() {
138 - currentLevel.pop()
139 - if (currentLevel.length == 0) {
140 - loadNextLevel()
141 - }
142 - }
143 - }
144 - }
145 -}
146 -
147 -function _asString(fn) { return fn.toString() }
148 -
149 -function _handleModuleRequest(reqPath, res) {
150 - try { var code = _getModuleCode(res, reqPath) }
151 - catch(err) { return _sendError(res, err.stack || err) }
152 -
153 - code += '\n\n'
154 -
155 - var buf = new Buffer(code)
156 - res.writeHead(200, { 'Cache-Control':'no-cache', 'Expires':'Fri, 31 Dec 1998 12:00:00 GMT', 'Content-Length':buf.length, 'Content-Type':'text/javascript' })
157 - res.end(buf)
158 -}
159 -
160 -function _getModuleCode(res, reqPath) {
161 - var code = getCode(reqPath)
162 - var requireStatements = getRequireStatements(code)
163 -
164 - try {
165 - each(requireStatements, function(requireStmnt) {
166 - var depPath = resolve.requireStatement(requireStmnt, reqPath)
167 - if (!depPath) { throw 'Could not resolve module' }
168 - code = code.replace(requireStmnt, '__require__["'+depPath+'"]')
169 - })
170 - } catch(e) {
171 - _sendError(res, e.message || e)
172 - }
173 -
174 - var _closureStart = ';(function(){'
175 - var _moduleDef = 'var module={exports:{}},exports=module.exports;/*FILE BEGIN*/ '
176 - var _closureEnd = '/*FILE END*/__require__["'+reqPath+'"]=module.exports; __require__.onModuleLoaded()\n})()'
177 - return _closureStart + _moduleDef + code + // all on the first line to make error line number reports correct
178 - '\n' + _closureEnd
179 -}
180 -
181 -function _sendError(res, msg) {
182 - if (msg) { msg = msg.replace(/\n/g, '\\n').replace(/"/g, '\\"') }
183 - res.writeHead(200)
184 - res.end('alert("error: ' + msg + '")')
185 -}
1 -language: node_js
2 -node_js:
3 - - 0.8
4 - - "0.10"
...\ No newline at end of file ...\ No newline at end of file
1 -# Change Log
2 -
3 -## 0.1.43
4 -
5 -* Performance improvements for `SourceMapGenerator` and `SourceNode`. See issue
6 - #148 for some discussion and issues #150, #151, and #152 for implementations.
7 -
8 -## 0.1.42
9 -
10 -* Fix an issue where `SourceNode`s from different versions of the source-map
11 - library couldn't be used in conjunction with each other. See issue #142.
12 -
13 -## 0.1.41
14 -
15 -* Fix a bug with getting the source content of relative sources with a "./"
16 - prefix. See issue #145 and [Bug 1090768](bugzil.la/1090768).
17 -
18 -* Add the `SourceMapConsumer.prototype.computeColumnSpans` method to compute the
19 - column span of each mapping.
20 -
21 -* Add the `SourceMapConsumer.prototype.allGeneratedPositionsFor` method to find
22 - all generated positions associated with a given original source and line.
23 -
24 -## 0.1.40
25 -
26 -* Performance improvements for parsing source maps in SourceMapConsumer.
27 -
28 -## 0.1.39
29 -
30 -* Fix a bug where setting a source's contents to null before any source content
31 - had been set before threw a TypeError. See issue #131.
32 -
33 -## 0.1.38
34 -
35 -* Fix a bug where finding relative paths from an empty path were creating
36 - absolute paths. See issue #129.
37 -
38 -## 0.1.37
39 -
40 -* Fix a bug where if the source root was an empty string, relative source paths
41 - would turn into absolute source paths. Issue #124.
42 -
43 -## 0.1.36
44 -
45 -* Allow the `names` mapping property to be an empty string. Issue #121.
46 -
47 -## 0.1.35
48 -
49 -* A third optional parameter was added to `SourceNode.fromStringWithSourceMap`
50 - to specify a path that relative sources in the second parameter should be
51 - relative to. Issue #105.
52 -
53 -* If no file property is given to a `SourceMapGenerator`, then the resulting
54 - source map will no longer have a `null` file property. The property will
55 - simply not exist. Issue #104.
56 -
57 -* Fixed a bug where consecutive newlines were ignored in `SourceNode`s.
58 - Issue #116.
59 -
60 -## 0.1.34
61 -
62 -* Make `SourceNode` work with windows style ("\r\n") newlines. Issue #103.
63 -
64 -* Fix bug involving source contents and the
65 - `SourceMapGenerator.prototype.applySourceMap`. Issue #100.
66 -
67 -## 0.1.33
68 -
69 -* Fix some edge cases surrounding path joining and URL resolution.
70 -
71 -* Add a third parameter for relative path to
72 - `SourceMapGenerator.prototype.applySourceMap`.
73 -
74 -* Fix issues with mappings and EOLs.
75 -
76 -## 0.1.32
77 -
78 -* Fixed a bug where SourceMapConsumer couldn't handle negative relative columns
79 - (issue 92).
80 -
81 -* Fixed test runner to actually report number of failed tests as its process
82 - exit code.
83 -
84 -* Fixed a typo when reporting bad mappings (issue 87).
85 -
86 -## 0.1.31
87 -
88 -* Delay parsing the mappings in SourceMapConsumer until queried for a source
89 - location.
90 -
91 -* Support Sass source maps (which at the time of writing deviate from the spec
92 - in small ways) in SourceMapConsumer.
93 -
94 -## 0.1.30
95 -
96 -* Do not join source root with a source, when the source is a data URI.
97 -
98 -* Extend the test runner to allow running single specific test files at a time.
99 -
100 -* Performance improvements in `SourceNode.prototype.walk` and
101 - `SourceMapConsumer.prototype.eachMapping`.
102 -
103 -* Source map browser builds will now work inside Workers.
104 -
105 -* Better error messages when attempting to add an invalid mapping to a
106 - `SourceMapGenerator`.
107 -
108 -## 0.1.29
109 -
110 -* Allow duplicate entries in the `names` and `sources` arrays of source maps
111 - (usually from TypeScript) we are parsing. Fixes github issue 72.
112 -
113 -## 0.1.28
114 -
115 -* Skip duplicate mappings when creating source maps from SourceNode; github
116 - issue 75.
117 -
118 -## 0.1.27
119 -
120 -* Don't throw an error when the `file` property is missing in SourceMapConsumer,
121 - we don't use it anyway.
122 -
123 -## 0.1.26
124 -
125 -* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70.
126 -
127 -## 0.1.25
128 -
129 -* Make compatible with browserify
130 -
131 -## 0.1.24
132 -
133 -* Fix issue with absolute paths and `file://` URIs. See
134 - https://bugzilla.mozilla.org/show_bug.cgi?id=885597
135 -
136 -## 0.1.23
137 -
138 -* Fix issue with absolute paths and sourcesContent, github issue 64.
139 -
140 -## 0.1.22
141 -
142 -* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21.
143 -
144 -## 0.1.21
145 -
146 -* Fixed handling of sources that start with a slash so that they are relative to
147 - the source root's host.
148 -
149 -## 0.1.20
150 -
151 -* Fixed github issue #43: absolute URLs aren't joined with the source root
152 - anymore.
153 -
154 -## 0.1.19
155 -
156 -* Using Travis CI to run tests.
157 -
158 -## 0.1.18
159 -
160 -* Fixed a bug in the handling of sourceRoot.
161 -
162 -## 0.1.17
163 -
164 -* Added SourceNode.fromStringWithSourceMap.
165 -
166 -## 0.1.16
167 -
168 -* Added missing documentation.
169 -
170 -* Fixed the generating of empty mappings in SourceNode.
171 -
172 -## 0.1.15
173 -
174 -* Added SourceMapGenerator.applySourceMap.
175 -
176 -## 0.1.14
177 -
178 -* The sourceRoot is now handled consistently.
179 -
180 -## 0.1.13
181 -
182 -* Added SourceMapGenerator.fromSourceMap.
183 -
184 -## 0.1.12
185 -
186 -* SourceNode now generates empty mappings too.
187 -
188 -## 0.1.11
189 -
190 -* Added name support to SourceNode.
191 -
192 -## 0.1.10
193 -
194 -* Added sourcesContent support to the customer and generator.
1 -
2 -Copyright (c) 2009-2011, Mozilla Foundation and contributors
3 -All rights reserved.
4 -
5 -Redistribution and use in source and binary forms, with or without
6 -modification, are permitted provided that the following conditions are met:
7 -
8 -* Redistributions of source code must retain the above copyright notice, this
9 - list of conditions and the following disclaimer.
10 -
11 -* Redistributions in binary form must reproduce the above copyright notice,
12 - this list of conditions and the following disclaimer in the documentation
13 - and/or other materials provided with the distribution.
14 -
15 -* Neither the names of the Mozilla Foundation nor the names of project
16 - contributors may be used to endorse or promote products derived from this
17 - software without specific prior written permission.
18 -
19 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -var path = require('path');
8 -var fs = require('fs');
9 -var copy = require('dryice').copy;
10 -
11 -function removeAmdefine(src) {
12 - src = String(src).replace(
13 - /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g,
14 - '');
15 - src = src.replace(
16 - /\b(define\(.*)('amdefine',?)/gm,
17 - '$1');
18 - return src;
19 -}
20 -removeAmdefine.onRead = true;
21 -
22 -function makeNonRelative(src) {
23 - return src
24 - .replace(/require\('.\//g, 'require(\'source-map/')
25 - .replace(/\.\.\/\.\.\/lib\//g, '');
26 -}
27 -makeNonRelative.onRead = true;
28 -
29 -function buildBrowser() {
30 - console.log('\nCreating dist/source-map.js');
31 -
32 - var project = copy.createCommonJsProject({
33 - roots: [ path.join(__dirname, 'lib') ]
34 - });
35 -
36 - copy({
37 - source: [
38 - 'build/mini-require.js',
39 - {
40 - project: project,
41 - require: [ 'source-map/source-map-generator',
42 - 'source-map/source-map-consumer',
43 - 'source-map/source-node']
44 - },
45 - 'build/suffix-browser.js'
46 - ],
47 - filter: [
48 - copy.filter.moduleDefines,
49 - removeAmdefine
50 - ],
51 - dest: 'dist/source-map.js'
52 - });
53 -}
54 -
55 -function buildBrowserMin() {
56 - console.log('\nCreating dist/source-map.min.js');
57 -
58 - copy({
59 - source: 'dist/source-map.js',
60 - filter: copy.filter.uglifyjs,
61 - dest: 'dist/source-map.min.js'
62 - });
63 -}
64 -
65 -function buildFirefox() {
66 - console.log('\nCreating dist/SourceMap.jsm');
67 -
68 - var project = copy.createCommonJsProject({
69 - roots: [ path.join(__dirname, 'lib') ]
70 - });
71 -
72 - copy({
73 - source: [
74 - 'build/prefix-source-map.jsm',
75 - {
76 - project: project,
77 - require: [ 'source-map/source-map-consumer',
78 - 'source-map/source-map-generator',
79 - 'source-map/source-node' ]
80 - },
81 - 'build/suffix-source-map.jsm'
82 - ],
83 - filter: [
84 - copy.filter.moduleDefines,
85 - removeAmdefine,
86 - makeNonRelative
87 - ],
88 - dest: 'dist/SourceMap.jsm'
89 - });
90 -
91 - // Create dist/test/Utils.jsm
92 - console.log('\nCreating dist/test/Utils.jsm');
93 -
94 - project = copy.createCommonJsProject({
95 - roots: [ __dirname, path.join(__dirname, 'lib') ]
96 - });
97 -
98 - copy({
99 - source: [
100 - 'build/prefix-utils.jsm',
101 - 'build/assert-shim.js',
102 - {
103 - project: project,
104 - require: [ 'test/source-map/util' ]
105 - },
106 - 'build/suffix-utils.jsm'
107 - ],
108 - filter: [
109 - copy.filter.moduleDefines,
110 - removeAmdefine,
111 - makeNonRelative
112 - ],
113 - dest: 'dist/test/Utils.jsm'
114 - });
115 -
116 - function isTestFile(f) {
117 - return /^test\-.*?\.js/.test(f);
118 - }
119 -
120 - var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile);
121 -
122 - testFiles.forEach(function (testFile) {
123 - console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_')));
124 -
125 - copy({
126 - source: [
127 - 'build/test-prefix.js',
128 - path.join('test', 'source-map', testFile),
129 - 'build/test-suffix.js'
130 - ],
131 - filter: [
132 - removeAmdefine,
133 - makeNonRelative,
134 - function (input, source) {
135 - return input.replace('define(',
136 - 'define("'
137 - + path.join('test', 'source-map', testFile.replace(/\.js$/, ''))
138 - + '", ["require", "exports", "module"], ');
139 - },
140 - function (input, source) {
141 - return input.replace('{THIS_MODULE}', function () {
142 - return "test/source-map/" + testFile.replace(/\.js$/, '');
143 - });
144 - }
145 - ],
146 - dest: path.join('dist', 'test', testFile.replace(/\-/g, '_'))
147 - });
148 - });
149 -}
150 -
151 -function ensureDir(name) {
152 - var dirExists = false;
153 - try {
154 - dirExists = fs.statSync(name).isDirectory();
155 - } catch (err) {}
156 -
157 - if (!dirExists) {
158 - fs.mkdirSync(name, 0777);
159 - }
160 -}
161 -
162 -ensureDir("dist");
163 -ensureDir("dist/test");
164 -buildFirefox();
165 -buildBrowser();
166 -buildBrowserMin();
1 -# Source Map
2 -
3 -This is a library to generate and consume the source map format
4 -[described here][format].
5 -
6 -This library is written in the Asynchronous Module Definition format, and works
7 -in the following environments:
8 -
9 -* Modern Browsers supporting ECMAScript 5 (either after the build, or with an
10 - AMD loader such as RequireJS)
11 -
12 -* Inside Firefox (as a JSM file, after the build)
13 -
14 -* With NodeJS versions 0.8.X and higher
15 -
16 -## Node
17 -
18 - $ npm install source-map
19 -
20 -## Building from Source (for everywhere else)
21 -
22 -Install Node and then run
23 -
24 - $ git clone https://fitzgen@github.com/mozilla/source-map.git
25 - $ cd source-map
26 - $ npm link .
27 -
28 -Next, run
29 -
30 - $ node Makefile.dryice.js
31 -
32 -This should spew a bunch of stuff to stdout, and create the following files:
33 -
34 -* `dist/source-map.js` - The unminified browser version.
35 -
36 -* `dist/source-map.min.js` - The minified browser version.
37 -
38 -* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source.
39 -
40 -## Examples
41 -
42 -### Consuming a source map
43 -
44 - var rawSourceMap = {
45 - version: 3,
46 - file: 'min.js',
47 - names: ['bar', 'baz', 'n'],
48 - sources: ['one.js', 'two.js'],
49 - sourceRoot: 'http://example.com/www/js/',
50 - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
51 - };
52 -
53 - var smc = new SourceMapConsumer(rawSourceMap);
54 -
55 - console.log(smc.sources);
56 - // [ 'http://example.com/www/js/one.js',
57 - // 'http://example.com/www/js/two.js' ]
58 -
59 - console.log(smc.originalPositionFor({
60 - line: 2,
61 - column: 28
62 - }));
63 - // { source: 'http://example.com/www/js/two.js',
64 - // line: 2,
65 - // column: 10,
66 - // name: 'n' }
67 -
68 - console.log(smc.generatedPositionFor({
69 - source: 'http://example.com/www/js/two.js',
70 - line: 2,
71 - column: 10
72 - }));
73 - // { line: 2, column: 28 }
74 -
75 - smc.eachMapping(function (m) {
76 - // ...
77 - });
78 -
79 -### Generating a source map
80 -
81 -In depth guide:
82 -[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/)
83 -
84 -#### With SourceNode (high level API)
85 -
86 - function compile(ast) {
87 - switch (ast.type) {
88 - case 'BinaryExpression':
89 - return new SourceNode(
90 - ast.location.line,
91 - ast.location.column,
92 - ast.location.source,
93 - [compile(ast.left), " + ", compile(ast.right)]
94 - );
95 - case 'Literal':
96 - return new SourceNode(
97 - ast.location.line,
98 - ast.location.column,
99 - ast.location.source,
100 - String(ast.value)
101 - );
102 - // ...
103 - default:
104 - throw new Error("Bad AST");
105 - }
106 - }
107 -
108 - var ast = parse("40 + 2", "add.js");
109 - console.log(compile(ast).toStringWithSourceMap({
110 - file: 'add.js'
111 - }));
112 - // { code: '40 + 2',
113 - // map: [object SourceMapGenerator] }
114 -
115 -#### With SourceMapGenerator (low level API)
116 -
117 - var map = new SourceMapGenerator({
118 - file: "source-mapped.js"
119 - });
120 -
121 - map.addMapping({
122 - generated: {
123 - line: 10,
124 - column: 35
125 - },
126 - source: "foo.js",
127 - original: {
128 - line: 33,
129 - column: 2
130 - },
131 - name: "christopher"
132 - });
133 -
134 - console.log(map.toString());
135 - // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}'
136 -
137 -## API
138 -
139 -Get a reference to the module:
140 -
141 - // NodeJS
142 - var sourceMap = require('source-map');
143 -
144 - // Browser builds
145 - var sourceMap = window.sourceMap;
146 -
147 - // Inside Firefox
148 - let sourceMap = {};
149 - Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);
150 -
151 -### SourceMapConsumer
152 -
153 -A SourceMapConsumer instance represents a parsed source map which we can query
154 -for information about the original file positions by giving it a file position
155 -in the generated source.
156 -
157 -#### new SourceMapConsumer(rawSourceMap)
158 -
159 -The only parameter is the raw source map (either as a string which can be
160 -`JSON.parse`'d, or an object). According to the spec, source maps have the
161 -following attributes:
162 -
163 -* `version`: Which version of the source map spec this map is following.
164 -
165 -* `sources`: An array of URLs to the original source files.
166 -
167 -* `names`: An array of identifiers which can be referrenced by individual
168 - mappings.
169 -
170 -* `sourceRoot`: Optional. The URL root from which all sources are relative.
171 -
172 -* `sourcesContent`: Optional. An array of contents of the original source files.
173 -
174 -* `mappings`: A string of base64 VLQs which contain the actual mappings.
175 -
176 -* `file`: Optional. The generated filename this source map is associated with.
177 -
178 -#### SourceMapConsumer.prototype.computeColumnSpans()
179 -
180 -Compute the last column for each generated mapping. The last column is
181 -inclusive.
182 -
183 -#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)
184 -
185 -Returns the original source, line, and column information for the generated
186 -source's line and column positions provided. The only argument is an object with
187 -the following properties:
188 -
189 -* `line`: The line number in the generated source.
190 -
191 -* `column`: The column number in the generated source.
192 -
193 -and an object is returned with the following properties:
194 -
195 -* `source`: The original source file, or null if this information is not
196 - available.
197 -
198 -* `line`: The line number in the original source, or null if this information is
199 - not available.
200 -
201 -* `column`: The column number in the original source, or null or null if this
202 - information is not available.
203 -
204 -* `name`: The original identifier, or null if this information is not available.
205 -
206 -#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)
207 -
208 -Returns the generated line and column information for the original source,
209 -line, and column positions provided. The only argument is an object with
210 -the following properties:
211 -
212 -* `source`: The filename of the original source.
213 -
214 -* `line`: The line number in the original source.
215 -
216 -* `column`: The column number in the original source.
217 -
218 -and an object is returned with the following properties:
219 -
220 -* `line`: The line number in the generated source, or null.
221 -
222 -* `column`: The column number in the generated source, or null.
223 -
224 -#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition)
225 -
226 -Returns all generated line and column information for the original source
227 -and line provided. The only argument is an object with the following
228 -properties:
229 -
230 -* `source`: The filename of the original source.
231 -
232 -* `line`: The line number in the original source.
233 -
234 -and an array of objects is returned, each with the following properties:
235 -
236 -* `line`: The line number in the generated source, or null.
237 -
238 -* `column`: The column number in the generated source, or null.
239 -
240 -#### SourceMapConsumer.prototype.sourceContentFor(source)
241 -
242 -Returns the original source content for the source provided. The only
243 -argument is the URL of the original source file.
244 -
245 -#### SourceMapConsumer.prototype.eachMapping(callback, context, order)
246 -
247 -Iterate over each mapping between an original source/line/column and a
248 -generated line/column in this source map.
249 -
250 -* `callback`: The function that is called with each mapping. Mappings have the
251 - form `{ source, generatedLine, generatedColumn, originalLine, originalColumn,
252 - name }`
253 -
254 -* `context`: Optional. If specified, this object will be the value of `this`
255 - every time that `callback` is called.
256 -
257 -* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or
258 - `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over
259 - the mappings sorted by the generated file's line/column order or the
260 - original's source/line/column order, respectively. Defaults to
261 - `SourceMapConsumer.GENERATED_ORDER`.
262 -
263 -### SourceMapGenerator
264 -
265 -An instance of the SourceMapGenerator represents a source map which is being
266 -built incrementally.
267 -
268 -#### new SourceMapGenerator([startOfSourceMap])
269 -
270 -You may pass an object with the following properties:
271 -
272 -* `file`: The filename of the generated source that this source map is
273 - associated with.
274 -
275 -* `sourceRoot`: A root for all relative URLs in this source map.
276 -
277 -* `skipValidation`: Optional. When `true`, disables validation of mappings as
278 - they are added. This can improve performance but should be used with
279 - discretion, as a last resort. Even then, one should avoid using this flag when
280 - running tests, if possible.
281 -
282 -#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)
283 -
284 -Creates a new SourceMapGenerator based on a SourceMapConsumer
285 -
286 -* `sourceMapConsumer` The SourceMap.
287 -
288 -#### SourceMapGenerator.prototype.addMapping(mapping)
289 -
290 -Add a single mapping from original source line and column to the generated
291 -source's line and column for this source map being created. The mapping object
292 -should have the following properties:
293 -
294 -* `generated`: An object with the generated line and column positions.
295 -
296 -* `original`: An object with the original line and column positions.
297 -
298 -* `source`: The original source file (relative to the sourceRoot).
299 -
300 -* `name`: An optional original token name for this mapping.
301 -
302 -#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)
303 -
304 -Set the source content for an original source file.
305 -
306 -* `sourceFile` the URL of the original source file.
307 -
308 -* `sourceContent` the content of the source file.
309 -
310 -#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]])
311 -
312 -Applies a SourceMap for a source file to the SourceMap.
313 -Each mapping to the supplied source file is rewritten using the
314 -supplied SourceMap. Note: The resolution for the resulting mappings
315 -is the minimium of this map and the supplied map.
316 -
317 -* `sourceMapConsumer`: The SourceMap to be applied.
318 -
319 -* `sourceFile`: Optional. The filename of the source file.
320 - If omitted, sourceMapConsumer.file will be used, if it exists.
321 - Otherwise an error will be thrown.
322 -
323 -* `sourceMapPath`: Optional. The dirname of the path to the SourceMap
324 - to be applied. If relative, it is relative to the SourceMap.
325 -
326 - This parameter is needed when the two SourceMaps aren't in the same
327 - directory, and the SourceMap to be applied contains relative source
328 - paths. If so, those relative source paths need to be rewritten
329 - relative to the SourceMap.
330 -
331 - If omitted, it is assumed that both SourceMaps are in the same directory,
332 - thus not needing any rewriting. (Supplying `'.'` has the same effect.)
333 -
334 -#### SourceMapGenerator.prototype.toString()
335 -
336 -Renders the source map being generated to a string.
337 -
338 -### SourceNode
339 -
340 -SourceNodes provide a way to abstract over interpolating and/or concatenating
341 -snippets of generated JavaScript source code, while maintaining the line and
342 -column information associated between those snippets and the original source
343 -code. This is useful as the final intermediate representation a compiler might
344 -use before outputting the generated JS and source map.
345 -
346 -#### new SourceNode([line, column, source[, chunk[, name]]])
347 -
348 -* `line`: The original line number associated with this source node, or null if
349 - it isn't associated with an original line.
350 -
351 -* `column`: The original column number associated with this source node, or null
352 - if it isn't associated with an original column.
353 -
354 -* `source`: The original source's filename; null if no filename is provided.
355 -
356 -* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see
357 - below.
358 -
359 -* `name`: Optional. The original identifier.
360 -
361 -#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath])
362 -
363 -Creates a SourceNode from generated code and a SourceMapConsumer.
364 -
365 -* `code`: The generated code
366 -
367 -* `sourceMapConsumer` The SourceMap for the generated code
368 -
369 -* `relativePath` The optional path that relative sources in `sourceMapConsumer`
370 - should be relative to.
371 -
372 -#### SourceNode.prototype.add(chunk)
373 -
374 -Add a chunk of generated JS to this source node.
375 -
376 -* `chunk`: A string snippet of generated JS code, another instance of
377 - `SourceNode`, or an array where each member is one of those things.
378 -
379 -#### SourceNode.prototype.prepend(chunk)
380 -
381 -Prepend a chunk of generated JS to this source node.
382 -
383 -* `chunk`: A string snippet of generated JS code, another instance of
384 - `SourceNode`, or an array where each member is one of those things.
385 -
386 -#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)
387 -
388 -Set the source content for a source file. This will be added to the
389 -`SourceMap` in the `sourcesContent` field.
390 -
391 -* `sourceFile`: The filename of the source file
392 -
393 -* `sourceContent`: The content of the source file
394 -
395 -#### SourceNode.prototype.walk(fn)
396 -
397 -Walk over the tree of JS snippets in this node and its children. The walking
398 -function is called once for each snippet of JS and is passed that snippet and
399 -the its original associated source's line/column location.
400 -
401 -* `fn`: The traversal function.
402 -
403 -#### SourceNode.prototype.walkSourceContents(fn)
404 -
405 -Walk over the tree of SourceNodes. The walking function is called for each
406 -source file content and is passed the filename and source content.
407 -
408 -* `fn`: The traversal function.
409 -
410 -#### SourceNode.prototype.join(sep)
411 -
412 -Like `Array.prototype.join` except for SourceNodes. Inserts the separator
413 -between each of this source node's children.
414 -
415 -* `sep`: The separator.
416 -
417 -#### SourceNode.prototype.replaceRight(pattern, replacement)
418 -
419 -Call `String.prototype.replace` on the very right-most source snippet. Useful
420 -for trimming whitespace from the end of a source node, etc.
421 -
422 -* `pattern`: The pattern to replace.
423 -
424 -* `replacement`: The thing to replace the pattern with.
425 -
426 -#### SourceNode.prototype.toString()
427 -
428 -Return the string representation of this source node. Walks over the tree and
429 -concatenates all the various snippets together to one string.
430 -
431 -#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap])
432 -
433 -Returns the string representation of this tree of source nodes, plus a
434 -SourceMapGenerator which contains all the mappings between the generated and
435 -original sources.
436 -
437 -The arguments are the same as those to `new SourceMapGenerator`.
438 -
439 -## Tests
440 -
441 -[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)
442 -
443 -Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`.
444 -
445 -To add new tests, create a new file named `test/test-<your new test name>.js`
446 -and export your test functions with names that start with "test", for example
447 -
448 - exports["test doing the foo bar"] = function (assert, util) {
449 - ...
450 - };
451 -
452 -The new test will be located automatically when you run the suite.
453 -
454 -The `util` argument is the test utility module located at `test/source-map/util`.
455 -
456 -The `assert` argument is a cut down version of node's assert module. You have
457 -access to the following assertion functions:
458 -
459 -* `doesNotThrow`
460 -
461 -* `equal`
462 -
463 -* `ok`
464 -
465 -* `strictEqual`
466 -
467 -* `throws`
468 -
469 -(The reason for the restricted set of test functions is because we need the
470 -tests to run inside Firefox's test suite as well and so the assert module is
471 -shimmed in that environment. See `build/assert-shim.js`.)
472 -
473 -[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
474 -[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap
475 -[Dryice]: https://github.com/mozilla/dryice
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -define('test/source-map/assert', ['exports'], function (exports) {
8 -
9 - let do_throw = function (msg) {
10 - throw new Error(msg);
11 - };
12 -
13 - exports.init = function (throw_fn) {
14 - do_throw = throw_fn;
15 - };
16 -
17 - exports.doesNotThrow = function (fn) {
18 - try {
19 - fn();
20 - }
21 - catch (e) {
22 - do_throw(e.message);
23 - }
24 - };
25 -
26 - exports.equal = function (actual, expected, msg) {
27 - msg = msg || String(actual) + ' != ' + String(expected);
28 - if (actual != expected) {
29 - do_throw(msg);
30 - }
31 - };
32 -
33 - exports.ok = function (val, msg) {
34 - msg = msg || String(val) + ' is falsey';
35 - if (!Boolean(val)) {
36 - do_throw(msg);
37 - }
38 - };
39 -
40 - exports.strictEqual = function (actual, expected, msg) {
41 - msg = msg || String(actual) + ' !== ' + String(expected);
42 - if (actual !== expected) {
43 - do_throw(msg);
44 - }
45 - };
46 -
47 - exports.throws = function (fn) {
48 - try {
49 - fn();
50 - do_throw('Expected an error to be thrown, but it wasn\'t.');
51 - }
52 - catch (e) {
53 - }
54 - };
55 -
56 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -
8 -/**
9 - * Define a module along with a payload.
10 - * @param {string} moduleName Name for the payload
11 - * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec
12 - * @param {function} payload Function with (require, exports, module) params
13 - */
14 -function define(moduleName, deps, payload) {
15 - if (typeof moduleName != "string") {
16 - throw new TypeError('Expected string, got: ' + moduleName);
17 - }
18 -
19 - if (arguments.length == 2) {
20 - payload = deps;
21 - }
22 -
23 - if (moduleName in define.modules) {
24 - throw new Error("Module already defined: " + moduleName);
25 - }
26 - define.modules[moduleName] = payload;
27 -};
28 -
29 -/**
30 - * The global store of un-instantiated modules
31 - */
32 -define.modules = {};
33 -
34 -
35 -/**
36 - * We invoke require() in the context of a Domain so we can have multiple
37 - * sets of modules running separate from each other.
38 - * This contrasts with JSMs which are singletons, Domains allows us to
39 - * optionally load a CommonJS module twice with separate data each time.
40 - * Perhaps you want 2 command lines with a different set of commands in each,
41 - * for example.
42 - */
43 -function Domain() {
44 - this.modules = {};
45 - this._currentModule = null;
46 -}
47 -
48 -(function () {
49 -
50 - /**
51 - * Lookup module names and resolve them by calling the definition function if
52 - * needed.
53 - * There are 2 ways to call this, either with an array of dependencies and a
54 - * callback to call when the dependencies are found (which can happen
55 - * asynchronously in an in-page context) or with a single string an no callback
56 - * where the dependency is resolved synchronously and returned.
57 - * The API is designed to be compatible with the CommonJS AMD spec and
58 - * RequireJS.
59 - * @param {string[]|string} deps A name, or names for the payload
60 - * @param {function|undefined} callback Function to call when the dependencies
61 - * are resolved
62 - * @return {undefined|object} The module required or undefined for
63 - * array/callback method
64 - */
65 - Domain.prototype.require = function(deps, callback) {
66 - if (Array.isArray(deps)) {
67 - var params = deps.map(function(dep) {
68 - return this.lookup(dep);
69 - }, this);
70 - if (callback) {
71 - callback.apply(null, params);
72 - }
73 - return undefined;
74 - }
75 - else {
76 - return this.lookup(deps);
77 - }
78 - };
79 -
80 - function normalize(path) {
81 - var bits = path.split('/');
82 - var i = 1;
83 - while (i < bits.length) {
84 - if (bits[i] === '..') {
85 - bits.splice(i-1, 1);
86 - } else if (bits[i] === '.') {
87 - bits.splice(i, 1);
88 - } else {
89 - i++;
90 - }
91 - }
92 - return bits.join('/');
93 - }
94 -
95 - function join(a, b) {
96 - a = a.trim();
97 - b = b.trim();
98 - if (/^\//.test(b)) {
99 - return b;
100 - } else {
101 - return a.replace(/\/*$/, '/') + b;
102 - }
103 - }
104 -
105 - function dirname(path) {
106 - var bits = path.split('/');
107 - bits.pop();
108 - return bits.join('/');
109 - }
110 -
111 - /**
112 - * Lookup module names and resolve them by calling the definition function if
113 - * needed.
114 - * @param {string} moduleName A name for the payload to lookup
115 - * @return {object} The module specified by aModuleName or null if not found.
116 - */
117 - Domain.prototype.lookup = function(moduleName) {
118 - if (/^\./.test(moduleName)) {
119 - moduleName = normalize(join(dirname(this._currentModule), moduleName));
120 - }
121 -
122 - if (moduleName in this.modules) {
123 - var module = this.modules[moduleName];
124 - return module;
125 - }
126 -
127 - if (!(moduleName in define.modules)) {
128 - throw new Error("Module not defined: " + moduleName);
129 - }
130 -
131 - var module = define.modules[moduleName];
132 -
133 - if (typeof module == "function") {
134 - var exports = {};
135 - var previousModule = this._currentModule;
136 - this._currentModule = moduleName;
137 - module(this.require.bind(this), exports, { id: moduleName, uri: "" });
138 - this._currentModule = previousModule;
139 - module = exports;
140 - }
141 -
142 - // cache the resulting module object for next time
143 - this.modules[moduleName] = module;
144 -
145 - return module;
146 - };
147 -
148 -}());
149 -
150 -define.Domain = Domain;
151 -define.globalDomain = new Domain();
152 -var require = define.globalDomain.require.bind(define.globalDomain);
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -
8 -/*
9 - * WARNING!
10 - *
11 - * Do not edit this file directly, it is built from the sources at
12 - * https://github.com/mozilla/source-map/
13 - */
14 -
15 -///////////////////////////////////////////////////////////////////////////////
16 -
17 -
18 -this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ];
19 -
20 -Components.utils.import('resource://gre/modules/devtools/Require.jsm');
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -
8 -/*
9 - * WARNING!
10 - *
11 - * Do not edit this file directly, it is built from the sources at
12 - * https://github.com/mozilla/source-map/
13 - */
14 -
15 -Components.utils.import('resource://gre/modules/devtools/Require.jsm');
16 -Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm');
17 -
18 -this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ];
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -///////////////////////////////////////////////////////////////////////////////
3 -
4 -this.sourceMap = {
5 - SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer,
6 - SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator,
7 - SourceNode: require('source-map/source-node').SourceNode
8 -};
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -///////////////////////////////////////////////////////////////////////////////
3 -
4 -this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer;
5 -this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
6 -this.SourceNode = require('source-map/source-node').SourceNode;
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -function runSourceMapTests(modName, do_throw) {
8 - let mod = require(modName);
9 - let assert = require('test/source-map/assert');
10 - let util = require('test/source-map/util');
11 -
12 - assert.init(do_throw);
13 -
14 - for (let k in mod) {
15 - if (/^test/.test(k)) {
16 - mod[k](assert, util);
17 - }
18 - }
19 -
20 -}
21 -this.runSourceMapTests = runSourceMapTests;
1 -/*
2 - * WARNING!
3 - *
4 - * Do not edit this file directly, it is built from the sources at
5 - * https://github.com/mozilla/source-map/
6 - */
7 -
8 -Components.utils.import('resource://test/Utils.jsm');
1 -function run_test() {
2 - runSourceMapTests('{THIS_MODULE}', do_throw);
3 -}
1 -/*
2 - * Copyright 2009-2011 Mozilla Foundation and contributors
3 - * Licensed under the New BSD license. See LICENSE.txt or:
4 - * http://opensource.org/licenses/BSD-3-Clause
5 - */
6 -exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator;
7 -exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer;
8 -exports.SourceNode = require('./source-map/source-node').SourceNode;
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var util = require('./util');
13 -
14 - /**
15 - * A data structure which is a combination of an array and a set. Adding a new
16 - * member is O(1), testing for membership is O(1), and finding the index of an
17 - * element is O(1). Removing elements from the set is not supported. Only
18 - * strings are supported for membership.
19 - */
20 - function ArraySet() {
21 - this._array = [];
22 - this._set = {};
23 - }
24 -
25 - /**
26 - * Static method for creating ArraySet instances from an existing array.
27 - */
28 - ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
29 - var set = new ArraySet();
30 - for (var i = 0, len = aArray.length; i < len; i++) {
31 - set.add(aArray[i], aAllowDuplicates);
32 - }
33 - return set;
34 - };
35 -
36 - /**
37 - * Add the given string to this set.
38 - *
39 - * @param String aStr
40 - */
41 - ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
42 - var isDuplicate = this.has(aStr);
43 - var idx = this._array.length;
44 - if (!isDuplicate || aAllowDuplicates) {
45 - this._array.push(aStr);
46 - }
47 - if (!isDuplicate) {
48 - this._set[util.toSetString(aStr)] = idx;
49 - }
50 - };
51 -
52 - /**
53 - * Is the given string a member of this set?
54 - *
55 - * @param String aStr
56 - */
57 - ArraySet.prototype.has = function ArraySet_has(aStr) {
58 - return Object.prototype.hasOwnProperty.call(this._set,
59 - util.toSetString(aStr));
60 - };
61 -
62 - /**
63 - * What is the index of the given string in the array?
64 - *
65 - * @param String aStr
66 - */
67 - ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
68 - if (this.has(aStr)) {
69 - return this._set[util.toSetString(aStr)];
70 - }
71 - throw new Error('"' + aStr + '" is not in the set.');
72 - };
73 -
74 - /**
75 - * What is the element at the given index?
76 - *
77 - * @param Number aIdx
78 - */
79 - ArraySet.prototype.at = function ArraySet_at(aIdx) {
80 - if (aIdx >= 0 && aIdx < this._array.length) {
81 - return this._array[aIdx];
82 - }
83 - throw new Error('No element indexed by ' + aIdx);
84 - };
85 -
86 - /**
87 - * Returns the array representation of this set (which has the proper indices
88 - * indicated by indexOf). Note that this is a copy of the internal array used
89 - * for storing the members so that no one can mess with internal state.
90 - */
91 - ArraySet.prototype.toArray = function ArraySet_toArray() {
92 - return this._array.slice();
93 - };
94 -
95 - exports.ArraySet = ArraySet;
96 -
97 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - *
7 - * Based on the Base 64 VLQ implementation in Closure Compiler:
8 - * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
9 - *
10 - * Copyright 2011 The Closure Compiler Authors. All rights reserved.
11 - * Redistribution and use in source and binary forms, with or without
12 - * modification, are permitted provided that the following conditions are
13 - * met:
14 - *
15 - * * Redistributions of source code must retain the above copyright
16 - * notice, this list of conditions and the following disclaimer.
17 - * * Redistributions in binary form must reproduce the above
18 - * copyright notice, this list of conditions and the following
19 - * disclaimer in the documentation and/or other materials provided
20 - * with the distribution.
21 - * * Neither the name of Google Inc. nor the names of its
22 - * contributors may be used to endorse or promote products derived
23 - * from this software without specific prior written permission.
24 - *
25 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 - */
37 -if (typeof define !== 'function') {
38 - var define = require('amdefine')(module, require);
39 -}
40 -define(function (require, exports, module) {
41 -
42 - var base64 = require('./base64');
43 -
44 - // A single base 64 digit can contain 6 bits of data. For the base 64 variable
45 - // length quantities we use in the source map spec, the first bit is the sign,
46 - // the next four bits are the actual value, and the 6th bit is the
47 - // continuation bit. The continuation bit tells us whether there are more
48 - // digits in this value following this digit.
49 - //
50 - // Continuation
51 - // | Sign
52 - // | |
53 - // V V
54 - // 101011
55 -
56 - var VLQ_BASE_SHIFT = 5;
57 -
58 - // binary: 100000
59 - var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
60 -
61 - // binary: 011111
62 - var VLQ_BASE_MASK = VLQ_BASE - 1;
63 -
64 - // binary: 100000
65 - var VLQ_CONTINUATION_BIT = VLQ_BASE;
66 -
67 - /**
68 - * Converts from a two-complement value to a value where the sign bit is
69 - * placed in the least significant bit. For example, as decimals:
70 - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
71 - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
72 - */
73 - function toVLQSigned(aValue) {
74 - return aValue < 0
75 - ? ((-aValue) << 1) + 1
76 - : (aValue << 1) + 0;
77 - }
78 -
79 - /**
80 - * Converts to a two-complement value from a value where the sign bit is
81 - * placed in the least significant bit. For example, as decimals:
82 - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
83 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
84 - */
85 - function fromVLQSigned(aValue) {
86 - var isNegative = (aValue & 1) === 1;
87 - var shifted = aValue >> 1;
88 - return isNegative
89 - ? -shifted
90 - : shifted;
91 - }
92 -
93 - /**
94 - * Returns the base 64 VLQ encoded value.
95 - */
96 - exports.encode = function base64VLQ_encode(aValue) {
97 - var encoded = "";
98 - var digit;
99 -
100 - var vlq = toVLQSigned(aValue);
101 -
102 - do {
103 - digit = vlq & VLQ_BASE_MASK;
104 - vlq >>>= VLQ_BASE_SHIFT;
105 - if (vlq > 0) {
106 - // There are still more digits in this value, so we must make sure the
107 - // continuation bit is marked.
108 - digit |= VLQ_CONTINUATION_BIT;
109 - }
110 - encoded += base64.encode(digit);
111 - } while (vlq > 0);
112 -
113 - return encoded;
114 - };
115 -
116 - /**
117 - * Decodes the next base 64 VLQ value from the given string and returns the
118 - * value and the rest of the string via the out parameter.
119 - */
120 - exports.decode = function base64VLQ_decode(aStr, aOutParam) {
121 - var i = 0;
122 - var strLen = aStr.length;
123 - var result = 0;
124 - var shift = 0;
125 - var continuation, digit;
126 -
127 - do {
128 - if (i >= strLen) {
129 - throw new Error("Expected more digits in base 64 VLQ value.");
130 - }
131 - digit = base64.decode(aStr.charAt(i++));
132 - continuation = !!(digit & VLQ_CONTINUATION_BIT);
133 - digit &= VLQ_BASE_MASK;
134 - result = result + (digit << shift);
135 - shift += VLQ_BASE_SHIFT;
136 - } while (continuation);
137 -
138 - aOutParam.value = fromVLQSigned(result);
139 - aOutParam.rest = aStr.slice(i);
140 - };
141 -
142 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var charToIntMap = {};
13 - var intToCharMap = {};
14 -
15 - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
16 - .split('')
17 - .forEach(function (ch, index) {
18 - charToIntMap[ch] = index;
19 - intToCharMap[index] = ch;
20 - });
21 -
22 - /**
23 - * Encode an integer in the range of 0 to 63 to a single base 64 digit.
24 - */
25 - exports.encode = function base64_encode(aNumber) {
26 - if (aNumber in intToCharMap) {
27 - return intToCharMap[aNumber];
28 - }
29 - throw new TypeError("Must be between 0 and 63: " + aNumber);
30 - };
31 -
32 - /**
33 - * Decode a single base 64 digit to an integer.
34 - */
35 - exports.decode = function base64_decode(aChar) {
36 - if (aChar in charToIntMap) {
37 - return charToIntMap[aChar];
38 - }
39 - throw new TypeError("Not a valid base 64 digit: " + aChar);
40 - };
41 -
42 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - /**
13 - * Recursive implementation of binary search.
14 - *
15 - * @param aLow Indices here and lower do not contain the needle.
16 - * @param aHigh Indices here and higher do not contain the needle.
17 - * @param aNeedle The element being searched for.
18 - * @param aHaystack The non-empty array being searched.
19 - * @param aCompare Function which takes two elements and returns -1, 0, or 1.
20 - */
21 - function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
22 - // This function terminates when one of the following is true:
23 - //
24 - // 1. We find the exact element we are looking for.
25 - //
26 - // 2. We did not find the exact element, but we can return the index of
27 - // the next closest element that is less than that element.
28 - //
29 - // 3. We did not find the exact element, and there is no next-closest
30 - // element which is less than the one we are searching for, so we
31 - // return -1.
32 - var mid = Math.floor((aHigh - aLow) / 2) + aLow;
33 - var cmp = aCompare(aNeedle, aHaystack[mid], true);
34 - if (cmp === 0) {
35 - // Found the element we are looking for.
36 - return mid;
37 - }
38 - else if (cmp > 0) {
39 - // aHaystack[mid] is greater than our needle.
40 - if (aHigh - mid > 1) {
41 - // The element is in the upper half.
42 - return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);
43 - }
44 - // We did not find an exact match, return the next closest one
45 - // (termination case 2).
46 - return mid;
47 - }
48 - else {
49 - // aHaystack[mid] is less than our needle.
50 - if (mid - aLow > 1) {
51 - // The element is in the lower half.
52 - return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);
53 - }
54 - // The exact needle element was not found in this haystack. Determine if
55 - // we are in termination case (2) or (3) and return the appropriate thing.
56 - return aLow < 0 ? -1 : aLow;
57 - }
58 - }
59 -
60 - /**
61 - * This is an implementation of binary search which will always try and return
62 - * the index of next lowest value checked if there is no exact hit. This is
63 - * because mappings between original and generated line/col pairs are single
64 - * points, and there is an implicit region between each of them, so a miss
65 - * just means that you aren't on the very start of a region.
66 - *
67 - * @param aNeedle The element you are looking for.
68 - * @param aHaystack The array that is being searched.
69 - * @param aCompare A function which takes the needle and an element in the
70 - * array and returns -1, 0, or 1 depending on whether the needle is less
71 - * than, equal to, or greater than the element, respectively.
72 - */
73 - exports.search = function search(aNeedle, aHaystack, aCompare) {
74 - if (aHaystack.length === 0) {
75 - return -1;
76 - }
77 - return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)
78 - };
79 -
80 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2014 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var util = require('./util');
13 -
14 - /**
15 - * Determine whether mappingB is after mappingA with respect to generated
16 - * position.
17 - */
18 - function generatedPositionAfter(mappingA, mappingB) {
19 - // Optimized for most common case
20 - var lineA = mappingA.generatedLine;
21 - var lineB = mappingB.generatedLine;
22 - var columnA = mappingA.generatedColumn;
23 - var columnB = mappingB.generatedColumn;
24 - return lineB > lineA || lineB == lineA && columnB >= columnA ||
25 - util.compareByGeneratedPositions(mappingA, mappingB) <= 0;
26 - }
27 -
28 - /**
29 - * A data structure to provide a sorted view of accumulated mappings in a
30 - * performance conscious manner. It trades a neglibable overhead in general
31 - * case for a large speedup in case of mappings being added in order.
32 - */
33 - function MappingList() {
34 - this._array = [];
35 - this._sorted = true;
36 - // Serves as infimum
37 - this._last = {generatedLine: -1, generatedColumn: 0};
38 - }
39 -
40 - /**
41 - * Iterate through internal items. This method takes the same arguments that
42 - * `Array.prototype.forEach` takes.
43 - *
44 - * NOTE: The order of the mappings is NOT guaranteed.
45 - */
46 - MappingList.prototype.unsortedForEach =
47 - function MappingList_forEach(aCallback, aThisArg) {
48 - this._array.forEach(aCallback, aThisArg);
49 - };
50 -
51 - /**
52 - * Add the given source mapping.
53 - *
54 - * @param Object aMapping
55 - */
56 - MappingList.prototype.add = function MappingList_add(aMapping) {
57 - var mapping;
58 - if (generatedPositionAfter(this._last, aMapping)) {
59 - this._last = aMapping;
60 - this._array.push(aMapping);
61 - } else {
62 - this._sorted = false;
63 - this._array.push(aMapping);
64 - }
65 - };
66 -
67 - /**
68 - * Returns the flat, sorted array of mappings. The mappings are sorted by
69 - * generated position.
70 - *
71 - * WARNING: This method returns internal data without copying, for
72 - * performance. The return value must NOT be mutated, and should be treated as
73 - * an immutable borrow. If you want to take ownership, you must make your own
74 - * copy.
75 - */
76 - MappingList.prototype.toArray = function MappingList_toArray() {
77 - if (!this._sorted) {
78 - this._array.sort(util.compareByGeneratedPositions);
79 - this._sorted = true;
80 - }
81 - return this._array;
82 - };
83 -
84 - exports.MappingList = MappingList;
85 -
86 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var util = require('./util');
13 - var binarySearch = require('./binary-search');
14 - var ArraySet = require('./array-set').ArraySet;
15 - var base64VLQ = require('./base64-vlq');
16 -
17 - /**
18 - * A SourceMapConsumer instance represents a parsed source map which we can
19 - * query for information about the original file positions by giving it a file
20 - * position in the generated source.
21 - *
22 - * The only parameter is the raw source map (either as a JSON string, or
23 - * already parsed to an object). According to the spec, source maps have the
24 - * following attributes:
25 - *
26 - * - version: Which version of the source map spec this map is following.
27 - * - sources: An array of URLs to the original source files.
28 - * - names: An array of identifiers which can be referrenced by individual mappings.
29 - * - sourceRoot: Optional. The URL root from which all sources are relative.
30 - * - sourcesContent: Optional. An array of contents of the original source files.
31 - * - mappings: A string of base64 VLQs which contain the actual mappings.
32 - * - file: Optional. The generated file this source map is associated with.
33 - *
34 - * Here is an example source map, taken from the source map spec[0]:
35 - *
36 - * {
37 - * version : 3,
38 - * file: "out.js",
39 - * sourceRoot : "",
40 - * sources: ["foo.js", "bar.js"],
41 - * names: ["src", "maps", "are", "fun"],
42 - * mappings: "AA,AB;;ABCDE;"
43 - * }
44 - *
45 - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
46 - */
47 - function SourceMapConsumer(aSourceMap) {
48 - var sourceMap = aSourceMap;
49 - if (typeof aSourceMap === 'string') {
50 - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
51 - }
52 -
53 - var version = util.getArg(sourceMap, 'version');
54 - var sources = util.getArg(sourceMap, 'sources');
55 - // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
56 - // requires the array) to play nice here.
57 - var names = util.getArg(sourceMap, 'names', []);
58 - var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
59 - var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
60 - var mappings = util.getArg(sourceMap, 'mappings');
61 - var file = util.getArg(sourceMap, 'file', null);
62 -
63 - // Once again, Sass deviates from the spec and supplies the version as a
64 - // string rather than a number, so we use loose equality checking here.
65 - if (version != this._version) {
66 - throw new Error('Unsupported version: ' + version);
67 - }
68 -
69 - // Some source maps produce relative source paths like "./foo.js" instead of
70 - // "foo.js". Normalize these first so that future comparisons will succeed.
71 - // See bugzil.la/1090768.
72 - sources = sources.map(util.normalize);
73 -
74 - // Pass `true` below to allow duplicate names and sources. While source maps
75 - // are intended to be compressed and deduplicated, the TypeScript compiler
76 - // sometimes generates source maps with duplicates in them. See Github issue
77 - // #72 and bugzil.la/889492.
78 - this._names = ArraySet.fromArray(names, true);
79 - this._sources = ArraySet.fromArray(sources, true);
80 -
81 - this.sourceRoot = sourceRoot;
82 - this.sourcesContent = sourcesContent;
83 - this._mappings = mappings;
84 - this.file = file;
85 - }
86 -
87 - /**
88 - * Create a SourceMapConsumer from a SourceMapGenerator.
89 - *
90 - * @param SourceMapGenerator aSourceMap
91 - * The source map that will be consumed.
92 - * @returns SourceMapConsumer
93 - */
94 - SourceMapConsumer.fromSourceMap =
95 - function SourceMapConsumer_fromSourceMap(aSourceMap) {
96 - var smc = Object.create(SourceMapConsumer.prototype);
97 -
98 - smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
99 - smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
100 - smc.sourceRoot = aSourceMap._sourceRoot;
101 - smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
102 - smc.sourceRoot);
103 - smc.file = aSourceMap._file;
104 -
105 - smc.__generatedMappings = aSourceMap._mappings.toArray().slice();
106 - smc.__originalMappings = aSourceMap._mappings.toArray().slice()
107 - .sort(util.compareByOriginalPositions);
108 -
109 - return smc;
110 - };
111 -
112 - /**
113 - * The version of the source mapping spec that we are consuming.
114 - */
115 - SourceMapConsumer.prototype._version = 3;
116 -
117 - /**
118 - * The list of original sources.
119 - */
120 - Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
121 - get: function () {
122 - return this._sources.toArray().map(function (s) {
123 - return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
124 - }, this);
125 - }
126 - });
127 -
128 - // `__generatedMappings` and `__originalMappings` are arrays that hold the
129 - // parsed mapping coordinates from the source map's "mappings" attribute. They
130 - // are lazily instantiated, accessed via the `_generatedMappings` and
131 - // `_originalMappings` getters respectively, and we only parse the mappings
132 - // and create these arrays once queried for a source location. We jump through
133 - // these hoops because there can be many thousands of mappings, and parsing
134 - // them is expensive, so we only want to do it if we must.
135 - //
136 - // Each object in the arrays is of the form:
137 - //
138 - // {
139 - // generatedLine: The line number in the generated code,
140 - // generatedColumn: The column number in the generated code,
141 - // source: The path to the original source file that generated this
142 - // chunk of code,
143 - // originalLine: The line number in the original source that
144 - // corresponds to this chunk of generated code,
145 - // originalColumn: The column number in the original source that
146 - // corresponds to this chunk of generated code,
147 - // name: The name of the original symbol which generated this chunk of
148 - // code.
149 - // }
150 - //
151 - // All properties except for `generatedLine` and `generatedColumn` can be
152 - // `null`.
153 - //
154 - // `_generatedMappings` is ordered by the generated positions.
155 - //
156 - // `_originalMappings` is ordered by the original positions.
157 -
158 - SourceMapConsumer.prototype.__generatedMappings = null;
159 - Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {
160 - get: function () {
161 - if (!this.__generatedMappings) {
162 - this.__generatedMappings = [];
163 - this.__originalMappings = [];
164 - this._parseMappings(this._mappings, this.sourceRoot);
165 - }
166 -
167 - return this.__generatedMappings;
168 - }
169 - });
170 -
171 - SourceMapConsumer.prototype.__originalMappings = null;
172 - Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {
173 - get: function () {
174 - if (!this.__originalMappings) {
175 - this.__generatedMappings = [];
176 - this.__originalMappings = [];
177 - this._parseMappings(this._mappings, this.sourceRoot);
178 - }
179 -
180 - return this.__originalMappings;
181 - }
182 - });
183 -
184 - SourceMapConsumer.prototype._nextCharIsMappingSeparator =
185 - function SourceMapConsumer_nextCharIsMappingSeparator(aStr) {
186 - var c = aStr.charAt(0);
187 - return c === ";" || c === ",";
188 - };
189 -
190 - /**
191 - * Parse the mappings in a string in to a data structure which we can easily
192 - * query (the ordered arrays in the `this.__generatedMappings` and
193 - * `this.__originalMappings` properties).
194 - */
195 - SourceMapConsumer.prototype._parseMappings =
196 - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
197 - var generatedLine = 1;
198 - var previousGeneratedColumn = 0;
199 - var previousOriginalLine = 0;
200 - var previousOriginalColumn = 0;
201 - var previousSource = 0;
202 - var previousName = 0;
203 - var str = aStr;
204 - var temp = {};
205 - var mapping;
206 -
207 - while (str.length > 0) {
208 - if (str.charAt(0) === ';') {
209 - generatedLine++;
210 - str = str.slice(1);
211 - previousGeneratedColumn = 0;
212 - }
213 - else if (str.charAt(0) === ',') {
214 - str = str.slice(1);
215 - }
216 - else {
217 - mapping = {};
218 - mapping.generatedLine = generatedLine;
219 -
220 - // Generated column.
221 - base64VLQ.decode(str, temp);
222 - mapping.generatedColumn = previousGeneratedColumn + temp.value;
223 - previousGeneratedColumn = mapping.generatedColumn;
224 - str = temp.rest;
225 -
226 - if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
227 - // Original source.
228 - base64VLQ.decode(str, temp);
229 - mapping.source = this._sources.at(previousSource + temp.value);
230 - previousSource += temp.value;
231 - str = temp.rest;
232 - if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
233 - throw new Error('Found a source, but no line and column');
234 - }
235 -
236 - // Original line.
237 - base64VLQ.decode(str, temp);
238 - mapping.originalLine = previousOriginalLine + temp.value;
239 - previousOriginalLine = mapping.originalLine;
240 - // Lines are stored 0-based
241 - mapping.originalLine += 1;
242 - str = temp.rest;
243 - if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
244 - throw new Error('Found a source and line, but no column');
245 - }
246 -
247 - // Original column.
248 - base64VLQ.decode(str, temp);
249 - mapping.originalColumn = previousOriginalColumn + temp.value;
250 - previousOriginalColumn = mapping.originalColumn;
251 - str = temp.rest;
252 -
253 - if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
254 - // Original name.
255 - base64VLQ.decode(str, temp);
256 - mapping.name = this._names.at(previousName + temp.value);
257 - previousName += temp.value;
258 - str = temp.rest;
259 - }
260 - }
261 -
262 - this.__generatedMappings.push(mapping);
263 - if (typeof mapping.originalLine === 'number') {
264 - this.__originalMappings.push(mapping);
265 - }
266 - }
267 - }
268 -
269 - this.__generatedMappings.sort(util.compareByGeneratedPositions);
270 - this.__originalMappings.sort(util.compareByOriginalPositions);
271 - };
272 -
273 - /**
274 - * Find the mapping that best matches the hypothetical "needle" mapping that
275 - * we are searching for in the given "haystack" of mappings.
276 - */
277 - SourceMapConsumer.prototype._findMapping =
278 - function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
279 - aColumnName, aComparator) {
280 - // To return the position we are searching for, we must first find the
281 - // mapping for the given position and then return the opposite position it
282 - // points to. Because the mappings are sorted, we can use binary search to
283 - // find the best mapping.
284 -
285 - if (aNeedle[aLineName] <= 0) {
286 - throw new TypeError('Line must be greater than or equal to 1, got '
287 - + aNeedle[aLineName]);
288 - }
289 - if (aNeedle[aColumnName] < 0) {
290 - throw new TypeError('Column must be greater than or equal to 0, got '
291 - + aNeedle[aColumnName]);
292 - }
293 -
294 - return binarySearch.search(aNeedle, aMappings, aComparator);
295 - };
296 -
297 - /**
298 - * Compute the last column for each generated mapping. The last column is
299 - * inclusive.
300 - */
301 - SourceMapConsumer.prototype.computeColumnSpans =
302 - function SourceMapConsumer_computeColumnSpans() {
303 - for (var index = 0; index < this._generatedMappings.length; ++index) {
304 - var mapping = this._generatedMappings[index];
305 -
306 - // Mappings do not contain a field for the last generated columnt. We
307 - // can come up with an optimistic estimate, however, by assuming that
308 - // mappings are contiguous (i.e. given two consecutive mappings, the
309 - // first mapping ends where the second one starts).
310 - if (index + 1 < this._generatedMappings.length) {
311 - var nextMapping = this._generatedMappings[index + 1];
312 -
313 - if (mapping.generatedLine === nextMapping.generatedLine) {
314 - mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
315 - continue;
316 - }
317 - }
318 -
319 - // The last mapping for each line spans the entire line.
320 - mapping.lastGeneratedColumn = Infinity;
321 - }
322 - };
323 -
324 - /**
325 - * Returns the original source, line, and column information for the generated
326 - * source's line and column positions provided. The only argument is an object
327 - * with the following properties:
328 - *
329 - * - line: The line number in the generated source.
330 - * - column: The column number in the generated source.
331 - *
332 - * and an object is returned with the following properties:
333 - *
334 - * - source: The original source file, or null.
335 - * - line: The line number in the original source, or null.
336 - * - column: The column number in the original source, or null.
337 - * - name: The original identifier, or null.
338 - */
339 - SourceMapConsumer.prototype.originalPositionFor =
340 - function SourceMapConsumer_originalPositionFor(aArgs) {
341 - var needle = {
342 - generatedLine: util.getArg(aArgs, 'line'),
343 - generatedColumn: util.getArg(aArgs, 'column')
344 - };
345 -
346 - var index = this._findMapping(needle,
347 - this._generatedMappings,
348 - "generatedLine",
349 - "generatedColumn",
350 - util.compareByGeneratedPositions);
351 -
352 - if (index >= 0) {
353 - var mapping = this._generatedMappings[index];
354 -
355 - if (mapping.generatedLine === needle.generatedLine) {
356 - var source = util.getArg(mapping, 'source', null);
357 - if (source != null && this.sourceRoot != null) {
358 - source = util.join(this.sourceRoot, source);
359 - }
360 - return {
361 - source: source,
362 - line: util.getArg(mapping, 'originalLine', null),
363 - column: util.getArg(mapping, 'originalColumn', null),
364 - name: util.getArg(mapping, 'name', null)
365 - };
366 - }
367 - }
368 -
369 - return {
370 - source: null,
371 - line: null,
372 - column: null,
373 - name: null
374 - };
375 - };
376 -
377 - /**
378 - * Returns the original source content. The only argument is the url of the
379 - * original source file. Returns null if no original source content is
380 - * availible.
381 - */
382 - SourceMapConsumer.prototype.sourceContentFor =
383 - function SourceMapConsumer_sourceContentFor(aSource) {
384 - if (!this.sourcesContent) {
385 - return null;
386 - }
387 -
388 - if (this.sourceRoot != null) {
389 - aSource = util.relative(this.sourceRoot, aSource);
390 - }
391 -
392 - if (this._sources.has(aSource)) {
393 - return this.sourcesContent[this._sources.indexOf(aSource)];
394 - }
395 -
396 - var url;
397 - if (this.sourceRoot != null
398 - && (url = util.urlParse(this.sourceRoot))) {
399 - // XXX: file:// URIs and absolute paths lead to unexpected behavior for
400 - // many users. We can help them out when they expect file:// URIs to
401 - // behave like it would if they were running a local HTTP server. See
402 - // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
403 - var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
404 - if (url.scheme == "file"
405 - && this._sources.has(fileUriAbsPath)) {
406 - return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
407 - }
408 -
409 - if ((!url.path || url.path == "/")
410 - && this._sources.has("/" + aSource)) {
411 - return this.sourcesContent[this._sources.indexOf("/" + aSource)];
412 - }
413 - }
414 -
415 - throw new Error('"' + aSource + '" is not in the SourceMap.');
416 - };
417 -
418 - /**
419 - * Returns the generated line and column information for the original source,
420 - * line, and column positions provided. The only argument is an object with
421 - * the following properties:
422 - *
423 - * - source: The filename of the original source.
424 - * - line: The line number in the original source.
425 - * - column: The column number in the original source.
426 - *
427 - * and an object is returned with the following properties:
428 - *
429 - * - line: The line number in the generated source, or null.
430 - * - column: The column number in the generated source, or null.
431 - */
432 - SourceMapConsumer.prototype.generatedPositionFor =
433 - function SourceMapConsumer_generatedPositionFor(aArgs) {
434 - var needle = {
435 - source: util.getArg(aArgs, 'source'),
436 - originalLine: util.getArg(aArgs, 'line'),
437 - originalColumn: util.getArg(aArgs, 'column')
438 - };
439 -
440 - if (this.sourceRoot != null) {
441 - needle.source = util.relative(this.sourceRoot, needle.source);
442 - }
443 -
444 - var index = this._findMapping(needle,
445 - this._originalMappings,
446 - "originalLine",
447 - "originalColumn",
448 - util.compareByOriginalPositions);
449 -
450 - if (index >= 0) {
451 - var mapping = this._originalMappings[index];
452 -
453 - return {
454 - line: util.getArg(mapping, 'generatedLine', null),
455 - column: util.getArg(mapping, 'generatedColumn', null),
456 - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
457 - };
458 - }
459 -
460 - return {
461 - line: null,
462 - column: null,
463 - lastColumn: null
464 - };
465 - };
466 -
467 - /**
468 - * Returns all generated line and column information for the original source
469 - * and line provided. The only argument is an object with the following
470 - * properties:
471 - *
472 - * - source: The filename of the original source.
473 - * - line: The line number in the original source.
474 - *
475 - * and an array of objects is returned, each with the following properties:
476 - *
477 - * - line: The line number in the generated source, or null.
478 - * - column: The column number in the generated source, or null.
479 - */
480 - SourceMapConsumer.prototype.allGeneratedPositionsFor =
481 - function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
482 - // When there is no exact match, SourceMapConsumer.prototype._findMapping
483 - // returns the index of the closest mapping less than the needle. By
484 - // setting needle.originalColumn to Infinity, we thus find the last
485 - // mapping for the given line, provided such a mapping exists.
486 - var needle = {
487 - source: util.getArg(aArgs, 'source'),
488 - originalLine: util.getArg(aArgs, 'line'),
489 - originalColumn: Infinity
490 - };
491 -
492 - if (this.sourceRoot != null) {
493 - needle.source = util.relative(this.sourceRoot, needle.source);
494 - }
495 -
496 - var mappings = [];
497 -
498 - var index = this._findMapping(needle,
499 - this._originalMappings,
500 - "originalLine",
501 - "originalColumn",
502 - util.compareByOriginalPositions);
503 - if (index >= 0) {
504 - var mapping = this._originalMappings[index];
505 -
506 - while (mapping && mapping.originalLine === needle.originalLine) {
507 - mappings.push({
508 - line: util.getArg(mapping, 'generatedLine', null),
509 - column: util.getArg(mapping, 'generatedColumn', null),
510 - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
511 - });
512 -
513 - mapping = this._originalMappings[--index];
514 - }
515 - }
516 -
517 - return mappings.reverse();
518 - };
519 -
520 - SourceMapConsumer.GENERATED_ORDER = 1;
521 - SourceMapConsumer.ORIGINAL_ORDER = 2;
522 -
523 - /**
524 - * Iterate over each mapping between an original source/line/column and a
525 - * generated line/column in this source map.
526 - *
527 - * @param Function aCallback
528 - * The function that is called with each mapping.
529 - * @param Object aContext
530 - * Optional. If specified, this object will be the value of `this` every
531 - * time that `aCallback` is called.
532 - * @param aOrder
533 - * Either `SourceMapConsumer.GENERATED_ORDER` or
534 - * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
535 - * iterate over the mappings sorted by the generated file's line/column
536 - * order or the original's source/line/column order, respectively. Defaults to
537 - * `SourceMapConsumer.GENERATED_ORDER`.
538 - */
539 - SourceMapConsumer.prototype.eachMapping =
540 - function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
541 - var context = aContext || null;
542 - var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
543 -
544 - var mappings;
545 - switch (order) {
546 - case SourceMapConsumer.GENERATED_ORDER:
547 - mappings = this._generatedMappings;
548 - break;
549 - case SourceMapConsumer.ORIGINAL_ORDER:
550 - mappings = this._originalMappings;
551 - break;
552 - default:
553 - throw new Error("Unknown order of iteration.");
554 - }
555 -
556 - var sourceRoot = this.sourceRoot;
557 - mappings.map(function (mapping) {
558 - var source = mapping.source;
559 - if (source != null && sourceRoot != null) {
560 - source = util.join(sourceRoot, source);
561 - }
562 - return {
563 - source: source,
564 - generatedLine: mapping.generatedLine,
565 - generatedColumn: mapping.generatedColumn,
566 - originalLine: mapping.originalLine,
567 - originalColumn: mapping.originalColumn,
568 - name: mapping.name
569 - };
570 - }).forEach(aCallback, context);
571 - };
572 -
573 - exports.SourceMapConsumer = SourceMapConsumer;
574 -
575 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var base64VLQ = require('./base64-vlq');
13 - var util = require('./util');
14 - var ArraySet = require('./array-set').ArraySet;
15 - var MappingList = require('./mapping-list').MappingList;
16 -
17 - /**
18 - * An instance of the SourceMapGenerator represents a source map which is
19 - * being built incrementally. You may pass an object with the following
20 - * properties:
21 - *
22 - * - file: The filename of the generated source.
23 - * - sourceRoot: A root for all relative URLs in this source map.
24 - */
25 - function SourceMapGenerator(aArgs) {
26 - if (!aArgs) {
27 - aArgs = {};
28 - }
29 - this._file = util.getArg(aArgs, 'file', null);
30 - this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
31 - this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
32 - this._sources = new ArraySet();
33 - this._names = new ArraySet();
34 - this._mappings = new MappingList();
35 - this._sourcesContents = null;
36 - }
37 -
38 - SourceMapGenerator.prototype._version = 3;
39 -
40 - /**
41 - * Creates a new SourceMapGenerator based on a SourceMapConsumer
42 - *
43 - * @param aSourceMapConsumer The SourceMap.
44 - */
45 - SourceMapGenerator.fromSourceMap =
46 - function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
47 - var sourceRoot = aSourceMapConsumer.sourceRoot;
48 - var generator = new SourceMapGenerator({
49 - file: aSourceMapConsumer.file,
50 - sourceRoot: sourceRoot
51 - });
52 - aSourceMapConsumer.eachMapping(function (mapping) {
53 - var newMapping = {
54 - generated: {
55 - line: mapping.generatedLine,
56 - column: mapping.generatedColumn
57 - }
58 - };
59 -
60 - if (mapping.source != null) {
61 - newMapping.source = mapping.source;
62 - if (sourceRoot != null) {
63 - newMapping.source = util.relative(sourceRoot, newMapping.source);
64 - }
65 -
66 - newMapping.original = {
67 - line: mapping.originalLine,
68 - column: mapping.originalColumn
69 - };
70 -
71 - if (mapping.name != null) {
72 - newMapping.name = mapping.name;
73 - }
74 - }
75 -
76 - generator.addMapping(newMapping);
77 - });
78 - aSourceMapConsumer.sources.forEach(function (sourceFile) {
79 - var content = aSourceMapConsumer.sourceContentFor(sourceFile);
80 - if (content != null) {
81 - generator.setSourceContent(sourceFile, content);
82 - }
83 - });
84 - return generator;
85 - };
86 -
87 - /**
88 - * Add a single mapping from original source line and column to the generated
89 - * source's line and column for this source map being created. The mapping
90 - * object should have the following properties:
91 - *
92 - * - generated: An object with the generated line and column positions.
93 - * - original: An object with the original line and column positions.
94 - * - source: The original source file (relative to the sourceRoot).
95 - * - name: An optional original token name for this mapping.
96 - */
97 - SourceMapGenerator.prototype.addMapping =
98 - function SourceMapGenerator_addMapping(aArgs) {
99 - var generated = util.getArg(aArgs, 'generated');
100 - var original = util.getArg(aArgs, 'original', null);
101 - var source = util.getArg(aArgs, 'source', null);
102 - var name = util.getArg(aArgs, 'name', null);
103 -
104 - if (!this._skipValidation) {
105 - this._validateMapping(generated, original, source, name);
106 - }
107 -
108 - if (source != null && !this._sources.has(source)) {
109 - this._sources.add(source);
110 - }
111 -
112 - if (name != null && !this._names.has(name)) {
113 - this._names.add(name);
114 - }
115 -
116 - this._mappings.add({
117 - generatedLine: generated.line,
118 - generatedColumn: generated.column,
119 - originalLine: original != null && original.line,
120 - originalColumn: original != null && original.column,
121 - source: source,
122 - name: name
123 - });
124 - };
125 -
126 - /**
127 - * Set the source content for a source file.
128 - */
129 - SourceMapGenerator.prototype.setSourceContent =
130 - function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
131 - var source = aSourceFile;
132 - if (this._sourceRoot != null) {
133 - source = util.relative(this._sourceRoot, source);
134 - }
135 -
136 - if (aSourceContent != null) {
137 - // Add the source content to the _sourcesContents map.
138 - // Create a new _sourcesContents map if the property is null.
139 - if (!this._sourcesContents) {
140 - this._sourcesContents = {};
141 - }
142 - this._sourcesContents[util.toSetString(source)] = aSourceContent;
143 - } else if (this._sourcesContents) {
144 - // Remove the source file from the _sourcesContents map.
145 - // If the _sourcesContents map is empty, set the property to null.
146 - delete this._sourcesContents[util.toSetString(source)];
147 - if (Object.keys(this._sourcesContents).length === 0) {
148 - this._sourcesContents = null;
149 - }
150 - }
151 - };
152 -
153 - /**
154 - * Applies the mappings of a sub-source-map for a specific source file to the
155 - * source map being generated. Each mapping to the supplied source file is
156 - * rewritten using the supplied source map. Note: The resolution for the
157 - * resulting mappings is the minimium of this map and the supplied map.
158 - *
159 - * @param aSourceMapConsumer The source map to be applied.
160 - * @param aSourceFile Optional. The filename of the source file.
161 - * If omitted, SourceMapConsumer's file property will be used.
162 - * @param aSourceMapPath Optional. The dirname of the path to the source map
163 - * to be applied. If relative, it is relative to the SourceMapConsumer.
164 - * This parameter is needed when the two source maps aren't in the same
165 - * directory, and the source map to be applied contains relative source
166 - * paths. If so, those relative source paths need to be rewritten
167 - * relative to the SourceMapGenerator.
168 - */
169 - SourceMapGenerator.prototype.applySourceMap =
170 - function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
171 - var sourceFile = aSourceFile;
172 - // If aSourceFile is omitted, we will use the file property of the SourceMap
173 - if (aSourceFile == null) {
174 - if (aSourceMapConsumer.file == null) {
175 - throw new Error(
176 - 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
177 - 'or the source map\'s "file" property. Both were omitted.'
178 - );
179 - }
180 - sourceFile = aSourceMapConsumer.file;
181 - }
182 - var sourceRoot = this._sourceRoot;
183 - // Make "sourceFile" relative if an absolute Url is passed.
184 - if (sourceRoot != null) {
185 - sourceFile = util.relative(sourceRoot, sourceFile);
186 - }
187 - // Applying the SourceMap can add and remove items from the sources and
188 - // the names array.
189 - var newSources = new ArraySet();
190 - var newNames = new ArraySet();
191 -
192 - // Find mappings for the "sourceFile"
193 - this._mappings.unsortedForEach(function (mapping) {
194 - if (mapping.source === sourceFile && mapping.originalLine != null) {
195 - // Check if it can be mapped by the source map, then update the mapping.
196 - var original = aSourceMapConsumer.originalPositionFor({
197 - line: mapping.originalLine,
198 - column: mapping.originalColumn
199 - });
200 - if (original.source != null) {
201 - // Copy mapping
202 - mapping.source = original.source;
203 - if (aSourceMapPath != null) {
204 - mapping.source = util.join(aSourceMapPath, mapping.source)
205 - }
206 - if (sourceRoot != null) {
207 - mapping.source = util.relative(sourceRoot, mapping.source);
208 - }
209 - mapping.originalLine = original.line;
210 - mapping.originalColumn = original.column;
211 - if (original.name != null) {
212 - mapping.name = original.name;
213 - }
214 - }
215 - }
216 -
217 - var source = mapping.source;
218 - if (source != null && !newSources.has(source)) {
219 - newSources.add(source);
220 - }
221 -
222 - var name = mapping.name;
223 - if (name != null && !newNames.has(name)) {
224 - newNames.add(name);
225 - }
226 -
227 - }, this);
228 - this._sources = newSources;
229 - this._names = newNames;
230 -
231 - // Copy sourcesContents of applied map.
232 - aSourceMapConsumer.sources.forEach(function (sourceFile) {
233 - var content = aSourceMapConsumer.sourceContentFor(sourceFile);
234 - if (content != null) {
235 - if (aSourceMapPath != null) {
236 - sourceFile = util.join(aSourceMapPath, sourceFile);
237 - }
238 - if (sourceRoot != null) {
239 - sourceFile = util.relative(sourceRoot, sourceFile);
240 - }
241 - this.setSourceContent(sourceFile, content);
242 - }
243 - }, this);
244 - };
245 -
246 - /**
247 - * A mapping can have one of the three levels of data:
248 - *
249 - * 1. Just the generated position.
250 - * 2. The Generated position, original position, and original source.
251 - * 3. Generated and original position, original source, as well as a name
252 - * token.
253 - *
254 - * To maintain consistency, we validate that any new mapping being added falls
255 - * in to one of these categories.
256 - */
257 - SourceMapGenerator.prototype._validateMapping =
258 - function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
259 - aName) {
260 - if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
261 - && aGenerated.line > 0 && aGenerated.column >= 0
262 - && !aOriginal && !aSource && !aName) {
263 - // Case 1.
264 - return;
265 - }
266 - else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
267 - && aOriginal && 'line' in aOriginal && 'column' in aOriginal
268 - && aGenerated.line > 0 && aGenerated.column >= 0
269 - && aOriginal.line > 0 && aOriginal.column >= 0
270 - && aSource) {
271 - // Cases 2 and 3.
272 - return;
273 - }
274 - else {
275 - throw new Error('Invalid mapping: ' + JSON.stringify({
276 - generated: aGenerated,
277 - source: aSource,
278 - original: aOriginal,
279 - name: aName
280 - }));
281 - }
282 - };
283 -
284 - /**
285 - * Serialize the accumulated mappings in to the stream of base 64 VLQs
286 - * specified by the source map format.
287 - */
288 - SourceMapGenerator.prototype._serializeMappings =
289 - function SourceMapGenerator_serializeMappings() {
290 - var previousGeneratedColumn = 0;
291 - var previousGeneratedLine = 1;
292 - var previousOriginalColumn = 0;
293 - var previousOriginalLine = 0;
294 - var previousName = 0;
295 - var previousSource = 0;
296 - var result = '';
297 - var mapping;
298 -
299 - var mappings = this._mappings.toArray();
300 -
301 - for (var i = 0, len = mappings.length; i < len; i++) {
302 - mapping = mappings[i];
303 -
304 - if (mapping.generatedLine !== previousGeneratedLine) {
305 - previousGeneratedColumn = 0;
306 - while (mapping.generatedLine !== previousGeneratedLine) {
307 - result += ';';
308 - previousGeneratedLine++;
309 - }
310 - }
311 - else {
312 - if (i > 0) {
313 - if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) {
314 - continue;
315 - }
316 - result += ',';
317 - }
318 - }
319 -
320 - result += base64VLQ.encode(mapping.generatedColumn
321 - - previousGeneratedColumn);
322 - previousGeneratedColumn = mapping.generatedColumn;
323 -
324 - if (mapping.source != null) {
325 - result += base64VLQ.encode(this._sources.indexOf(mapping.source)
326 - - previousSource);
327 - previousSource = this._sources.indexOf(mapping.source);
328 -
329 - // lines are stored 0-based in SourceMap spec version 3
330 - result += base64VLQ.encode(mapping.originalLine - 1
331 - - previousOriginalLine);
332 - previousOriginalLine = mapping.originalLine - 1;
333 -
334 - result += base64VLQ.encode(mapping.originalColumn
335 - - previousOriginalColumn);
336 - previousOriginalColumn = mapping.originalColumn;
337 -
338 - if (mapping.name != null) {
339 - result += base64VLQ.encode(this._names.indexOf(mapping.name)
340 - - previousName);
341 - previousName = this._names.indexOf(mapping.name);
342 - }
343 - }
344 - }
345 -
346 - return result;
347 - };
348 -
349 - SourceMapGenerator.prototype._generateSourcesContent =
350 - function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
351 - return aSources.map(function (source) {
352 - if (!this._sourcesContents) {
353 - return null;
354 - }
355 - if (aSourceRoot != null) {
356 - source = util.relative(aSourceRoot, source);
357 - }
358 - var key = util.toSetString(source);
359 - return Object.prototype.hasOwnProperty.call(this._sourcesContents,
360 - key)
361 - ? this._sourcesContents[key]
362 - : null;
363 - }, this);
364 - };
365 -
366 - /**
367 - * Externalize the source map.
368 - */
369 - SourceMapGenerator.prototype.toJSON =
370 - function SourceMapGenerator_toJSON() {
371 - var map = {
372 - version: this._version,
373 - sources: this._sources.toArray(),
374 - names: this._names.toArray(),
375 - mappings: this._serializeMappings()
376 - };
377 - if (this._file != null) {
378 - map.file = this._file;
379 - }
380 - if (this._sourceRoot != null) {
381 - map.sourceRoot = this._sourceRoot;
382 - }
383 - if (this._sourcesContents) {
384 - map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
385 - }
386 -
387 - return map;
388 - };
389 -
390 - /**
391 - * Render the source map being generated to a string.
392 - */
393 - SourceMapGenerator.prototype.toString =
394 - function SourceMapGenerator_toString() {
395 - return JSON.stringify(this);
396 - };
397 -
398 - exports.SourceMapGenerator = SourceMapGenerator;
399 -
400 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
13 - var util = require('./util');
14 -
15 - // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
16 - // operating systems these days (capturing the result).
17 - var REGEX_NEWLINE = /(\r?\n)/;
18 -
19 - // Newline character code for charCodeAt() comparisons
20 - var NEWLINE_CODE = 10;
21 -
22 - // Private symbol for identifying `SourceNode`s when multiple versions of
23 - // the source-map library are loaded. This MUST NOT CHANGE across
24 - // versions!
25 - var isSourceNode = "$$$isSourceNode$$$";
26 -
27 - /**
28 - * SourceNodes provide a way to abstract over interpolating/concatenating
29 - * snippets of generated JavaScript source code while maintaining the line and
30 - * column information associated with the original source code.
31 - *
32 - * @param aLine The original line number.
33 - * @param aColumn The original column number.
34 - * @param aSource The original source's filename.
35 - * @param aChunks Optional. An array of strings which are snippets of
36 - * generated JS, or other SourceNodes.
37 - * @param aName The original identifier.
38 - */
39 - function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
40 - this.children = [];
41 - this.sourceContents = {};
42 - this.line = aLine == null ? null : aLine;
43 - this.column = aColumn == null ? null : aColumn;
44 - this.source = aSource == null ? null : aSource;
45 - this.name = aName == null ? null : aName;
46 - this[isSourceNode] = true;
47 - if (aChunks != null) this.add(aChunks);
48 - }
49 -
50 - /**
51 - * Creates a SourceNode from generated code and a SourceMapConsumer.
52 - *
53 - * @param aGeneratedCode The generated code
54 - * @param aSourceMapConsumer The SourceMap for the generated code
55 - * @param aRelativePath Optional. The path that relative sources in the
56 - * SourceMapConsumer should be relative to.
57 - */
58 - SourceNode.fromStringWithSourceMap =
59 - function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
60 - // The SourceNode we want to fill with the generated code
61 - // and the SourceMap
62 - var node = new SourceNode();
63 -
64 - // All even indices of this array are one line of the generated code,
65 - // while all odd indices are the newlines between two adjacent lines
66 - // (since `REGEX_NEWLINE` captures its match).
67 - // Processed fragments are removed from this array, by calling `shiftNextLine`.
68 - var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
69 - var shiftNextLine = function() {
70 - var lineContents = remainingLines.shift();
71 - // The last line of a file might not have a newline.
72 - var newLine = remainingLines.shift() || "";
73 - return lineContents + newLine;
74 - };
75 -
76 - // We need to remember the position of "remainingLines"
77 - var lastGeneratedLine = 1, lastGeneratedColumn = 0;
78 -
79 - // The generate SourceNodes we need a code range.
80 - // To extract it current and last mapping is used.
81 - // Here we store the last mapping.
82 - var lastMapping = null;
83 -
84 - aSourceMapConsumer.eachMapping(function (mapping) {
85 - if (lastMapping !== null) {
86 - // We add the code from "lastMapping" to "mapping":
87 - // First check if there is a new line in between.
88 - if (lastGeneratedLine < mapping.generatedLine) {
89 - var code = "";
90 - // Associate first line with "lastMapping"
91 - addMappingWithCode(lastMapping, shiftNextLine());
92 - lastGeneratedLine++;
93 - lastGeneratedColumn = 0;
94 - // The remaining code is added without mapping
95 - } else {
96 - // There is no new line in between.
97 - // Associate the code between "lastGeneratedColumn" and
98 - // "mapping.generatedColumn" with "lastMapping"
99 - var nextLine = remainingLines[0];
100 - var code = nextLine.substr(0, mapping.generatedColumn -
101 - lastGeneratedColumn);
102 - remainingLines[0] = nextLine.substr(mapping.generatedColumn -
103 - lastGeneratedColumn);
104 - lastGeneratedColumn = mapping.generatedColumn;
105 - addMappingWithCode(lastMapping, code);
106 - // No more remaining code, continue
107 - lastMapping = mapping;
108 - return;
109 - }
110 - }
111 - // We add the generated code until the first mapping
112 - // to the SourceNode without any mapping.
113 - // Each line is added as separate string.
114 - while (lastGeneratedLine < mapping.generatedLine) {
115 - node.add(shiftNextLine());
116 - lastGeneratedLine++;
117 - }
118 - if (lastGeneratedColumn < mapping.generatedColumn) {
119 - var nextLine = remainingLines[0];
120 - node.add(nextLine.substr(0, mapping.generatedColumn));
121 - remainingLines[0] = nextLine.substr(mapping.generatedColumn);
122 - lastGeneratedColumn = mapping.generatedColumn;
123 - }
124 - lastMapping = mapping;
125 - }, this);
126 - // We have processed all mappings.
127 - if (remainingLines.length > 0) {
128 - if (lastMapping) {
129 - // Associate the remaining code in the current line with "lastMapping"
130 - addMappingWithCode(lastMapping, shiftNextLine());
131 - }
132 - // and add the remaining lines without any mapping
133 - node.add(remainingLines.join(""));
134 - }
135 -
136 - // Copy sourcesContent into SourceNode
137 - aSourceMapConsumer.sources.forEach(function (sourceFile) {
138 - var content = aSourceMapConsumer.sourceContentFor(sourceFile);
139 - if (content != null) {
140 - if (aRelativePath != null) {
141 - sourceFile = util.join(aRelativePath, sourceFile);
142 - }
143 - node.setSourceContent(sourceFile, content);
144 - }
145 - });
146 -
147 - return node;
148 -
149 - function addMappingWithCode(mapping, code) {
150 - if (mapping === null || mapping.source === undefined) {
151 - node.add(code);
152 - } else {
153 - var source = aRelativePath
154 - ? util.join(aRelativePath, mapping.source)
155 - : mapping.source;
156 - node.add(new SourceNode(mapping.originalLine,
157 - mapping.originalColumn,
158 - source,
159 - code,
160 - mapping.name));
161 - }
162 - }
163 - };
164 -
165 - /**
166 - * Add a chunk of generated JS to this source node.
167 - *
168 - * @param aChunk A string snippet of generated JS code, another instance of
169 - * SourceNode, or an array where each member is one of those things.
170 - */
171 - SourceNode.prototype.add = function SourceNode_add(aChunk) {
172 - if (Array.isArray(aChunk)) {
173 - aChunk.forEach(function (chunk) {
174 - this.add(chunk);
175 - }, this);
176 - }
177 - else if (aChunk[isSourceNode] || typeof aChunk === "string") {
178 - if (aChunk) {
179 - this.children.push(aChunk);
180 - }
181 - }
182 - else {
183 - throw new TypeError(
184 - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
185 - );
186 - }
187 - return this;
188 - };
189 -
190 - /**
191 - * Add a chunk of generated JS to the beginning of this source node.
192 - *
193 - * @param aChunk A string snippet of generated JS code, another instance of
194 - * SourceNode, or an array where each member is one of those things.
195 - */
196 - SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
197 - if (Array.isArray(aChunk)) {
198 - for (var i = aChunk.length-1; i >= 0; i--) {
199 - this.prepend(aChunk[i]);
200 - }
201 - }
202 - else if (aChunk[isSourceNode] || typeof aChunk === "string") {
203 - this.children.unshift(aChunk);
204 - }
205 - else {
206 - throw new TypeError(
207 - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
208 - );
209 - }
210 - return this;
211 - };
212 -
213 - /**
214 - * Walk over the tree of JS snippets in this node and its children. The
215 - * walking function is called once for each snippet of JS and is passed that
216 - * snippet and the its original associated source's line/column location.
217 - *
218 - * @param aFn The traversal function.
219 - */
220 - SourceNode.prototype.walk = function SourceNode_walk(aFn) {
221 - var chunk;
222 - for (var i = 0, len = this.children.length; i < len; i++) {
223 - chunk = this.children[i];
224 - if (chunk[isSourceNode]) {
225 - chunk.walk(aFn);
226 - }
227 - else {
228 - if (chunk !== '') {
229 - aFn(chunk, { source: this.source,
230 - line: this.line,
231 - column: this.column,
232 - name: this.name });
233 - }
234 - }
235 - }
236 - };
237 -
238 - /**
239 - * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
240 - * each of `this.children`.
241 - *
242 - * @param aSep The separator.
243 - */
244 - SourceNode.prototype.join = function SourceNode_join(aSep) {
245 - var newChildren;
246 - var i;
247 - var len = this.children.length;
248 - if (len > 0) {
249 - newChildren = [];
250 - for (i = 0; i < len-1; i++) {
251 - newChildren.push(this.children[i]);
252 - newChildren.push(aSep);
253 - }
254 - newChildren.push(this.children[i]);
255 - this.children = newChildren;
256 - }
257 - return this;
258 - };
259 -
260 - /**
261 - * Call String.prototype.replace on the very right-most source snippet. Useful
262 - * for trimming whitespace from the end of a source node, etc.
263 - *
264 - * @param aPattern The pattern to replace.
265 - * @param aReplacement The thing to replace the pattern with.
266 - */
267 - SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
268 - var lastChild = this.children[this.children.length - 1];
269 - if (lastChild[isSourceNode]) {
270 - lastChild.replaceRight(aPattern, aReplacement);
271 - }
272 - else if (typeof lastChild === 'string') {
273 - this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
274 - }
275 - else {
276 - this.children.push(''.replace(aPattern, aReplacement));
277 - }
278 - return this;
279 - };
280 -
281 - /**
282 - * Set the source content for a source file. This will be added to the SourceMapGenerator
283 - * in the sourcesContent field.
284 - *
285 - * @param aSourceFile The filename of the source file
286 - * @param aSourceContent The content of the source file
287 - */
288 - SourceNode.prototype.setSourceContent =
289 - function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
290 - this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
291 - };
292 -
293 - /**
294 - * Walk over the tree of SourceNodes. The walking function is called for each
295 - * source file content and is passed the filename and source content.
296 - *
297 - * @param aFn The traversal function.
298 - */
299 - SourceNode.prototype.walkSourceContents =
300 - function SourceNode_walkSourceContents(aFn) {
301 - for (var i = 0, len = this.children.length; i < len; i++) {
302 - if (this.children[i][isSourceNode]) {
303 - this.children[i].walkSourceContents(aFn);
304 - }
305 - }
306 -
307 - var sources = Object.keys(this.sourceContents);
308 - for (var i = 0, len = sources.length; i < len; i++) {
309 - aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
310 - }
311 - };
312 -
313 - /**
314 - * Return the string representation of this source node. Walks over the tree
315 - * and concatenates all the various snippets together to one string.
316 - */
317 - SourceNode.prototype.toString = function SourceNode_toString() {
318 - var str = "";
319 - this.walk(function (chunk) {
320 - str += chunk;
321 - });
322 - return str;
323 - };
324 -
325 - /**
326 - * Returns the string representation of this source node along with a source
327 - * map.
328 - */
329 - SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
330 - var generated = {
331 - code: "",
332 - line: 1,
333 - column: 0
334 - };
335 - var map = new SourceMapGenerator(aArgs);
336 - var sourceMappingActive = false;
337 - var lastOriginalSource = null;
338 - var lastOriginalLine = null;
339 - var lastOriginalColumn = null;
340 - var lastOriginalName = null;
341 - this.walk(function (chunk, original) {
342 - generated.code += chunk;
343 - if (original.source !== null
344 - && original.line !== null
345 - && original.column !== null) {
346 - if(lastOriginalSource !== original.source
347 - || lastOriginalLine !== original.line
348 - || lastOriginalColumn !== original.column
349 - || lastOriginalName !== original.name) {
350 - map.addMapping({
351 - source: original.source,
352 - original: {
353 - line: original.line,
354 - column: original.column
355 - },
356 - generated: {
357 - line: generated.line,
358 - column: generated.column
359 - },
360 - name: original.name
361 - });
362 - }
363 - lastOriginalSource = original.source;
364 - lastOriginalLine = original.line;
365 - lastOriginalColumn = original.column;
366 - lastOriginalName = original.name;
367 - sourceMappingActive = true;
368 - } else if (sourceMappingActive) {
369 - map.addMapping({
370 - generated: {
371 - line: generated.line,
372 - column: generated.column
373 - }
374 - });
375 - lastOriginalSource = null;
376 - sourceMappingActive = false;
377 - }
378 - for (var idx = 0, length = chunk.length; idx < length; idx++) {
379 - if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
380 - generated.line++;
381 - generated.column = 0;
382 - // Mappings end at eol
383 - if (idx + 1 === length) {
384 - lastOriginalSource = null;
385 - sourceMappingActive = false;
386 - } else if (sourceMappingActive) {
387 - map.addMapping({
388 - source: original.source,
389 - original: {
390 - line: original.line,
391 - column: original.column
392 - },
393 - generated: {
394 - line: generated.line,
395 - column: generated.column
396 - },
397 - name: original.name
398 - });
399 - }
400 - } else {
401 - generated.column++;
402 - }
403 - }
404 - });
405 - this.walkSourceContents(function (sourceFile, sourceContent) {
406 - map.setSourceContent(sourceFile, sourceContent);
407 - });
408 -
409 - return { code: generated.code, map: map };
410 - };
411 -
412 - exports.SourceNode = SourceNode;
413 -
414 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - /**
13 - * This is a helper function for getting values from parameter/options
14 - * objects.
15 - *
16 - * @param args The object we are extracting values from
17 - * @param name The name of the property we are getting.
18 - * @param defaultValue An optional value to return if the property is missing
19 - * from the object. If this is not specified and the property is missing, an
20 - * error will be thrown.
21 - */
22 - function getArg(aArgs, aName, aDefaultValue) {
23 - if (aName in aArgs) {
24 - return aArgs[aName];
25 - } else if (arguments.length === 3) {
26 - return aDefaultValue;
27 - } else {
28 - throw new Error('"' + aName + '" is a required argument.');
29 - }
30 - }
31 - exports.getArg = getArg;
32 -
33 - var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/;
34 - var dataUrlRegexp = /^data:.+\,.+$/;
35 -
36 - function urlParse(aUrl) {
37 - var match = aUrl.match(urlRegexp);
38 - if (!match) {
39 - return null;
40 - }
41 - return {
42 - scheme: match[1],
43 - auth: match[2],
44 - host: match[3],
45 - port: match[4],
46 - path: match[5]
47 - };
48 - }
49 - exports.urlParse = urlParse;
50 -
51 - function urlGenerate(aParsedUrl) {
52 - var url = '';
53 - if (aParsedUrl.scheme) {
54 - url += aParsedUrl.scheme + ':';
55 - }
56 - url += '//';
57 - if (aParsedUrl.auth) {
58 - url += aParsedUrl.auth + '@';
59 - }
60 - if (aParsedUrl.host) {
61 - url += aParsedUrl.host;
62 - }
63 - if (aParsedUrl.port) {
64 - url += ":" + aParsedUrl.port
65 - }
66 - if (aParsedUrl.path) {
67 - url += aParsedUrl.path;
68 - }
69 - return url;
70 - }
71 - exports.urlGenerate = urlGenerate;
72 -
73 - /**
74 - * Normalizes a path, or the path portion of a URL:
75 - *
76 - * - Replaces consequtive slashes with one slash.
77 - * - Removes unnecessary '.' parts.
78 - * - Removes unnecessary '<dir>/..' parts.
79 - *
80 - * Based on code in the Node.js 'path' core module.
81 - *
82 - * @param aPath The path or url to normalize.
83 - */
84 - function normalize(aPath) {
85 - var path = aPath;
86 - var url = urlParse(aPath);
87 - if (url) {
88 - if (!url.path) {
89 - return aPath;
90 - }
91 - path = url.path;
92 - }
93 - var isAbsolute = (path.charAt(0) === '/');
94 -
95 - var parts = path.split(/\/+/);
96 - for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
97 - part = parts[i];
98 - if (part === '.') {
99 - parts.splice(i, 1);
100 - } else if (part === '..') {
101 - up++;
102 - } else if (up > 0) {
103 - if (part === '') {
104 - // The first part is blank if the path is absolute. Trying to go
105 - // above the root is a no-op. Therefore we can remove all '..' parts
106 - // directly after the root.
107 - parts.splice(i + 1, up);
108 - up = 0;
109 - } else {
110 - parts.splice(i, 2);
111 - up--;
112 - }
113 - }
114 - }
115 - path = parts.join('/');
116 -
117 - if (path === '') {
118 - path = isAbsolute ? '/' : '.';
119 - }
120 -
121 - if (url) {
122 - url.path = path;
123 - return urlGenerate(url);
124 - }
125 - return path;
126 - }
127 - exports.normalize = normalize;
128 -
129 - /**
130 - * Joins two paths/URLs.
131 - *
132 - * @param aRoot The root path or URL.
133 - * @param aPath The path or URL to be joined with the root.
134 - *
135 - * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
136 - * scheme-relative URL: Then the scheme of aRoot, if any, is prepended
137 - * first.
138 - * - Otherwise aPath is a path. If aRoot is a URL, then its path portion
139 - * is updated with the result and aRoot is returned. Otherwise the result
140 - * is returned.
141 - * - If aPath is absolute, the result is aPath.
142 - * - Otherwise the two paths are joined with a slash.
143 - * - Joining for example 'http://' and 'www.example.com' is also supported.
144 - */
145 - function join(aRoot, aPath) {
146 - if (aRoot === "") {
147 - aRoot = ".";
148 - }
149 - if (aPath === "") {
150 - aPath = ".";
151 - }
152 - var aPathUrl = urlParse(aPath);
153 - var aRootUrl = urlParse(aRoot);
154 - if (aRootUrl) {
155 - aRoot = aRootUrl.path || '/';
156 - }
157 -
158 - // `join(foo, '//www.example.org')`
159 - if (aPathUrl && !aPathUrl.scheme) {
160 - if (aRootUrl) {
161 - aPathUrl.scheme = aRootUrl.scheme;
162 - }
163 - return urlGenerate(aPathUrl);
164 - }
165 -
166 - if (aPathUrl || aPath.match(dataUrlRegexp)) {
167 - return aPath;
168 - }
169 -
170 - // `join('http://', 'www.example.com')`
171 - if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
172 - aRootUrl.host = aPath;
173 - return urlGenerate(aRootUrl);
174 - }
175 -
176 - var joined = aPath.charAt(0) === '/'
177 - ? aPath
178 - : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
179 -
180 - if (aRootUrl) {
181 - aRootUrl.path = joined;
182 - return urlGenerate(aRootUrl);
183 - }
184 - return joined;
185 - }
186 - exports.join = join;
187 -
188 - /**
189 - * Make a path relative to a URL or another path.
190 - *
191 - * @param aRoot The root path or URL.
192 - * @param aPath The path or URL to be made relative to aRoot.
193 - */
194 - function relative(aRoot, aPath) {
195 - if (aRoot === "") {
196 - aRoot = ".";
197 - }
198 -
199 - aRoot = aRoot.replace(/\/$/, '');
200 -
201 - // XXX: It is possible to remove this block, and the tests still pass!
202 - var url = urlParse(aRoot);
203 - if (aPath.charAt(0) == "/" && url && url.path == "/") {
204 - return aPath.slice(1);
205 - }
206 -
207 - return aPath.indexOf(aRoot + '/') === 0
208 - ? aPath.substr(aRoot.length + 1)
209 - : aPath;
210 - }
211 - exports.relative = relative;
212 -
213 - /**
214 - * Because behavior goes wacky when you set `__proto__` on objects, we
215 - * have to prefix all the strings in our set with an arbitrary character.
216 - *
217 - * See https://github.com/mozilla/source-map/pull/31 and
218 - * https://github.com/mozilla/source-map/issues/30
219 - *
220 - * @param String aStr
221 - */
222 - function toSetString(aStr) {
223 - return '$' + aStr;
224 - }
225 - exports.toSetString = toSetString;
226 -
227 - function fromSetString(aStr) {
228 - return aStr.substr(1);
229 - }
230 - exports.fromSetString = fromSetString;
231 -
232 - function strcmp(aStr1, aStr2) {
233 - var s1 = aStr1 || "";
234 - var s2 = aStr2 || "";
235 - return (s1 > s2) - (s1 < s2);
236 - }
237 -
238 - /**
239 - * Comparator between two mappings where the original positions are compared.
240 - *
241 - * Optionally pass in `true` as `onlyCompareGenerated` to consider two
242 - * mappings with the same original source/line/column, but different generated
243 - * line and column the same. Useful when searching for a mapping with a
244 - * stubbed out mapping.
245 - */
246 - function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
247 - var cmp;
248 -
249 - cmp = strcmp(mappingA.source, mappingB.source);
250 - if (cmp) {
251 - return cmp;
252 - }
253 -
254 - cmp = mappingA.originalLine - mappingB.originalLine;
255 - if (cmp) {
256 - return cmp;
257 - }
258 -
259 - cmp = mappingA.originalColumn - mappingB.originalColumn;
260 - if (cmp || onlyCompareOriginal) {
261 - return cmp;
262 - }
263 -
264 - cmp = strcmp(mappingA.name, mappingB.name);
265 - if (cmp) {
266 - return cmp;
267 - }
268 -
269 - cmp = mappingA.generatedLine - mappingB.generatedLine;
270 - if (cmp) {
271 - return cmp;
272 - }
273 -
274 - return mappingA.generatedColumn - mappingB.generatedColumn;
275 - };
276 - exports.compareByOriginalPositions = compareByOriginalPositions;
277 -
278 - /**
279 - * Comparator between two mappings where the generated positions are
280 - * compared.
281 - *
282 - * Optionally pass in `true` as `onlyCompareGenerated` to consider two
283 - * mappings with the same generated line and column, but different
284 - * source/name/original line and column the same. Useful when searching for a
285 - * mapping with a stubbed out mapping.
286 - */
287 - function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) {
288 - var cmp;
289 -
290 - cmp = mappingA.generatedLine - mappingB.generatedLine;
291 - if (cmp) {
292 - return cmp;
293 - }
294 -
295 - cmp = mappingA.generatedColumn - mappingB.generatedColumn;
296 - if (cmp || onlyCompareGenerated) {
297 - return cmp;
298 - }
299 -
300 - cmp = strcmp(mappingA.source, mappingB.source);
301 - if (cmp) {
302 - return cmp;
303 - }
304 -
305 - cmp = mappingA.originalLine - mappingB.originalLine;
306 - if (cmp) {
307 - return cmp;
308 - }
309 -
310 - cmp = mappingA.originalColumn - mappingB.originalColumn;
311 - if (cmp) {
312 - return cmp;
313 - }
314 -
315 - return strcmp(mappingA.name, mappingB.name);
316 - };
317 - exports.compareByGeneratedPositions = compareByGeneratedPositions;
318 -
319 -});
1 -{
2 - "_from": "source-map@~0.1.7",
3 - "_id": "source-map@0.1.43",
4 - "_inBundle": false,
5 - "_integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
6 - "_location": "/source-map",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "range",
10 - "registry": true,
11 - "raw": "source-map@~0.1.7",
12 - "name": "source-map",
13 - "escapedName": "source-map",
14 - "rawSpec": "~0.1.7",
15 - "saveSpec": null,
16 - "fetchSpec": "~0.1.7"
17 - },
18 - "_requiredBy": [
19 - "/uglify-js"
20 - ],
21 - "_resolved": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
22 - "_shasum": "c24bc146ca517c1471f5dacbe2571b2b7f9e3346",
23 - "_spec": "source-map@~0.1.7",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\uglify-js",
25 - "author": {
26 - "name": "Nick Fitzgerald",
27 - "email": "nfitzgerald@mozilla.com"
28 - },
29 - "bugs": {
30 - "url": "https://github.com/mozilla/source-map/issues"
31 - },
32 - "bundleDependencies": false,
33 - "contributors": [
34 - {
35 - "name": "Tobias Koppers",
36 - "email": "tobias.koppers@googlemail.com"
37 - },
38 - {
39 - "name": "Duncan Beevers",
40 - "email": "duncan@dweebd.com"
41 - },
42 - {
43 - "name": "Stephen Crane",
44 - "email": "scrane@mozilla.com"
45 - },
46 - {
47 - "name": "Ryan Seddon",
48 - "email": "seddon.ryan@gmail.com"
49 - },
50 - {
51 - "name": "Miles Elam",
52 - "email": "miles.elam@deem.com"
53 - },
54 - {
55 - "name": "Mihai Bazon",
56 - "email": "mihai.bazon@gmail.com"
57 - },
58 - {
59 - "name": "Michael Ficarra",
60 - "email": "github.public.email@michael.ficarra.me"
61 - },
62 - {
63 - "name": "Todd Wolfson",
64 - "email": "todd@twolfson.com"
65 - },
66 - {
67 - "name": "Alexander Solovyov",
68 - "email": "alexander@solovyov.net"
69 - },
70 - {
71 - "name": "Felix Gnass",
72 - "email": "fgnass@gmail.com"
73 - },
74 - {
75 - "name": "Conrad Irwin",
76 - "email": "conrad.irwin@gmail.com"
77 - },
78 - {
79 - "name": "usrbincc",
80 - "email": "usrbincc@yahoo.com"
81 - },
82 - {
83 - "name": "David Glasser",
84 - "email": "glasser@davidglasser.net"
85 - },
86 - {
87 - "name": "Chase Douglas",
88 - "email": "chase@newrelic.com"
89 - },
90 - {
91 - "name": "Evan Wallace",
92 - "email": "evan.exe@gmail.com"
93 - },
94 - {
95 - "name": "Heather Arthur",
96 - "email": "fayearthur@gmail.com"
97 - },
98 - {
99 - "name": "Hugh Kennedy",
100 - "email": "hughskennedy@gmail.com"
101 - },
102 - {
103 - "name": "David Glasser",
104 - "email": "glasser@davidglasser.net"
105 - },
106 - {
107 - "name": "Simon Lydell",
108 - "email": "simon.lydell@gmail.com"
109 - },
110 - {
111 - "name": "Jmeas Smith",
112 - "email": "jellyes2@gmail.com"
113 - },
114 - {
115 - "name": "Michael Z Goddard",
116 - "email": "mzgoddard@gmail.com"
117 - },
118 - {
119 - "name": "azu",
120 - "email": "azu@users.noreply.github.com"
121 - },
122 - {
123 - "name": "John Gozde",
124 - "email": "john@gozde.ca"
125 - },
126 - {
127 - "name": "Adam Kirkton",
128 - "email": "akirkton@truefitinnovation.com"
129 - },
130 - {
131 - "name": "Chris Montgomery",
132 - "email": "christopher.montgomery@dowjones.com"
133 - },
134 - {
135 - "name": "J. Ryan Stinnett",
136 - "email": "jryans@gmail.com"
137 - },
138 - {
139 - "name": "Jack Herrington",
140 - "email": "jherrington@walmartlabs.com"
141 - },
142 - {
143 - "name": "Chris Truter",
144 - "email": "jeffpalentine@gmail.com"
145 - },
146 - {
147 - "name": "Daniel Espeset",
148 - "email": "daniel@danielespeset.com"
149 - }
150 - ],
151 - "dependencies": {
152 - "amdefine": ">=0.0.4"
153 - },
154 - "deprecated": false,
155 - "description": "Generates and consumes source maps",
156 - "devDependencies": {
157 - "dryice": ">=0.4.8"
158 - },
159 - "directories": {
160 - "lib": "./lib"
161 - },
162 - "engines": {
163 - "node": ">=0.8.0"
164 - },
165 - "homepage": "https://github.com/mozilla/source-map",
166 - "licenses": [
167 - {
168 - "type": "BSD",
169 - "url": "http://opensource.org/licenses/BSD-3-Clause"
170 - }
171 - ],
172 - "main": "./lib/source-map.js",
173 - "name": "source-map",
174 - "repository": {
175 - "type": "git",
176 - "url": "git+ssh://git@github.com/mozilla/source-map.git"
177 - },
178 - "scripts": {
179 - "build": "node Makefile.dryice.js",
180 - "test": "node test/run-tests.js"
181 - },
182 - "version": "0.1.43"
183 -}
1 -#!/usr/bin/env node
2 -/* -*- Mode: js; js-indent-level: 2; -*- */
3 -/*
4 - * Copyright 2011 Mozilla Foundation and contributors
5 - * Licensed under the New BSD license. See LICENSE or:
6 - * http://opensource.org/licenses/BSD-3-Clause
7 - */
8 -var assert = require('assert');
9 -var fs = require('fs');
10 -var path = require('path');
11 -var util = require('./source-map/util');
12 -
13 -function run(tests) {
14 - var total = 0;
15 - var passed = 0;
16 -
17 - for (var i = 0; i < tests.length; i++) {
18 - for (var k in tests[i].testCase) {
19 - if (/^test/.test(k)) {
20 - total++;
21 - try {
22 - tests[i].testCase[k](assert, util);
23 - passed++;
24 - }
25 - catch (e) {
26 - console.log('FAILED ' + tests[i].name + ': ' + k + '!');
27 - console.log(e.stack);
28 - }
29 - }
30 - }
31 - }
32 -
33 - console.log('');
34 - console.log(passed + ' / ' + total + ' tests passed.');
35 - console.log('');
36 -
37 - return total - passed;
38 -}
39 -
40 -function isTestFile(f) {
41 - var testToRun = process.argv[2];
42 - return testToRun
43 - ? path.basename(testToRun) === f
44 - : /^test\-.*?\.js/.test(f);
45 -}
46 -
47 -function toModule(f) {
48 - return './source-map/' + f.replace(/\.js$/, '');
49 -}
50 -
51 -var requires = fs.readdirSync(path.join(__dirname, 'source-map'))
52 - .filter(isTestFile)
53 - .map(toModule);
54 -
55 -var code = run(requires.map(require).map(function (mod, i) {
56 - return {
57 - name: requires[i],
58 - testCase: mod
59 - };
60 -}));
61 -
62 -process.exit(code);
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2012 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var sourceMap;
13 - try {
14 - sourceMap = require('../../lib/source-map');
15 - } catch (e) {
16 - sourceMap = {};
17 - Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);
18 - }
19 -
20 - exports['test that the api is properly exposed in the top level'] = function (assert, util) {
21 - assert.equal(typeof sourceMap.SourceMapGenerator, "function");
22 - assert.equal(typeof sourceMap.SourceMapConsumer, "function");
23 - assert.equal(typeof sourceMap.SourceNode, "function");
24 - };
25 -
26 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var ArraySet = require('../../lib/source-map/array-set').ArraySet;
13 -
14 - function makeTestSet() {
15 - var set = new ArraySet();
16 - for (var i = 0; i < 100; i++) {
17 - set.add(String(i));
18 - }
19 - return set;
20 - }
21 -
22 - exports['test .has() membership'] = function (assert, util) {
23 - var set = makeTestSet();
24 - for (var i = 0; i < 100; i++) {
25 - assert.ok(set.has(String(i)));
26 - }
27 - };
28 -
29 - exports['test .indexOf() elements'] = function (assert, util) {
30 - var set = makeTestSet();
31 - for (var i = 0; i < 100; i++) {
32 - assert.strictEqual(set.indexOf(String(i)), i);
33 - }
34 - };
35 -
36 - exports['test .at() indexing'] = function (assert, util) {
37 - var set = makeTestSet();
38 - for (var i = 0; i < 100; i++) {
39 - assert.strictEqual(set.at(i), String(i));
40 - }
41 - };
42 -
43 - exports['test creating from an array'] = function (assert, util) {
44 - var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']);
45 -
46 - assert.ok(set.has('foo'));
47 - assert.ok(set.has('bar'));
48 - assert.ok(set.has('baz'));
49 - assert.ok(set.has('quux'));
50 - assert.ok(set.has('hasOwnProperty'));
51 -
52 - assert.strictEqual(set.indexOf('foo'), 0);
53 - assert.strictEqual(set.indexOf('bar'), 1);
54 - assert.strictEqual(set.indexOf('baz'), 2);
55 - assert.strictEqual(set.indexOf('quux'), 3);
56 -
57 - assert.strictEqual(set.at(0), 'foo');
58 - assert.strictEqual(set.at(1), 'bar');
59 - assert.strictEqual(set.at(2), 'baz');
60 - assert.strictEqual(set.at(3), 'quux');
61 - };
62 -
63 - exports['test that you can add __proto__; see github issue #30'] = function (assert, util) {
64 - var set = new ArraySet();
65 - set.add('__proto__');
66 - assert.ok(set.has('__proto__'));
67 - assert.strictEqual(set.at(0), '__proto__');
68 - assert.strictEqual(set.indexOf('__proto__'), 0);
69 - };
70 -
71 - exports['test .fromArray() with duplicates'] = function (assert, util) {
72 - var set = ArraySet.fromArray(['foo', 'foo']);
73 - assert.ok(set.has('foo'));
74 - assert.strictEqual(set.at(0), 'foo');
75 - assert.strictEqual(set.indexOf('foo'), 0);
76 - assert.strictEqual(set.toArray().length, 1);
77 -
78 - set = ArraySet.fromArray(['foo', 'foo'], true);
79 - assert.ok(set.has('foo'));
80 - assert.strictEqual(set.at(0), 'foo');
81 - assert.strictEqual(set.at(1), 'foo');
82 - assert.strictEqual(set.indexOf('foo'), 0);
83 - assert.strictEqual(set.toArray().length, 2);
84 - };
85 -
86 - exports['test .add() with duplicates'] = function (assert, util) {
87 - var set = new ArraySet();
88 - set.add('foo');
89 -
90 - set.add('foo');
91 - assert.ok(set.has('foo'));
92 - assert.strictEqual(set.at(0), 'foo');
93 - assert.strictEqual(set.indexOf('foo'), 0);
94 - assert.strictEqual(set.toArray().length, 1);
95 -
96 - set.add('foo', true);
97 - assert.ok(set.has('foo'));
98 - assert.strictEqual(set.at(0), 'foo');
99 - assert.strictEqual(set.at(1), 'foo');
100 - assert.strictEqual(set.indexOf('foo'), 0);
101 - assert.strictEqual(set.toArray().length, 2);
102 - };
103 -
104 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var base64VLQ = require('../../lib/source-map/base64-vlq');
13 -
14 - exports['test normal encoding and decoding'] = function (assert, util) {
15 - var result = {};
16 - for (var i = -255; i < 256; i++) {
17 - base64VLQ.decode(base64VLQ.encode(i), result);
18 - assert.equal(result.value, i);
19 - assert.equal(result.rest, "");
20 - }
21 - };
22 -
23 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var base64 = require('../../lib/source-map/base64');
13 -
14 - exports['test out of range encoding'] = function (assert, util) {
15 - assert.throws(function () {
16 - base64.encode(-1);
17 - });
18 - assert.throws(function () {
19 - base64.encode(64);
20 - });
21 - };
22 -
23 - exports['test out of range decoding'] = function (assert, util) {
24 - assert.throws(function () {
25 - base64.decode('=');
26 - });
27 - };
28 -
29 - exports['test normal encoding and decoding'] = function (assert, util) {
30 - for (var i = 0; i < 64; i++) {
31 - assert.equal(base64.decode(base64.encode(i)), i);
32 - }
33 - };
34 -
35 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var binarySearch = require('../../lib/source-map/binary-search');
13 -
14 - function numberCompare(a, b) {
15 - return a - b;
16 - }
17 -
18 - exports['test too high'] = function (assert, util) {
19 - var needle = 30;
20 - var haystack = [2,4,6,8,10,12,14,16,18,20];
21 -
22 - assert.doesNotThrow(function () {
23 - binarySearch.search(needle, haystack, numberCompare);
24 - });
25 -
26 - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 20);
27 - };
28 -
29 - exports['test too low'] = function (assert, util) {
30 - var needle = 1;
31 - var haystack = [2,4,6,8,10,12,14,16,18,20];
32 -
33 - assert.doesNotThrow(function () {
34 - binarySearch.search(needle, haystack, numberCompare);
35 - });
36 -
37 - assert.equal(binarySearch.search(needle, haystack, numberCompare), -1);
38 - };
39 -
40 - exports['test exact search'] = function (assert, util) {
41 - var needle = 4;
42 - var haystack = [2,4,6,8,10,12,14,16,18,20];
43 -
44 - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 4);
45 - };
46 -
47 - exports['test fuzzy search'] = function (assert, util) {
48 - var needle = 19;
49 - var haystack = [2,4,6,8,10,12,14,16,18,20];
50 -
51 - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 18);
52 - };
53 -
54 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer;
13 - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator;
14 -
15 - exports['test eating our own dog food'] = function (assert, util) {
16 - var smg = new SourceMapGenerator({
17 - file: 'testing.js',
18 - sourceRoot: '/wu/tang'
19 - });
20 -
21 - smg.addMapping({
22 - source: 'gza.coffee',
23 - original: { line: 1, column: 0 },
24 - generated: { line: 2, column: 2 }
25 - });
26 -
27 - smg.addMapping({
28 - source: 'gza.coffee',
29 - original: { line: 2, column: 0 },
30 - generated: { line: 3, column: 2 }
31 - });
32 -
33 - smg.addMapping({
34 - source: 'gza.coffee',
35 - original: { line: 3, column: 0 },
36 - generated: { line: 4, column: 2 }
37 - });
38 -
39 - smg.addMapping({
40 - source: 'gza.coffee',
41 - original: { line: 4, column: 0 },
42 - generated: { line: 5, column: 2 }
43 - });
44 -
45 - smg.addMapping({
46 - source: 'gza.coffee',
47 - original: { line: 5, column: 10 },
48 - generated: { line: 6, column: 12 }
49 - });
50 -
51 - var smc = new SourceMapConsumer(smg.toString());
52 -
53 - // Exact
54 - util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert);
55 - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert);
56 - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert);
57 - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert);
58 - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 10, null, smc, assert);
59 -
60 - // Fuzzy
61 -
62 - // Generated to original
63 - util.assertMapping(2, 0, null, null, null, null, smc, assert, true);
64 - util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true);
65 - util.assertMapping(3, 0, null, null, null, null, smc, assert, true);
66 - util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true);
67 - util.assertMapping(4, 0, null, null, null, null, smc, assert, true);
68 - util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true);
69 - util.assertMapping(5, 0, null, null, null, null, smc, assert, true);
70 - util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true);
71 - util.assertMapping(6, 0, null, null, null, null, smc, assert, true);
72 - util.assertMapping(6, 9, null, null, null, null, smc, assert, true);
73 - util.assertMapping(6, 13, '/wu/tang/gza.coffee', 5, 10, null, smc, assert, true);
74 -
75 - // Original to generated
76 - util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true);
77 - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true);
78 - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true);
79 - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true);
80 - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 5, 9, null, smc, assert, null, true);
81 - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 6, 19, null, smc, assert, null, true);
82 - };
83 -
84 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer;
13 - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator;
14 -
15 - exports['test that we can instantiate with a string or an object'] = function (assert, util) {
16 - assert.doesNotThrow(function () {
17 - var map = new SourceMapConsumer(util.testMap);
18 - });
19 - assert.doesNotThrow(function () {
20 - var map = new SourceMapConsumer(JSON.stringify(util.testMap));
21 - });
22 - };
23 -
24 - exports['test that the `sources` field has the original sources'] = function (assert, util) {
25 - var map;
26 - var sources;
27 -
28 - map = new SourceMapConsumer(util.testMap);
29 - sources = map.sources;
30 - assert.equal(sources[0], '/the/root/one.js');
31 - assert.equal(sources[1], '/the/root/two.js');
32 - assert.equal(sources.length, 2);
33 -
34 - map = new SourceMapConsumer(util.testMapNoSourceRoot);
35 - sources = map.sources;
36 - assert.equal(sources[0], 'one.js');
37 - assert.equal(sources[1], 'two.js');
38 - assert.equal(sources.length, 2);
39 -
40 - map = new SourceMapConsumer(util.testMapEmptySourceRoot);
41 - sources = map.sources;
42 - assert.equal(sources[0], 'one.js');
43 - assert.equal(sources[1], 'two.js');
44 - assert.equal(sources.length, 2);
45 - };
46 -
47 - exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) {
48 - var map;
49 - var mapping;
50 -
51 - map = new SourceMapConsumer(util.testMap);
52 -
53 - mapping = map.originalPositionFor({
54 - line: 2,
55 - column: 1
56 - });
57 - assert.equal(mapping.source, '/the/root/two.js');
58 -
59 - mapping = map.originalPositionFor({
60 - line: 1,
61 - column: 1
62 - });
63 - assert.equal(mapping.source, '/the/root/one.js');
64 -
65 -
66 - map = new SourceMapConsumer(util.testMapNoSourceRoot);
67 -
68 - mapping = map.originalPositionFor({
69 - line: 2,
70 - column: 1
71 - });
72 - assert.equal(mapping.source, 'two.js');
73 -
74 - mapping = map.originalPositionFor({
75 - line: 1,
76 - column: 1
77 - });
78 - assert.equal(mapping.source, 'one.js');
79 -
80 -
81 - map = new SourceMapConsumer(util.testMapEmptySourceRoot);
82 -
83 - mapping = map.originalPositionFor({
84 - line: 2,
85 - column: 1
86 - });
87 - assert.equal(mapping.source, 'two.js');
88 -
89 - mapping = map.originalPositionFor({
90 - line: 1,
91 - column: 1
92 - });
93 - assert.equal(mapping.source, 'one.js');
94 - };
95 -
96 - exports['test mapping tokens back exactly'] = function (assert, util) {
97 - var map = new SourceMapConsumer(util.testMap);
98 -
99 - util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert);
100 - util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert);
101 - util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert);
102 - util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert);
103 - util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert);
104 - util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert);
105 - util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert);
106 -
107 - util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert);
108 - util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert);
109 - util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert);
110 - util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert);
111 - util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert);
112 - util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert);
113 - };
114 -
115 - exports['test mapping tokens fuzzy'] = function (assert, util) {
116 - var map = new SourceMapConsumer(util.testMap);
117 -
118 - // Finding original positions
119 - util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true);
120 - util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true);
121 - util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true);
122 -
123 - // Finding generated positions
124 - util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true);
125 - util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true);
126 - util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true);
127 - };
128 -
129 - exports['test mappings and end of lines'] = function (assert, util) {
130 - var smg = new SourceMapGenerator({
131 - file: 'foo.js'
132 - });
133 - smg.addMapping({
134 - original: { line: 1, column: 1 },
135 - generated: { line: 1, column: 1 },
136 - source: 'bar.js'
137 - });
138 - smg.addMapping({
139 - original: { line: 2, column: 2 },
140 - generated: { line: 2, column: 2 },
141 - source: 'bar.js'
142 - });
143 -
144 - var map = SourceMapConsumer.fromSourceMap(smg);
145 -
146 - // When finding original positions, mappings end at the end of the line.
147 - util.assertMapping(2, 1, null, null, null, null, map, assert, true)
148 -
149 - // When finding generated positions, mappings do not end at the end of the line.
150 - util.assertMapping(1, 1, 'bar.js', 2, 1, null, map, assert, null, true);
151 - };
152 -
153 - exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) {
154 - assert.doesNotThrow(function () {
155 - var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap));
156 - });
157 - };
158 -
159 - exports['test eachMapping'] = function (assert, util) {
160 - var map;
161 -
162 - map = new SourceMapConsumer(util.testMap);
163 - var previousLine = -Infinity;
164 - var previousColumn = -Infinity;
165 - map.eachMapping(function (mapping) {
166 - assert.ok(mapping.generatedLine >= previousLine);
167 -
168 - assert.ok(mapping.source === '/the/root/one.js' || mapping.source === '/the/root/two.js');
169 -
170 - if (mapping.generatedLine === previousLine) {
171 - assert.ok(mapping.generatedColumn >= previousColumn);
172 - previousColumn = mapping.generatedColumn;
173 - }
174 - else {
175 - previousLine = mapping.generatedLine;
176 - previousColumn = -Infinity;
177 - }
178 - });
179 -
180 - map = new SourceMapConsumer(util.testMapNoSourceRoot);
181 - map.eachMapping(function (mapping) {
182 - assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js');
183 - });
184 -
185 - map = new SourceMapConsumer(util.testMapEmptySourceRoot);
186 - map.eachMapping(function (mapping) {
187 - assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js');
188 - });
189 - };
190 -
191 - exports['test iterating over mappings in a different order'] = function (assert, util) {
192 - var map = new SourceMapConsumer(util.testMap);
193 - var previousLine = -Infinity;
194 - var previousColumn = -Infinity;
195 - var previousSource = "";
196 - map.eachMapping(function (mapping) {
197 - assert.ok(mapping.source >= previousSource);
198 -
199 - if (mapping.source === previousSource) {
200 - assert.ok(mapping.originalLine >= previousLine);
201 -
202 - if (mapping.originalLine === previousLine) {
203 - assert.ok(mapping.originalColumn >= previousColumn);
204 - previousColumn = mapping.originalColumn;
205 - }
206 - else {
207 - previousLine = mapping.originalLine;
208 - previousColumn = -Infinity;
209 - }
210 - }
211 - else {
212 - previousSource = mapping.source;
213 - previousLine = -Infinity;
214 - previousColumn = -Infinity;
215 - }
216 - }, null, SourceMapConsumer.ORIGINAL_ORDER);
217 - };
218 -
219 - exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) {
220 - var map = new SourceMapConsumer(util.testMap);
221 - var context = {};
222 - map.eachMapping(function () {
223 - assert.equal(this, context);
224 - }, context);
225 - };
226 -
227 - exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) {
228 - var map = new SourceMapConsumer(util.testMapWithSourcesContent);
229 - var sourcesContent = map.sourcesContent;
230 -
231 - assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };');
232 - assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };');
233 - assert.equal(sourcesContent.length, 2);
234 - };
235 -
236 - exports['test that we can get the original sources for the sources'] = function (assert, util) {
237 - var map = new SourceMapConsumer(util.testMapWithSourcesContent);
238 - var sources = map.sources;
239 -
240 - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };');
241 - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };');
242 - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };');
243 - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };');
244 - assert.throws(function () {
245 - map.sourceContentFor("");
246 - }, Error);
247 - assert.throws(function () {
248 - map.sourceContentFor("/the/root/three.js");
249 - }, Error);
250 - assert.throws(function () {
251 - map.sourceContentFor("three.js");
252 - }, Error);
253 - };
254 -
255 - exports['test that we can get the original source content with relative source paths'] = function (assert, util) {
256 - var map = new SourceMapConsumer(util.testMapRelativeSources);
257 - var sources = map.sources;
258 -
259 - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };');
260 - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };');
261 - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };');
262 - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };');
263 - assert.throws(function () {
264 - map.sourceContentFor("");
265 - }, Error);
266 - assert.throws(function () {
267 - map.sourceContentFor("/the/root/three.js");
268 - }, Error);
269 - assert.throws(function () {
270 - map.sourceContentFor("three.js");
271 - }, Error);
272 - };
273 -
274 - exports['test sourceRoot + generatedPositionFor'] = function (assert, util) {
275 - var map = new SourceMapGenerator({
276 - sourceRoot: 'foo/bar',
277 - file: 'baz.js'
278 - });
279 - map.addMapping({
280 - original: { line: 1, column: 1 },
281 - generated: { line: 2, column: 2 },
282 - source: 'bang.coffee'
283 - });
284 - map.addMapping({
285 - original: { line: 5, column: 5 },
286 - generated: { line: 6, column: 6 },
287 - source: 'bang.coffee'
288 - });
289 - map = new SourceMapConsumer(map.toString());
290 -
291 - // Should handle without sourceRoot.
292 - var pos = map.generatedPositionFor({
293 - line: 1,
294 - column: 1,
295 - source: 'bang.coffee'
296 - });
297 -
298 - assert.equal(pos.line, 2);
299 - assert.equal(pos.column, 2);
300 -
301 - // Should handle with sourceRoot.
302 - var pos = map.generatedPositionFor({
303 - line: 1,
304 - column: 1,
305 - source: 'foo/bar/bang.coffee'
306 - });
307 -
308 - assert.equal(pos.line, 2);
309 - assert.equal(pos.column, 2);
310 - };
311 -
312 - exports['test allGeneratedPositionsFor'] = function (assert, util) {
313 - var map = new SourceMapGenerator({
314 - file: 'generated.js'
315 - });
316 - map.addMapping({
317 - original: { line: 1, column: 1 },
318 - generated: { line: 2, column: 2 },
319 - source: 'foo.coffee'
320 - });
321 - map.addMapping({
322 - original: { line: 1, column: 1 },
323 - generated: { line: 2, column: 2 },
324 - source: 'bar.coffee'
325 - });
326 - map.addMapping({
327 - original: { line: 2, column: 1 },
328 - generated: { line: 3, column: 2 },
329 - source: 'bar.coffee'
330 - });
331 - map.addMapping({
332 - original: { line: 2, column: 2 },
333 - generated: { line: 3, column: 3 },
334 - source: 'bar.coffee'
335 - });
336 - map.addMapping({
337 - original: { line: 3, column: 1 },
338 - generated: { line: 4, column: 2 },
339 - source: 'bar.coffee'
340 - });
341 - map = new SourceMapConsumer(map.toString());
342 -
343 - var mappings = map.allGeneratedPositionsFor({
344 - line: 2,
345 - source: 'bar.coffee'
346 - });
347 -
348 - assert.equal(mappings.length, 2);
349 - assert.equal(mappings[0].line, 3);
350 - assert.equal(mappings[0].column, 2);
351 - assert.equal(mappings[1].line, 3);
352 - assert.equal(mappings[1].column, 3);
353 - };
354 -
355 - exports['test allGeneratedPositionsFor for line with no mappings'] = function (assert, util) {
356 - var map = new SourceMapGenerator({
357 - file: 'generated.js'
358 - });
359 - map.addMapping({
360 - original: { line: 1, column: 1 },
361 - generated: { line: 2, column: 2 },
362 - source: 'foo.coffee'
363 - });
364 - map.addMapping({
365 - original: { line: 1, column: 1 },
366 - generated: { line: 2, column: 2 },
367 - source: 'bar.coffee'
368 - });
369 - map.addMapping({
370 - original: { line: 3, column: 1 },
371 - generated: { line: 4, column: 2 },
372 - source: 'bar.coffee'
373 - });
374 - map = new SourceMapConsumer(map.toString());
375 -
376 - var mappings = map.allGeneratedPositionsFor({
377 - line: 2,
378 - source: 'bar.coffee'
379 - });
380 -
381 - assert.equal(mappings.length, 0);
382 - };
383 -
384 - exports['test allGeneratedPositionsFor source map with no mappings'] = function (assert, util) {
385 - var map = new SourceMapGenerator({
386 - file: 'generated.js'
387 - });
388 - map = new SourceMapConsumer(map.toString());
389 -
390 - var mappings = map.allGeneratedPositionsFor({
391 - line: 2,
392 - source: 'bar.coffee'
393 - });
394 -
395 - assert.equal(mappings.length, 0);
396 - };
397 -
398 - exports['test computeColumnSpans'] = function (assert, util) {
399 - var map = new SourceMapGenerator({
400 - file: 'generated.js'
401 - });
402 - map.addMapping({
403 - original: { line: 1, column: 1 },
404 - generated: { line: 1, column: 1 },
405 - source: 'foo.coffee'
406 - });
407 - map.addMapping({
408 - original: { line: 2, column: 1 },
409 - generated: { line: 2, column: 1 },
410 - source: 'foo.coffee'
411 - });
412 - map.addMapping({
413 - original: { line: 2, column: 2 },
414 - generated: { line: 2, column: 10 },
415 - source: 'foo.coffee'
416 - });
417 - map.addMapping({
418 - original: { line: 2, column: 3 },
419 - generated: { line: 2, column: 20 },
420 - source: 'foo.coffee'
421 - });
422 - map.addMapping({
423 - original: { line: 3, column: 1 },
424 - generated: { line: 3, column: 1 },
425 - source: 'foo.coffee'
426 - });
427 - map.addMapping({
428 - original: { line: 3, column: 2 },
429 - generated: { line: 3, column: 2 },
430 - source: 'foo.coffee'
431 - });
432 - map = new SourceMapConsumer(map.toString());
433 -
434 - map.computeColumnSpans();
435 -
436 - var mappings = map.allGeneratedPositionsFor({
437 - line: 1,
438 - source: 'foo.coffee'
439 - });
440 -
441 - assert.equal(mappings.length, 1);
442 - assert.equal(mappings[0].lastColumn, Infinity);
443 -
444 - var mappings = map.allGeneratedPositionsFor({
445 - line: 2,
446 - source: 'foo.coffee'
447 - });
448 -
449 - assert.equal(mappings.length, 3);
450 - assert.equal(mappings[0].lastColumn, 9);
451 - assert.equal(mappings[1].lastColumn, 19);
452 - assert.equal(mappings[2].lastColumn, Infinity);
453 -
454 - var mappings = map.allGeneratedPositionsFor({
455 - line: 3,
456 - source: 'foo.coffee'
457 - });
458 -
459 - assert.equal(mappings.length, 2);
460 - assert.equal(mappings[0].lastColumn, 1);
461 - assert.equal(mappings[1].lastColumn, Infinity);
462 - };
463 -
464 - exports['test sourceRoot + originalPositionFor'] = function (assert, util) {
465 - var map = new SourceMapGenerator({
466 - sourceRoot: 'foo/bar',
467 - file: 'baz.js'
468 - });
469 - map.addMapping({
470 - original: { line: 1, column: 1 },
471 - generated: { line: 2, column: 2 },
472 - source: 'bang.coffee'
473 - });
474 - map = new SourceMapConsumer(map.toString());
475 -
476 - var pos = map.originalPositionFor({
477 - line: 2,
478 - column: 2,
479 - });
480 -
481 - // Should always have the prepended source root
482 - assert.equal(pos.source, 'foo/bar/bang.coffee');
483 - assert.equal(pos.line, 1);
484 - assert.equal(pos.column, 1);
485 - };
486 -
487 - exports['test github issue #56'] = function (assert, util) {
488 - var map = new SourceMapGenerator({
489 - sourceRoot: 'http://',
490 - file: 'www.example.com/foo.js'
491 - });
492 - map.addMapping({
493 - original: { line: 1, column: 1 },
494 - generated: { line: 2, column: 2 },
495 - source: 'www.example.com/original.js'
496 - });
497 - map = new SourceMapConsumer(map.toString());
498 -
499 - var sources = map.sources;
500 - assert.equal(sources.length, 1);
501 - assert.equal(sources[0], 'http://www.example.com/original.js');
502 - };
503 -
504 - exports['test github issue #43'] = function (assert, util) {
505 - var map = new SourceMapGenerator({
506 - sourceRoot: 'http://example.com',
507 - file: 'foo.js'
508 - });
509 - map.addMapping({
510 - original: { line: 1, column: 1 },
511 - generated: { line: 2, column: 2 },
512 - source: 'http://cdn.example.com/original.js'
513 - });
514 - map = new SourceMapConsumer(map.toString());
515 -
516 - var sources = map.sources;
517 - assert.equal(sources.length, 1,
518 - 'Should only be one source.');
519 - assert.equal(sources[0], 'http://cdn.example.com/original.js',
520 - 'Should not be joined with the sourceRoot.');
521 - };
522 -
523 - exports['test absolute path, but same host sources'] = function (assert, util) {
524 - var map = new SourceMapGenerator({
525 - sourceRoot: 'http://example.com/foo/bar',
526 - file: 'foo.js'
527 - });
528 - map.addMapping({
529 - original: { line: 1, column: 1 },
530 - generated: { line: 2, column: 2 },
531 - source: '/original.js'
532 - });
533 - map = new SourceMapConsumer(map.toString());
534 -
535 - var sources = map.sources;
536 - assert.equal(sources.length, 1,
537 - 'Should only be one source.');
538 - assert.equal(sources[0], 'http://example.com/original.js',
539 - 'Source should be relative the host of the source root.');
540 - };
541 -
542 - exports['test github issue #64'] = function (assert, util) {
543 - var map = new SourceMapConsumer({
544 - "version": 3,
545 - "file": "foo.js",
546 - "sourceRoot": "http://example.com/",
547 - "sources": ["/a"],
548 - "names": [],
549 - "mappings": "AACA",
550 - "sourcesContent": ["foo"]
551 - });
552 -
553 - assert.equal(map.sourceContentFor("a"), "foo");
554 - assert.equal(map.sourceContentFor("/a"), "foo");
555 - };
556 -
557 - exports['test bug 885597'] = function (assert, util) {
558 - var map = new SourceMapConsumer({
559 - "version": 3,
560 - "file": "foo.js",
561 - "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/",
562 - "sources": ["/a"],
563 - "names": [],
564 - "mappings": "AACA",
565 - "sourcesContent": ["foo"]
566 - });
567 -
568 - var s = map.sources[0];
569 - assert.equal(map.sourceContentFor(s), "foo");
570 - };
571 -
572 - exports['test github issue #72, duplicate sources'] = function (assert, util) {
573 - var map = new SourceMapConsumer({
574 - "version": 3,
575 - "file": "foo.js",
576 - "sources": ["source1.js", "source1.js", "source3.js"],
577 - "names": [],
578 - "mappings": ";EAAC;;IAEE;;MEEE",
579 - "sourceRoot": "http://example.com"
580 - });
581 -
582 - var pos = map.originalPositionFor({
583 - line: 2,
584 - column: 2
585 - });
586 - assert.equal(pos.source, 'http://example.com/source1.js');
587 - assert.equal(pos.line, 1);
588 - assert.equal(pos.column, 1);
589 -
590 - var pos = map.originalPositionFor({
591 - line: 4,
592 - column: 4
593 - });
594 - assert.equal(pos.source, 'http://example.com/source1.js');
595 - assert.equal(pos.line, 3);
596 - assert.equal(pos.column, 3);
597 -
598 - var pos = map.originalPositionFor({
599 - line: 6,
600 - column: 6
601 - });
602 - assert.equal(pos.source, 'http://example.com/source3.js');
603 - assert.equal(pos.line, 5);
604 - assert.equal(pos.column, 5);
605 - };
606 -
607 - exports['test github issue #72, duplicate names'] = function (assert, util) {
608 - var map = new SourceMapConsumer({
609 - "version": 3,
610 - "file": "foo.js",
611 - "sources": ["source.js"],
612 - "names": ["name1", "name1", "name3"],
613 - "mappings": ";EAACA;;IAEEA;;MAEEE",
614 - "sourceRoot": "http://example.com"
615 - });
616 -
617 - var pos = map.originalPositionFor({
618 - line: 2,
619 - column: 2
620 - });
621 - assert.equal(pos.name, 'name1');
622 - assert.equal(pos.line, 1);
623 - assert.equal(pos.column, 1);
624 -
625 - var pos = map.originalPositionFor({
626 - line: 4,
627 - column: 4
628 - });
629 - assert.equal(pos.name, 'name1');
630 - assert.equal(pos.line, 3);
631 - assert.equal(pos.column, 3);
632 -
633 - var pos = map.originalPositionFor({
634 - line: 6,
635 - column: 6
636 - });
637 - assert.equal(pos.name, 'name3');
638 - assert.equal(pos.line, 5);
639 - assert.equal(pos.column, 5);
640 - };
641 -
642 - exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) {
643 - var smg = new SourceMapGenerator({
644 - sourceRoot: 'http://example.com/',
645 - file: 'foo.js'
646 - });
647 - smg.addMapping({
648 - original: { line: 1, column: 1 },
649 - generated: { line: 2, column: 2 },
650 - source: 'bar.js'
651 - });
652 - smg.addMapping({
653 - original: { line: 2, column: 2 },
654 - generated: { line: 4, column: 4 },
655 - source: 'baz.js',
656 - name: 'dirtMcGirt'
657 - });
658 - smg.setSourceContent('baz.js', 'baz.js content');
659 -
660 - var smc = SourceMapConsumer.fromSourceMap(smg);
661 - assert.equal(smc.file, 'foo.js');
662 - assert.equal(smc.sourceRoot, 'http://example.com/');
663 - assert.equal(smc.sources.length, 2);
664 - assert.equal(smc.sources[0], 'http://example.com/bar.js');
665 - assert.equal(smc.sources[1], 'http://example.com/baz.js');
666 - assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content');
667 -
668 - var pos = smc.originalPositionFor({
669 - line: 2,
670 - column: 2
671 - });
672 - assert.equal(pos.line, 1);
673 - assert.equal(pos.column, 1);
674 - assert.equal(pos.source, 'http://example.com/bar.js');
675 - assert.equal(pos.name, null);
676 -
677 - pos = smc.generatedPositionFor({
678 - line: 1,
679 - column: 1,
680 - source: 'http://example.com/bar.js'
681 - });
682 - assert.equal(pos.line, 2);
683 - assert.equal(pos.column, 2);
684 -
685 - pos = smc.originalPositionFor({
686 - line: 4,
687 - column: 4
688 - });
689 - assert.equal(pos.line, 2);
690 - assert.equal(pos.column, 2);
691 - assert.equal(pos.source, 'http://example.com/baz.js');
692 - assert.equal(pos.name, 'dirtMcGirt');
693 -
694 - pos = smc.generatedPositionFor({
695 - line: 2,
696 - column: 2,
697 - source: 'http://example.com/baz.js'
698 - });
699 - assert.equal(pos.line, 4);
700 - assert.equal(pos.column, 4);
701 - };
702 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator;
13 - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer;
14 - var SourceNode = require('../../lib/source-map/source-node').SourceNode;
15 - var util = require('./util');
16 -
17 - exports['test some simple stuff'] = function (assert, util) {
18 - var map = new SourceMapGenerator({
19 - file: 'foo.js',
20 - sourceRoot: '.'
21 - });
22 - assert.ok(true);
23 -
24 - var map = new SourceMapGenerator().toJSON();
25 - assert.ok(!('file' in map));
26 - assert.ok(!('sourceRoot' in map));
27 - };
28 -
29 - exports['test JSON serialization'] = function (assert, util) {
30 - var map = new SourceMapGenerator({
31 - file: 'foo.js',
32 - sourceRoot: '.'
33 - });
34 - assert.equal(map.toString(), JSON.stringify(map));
35 - };
36 -
37 - exports['test adding mappings (case 1)'] = function (assert, util) {
38 - var map = new SourceMapGenerator({
39 - file: 'generated-foo.js',
40 - sourceRoot: '.'
41 - });
42 -
43 - assert.doesNotThrow(function () {
44 - map.addMapping({
45 - generated: { line: 1, column: 1 }
46 - });
47 - });
48 - };
49 -
50 - exports['test adding mappings (case 2)'] = function (assert, util) {
51 - var map = new SourceMapGenerator({
52 - file: 'generated-foo.js',
53 - sourceRoot: '.'
54 - });
55 -
56 - assert.doesNotThrow(function () {
57 - map.addMapping({
58 - generated: { line: 1, column: 1 },
59 - source: 'bar.js',
60 - original: { line: 1, column: 1 }
61 - });
62 - });
63 - };
64 -
65 - exports['test adding mappings (case 3)'] = function (assert, util) {
66 - var map = new SourceMapGenerator({
67 - file: 'generated-foo.js',
68 - sourceRoot: '.'
69 - });
70 -
71 - assert.doesNotThrow(function () {
72 - map.addMapping({
73 - generated: { line: 1, column: 1 },
74 - source: 'bar.js',
75 - original: { line: 1, column: 1 },
76 - name: 'someToken'
77 - });
78 - });
79 - };
80 -
81 - exports['test adding mappings (invalid)'] = function (assert, util) {
82 - var map = new SourceMapGenerator({
83 - file: 'generated-foo.js',
84 - sourceRoot: '.'
85 - });
86 -
87 - // Not enough info.
88 - assert.throws(function () {
89 - map.addMapping({});
90 - });
91 -
92 - // Original file position, but no source.
93 - assert.throws(function () {
94 - map.addMapping({
95 - generated: { line: 1, column: 1 },
96 - original: { line: 1, column: 1 }
97 - });
98 - });
99 - };
100 -
101 - exports['test adding mappings with skipValidation'] = function (assert, util) {
102 - var map = new SourceMapGenerator({
103 - file: 'generated-foo.js',
104 - sourceRoot: '.',
105 - skipValidation: true
106 - });
107 -
108 - // Not enough info, caught by `util.getArgs`
109 - assert.throws(function () {
110 - map.addMapping({});
111 - });
112 -
113 - // Original file position, but no source. Not checked.
114 - assert.doesNotThrow(function () {
115 - map.addMapping({
116 - generated: { line: 1, column: 1 },
117 - original: { line: 1, column: 1 }
118 - });
119 - });
120 - };
121 -
122 - exports['test that the correct mappings are being generated'] = function (assert, util) {
123 - var map = new SourceMapGenerator({
124 - file: 'min.js',
125 - sourceRoot: '/the/root'
126 - });
127 -
128 - map.addMapping({
129 - generated: { line: 1, column: 1 },
130 - original: { line: 1, column: 1 },
131 - source: 'one.js'
132 - });
133 - map.addMapping({
134 - generated: { line: 1, column: 5 },
135 - original: { line: 1, column: 5 },
136 - source: 'one.js'
137 - });
138 - map.addMapping({
139 - generated: { line: 1, column: 9 },
140 - original: { line: 1, column: 11 },
141 - source: 'one.js'
142 - });
143 - map.addMapping({
144 - generated: { line: 1, column: 18 },
145 - original: { line: 1, column: 21 },
146 - source: 'one.js',
147 - name: 'bar'
148 - });
149 - map.addMapping({
150 - generated: { line: 1, column: 21 },
151 - original: { line: 2, column: 3 },
152 - source: 'one.js'
153 - });
154 - map.addMapping({
155 - generated: { line: 1, column: 28 },
156 - original: { line: 2, column: 10 },
157 - source: 'one.js',
158 - name: 'baz'
159 - });
160 - map.addMapping({
161 - generated: { line: 1, column: 32 },
162 - original: { line: 2, column: 14 },
163 - source: 'one.js',
164 - name: 'bar'
165 - });
166 -
167 - map.addMapping({
168 - generated: { line: 2, column: 1 },
169 - original: { line: 1, column: 1 },
170 - source: 'two.js'
171 - });
172 - map.addMapping({
173 - generated: { line: 2, column: 5 },
174 - original: { line: 1, column: 5 },
175 - source: 'two.js'
176 - });
177 - map.addMapping({
178 - generated: { line: 2, column: 9 },
179 - original: { line: 1, column: 11 },
180 - source: 'two.js'
181 - });
182 - map.addMapping({
183 - generated: { line: 2, column: 18 },
184 - original: { line: 1, column: 21 },
185 - source: 'two.js',
186 - name: 'n'
187 - });
188 - map.addMapping({
189 - generated: { line: 2, column: 21 },
190 - original: { line: 2, column: 3 },
191 - source: 'two.js'
192 - });
193 - map.addMapping({
194 - generated: { line: 2, column: 28 },
195 - original: { line: 2, column: 10 },
196 - source: 'two.js',
197 - name: 'n'
198 - });
199 -
200 - map = JSON.parse(map.toString());
201 -
202 - util.assertEqualMaps(assert, map, util.testMap);
203 - };
204 -
205 - exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) {
206 - var map = new SourceMapGenerator({
207 - file: 'generated-foo.js',
208 - sourceRoot: '.'
209 - });
210 -
211 - map.addMapping({
212 - generated: { line: 1, column: 1 },
213 - source: 'bar.js',
214 - original: { line: 1, column: 1 },
215 - name: ''
216 - });
217 -
218 - assert.doesNotThrow(function () {
219 - JSON.parse(map.toString());
220 - });
221 - };
222 -
223 - exports['test that source content can be set'] = function (assert, util) {
224 - var map = new SourceMapGenerator({
225 - file: 'min.js',
226 - sourceRoot: '/the/root'
227 - });
228 - map.addMapping({
229 - generated: { line: 1, column: 1 },
230 - original: { line: 1, column: 1 },
231 - source: 'one.js'
232 - });
233 - map.addMapping({
234 - generated: { line: 2, column: 1 },
235 - original: { line: 1, column: 1 },
236 - source: 'two.js'
237 - });
238 - map.setSourceContent('one.js', 'one file content');
239 -
240 - map = JSON.parse(map.toString());
241 - assert.equal(map.sources[0], 'one.js');
242 - assert.equal(map.sources[1], 'two.js');
243 - assert.equal(map.sourcesContent[0], 'one file content');
244 - assert.equal(map.sourcesContent[1], null);
245 - };
246 -
247 - exports['test .fromSourceMap'] = function (assert, util) {
248 - var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap));
249 - util.assertEqualMaps(assert, map.toJSON(), util.testMap);
250 - };
251 -
252 - exports['test .fromSourceMap with sourcesContent'] = function (assert, util) {
253 - var map = SourceMapGenerator.fromSourceMap(
254 - new SourceMapConsumer(util.testMapWithSourcesContent));
255 - util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent);
256 - };
257 -
258 - exports['test applySourceMap'] = function (assert, util) {
259 - var node = new SourceNode(null, null, null, [
260 - new SourceNode(2, 0, 'fileX', 'lineX2\n'),
261 - 'genA1\n',
262 - new SourceNode(2, 0, 'fileY', 'lineY2\n'),
263 - 'genA2\n',
264 - new SourceNode(1, 0, 'fileX', 'lineX1\n'),
265 - 'genA3\n',
266 - new SourceNode(1, 0, 'fileY', 'lineY1\n')
267 - ]);
268 - var mapStep1 = node.toStringWithSourceMap({
269 - file: 'fileA'
270 - }).map;
271 - mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n');
272 - mapStep1 = mapStep1.toJSON();
273 -
274 - node = new SourceNode(null, null, null, [
275 - 'gen1\n',
276 - new SourceNode(1, 0, 'fileA', 'lineA1\n'),
277 - new SourceNode(2, 0, 'fileA', 'lineA2\n'),
278 - new SourceNode(3, 0, 'fileA', 'lineA3\n'),
279 - new SourceNode(4, 0, 'fileA', 'lineA4\n'),
280 - new SourceNode(1, 0, 'fileB', 'lineB1\n'),
281 - new SourceNode(2, 0, 'fileB', 'lineB2\n'),
282 - 'gen2\n'
283 - ]);
284 - var mapStep2 = node.toStringWithSourceMap({
285 - file: 'fileGen'
286 - }).map;
287 - mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n');
288 - mapStep2 = mapStep2.toJSON();
289 -
290 - node = new SourceNode(null, null, null, [
291 - 'gen1\n',
292 - new SourceNode(2, 0, 'fileX', 'lineA1\n'),
293 - new SourceNode(2, 0, 'fileA', 'lineA2\n'),
294 - new SourceNode(2, 0, 'fileY', 'lineA3\n'),
295 - new SourceNode(4, 0, 'fileA', 'lineA4\n'),
296 - new SourceNode(1, 0, 'fileB', 'lineB1\n'),
297 - new SourceNode(2, 0, 'fileB', 'lineB2\n'),
298 - 'gen2\n'
299 - ]);
300 - var expectedMap = node.toStringWithSourceMap({
301 - file: 'fileGen'
302 - }).map;
303 - expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n');
304 - expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n');
305 - expectedMap = expectedMap.toJSON();
306 -
307 - // apply source map "mapStep1" to "mapStep2"
308 - var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2));
309 - generator.applySourceMap(new SourceMapConsumer(mapStep1));
310 - var actualMap = generator.toJSON();
311 -
312 - util.assertEqualMaps(assert, actualMap, expectedMap);
313 - };
314 -
315 - exports['test applySourceMap throws when file is missing'] = function (assert, util) {
316 - var map = new SourceMapGenerator({
317 - file: 'test.js'
318 - });
319 - var map2 = new SourceMapGenerator();
320 - assert.throws(function() {
321 - map.applySourceMap(new SourceMapConsumer(map2.toJSON()));
322 - });
323 - };
324 -
325 - exports['test the two additional parameters of applySourceMap'] = function (assert, util) {
326 - // Assume the following directory structure:
327 - //
328 - // http://foo.org/
329 - // bar.coffee
330 - // app/
331 - // coffee/
332 - // foo.coffee
333 - // temp/
334 - // bundle.js
335 - // temp_maps/
336 - // bundle.js.map
337 - // public/
338 - // bundle.min.js
339 - // bundle.min.js.map
340 - //
341 - // http://www.example.com/
342 - // baz.coffee
343 -
344 - var bundleMap = new SourceMapGenerator({
345 - file: 'bundle.js'
346 - });
347 - bundleMap.addMapping({
348 - generated: { line: 3, column: 3 },
349 - original: { line: 2, column: 2 },
350 - source: '../../coffee/foo.coffee'
351 - });
352 - bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee');
353 - bundleMap.addMapping({
354 - generated: { line: 13, column: 13 },
355 - original: { line: 12, column: 12 },
356 - source: '/bar.coffee'
357 - });
358 - bundleMap.setSourceContent('/bar.coffee', 'bar coffee');
359 - bundleMap.addMapping({
360 - generated: { line: 23, column: 23 },
361 - original: { line: 22, column: 22 },
362 - source: 'http://www.example.com/baz.coffee'
363 - });
364 - bundleMap.setSourceContent(
365 - 'http://www.example.com/baz.coffee',
366 - 'baz coffee'
367 - );
368 - bundleMap = new SourceMapConsumer(bundleMap.toJSON());
369 -
370 - var minifiedMap = new SourceMapGenerator({
371 - file: 'bundle.min.js',
372 - sourceRoot: '..'
373 - });
374 - minifiedMap.addMapping({
375 - generated: { line: 1, column: 1 },
376 - original: { line: 3, column: 3 },
377 - source: 'temp/bundle.js'
378 - });
379 - minifiedMap.addMapping({
380 - generated: { line: 11, column: 11 },
381 - original: { line: 13, column: 13 },
382 - source: 'temp/bundle.js'
383 - });
384 - minifiedMap.addMapping({
385 - generated: { line: 21, column: 21 },
386 - original: { line: 23, column: 23 },
387 - source: 'temp/bundle.js'
388 - });
389 - minifiedMap = new SourceMapConsumer(minifiedMap.toJSON());
390 -
391 - var expectedMap = function (sources) {
392 - var map = new SourceMapGenerator({
393 - file: 'bundle.min.js',
394 - sourceRoot: '..'
395 - });
396 - map.addMapping({
397 - generated: { line: 1, column: 1 },
398 - original: { line: 2, column: 2 },
399 - source: sources[0]
400 - });
401 - map.setSourceContent(sources[0], 'foo coffee');
402 - map.addMapping({
403 - generated: { line: 11, column: 11 },
404 - original: { line: 12, column: 12 },
405 - source: sources[1]
406 - });
407 - map.setSourceContent(sources[1], 'bar coffee');
408 - map.addMapping({
409 - generated: { line: 21, column: 21 },
410 - original: { line: 22, column: 22 },
411 - source: sources[2]
412 - });
413 - map.setSourceContent(sources[2], 'baz coffee');
414 - return map.toJSON();
415 - }
416 -
417 - var actualMap = function (aSourceMapPath) {
418 - var map = SourceMapGenerator.fromSourceMap(minifiedMap);
419 - // Note that relying on `bundleMap.file` (which is simply 'bundle.js')
420 - // instead of supplying the second parameter wouldn't work here.
421 - map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath);
422 - return map.toJSON();
423 - }
424 -
425 - util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([
426 - 'coffee/foo.coffee',
427 - '/bar.coffee',
428 - 'http://www.example.com/baz.coffee'
429 - ]));
430 -
431 - util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([
432 - '/app/coffee/foo.coffee',
433 - '/bar.coffee',
434 - 'http://www.example.com/baz.coffee'
435 - ]));
436 -
437 - util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([
438 - 'http://foo.org/app/coffee/foo.coffee',
439 - 'http://foo.org/bar.coffee',
440 - 'http://www.example.com/baz.coffee'
441 - ]));
442 -
443 - // If the third parameter is omitted or set to the current working
444 - // directory we get incorrect source paths:
445 -
446 - util.assertEqualMaps(assert, actualMap(), expectedMap([
447 - '../coffee/foo.coffee',
448 - '/bar.coffee',
449 - 'http://www.example.com/baz.coffee'
450 - ]));
451 -
452 - util.assertEqualMaps(assert, actualMap(''), expectedMap([
453 - '../coffee/foo.coffee',
454 - '/bar.coffee',
455 - 'http://www.example.com/baz.coffee'
456 - ]));
457 -
458 - util.assertEqualMaps(assert, actualMap('.'), expectedMap([
459 - '../coffee/foo.coffee',
460 - '/bar.coffee',
461 - 'http://www.example.com/baz.coffee'
462 - ]));
463 -
464 - util.assertEqualMaps(assert, actualMap('./'), expectedMap([
465 - '../coffee/foo.coffee',
466 - '/bar.coffee',
467 - 'http://www.example.com/baz.coffee'
468 - ]));
469 - };
470 -
471 - exports['test applySourceMap name handling'] = function (assert, util) {
472 - // Imagine some CoffeeScript code being compiled into JavaScript and then
473 - // minified.
474 -
475 - var assertName = function(coffeeName, jsName, expectedName) {
476 - var minifiedMap = new SourceMapGenerator({
477 - file: 'test.js.min'
478 - });
479 - minifiedMap.addMapping({
480 - generated: { line: 1, column: 4 },
481 - original: { line: 1, column: 4 },
482 - source: 'test.js',
483 - name: jsName
484 - });
485 -
486 - var coffeeMap = new SourceMapGenerator({
487 - file: 'test.js'
488 - });
489 - coffeeMap.addMapping({
490 - generated: { line: 1, column: 4 },
491 - original: { line: 1, column: 0 },
492 - source: 'test.coffee',
493 - name: coffeeName
494 - });
495 -
496 - minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON()));
497 -
498 - new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) {
499 - assert.equal(mapping.name, expectedName);
500 - });
501 - };
502 -
503 - // `foo = 1` -> `var foo = 1;` -> `var a=1`
504 - // CoffeeScript doesn’t rename variables, so there’s no need for it to
505 - // provide names in its source maps. Minifiers do rename variables and
506 - // therefore do provide names in their source maps. So that name should be
507 - // retained if the original map lacks names.
508 - assertName(null, 'foo', 'foo');
509 -
510 - // `foo = 1` -> `var coffee$foo = 1;` -> `var a=1`
511 - // Imagine that CoffeeScript prefixed all variables with `coffee$`. Even
512 - // though the minifier then also provides a name, the original name is
513 - // what corresponds to the source.
514 - assertName('foo', 'coffee$foo', 'foo');
515 -
516 - // `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1`
517 - // Minifiers can turn off variable mangling. Then there’s no need to
518 - // provide names in the source map, but the names from the original map are
519 - // still needed.
520 - assertName('foo', null, 'foo');
521 -
522 - // `foo = 1` -> `var foo = 1;` -> `var foo=1`
523 - // No renaming at all.
524 - assertName(null, null, null);
525 - };
526 -
527 - exports['test sorting with duplicate generated mappings'] = function (assert, util) {
528 - var map = new SourceMapGenerator({
529 - file: 'test.js'
530 - });
531 - map.addMapping({
532 - generated: { line: 3, column: 0 },
533 - original: { line: 2, column: 0 },
534 - source: 'a.js'
535 - });
536 - map.addMapping({
537 - generated: { line: 2, column: 0 }
538 - });
539 - map.addMapping({
540 - generated: { line: 2, column: 0 }
541 - });
542 - map.addMapping({
543 - generated: { line: 1, column: 0 },
544 - original: { line: 1, column: 0 },
545 - source: 'a.js'
546 - });
547 -
548 - util.assertEqualMaps(assert, map.toJSON(), {
549 - version: 3,
550 - file: 'test.js',
551 - sources: ['a.js'],
552 - names: [],
553 - mappings: 'AAAA;A;AACA'
554 - });
555 - };
556 -
557 - exports['test ignore duplicate mappings.'] = function (assert, util) {
558 - var init = { file: 'min.js', sourceRoot: '/the/root' };
559 - var map1, map2;
560 -
561 - // null original source location
562 - var nullMapping1 = {
563 - generated: { line: 1, column: 0 }
564 - };
565 - var nullMapping2 = {
566 - generated: { line: 2, column: 2 }
567 - };
568 -
569 - map1 = new SourceMapGenerator(init);
570 - map2 = new SourceMapGenerator(init);
571 -
572 - map1.addMapping(nullMapping1);
573 - map1.addMapping(nullMapping1);
574 -
575 - map2.addMapping(nullMapping1);
576 -
577 - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
578 -
579 - map1.addMapping(nullMapping2);
580 - map1.addMapping(nullMapping1);
581 -
582 - map2.addMapping(nullMapping2);
583 -
584 - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
585 -
586 - // original source location
587 - var srcMapping1 = {
588 - generated: { line: 1, column: 0 },
589 - original: { line: 11, column: 0 },
590 - source: 'srcMapping1.js'
591 - };
592 - var srcMapping2 = {
593 - generated: { line: 2, column: 2 },
594 - original: { line: 11, column: 0 },
595 - source: 'srcMapping2.js'
596 - };
597 -
598 - map1 = new SourceMapGenerator(init);
599 - map2 = new SourceMapGenerator(init);
600 -
601 - map1.addMapping(srcMapping1);
602 - map1.addMapping(srcMapping1);
603 -
604 - map2.addMapping(srcMapping1);
605 -
606 - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
607 -
608 - map1.addMapping(srcMapping2);
609 - map1.addMapping(srcMapping1);
610 -
611 - map2.addMapping(srcMapping2);
612 -
613 - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
614 -
615 - // full original source and name information
616 - var fullMapping1 = {
617 - generated: { line: 1, column: 0 },
618 - original: { line: 11, column: 0 },
619 - source: 'fullMapping1.js',
620 - name: 'fullMapping1'
621 - };
622 - var fullMapping2 = {
623 - generated: { line: 2, column: 2 },
624 - original: { line: 11, column: 0 },
625 - source: 'fullMapping2.js',
626 - name: 'fullMapping2'
627 - };
628 -
629 - map1 = new SourceMapGenerator(init);
630 - map2 = new SourceMapGenerator(init);
631 -
632 - map1.addMapping(fullMapping1);
633 - map1.addMapping(fullMapping1);
634 -
635 - map2.addMapping(fullMapping1);
636 -
637 - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
638 -
639 - map1.addMapping(fullMapping2);
640 - map1.addMapping(fullMapping1);
641 -
642 - map2.addMapping(fullMapping2);
643 -
644 - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
645 - };
646 -
647 - exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) {
648 - var map = new SourceMapGenerator({
649 - file: 'test.js'
650 - });
651 - map.addMapping({
652 - generated: { line: 1, column: 1 },
653 - original: { line: 2, column: 2 },
654 - source: 'a.js',
655 - name: 'foo'
656 - });
657 - map.addMapping({
658 - generated: { line: 3, column: 3 },
659 - original: { line: 4, column: 4 },
660 - source: 'a.js',
661 - name: 'foo'
662 - });
663 - util.assertEqualMaps(assert, map.toJSON(), {
664 - version: 3,
665 - file: 'test.js',
666 - sources: ['a.js'],
667 - names: ['foo'],
668 - mappings: 'CACEA;;GAEEA'
669 - });
670 - };
671 -
672 - exports['test setting sourcesContent to null when already null'] = function (assert, util) {
673 - var smg = new SourceMapGenerator({ file: "foo.js" });
674 - assert.doesNotThrow(function() {
675 - smg.setSourceContent("bar.js", null);
676 - });
677 - };
678 -
679 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator;
13 - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer;
14 - var SourceNode = require('../../lib/source-map/source-node').SourceNode;
15 -
16 - function forEachNewline(fn) {
17 - return function (assert, util) {
18 - ['\n', '\r\n'].forEach(fn.bind(null, assert, util));
19 - }
20 - }
21 -
22 - exports['test .add()'] = function (assert, util) {
23 - var node = new SourceNode(null, null, null);
24 -
25 - // Adding a string works.
26 - node.add('function noop() {}');
27 -
28 - // Adding another source node works.
29 - node.add(new SourceNode(null, null, null));
30 -
31 - // Adding an array works.
32 - node.add(['function foo() {',
33 - new SourceNode(null, null, null,
34 - 'return 10;'),
35 - '}']);
36 -
37 - // Adding other stuff doesn't.
38 - assert.throws(function () {
39 - node.add({});
40 - });
41 - assert.throws(function () {
42 - node.add(function () {});
43 - });
44 - };
45 -
46 - exports['test .prepend()'] = function (assert, util) {
47 - var node = new SourceNode(null, null, null);
48 -
49 - // Prepending a string works.
50 - node.prepend('function noop() {}');
51 - assert.equal(node.children[0], 'function noop() {}');
52 - assert.equal(node.children.length, 1);
53 -
54 - // Prepending another source node works.
55 - node.prepend(new SourceNode(null, null, null));
56 - assert.equal(node.children[0], '');
57 - assert.equal(node.children[1], 'function noop() {}');
58 - assert.equal(node.children.length, 2);
59 -
60 - // Prepending an array works.
61 - node.prepend(['function foo() {',
62 - new SourceNode(null, null, null,
63 - 'return 10;'),
64 - '}']);
65 - assert.equal(node.children[0], 'function foo() {');
66 - assert.equal(node.children[1], 'return 10;');
67 - assert.equal(node.children[2], '}');
68 - assert.equal(node.children[3], '');
69 - assert.equal(node.children[4], 'function noop() {}');
70 - assert.equal(node.children.length, 5);
71 -
72 - // Prepending other stuff doesn't.
73 - assert.throws(function () {
74 - node.prepend({});
75 - });
76 - assert.throws(function () {
77 - node.prepend(function () {});
78 - });
79 - };
80 -
81 - exports['test .toString()'] = function (assert, util) {
82 - assert.equal((new SourceNode(null, null, null,
83 - ['function foo() {',
84 - new SourceNode(null, null, null, 'return 10;'),
85 - '}'])).toString(),
86 - 'function foo() {return 10;}');
87 - };
88 -
89 - exports['test .join()'] = function (assert, util) {
90 - assert.equal((new SourceNode(null, null, null,
91 - ['a', 'b', 'c', 'd'])).join(', ').toString(),
92 - 'a, b, c, d');
93 - };
94 -
95 - exports['test .walk()'] = function (assert, util) {
96 - var node = new SourceNode(null, null, null,
97 - ['(function () {\n',
98 - ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n',
99 - ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n',
100 - '}());']);
101 - var expected = [
102 - { str: '(function () {\n', source: null, line: null, column: null },
103 - { str: ' ', source: null, line: null, column: null },
104 - { str: 'someCall()', source: 'a.js', line: 1, column: 0 },
105 - { str: ';\n', source: null, line: null, column: null },
106 - { str: ' ', source: null, line: null, column: null },
107 - { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 },
108 - { str: ';\n', source: null, line: null, column: null },
109 - { str: '}());', source: null, line: null, column: null },
110 - ];
111 - var i = 0;
112 - node.walk(function (chunk, loc) {
113 - assert.equal(expected[i].str, chunk);
114 - assert.equal(expected[i].source, loc.source);
115 - assert.equal(expected[i].line, loc.line);
116 - assert.equal(expected[i].column, loc.column);
117 - i++;
118 - });
119 - };
120 -
121 - exports['test .replaceRight'] = function (assert, util) {
122 - var node;
123 -
124 - // Not nested
125 - node = new SourceNode(null, null, null, 'hello world');
126 - node.replaceRight(/world/, 'universe');
127 - assert.equal(node.toString(), 'hello universe');
128 -
129 - // Nested
130 - node = new SourceNode(null, null, null,
131 - [new SourceNode(null, null, null, 'hey sexy mama, '),
132 - new SourceNode(null, null, null, 'want to kill all humans?')]);
133 - node.replaceRight(/kill all humans/, 'watch Futurama');
134 - assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?');
135 - };
136 -
137 - exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) {
138 - var node = new SourceNode(null, null, null,
139 - ['(function () {' + nl,
140 - ' ',
141 - new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'),
142 - new SourceNode(1, 8, 'a.js', '()'),
143 - ';' + nl,
144 - ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl,
145 - '}());']);
146 - var result = node.toStringWithSourceMap({
147 - file: 'foo.js'
148 - });
149 -
150 - assert.equal(result.code, [
151 - '(function () {',
152 - ' someCall();',
153 - ' if (foo) bar();',
154 - '}());'
155 - ].join(nl));
156 -
157 - var map = result.map;
158 - var mapWithoutOptions = node.toStringWithSourceMap().map;
159 -
160 - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
161 - assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator');
162 - assert.ok(!('file' in mapWithoutOptions));
163 - mapWithoutOptions._file = 'foo.js';
164 - util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON());
165 -
166 - map = new SourceMapConsumer(map.toString());
167 -
168 - var actual;
169 -
170 - actual = map.originalPositionFor({
171 - line: 1,
172 - column: 4
173 - });
174 - assert.equal(actual.source, null);
175 - assert.equal(actual.line, null);
176 - assert.equal(actual.column, null);
177 -
178 - actual = map.originalPositionFor({
179 - line: 2,
180 - column: 2
181 - });
182 - assert.equal(actual.source, 'a.js');
183 - assert.equal(actual.line, 1);
184 - assert.equal(actual.column, 0);
185 - assert.equal(actual.name, 'originalCall');
186 -
187 - actual = map.originalPositionFor({
188 - line: 3,
189 - column: 2
190 - });
191 - assert.equal(actual.source, 'b.js');
192 - assert.equal(actual.line, 2);
193 - assert.equal(actual.column, 0);
194 -
195 - actual = map.originalPositionFor({
196 - line: 3,
197 - column: 16
198 - });
199 - assert.equal(actual.source, null);
200 - assert.equal(actual.line, null);
201 - assert.equal(actual.column, null);
202 -
203 - actual = map.originalPositionFor({
204 - line: 4,
205 - column: 2
206 - });
207 - assert.equal(actual.source, null);
208 - assert.equal(actual.line, null);
209 - assert.equal(actual.column, null);
210 - });
211 -
212 - exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) {
213 - var testCode = util.testGeneratedCode.replace(/\n/g, nl);
214 - var node = SourceNode.fromStringWithSourceMap(
215 - testCode,
216 - new SourceMapConsumer(util.testMap));
217 -
218 - var result = node.toStringWithSourceMap({
219 - file: 'min.js'
220 - });
221 - var map = result.map;
222 - var code = result.code;
223 -
224 - assert.equal(code, testCode);
225 - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
226 - map = map.toJSON();
227 - assert.equal(map.version, util.testMap.version);
228 - assert.equal(map.file, util.testMap.file);
229 - assert.equal(map.mappings, util.testMap.mappings);
230 - });
231 -
232 - exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) {
233 - var node = SourceNode.fromStringWithSourceMap(
234 - util.testGeneratedCode.replace(/\n/g, nl),
235 - new SourceMapConsumer(util.emptyMap));
236 - var result = node.toStringWithSourceMap({
237 - file: 'min.js'
238 - });
239 - var map = result.map;
240 - var code = result.code;
241 -
242 - assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl));
243 - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
244 - map = map.toJSON();
245 - assert.equal(map.version, util.emptyMap.version);
246 - assert.equal(map.file, util.emptyMap.file);
247 - assert.equal(map.mappings.length, util.emptyMap.mappings.length);
248 - assert.equal(map.mappings, util.emptyMap.mappings);
249 - });
250 -
251 - exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) {
252 - var input = new SourceNode(null, null, null, [
253 - "(function() {" + nl,
254 - " var Test = {};" + nl,
255 - " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl),
256 - " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl,
257 - "}());" + nl,
258 - "/* Generated Source */"]);
259 - input = input.toStringWithSourceMap({
260 - file: 'foo.js'
261 - });
262 -
263 - var node = SourceNode.fromStringWithSourceMap(
264 - input.code,
265 - new SourceMapConsumer(input.map.toString()));
266 -
267 - var result = node.toStringWithSourceMap({
268 - file: 'foo.js'
269 - });
270 - var map = result.map;
271 - var code = result.code;
272 -
273 - assert.equal(code, input.code);
274 - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
275 - map = map.toJSON();
276 - var inputMap = input.map.toJSON();
277 - util.assertEqualMaps(assert, map, inputMap);
278 - });
279 -
280 - exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) {
281 - // Assume the following directory structure:
282 - //
283 - // http://foo.org/
284 - // bar.coffee
285 - // app/
286 - // coffee/
287 - // foo.coffee
288 - // coffeeBundle.js # Made from {foo,bar,baz}.coffee
289 - // maps/
290 - // coffeeBundle.js.map
291 - // js/
292 - // foo.js
293 - // public/
294 - // app.js # Made from {foo,coffeeBundle}.js
295 - // app.js.map
296 - //
297 - // http://www.example.com/
298 - // baz.coffee
299 -
300 - var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n');
301 - coffeeBundle.setSourceContent('foo.coffee', 'foo coffee');
302 - coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n'));
303 - coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);'));
304 - coffeeBundle = coffeeBundle.toStringWithSourceMap({
305 - file: 'foo.js',
306 - sourceRoot: '..'
307 - });
308 -
309 - var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);');
310 -
311 - var test = function(relativePath, expectedSources) {
312 - var app = new SourceNode();
313 - app.add(SourceNode.fromStringWithSourceMap(
314 - coffeeBundle.code,
315 - new SourceMapConsumer(coffeeBundle.map.toString()),
316 - relativePath));
317 - app.add(foo);
318 - var i = 0;
319 - app.walk(function (chunk, loc) {
320 - assert.equal(loc.source, expectedSources[i]);
321 - i++;
322 - });
323 - app.walkSourceContents(function (sourceFile, sourceContent) {
324 - assert.equal(sourceFile, expectedSources[0]);
325 - assert.equal(sourceContent, 'foo coffee');
326 - })
327 - };
328 -
329 - test('../coffee/maps', [
330 - '../coffee/foo.coffee',
331 - '/bar.coffee',
332 - 'http://www.example.com/baz.coffee',
333 - 'foo.js'
334 - ]);
335 -
336 - // If the third parameter is omitted or set to the current working
337 - // directory we get incorrect source paths:
338 -
339 - test(undefined, [
340 - '../foo.coffee',
341 - '/bar.coffee',
342 - 'http://www.example.com/baz.coffee',
343 - 'foo.js'
344 - ]);
345 -
346 - test('', [
347 - '../foo.coffee',
348 - '/bar.coffee',
349 - 'http://www.example.com/baz.coffee',
350 - 'foo.js'
351 - ]);
352 -
353 - test('.', [
354 - '../foo.coffee',
355 - '/bar.coffee',
356 - 'http://www.example.com/baz.coffee',
357 - 'foo.js'
358 - ]);
359 -
360 - test('./', [
361 - '../foo.coffee',
362 - '/bar.coffee',
363 - 'http://www.example.com/baz.coffee',
364 - 'foo.js'
365 - ]);
366 - };
367 -
368 - exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) {
369 - var input = new SourceNode(null, null, null, [
370 - new SourceNode(1, 0, "a.js", "(function"),
371 - new SourceNode(1, 0, "a.js", "() {" + nl),
372 - " ",
373 - new SourceNode(1, 0, "a.js", "var Test = "),
374 - new SourceNode(1, 0, "b.js", "{};" + nl),
375 - new SourceNode(2, 0, "b.js", "Test"),
376 - new SourceNode(2, 0, "b.js", ".A", "A"),
377 - new SourceNode(2, 20, "b.js", " = { value: ", "A"),
378 - "1234",
379 - new SourceNode(2, 40, "b.js", " };" + nl, "A"),
380 - "}());" + nl,
381 - "/* Generated Source */"
382 - ]);
383 - input = input.toStringWithSourceMap({
384 - file: 'foo.js'
385 - });
386 -
387 - assert.equal(input.code, [
388 - "(function() {",
389 - " var Test = {};",
390 - "Test.A = { value: 1234 };",
391 - "}());",
392 - "/* Generated Source */"
393 - ].join(nl))
394 -
395 - var correctMap = new SourceMapGenerator({
396 - file: 'foo.js'
397 - });
398 - correctMap.addMapping({
399 - generated: { line: 1, column: 0 },
400 - source: 'a.js',
401 - original: { line: 1, column: 0 }
402 - });
403 - // Here is no need for a empty mapping,
404 - // because mappings ends at eol
405 - correctMap.addMapping({
406 - generated: { line: 2, column: 2 },
407 - source: 'a.js',
408 - original: { line: 1, column: 0 }
409 - });
410 - correctMap.addMapping({
411 - generated: { line: 2, column: 13 },
412 - source: 'b.js',
413 - original: { line: 1, column: 0 }
414 - });
415 - correctMap.addMapping({
416 - generated: { line: 3, column: 0 },
417 - source: 'b.js',
418 - original: { line: 2, column: 0 }
419 - });
420 - correctMap.addMapping({
421 - generated: { line: 3, column: 4 },
422 - source: 'b.js',
423 - name: 'A',
424 - original: { line: 2, column: 0 }
425 - });
426 - correctMap.addMapping({
427 - generated: { line: 3, column: 6 },
428 - source: 'b.js',
429 - name: 'A',
430 - original: { line: 2, column: 20 }
431 - });
432 - // This empty mapping is required,
433 - // because there is a hole in the middle of the line
434 - correctMap.addMapping({
435 - generated: { line: 3, column: 18 }
436 - });
437 - correctMap.addMapping({
438 - generated: { line: 3, column: 22 },
439 - source: 'b.js',
440 - name: 'A',
441 - original: { line: 2, column: 40 }
442 - });
443 - // Here is no need for a empty mapping,
444 - // because mappings ends at eol
445 -
446 - var inputMap = input.map.toJSON();
447 - correctMap = correctMap.toJSON();
448 - util.assertEqualMaps(assert, inputMap, correctMap);
449 - });
450 -
451 - exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) {
452 - var input = new SourceNode(null, null, null, [
453 - new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl),
454 - new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl),
455 - new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl),
456 - new SourceNode(2, 2, "b.js", "anotherLine();" + nl),
457 - "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl,
458 - new SourceNode(3, 4, "c.js", "anotherLine();" + nl),
459 - "/*" + nl + "Generated" + nl + "Source" + nl + "*/"
460 - ]);
461 - input = input.toStringWithSourceMap({
462 - file: 'foo.js'
463 - });
464 -
465 - assert.equal(input.code, [
466 - "(function() {",
467 - "var nextLine = 1;",
468 - "anotherLine();",
469 - "Test.call(this, 123);",
470 - "this['stuff'] = 'v';",
471 - "anotherLine();",
472 - "/*",
473 - "Generated",
474 - "Source",
475 - "*/",
476 - "anotherLine();",
477 - "/*",
478 - "Generated",
479 - "Source",
480 - "*/"
481 - ].join(nl));
482 -
483 - var correctMap = new SourceMapGenerator({
484 - file: 'foo.js'
485 - });
486 - correctMap.addMapping({
487 - generated: { line: 1, column: 0 },
488 - source: 'a.js',
489 - original: { line: 1, column: 0 }
490 - });
491 - correctMap.addMapping({
492 - generated: { line: 2, column: 0 },
493 - source: 'a.js',
494 - original: { line: 1, column: 0 }
495 - });
496 - correctMap.addMapping({
497 - generated: { line: 3, column: 0 },
498 - source: 'a.js',
499 - original: { line: 1, column: 0 }
500 - });
501 - correctMap.addMapping({
502 - generated: { line: 4, column: 0 },
503 - source: 'b.js',
504 - original: { line: 2, column: 2 }
505 - });
506 - correctMap.addMapping({
507 - generated: { line: 5, column: 0 },
508 - source: 'b.js',
509 - original: { line: 2, column: 2 }
510 - });
511 - correctMap.addMapping({
512 - generated: { line: 6, column: 0 },
513 - source: 'b.js',
514 - original: { line: 2, column: 2 }
515 - });
516 - correctMap.addMapping({
517 - generated: { line: 11, column: 0 },
518 - source: 'c.js',
519 - original: { line: 3, column: 4 }
520 - });
521 -
522 - var inputMap = input.map.toJSON();
523 - correctMap = correctMap.toJSON();
524 - util.assertEqualMaps(assert, inputMap, correctMap);
525 - });
526 -
527 - exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) {
528 - var node = new SourceNode(1, 0, 'empty.js', '');
529 - var result = node.toStringWithSourceMap();
530 - assert.equal(result.code, '');
531 - };
532 -
533 - exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) {
534 - var input = new SourceNode(null, null, null, [
535 - "/***/" + nl + nl,
536 - new SourceNode(1, 0, "a.js", "'use strict';" + nl),
537 - new SourceNode(2, 0, "a.js", "a();"),
538 - ]);
539 - input = input.toStringWithSourceMap({
540 - file: 'foo.js'
541 - });
542 -
543 - assert.equal(input.code, [
544 - "/***/",
545 - "",
546 - "'use strict';",
547 - "a();",
548 - ].join(nl));
549 -
550 - var correctMap = new SourceMapGenerator({
551 - file: 'foo.js'
552 - });
553 - correctMap.addMapping({
554 - generated: { line: 3, column: 0 },
555 - source: 'a.js',
556 - original: { line: 1, column: 0 }
557 - });
558 - correctMap.addMapping({
559 - generated: { line: 4, column: 0 },
560 - source: 'a.js',
561 - original: { line: 2, column: 0 }
562 - });
563 -
564 - var inputMap = input.map.toJSON();
565 - correctMap = correctMap.toJSON();
566 - util.assertEqualMaps(assert, inputMap, correctMap);
567 - });
568 -
569 - exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) {
570 - var aNode = new SourceNode(1, 1, 'a.js', 'a');
571 - aNode.setSourceContent('a.js', 'someContent');
572 - var node = new SourceNode(null, null, null,
573 - ['(function () {\n',
574 - ' ', aNode,
575 - ' ', new SourceNode(1, 1, 'b.js', 'b'),
576 - '}());']);
577 - node.setSourceContent('b.js', 'otherContent');
578 - var map = node.toStringWithSourceMap({
579 - file: 'foo.js'
580 - }).map;
581 -
582 - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
583 - map = new SourceMapConsumer(map.toString());
584 -
585 - assert.equal(map.sources.length, 2);
586 - assert.equal(map.sources[0], 'a.js');
587 - assert.equal(map.sources[1], 'b.js');
588 - assert.equal(map.sourcesContent.length, 2);
589 - assert.equal(map.sourcesContent[0], 'someContent');
590 - assert.equal(map.sourcesContent[1], 'otherContent');
591 - };
592 -
593 - exports['test walkSourceContents'] = function (assert, util) {
594 - var aNode = new SourceNode(1, 1, 'a.js', 'a');
595 - aNode.setSourceContent('a.js', 'someContent');
596 - var node = new SourceNode(null, null, null,
597 - ['(function () {\n',
598 - ' ', aNode,
599 - ' ', new SourceNode(1, 1, 'b.js', 'b'),
600 - '}());']);
601 - node.setSourceContent('b.js', 'otherContent');
602 - var results = [];
603 - node.walkSourceContents(function (sourceFile, sourceContent) {
604 - results.push([sourceFile, sourceContent]);
605 - });
606 - assert.equal(results.length, 2);
607 - assert.equal(results[0][0], 'a.js');
608 - assert.equal(results[0][1], 'someContent');
609 - assert.equal(results[1][0], 'b.js');
610 - assert.equal(results[1][1], 'otherContent');
611 - };
612 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2014 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var libUtil = require('../../lib/source-map/util');
13 -
14 - exports['test urls'] = function (assert, util) {
15 - var assertUrl = function (url) {
16 - assert.equal(url, libUtil.urlGenerate(libUtil.urlParse(url)));
17 - };
18 - assertUrl('http://');
19 - assertUrl('http://www.example.com');
20 - assertUrl('http://user:pass@www.example.com');
21 - assertUrl('http://www.example.com:80');
22 - assertUrl('http://www.example.com/');
23 - assertUrl('http://www.example.com/foo/bar');
24 - assertUrl('http://www.example.com/foo/bar/');
25 - assertUrl('http://user:pass@www.example.com:80/foo/bar/');
26 -
27 - assertUrl('//');
28 - assertUrl('//www.example.com');
29 - assertUrl('file:///www.example.com');
30 -
31 - assert.equal(libUtil.urlParse(''), null);
32 - assert.equal(libUtil.urlParse('.'), null);
33 - assert.equal(libUtil.urlParse('..'), null);
34 - assert.equal(libUtil.urlParse('a'), null);
35 - assert.equal(libUtil.urlParse('a/b'), null);
36 - assert.equal(libUtil.urlParse('a//b'), null);
37 - assert.equal(libUtil.urlParse('/a'), null);
38 - assert.equal(libUtil.urlParse('data:foo,bar'), null);
39 - };
40 -
41 - exports['test normalize()'] = function (assert, util) {
42 - assert.equal(libUtil.normalize('/..'), '/');
43 - assert.equal(libUtil.normalize('/../'), '/');
44 - assert.equal(libUtil.normalize('/../../../..'), '/');
45 - assert.equal(libUtil.normalize('/../../../../a/b/c'), '/a/b/c');
46 - assert.equal(libUtil.normalize('/a/b/c/../../../d/../../e'), '/e');
47 -
48 - assert.equal(libUtil.normalize('..'), '..');
49 - assert.equal(libUtil.normalize('../'), '../');
50 - assert.equal(libUtil.normalize('../../a/'), '../../a/');
51 - assert.equal(libUtil.normalize('a/..'), '.');
52 - assert.equal(libUtil.normalize('a/../../..'), '../..');
53 -
54 - assert.equal(libUtil.normalize('/.'), '/');
55 - assert.equal(libUtil.normalize('/./'), '/');
56 - assert.equal(libUtil.normalize('/./././.'), '/');
57 - assert.equal(libUtil.normalize('/././././a/b/c'), '/a/b/c');
58 - assert.equal(libUtil.normalize('/a/b/c/./././d/././e'), '/a/b/c/d/e');
59 -
60 - assert.equal(libUtil.normalize(''), '.');
61 - assert.equal(libUtil.normalize('.'), '.');
62 - assert.equal(libUtil.normalize('./'), '.');
63 - assert.equal(libUtil.normalize('././a'), 'a');
64 - assert.equal(libUtil.normalize('a/./'), 'a/');
65 - assert.equal(libUtil.normalize('a/././.'), 'a');
66 -
67 - assert.equal(libUtil.normalize('/a/b//c////d/////'), '/a/b/c/d/');
68 - assert.equal(libUtil.normalize('///a/b//c////d/////'), '///a/b/c/d/');
69 - assert.equal(libUtil.normalize('a/b//c////d'), 'a/b/c/d');
70 -
71 - assert.equal(libUtil.normalize('.///.././../a/b//./..'), '../../a')
72 -
73 - assert.equal(libUtil.normalize('http://www.example.com'), 'http://www.example.com');
74 - assert.equal(libUtil.normalize('http://www.example.com/'), 'http://www.example.com/');
75 - assert.equal(libUtil.normalize('http://www.example.com/./..//a/b/c/.././d//'), 'http://www.example.com/a/b/d/');
76 - };
77 -
78 - exports['test join()'] = function (assert, util) {
79 - assert.equal(libUtil.join('a', 'b'), 'a/b');
80 - assert.equal(libUtil.join('a/', 'b'), 'a/b');
81 - assert.equal(libUtil.join('a//', 'b'), 'a/b');
82 - assert.equal(libUtil.join('a', 'b/'), 'a/b/');
83 - assert.equal(libUtil.join('a', 'b//'), 'a/b/');
84 - assert.equal(libUtil.join('a/', '/b'), '/b');
85 - assert.equal(libUtil.join('a//', '//b'), '//b');
86 -
87 - assert.equal(libUtil.join('a', '..'), '.');
88 - assert.equal(libUtil.join('a', '../b'), 'b');
89 - assert.equal(libUtil.join('a/b', '../c'), 'a/c');
90 -
91 - assert.equal(libUtil.join('a', '.'), 'a');
92 - assert.equal(libUtil.join('a', './b'), 'a/b');
93 - assert.equal(libUtil.join('a/b', './c'), 'a/b/c');
94 -
95 - assert.equal(libUtil.join('a', 'http://www.example.com'), 'http://www.example.com');
96 - assert.equal(libUtil.join('a', 'data:foo,bar'), 'data:foo,bar');
97 -
98 -
99 - assert.equal(libUtil.join('', 'b'), 'b');
100 - assert.equal(libUtil.join('.', 'b'), 'b');
101 - assert.equal(libUtil.join('', 'b/'), 'b/');
102 - assert.equal(libUtil.join('.', 'b/'), 'b/');
103 - assert.equal(libUtil.join('', 'b//'), 'b/');
104 - assert.equal(libUtil.join('.', 'b//'), 'b/');
105 -
106 - assert.equal(libUtil.join('', '..'), '..');
107 - assert.equal(libUtil.join('.', '..'), '..');
108 - assert.equal(libUtil.join('', '../b'), '../b');
109 - assert.equal(libUtil.join('.', '../b'), '../b');
110 -
111 - assert.equal(libUtil.join('', '.'), '.');
112 - assert.equal(libUtil.join('.', '.'), '.');
113 - assert.equal(libUtil.join('', './b'), 'b');
114 - assert.equal(libUtil.join('.', './b'), 'b');
115 -
116 - assert.equal(libUtil.join('', 'http://www.example.com'), 'http://www.example.com');
117 - assert.equal(libUtil.join('.', 'http://www.example.com'), 'http://www.example.com');
118 - assert.equal(libUtil.join('', 'data:foo,bar'), 'data:foo,bar');
119 - assert.equal(libUtil.join('.', 'data:foo,bar'), 'data:foo,bar');
120 -
121 -
122 - assert.equal(libUtil.join('..', 'b'), '../b');
123 - assert.equal(libUtil.join('..', 'b/'), '../b/');
124 - assert.equal(libUtil.join('..', 'b//'), '../b/');
125 -
126 - assert.equal(libUtil.join('..', '..'), '../..');
127 - assert.equal(libUtil.join('..', '../b'), '../../b');
128 -
129 - assert.equal(libUtil.join('..', '.'), '..');
130 - assert.equal(libUtil.join('..', './b'), '../b');
131 -
132 - assert.equal(libUtil.join('..', 'http://www.example.com'), 'http://www.example.com');
133 - assert.equal(libUtil.join('..', 'data:foo,bar'), 'data:foo,bar');
134 -
135 -
136 - assert.equal(libUtil.join('a', ''), 'a');
137 - assert.equal(libUtil.join('a', '.'), 'a');
138 - assert.equal(libUtil.join('a/', ''), 'a');
139 - assert.equal(libUtil.join('a/', '.'), 'a');
140 - assert.equal(libUtil.join('a//', ''), 'a');
141 - assert.equal(libUtil.join('a//', '.'), 'a');
142 - assert.equal(libUtil.join('/a', ''), '/a');
143 - assert.equal(libUtil.join('/a', '.'), '/a');
144 - assert.equal(libUtil.join('', ''), '.');
145 - assert.equal(libUtil.join('.', ''), '.');
146 - assert.equal(libUtil.join('.', ''), '.');
147 - assert.equal(libUtil.join('.', '.'), '.');
148 - assert.equal(libUtil.join('..', ''), '..');
149 - assert.equal(libUtil.join('..', '.'), '..');
150 - assert.equal(libUtil.join('http://foo.org/a', ''), 'http://foo.org/a');
151 - assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a');
152 - assert.equal(libUtil.join('http://foo.org/a/', ''), 'http://foo.org/a');
153 - assert.equal(libUtil.join('http://foo.org/a/', '.'), 'http://foo.org/a');
154 - assert.equal(libUtil.join('http://foo.org/a//', ''), 'http://foo.org/a');
155 - assert.equal(libUtil.join('http://foo.org/a//', '.'), 'http://foo.org/a');
156 - assert.equal(libUtil.join('http://foo.org', ''), 'http://foo.org/');
157 - assert.equal(libUtil.join('http://foo.org', '.'), 'http://foo.org/');
158 - assert.equal(libUtil.join('http://foo.org/', ''), 'http://foo.org/');
159 - assert.equal(libUtil.join('http://foo.org/', '.'), 'http://foo.org/');
160 - assert.equal(libUtil.join('http://foo.org//', ''), 'http://foo.org/');
161 - assert.equal(libUtil.join('http://foo.org//', '.'), 'http://foo.org/');
162 - assert.equal(libUtil.join('//www.example.com', ''), '//www.example.com/');
163 - assert.equal(libUtil.join('//www.example.com', '.'), '//www.example.com/');
164 -
165 -
166 - assert.equal(libUtil.join('http://foo.org/a', 'b'), 'http://foo.org/a/b');
167 - assert.equal(libUtil.join('http://foo.org/a/', 'b'), 'http://foo.org/a/b');
168 - assert.equal(libUtil.join('http://foo.org/a//', 'b'), 'http://foo.org/a/b');
169 - assert.equal(libUtil.join('http://foo.org/a', 'b/'), 'http://foo.org/a/b/');
170 - assert.equal(libUtil.join('http://foo.org/a', 'b//'), 'http://foo.org/a/b/');
171 - assert.equal(libUtil.join('http://foo.org/a/', '/b'), 'http://foo.org/b');
172 - assert.equal(libUtil.join('http://foo.org/a//', '//b'), 'http://b');
173 -
174 - assert.equal(libUtil.join('http://foo.org/a', '..'), 'http://foo.org/');
175 - assert.equal(libUtil.join('http://foo.org/a', '../b'), 'http://foo.org/b');
176 - assert.equal(libUtil.join('http://foo.org/a/b', '../c'), 'http://foo.org/a/c');
177 -
178 - assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a');
179 - assert.equal(libUtil.join('http://foo.org/a', './b'), 'http://foo.org/a/b');
180 - assert.equal(libUtil.join('http://foo.org/a/b', './c'), 'http://foo.org/a/b/c');
181 -
182 - assert.equal(libUtil.join('http://foo.org/a', 'http://www.example.com'), 'http://www.example.com');
183 - assert.equal(libUtil.join('http://foo.org/a', 'data:foo,bar'), 'data:foo,bar');
184 -
185 -
186 - assert.equal(libUtil.join('http://foo.org', 'a'), 'http://foo.org/a');
187 - assert.equal(libUtil.join('http://foo.org/', 'a'), 'http://foo.org/a');
188 - assert.equal(libUtil.join('http://foo.org//', 'a'), 'http://foo.org/a');
189 - assert.equal(libUtil.join('http://foo.org', '/a'), 'http://foo.org/a');
190 - assert.equal(libUtil.join('http://foo.org/', '/a'), 'http://foo.org/a');
191 - assert.equal(libUtil.join('http://foo.org//', '/a'), 'http://foo.org/a');
192 -
193 -
194 - assert.equal(libUtil.join('http://', 'www.example.com'), 'http://www.example.com');
195 - assert.equal(libUtil.join('file:///', 'www.example.com'), 'file:///www.example.com');
196 - assert.equal(libUtil.join('http://', 'ftp://example.com'), 'ftp://example.com');
197 -
198 - assert.equal(libUtil.join('http://www.example.com', '//foo.org/bar'), 'http://foo.org/bar');
199 - assert.equal(libUtil.join('//www.example.com', '//foo.org/bar'), '//foo.org/bar');
200 - };
201 -
202 - // TODO Issue #128: Define and test this function properly.
203 - exports['test relative()'] = function (assert, util) {
204 - assert.equal(libUtil.relative('/the/root', '/the/root/one.js'), 'one.js');
205 - assert.equal(libUtil.relative('/the/root', '/the/rootone.js'), '/the/rootone.js');
206 -
207 - assert.equal(libUtil.relative('', '/the/root/one.js'), '/the/root/one.js');
208 - assert.equal(libUtil.relative('.', '/the/root/one.js'), '/the/root/one.js');
209 - assert.equal(libUtil.relative('', 'the/root/one.js'), 'the/root/one.js');
210 - assert.equal(libUtil.relative('.', 'the/root/one.js'), 'the/root/one.js');
211 -
212 - assert.equal(libUtil.relative('/', '/the/root/one.js'), 'the/root/one.js');
213 - assert.equal(libUtil.relative('/', 'the/root/one.js'), 'the/root/one.js');
214 - };
215 -
216 -});
1 -/* -*- Mode: js; js-indent-level: 2; -*- */
2 -/*
3 - * Copyright 2011 Mozilla Foundation and contributors
4 - * Licensed under the New BSD license. See LICENSE or:
5 - * http://opensource.org/licenses/BSD-3-Clause
6 - */
7 -if (typeof define !== 'function') {
8 - var define = require('amdefine')(module, require);
9 -}
10 -define(function (require, exports, module) {
11 -
12 - var util = require('../../lib/source-map/util');
13 -
14 - // This is a test mapping which maps functions from two different files
15 - // (one.js and two.js) to a minified generated source.
16 - //
17 - // Here is one.js:
18 - //
19 - // ONE.foo = function (bar) {
20 - // return baz(bar);
21 - // };
22 - //
23 - // Here is two.js:
24 - //
25 - // TWO.inc = function (n) {
26 - // return n + 1;
27 - // };
28 - //
29 - // And here is the generated code (min.js):
30 - //
31 - // ONE.foo=function(a){return baz(a);};
32 - // TWO.inc=function(a){return a+1;};
33 - exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+
34 - " TWO.inc=function(a){return a+1;};";
35 - exports.testMap = {
36 - version: 3,
37 - file: 'min.js',
38 - names: ['bar', 'baz', 'n'],
39 - sources: ['one.js', 'two.js'],
40 - sourceRoot: '/the/root',
41 - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
42 - };
43 - exports.testMapNoSourceRoot = {
44 - version: 3,
45 - file: 'min.js',
46 - names: ['bar', 'baz', 'n'],
47 - sources: ['one.js', 'two.js'],
48 - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
49 - };
50 - exports.testMapEmptySourceRoot = {
51 - version: 3,
52 - file: 'min.js',
53 - names: ['bar', 'baz', 'n'],
54 - sources: ['one.js', 'two.js'],
55 - sourceRoot: '',
56 - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
57 - };
58 - exports.testMapWithSourcesContent = {
59 - version: 3,
60 - file: 'min.js',
61 - names: ['bar', 'baz', 'n'],
62 - sources: ['one.js', 'two.js'],
63 - sourcesContent: [
64 - ' ONE.foo = function (bar) {\n' +
65 - ' return baz(bar);\n' +
66 - ' };',
67 - ' TWO.inc = function (n) {\n' +
68 - ' return n + 1;\n' +
69 - ' };'
70 - ],
71 - sourceRoot: '/the/root',
72 - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
73 - };
74 - exports.testMapRelativeSources = {
75 - version: 3,
76 - file: 'min.js',
77 - names: ['bar', 'baz', 'n'],
78 - sources: ['./one.js', './two.js'],
79 - sourcesContent: [
80 - ' ONE.foo = function (bar) {\n' +
81 - ' return baz(bar);\n' +
82 - ' };',
83 - ' TWO.inc = function (n) {\n' +
84 - ' return n + 1;\n' +
85 - ' };'
86 - ],
87 - sourceRoot: '/the/root',
88 - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
89 - };
90 - exports.emptyMap = {
91 - version: 3,
92 - file: 'min.js',
93 - names: [],
94 - sources: [],
95 - mappings: ''
96 - };
97 -
98 -
99 - function assertMapping(generatedLine, generatedColumn, originalSource,
100 - originalLine, originalColumn, name, map, assert,
101 - dontTestGenerated, dontTestOriginal) {
102 - if (!dontTestOriginal) {
103 - var origMapping = map.originalPositionFor({
104 - line: generatedLine,
105 - column: generatedColumn
106 - });
107 - assert.equal(origMapping.name, name,
108 - 'Incorrect name, expected ' + JSON.stringify(name)
109 - + ', got ' + JSON.stringify(origMapping.name));
110 - assert.equal(origMapping.line, originalLine,
111 - 'Incorrect line, expected ' + JSON.stringify(originalLine)
112 - + ', got ' + JSON.stringify(origMapping.line));
113 - assert.equal(origMapping.column, originalColumn,
114 - 'Incorrect column, expected ' + JSON.stringify(originalColumn)
115 - + ', got ' + JSON.stringify(origMapping.column));
116 -
117 - var expectedSource;
118 -
119 - if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) {
120 - expectedSource = originalSource;
121 - } else if (originalSource) {
122 - expectedSource = map.sourceRoot
123 - ? util.join(map.sourceRoot, originalSource)
124 - : originalSource;
125 - } else {
126 - expectedSource = null;
127 - }
128 -
129 - assert.equal(origMapping.source, expectedSource,
130 - 'Incorrect source, expected ' + JSON.stringify(expectedSource)
131 - + ', got ' + JSON.stringify(origMapping.source));
132 - }
133 -
134 - if (!dontTestGenerated) {
135 - var genMapping = map.generatedPositionFor({
136 - source: originalSource,
137 - line: originalLine,
138 - column: originalColumn
139 - });
140 - assert.equal(genMapping.line, generatedLine,
141 - 'Incorrect line, expected ' + JSON.stringify(generatedLine)
142 - + ', got ' + JSON.stringify(genMapping.line));
143 - assert.equal(genMapping.column, generatedColumn,
144 - 'Incorrect column, expected ' + JSON.stringify(generatedColumn)
145 - + ', got ' + JSON.stringify(genMapping.column));
146 - }
147 - }
148 - exports.assertMapping = assertMapping;
149 -
150 - function assertEqualMaps(assert, actualMap, expectedMap) {
151 - assert.equal(actualMap.version, expectedMap.version, "version mismatch");
152 - assert.equal(actualMap.file, expectedMap.file, "file mismatch");
153 - assert.equal(actualMap.names.length,
154 - expectedMap.names.length,
155 - "names length mismatch: " +
156 - actualMap.names.join(", ") + " != " + expectedMap.names.join(", "));
157 - for (var i = 0; i < actualMap.names.length; i++) {
158 - assert.equal(actualMap.names[i],
159 - expectedMap.names[i],
160 - "names[" + i + "] mismatch: " +
161 - actualMap.names.join(", ") + " != " + expectedMap.names.join(", "));
162 - }
163 - assert.equal(actualMap.sources.length,
164 - expectedMap.sources.length,
165 - "sources length mismatch: " +
166 - actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", "));
167 - for (var i = 0; i < actualMap.sources.length; i++) {
168 - assert.equal(actualMap.sources[i],
169 - expectedMap.sources[i],
170 - "sources[" + i + "] length mismatch: " +
171 - actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", "));
172 - }
173 - assert.equal(actualMap.sourceRoot,
174 - expectedMap.sourceRoot,
175 - "sourceRoot mismatch: " +
176 - actualMap.sourceRoot + " != " + expectedMap.sourceRoot);
177 - assert.equal(actualMap.mappings, expectedMap.mappings,
178 - "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings);
179 - if (actualMap.sourcesContent) {
180 - assert.equal(actualMap.sourcesContent.length,
181 - expectedMap.sourcesContent.length,
182 - "sourcesContent length mismatch");
183 - for (var i = 0; i < actualMap.sourcesContent.length; i++) {
184 - assert.equal(actualMap.sourcesContent[i],
185 - expectedMap.sourcesContent[i],
186 - "sourcesContent[" + i + "] mismatch");
187 - }
188 - }
189 - }
190 - exports.assertEqualMaps = assertEqualMaps;
191 -
192 -});
1 -var Class = require('./Class'),
2 - extend = require('./extend')
3 -
4 -module.exports = Class(function() {
5 -
6 - var defaults = {
7 - duration:250,
8 - interval:40,
9 - tween:function linearTween(delta) { return delta }
10 - }
11 -
12 - this.init = function(animationFunction, opts) {
13 - this._animationFunction = animationFunction
14 - opts = extend(opts, defaults)
15 - this._duration = opts.duration
16 - this._interval = opts.interval
17 - this._tween = opts.tween
18 - this._onDone = opts.onDone
19 - }
20 -
21 - this.start = function(reverse) {
22 - this._playing = true
23 - this._startT = new Date().getTime()
24 - this._reverse = reverse
25 - this._onInterval()
26 - this._intervalID = setInterval(bind(this, this._onInterval), this._interval)
27 - }
28 -
29 - this.stop = function() {
30 - this._playing = false
31 - clearInterval(this._intervalID)
32 - }
33 -
34 - this.isGoing = function() { return this._playing }
35 -
36 - this._onInterval = function() {
37 - var deltaT = new Date().getTime() - this._startT,
38 - duration = this._duration
39 - if (deltaT >= duration) {
40 - this.stop()
41 - this._animationFunction(this._tween(this._reverse ? 0 : 1))
42 - if (this._onDone) { this._onDone() }
43 - return
44 - }
45 - var delta = deltaT / duration
46 - if (this._reverse) { delta = 1 - delta }
47 - this._animationFunction(this._tween(delta))
48 - }
49 -})
50 -
51 -// Easing equation function for elastic tween: http://code.google.com/p/kawanet/source/browse/lang/as3/KTween/trunk/src/net/kawa/tween/easing/Elastic.as
52 -module.exports.elasticEaseOut = function(delta) {
53 - var x = 1 - delta,
54 - elasticity = 0.25
55 - value = 1 - Math.pow(x, 4) + x * x * Math.sin(delta * delta * Math.PI * elasticity)
56 - return value
57 -}
1 -v0.1.39
2 -+ Stop using Changelog. See `git log`
3 -
4 -v0.1.38
5 -+ implement parallel
6 -+ implement asyncEach
7 -+ implement asyncMap
8 -+ implement nextTick
9 -
10 -v0.1.37
11 -+ implemented waitFor
12 -+ implemented rand
13 -+ other improvements
14 -
15 -v0.1.35
16 -+ Better touch detection
17 -
18 -v0.1.34
19 -+ Better Promises
20 -+ Small fix in time.js
21 -
22 -v0.1.33
23 -+ extend now uses copy instead of create
24 -
25 -v0.1.32
26 -+ implement blockFunction.addBlock
27 -
28 -v0.1.31
29 -+ Beefed up proto.js
30 -
31 -v0.1.30
32 -+ Improved throttle
33 -
34 -v0.1.29
35 -+ import base64
36 -+ Many other changes...
37 -
38 -v0.1.28
39 -+ implement repeat
40 -+ implement deepEqual
41 -+ implement proto
42 -+ improved client detection in client.js
43 -
44 -v0.1.27
45 -+ make client a proper class, and add the beginnins to OS user-agent parsing
46 -+ improve url.js - enable getting and setting the hash/query params
47 -+ implement merge
48 -+ Add client.isMobile
49 -
50 -v0.1.26
51 -+ add client.name and client.is[IPhone, IPad, IPod]
52 -
53 -v0.1.25
54 -+ fix cookie.remove
55 -+ implement create
56 -+ implement arrayToObject
57 -+ implement defineGetter
58 -
59 -v0.1.24
60 -+ implement cookie
61 -+ move dom/* into ui library ui.js
62 -+ implement Animation
63 -+ add json, from JSON2 https://github.com/douglascrockford/JSON-js
64 -+ xhr improvements
65 -+ implement url
66 -+ implement trim
67 -+ implement isArguments
68 -+ use native isArray if available
69 -+ add @kaleb to contributors
70 -
71 -v0.1.23
72 -+ rename class _init to init
73 -+ add support for mixins
74 -+ implement Promise
75 -+ implement invokeWith
76 -+ implement recall
77 -+ implement Publisher mixin
78 -+ implement dom
79 -+ implement client
80 -+ implement popup
81 -
82 -v0.1.22
83 -+ implement ui/Component#_off
84 -+ implement ui/Component#_makeDraggable - publishes 'drag' and 'drop' events, both with a data object describing the drag
85 -+ implement throttle
86 -+ change implementation of delay to actually delay, rather than throttle
87 -+ Improved ui/Component event normalization (notably mousewheel)
88 -+ Implement browser
89 -+ Implement math.round
90 -
91 -v0.1.21
92 -+ start implementing std/time
93 -+ implement copy - shallow object/array copying, with a flag for deep copying
94 -+ implement keys
95 -+ implement flatten
96 -+ clean up xhr code
97 -+ fix xhr bug where callback would not get called for empty responses
98 -
99 -
100 -v0.1.20
101 -+ ui/Component API cleanup
102 -+ implement ui/Component display, hide and show
103 -+ fix ui/Component addClass/hasClass/removeClass/toggleClass
104 -+ better xhr error checking and xhr object cleanup
105 -+ implement invoke
106 -+ rename pick to filter. deprecate pick, but keep it around for now
107 -+ give Logger alert email functionality
108 -+ Fix delay
109 -+ fix ui/Input defaultValue class name mixup
110 -
111 -v0.1.19
112 -+ Add xhr option not to encode values
113 -+ Rename ui/Component#_dom to dom
114 -+ Fix xhr get requests without a ? in the URL
115 -+ fix context bug in delay
116 -
117 -v0.1.18
118 -+ implement delay
119 -+ implement Logger
120 -+ implement ui/Component
121 -+ implement ui/Select
122 -+ implement ui/Input
123 -
124 -v0.1.16
125 -+ Allow for passing in a context to each and map
126 -
127 -v0.1.15
128 -+ JSON.stringify xhr query parameters
129 -+ Use JSON.parse rather than eval to parse responses. Much safer :)
130 -
131 -v0.1.14
132 -+ implement xhr
133 -+ implement Publisher
134 -
135 -v0.1.12
136 -+ enable e.g. require('std/curry')
137 -
138 -v0.1.11
139 -+ add MIT license
140 -+ implement curry
141 -
142 -v0.1.10
143 -+ implement slice
144 -
145 -v0.1.9
146 -+ implement strip, for stripping off the whitespace of strings
147 -+ implement pick, for picking items out of an array
148 -
149 -v0.1.8
150 -+ fix stupid mistake
151 -
152 -v0.1.7
153 -+ import pack, unpack, crc32 and utf8_encode functions from phpjs
154 -+ move function files into lib
155 -
156 -v0.1.6
157 -+ extend now returns the first argument, or a new object if first argument is null
158 -
159 -v0.1.5
160 -+ fix bind when second argument is a string
161 -
162 -v0.1.4
163 -+ implement extend
164 -
165 -v0.1.3
166 -+ call class initializer functions _init rather than initialize
167 -
168 -v0.1.2
169 -+ implement Class
170 -
171 -v0.1.1
172 -+ implement isArray
173 -+ implement each
174 -+ implement map
175 -
176 -v0.1.0
177 -+ Implement bind
178 -+ Publish on npm as std
179 -
1 -/* Example usage:
2 -
3 - var UIComponent = Class(function() {
4 - this.init = function() { ... }
5 - this.create = function() { ... this.createDOM() ... }
6 - })
7 -
8 - var PublisherMixin = {
9 - init: function(){ ... },
10 - publish_: function() { ... }
11 - }
12 -
13 - var Button = Class(UIComponent, PublisherMixin, function(supr) {
14 - this.init = function(opts) {
15 - // call UIComponents init method, with the passed in arguments
16 - supr(this, 'init', arguments) // or, UIComponent.constructor.prototype.init.apply(this, arguments)
17 - this.color_ = opts && opts.color
18 - }
19 -
20 - // createDOM overwrites abstract method from parent class UIComponent
21 - this.createDOM = function() {
22 - this.getElement().onclick = bind(this, function(e) {
23 - // this.publish_ is a method added to Button by the Publisher mixin
24 - this.publish_('Click', e)
25 - })
26 - }
27 - })
28 -
29 -*/
30 -module.exports = function Class(/* optParent, optMixin1, optMixin2, ..., proto */) {
31 - var args = arguments,
32 - numOptArgs = args.length - 1,
33 - mixins = []
34 -
35 - // the prototype function is always the last argument
36 - var proto = args[numOptArgs]
37 -
38 - // if there's more than one argument, then the first argument is the parent class
39 - if (numOptArgs) {
40 - var parent = args[0]
41 - if (parent) { proto.prototype = parent.prototype }
42 - }
43 -
44 - for (var i=1; i < numOptArgs; i++) { mixins.push(arguments[i]) }
45 -
46 - // cls is the actual class function. Classes may implement this.init = function(){ ... },
47 - // which gets called upon instantiation
48 - var cls = function() {
49 - if(this.init) { this.init.apply(this, arguments) }
50 - for (var i=0, mixin; mixin = mixins[i]; i++) {
51 - if (mixin.init) { mixin.init.apply(this) }
52 - }
53 - }
54 -
55 - // the proto function gets called with the supr function as an argument. supr climbs the
56 - // inheritence chain, looking for the named method
57 - cls.prototype = new proto(function supr(context, method, args) {
58 - var target = parent
59 - while(target = target.prototype) {
60 - if(target[method]) {
61 - return target[method].apply(context, args || [])
62 - }
63 - }
64 - throw new Error('supr: parent method ' + method + ' does not exist')
65 - })
66 -
67 - // add all mixins' properties to the class' prototype object
68 - for (var i=0, mixin; mixin = mixins[i]; i++) {
69 - for (var propertyName in mixin) {
70 - if (!mixin.hasOwnProperty(propertyName) || propertyName == 'init') { continue }
71 - if (cls.prototype.hasOwnProperty(propertyName)) {
72 - throw new Error('Mixin property "'+propertyName+'" already exists on class')
73 - }
74 - cls.prototype[propertyName] = mixin[propertyName]
75 - }
76 - }
77 -
78 - cls.prototype.constructor = cls
79 - return cls
80 -}
1 -Copyright (c) 2011 Marcus Westin
2 -
3 -Permission is hereby granted, free of charge, to any person
4 -obtaining a copy of this software and associated documentation
5 -files (the "Software"), to deal in the Software without
6 -restriction, including without limitation the rights to use,
7 -copy, modify, merge, publish, distribute, sublicense, and/or sell
8 -copies of the Software, and to permit persons to whom the
9 -Software is furnished to do so, subject to the following
10 -conditions:
11 -
12 -The above copyright notice and this permission notice shall be
13 -included in all copies or substantial portions of the Software.
14 -
15 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 -OTHER DEALINGS IN THE SOFTWARE.
1 -var proto = require('./proto'),
2 - bind = require('./bind')
3 -
4 -module.exports = proto(null,
5 - function(waitForNum, callback) {
6 - this._waitingFor = waitForNum
7 - this._callbacks = []
8 - this._results = []
9 - this._error = null
10 - if (callback) { this.add(callback) }
11 - }, {
12 - add: function(callback) {
13 - if (!this._waitingFor) {
14 - this._notify(callback)
15 - } else {
16 - this._callbacks.push(callback)
17 - }
18 - },
19 - getResponder: function() {
20 - return bind(this, function(err, res) {
21 - if (err) { this.fail(err) }
22 - else { this.fulfill(res) }
23 - })
24 - },
25 - fulfill: function(result) {
26 - if (!this._waitingFor) { throw new Error('ListPromise fulfilled too many times') }
27 - this._results.push(result)
28 - if (!--this._waitingFor) {
29 - this._notifyAll()
30 - }
31 - },
32 - fail: function(error) {
33 - this._error = error
34 - this._notifyAll()
35 - },
36 - _notifyAll: function() {
37 - if (!this._callbacks) { return }
38 - for (var i=0; i<this._callbacks.length; i++) {
39 - this._notify(this._callbacks[i])
40 - }
41 - delete this._callbacks
42 - },
43 - _notify: function(callback) {
44 - callback(this._error, !this._error && this._results)
45 - }
46 - }
47 -)
1 -var std = require('std')
2 -
3 -// TODO Send email on error
4 -module.exports = std.Class(function() {
5 -
6 - var defaults = {
7 - name: 'Logger'
8 - }
9 -
10 - this.init = function(opts) {
11 - if (typeof opts == 'string') { opts = { name:opts } }
12 - opts = std.extend(opts, defaults)
13 - this._name = opts.name
14 - this._emailQueue = []
15 - }
16 -
17 - this.log = function() {
18 - this._consoleLog(std.slice(arguments))
19 - }
20 -
21 - this.error = function(err) {
22 - var message = this._message(err.stack)
23 - this._consoleLog(message)
24 - if (emailAlertSettings) {
25 - this._emailQueue.push(message)
26 - this._scheduleEmailDispatch()
27 - }
28 - }
29 -
30 - this._message = function(message) {
31 - return [this._name, new Date().getTime(), message]
32 - }
33 -
34 - this._consoleLog = function(messageParts) {
35 - console.log(joinParts(messageParts))
36 - }
37 -
38 - this._scheduleEmailDispatch = std.delay(function() {
39 - var mail = require('mail'),
40 - messages = std.map(this._emailQueue, joinParts).join('\n\n'),
41 - s = emailAlertSettings,
42 - from = [s.username, '@', s.domain].join(''),
43 - to = [s.alert, '+', this._name.replace(/\s/g, '_'), '@', s.domain].join('')
44 -
45 - this._emailQueue = []
46 -
47 - var message = new mail.Message({ from:from, to:to, subject: this._name + ' alert' })
48 - message.body(messages)
49 -
50 - var client = mail.createClient({ host:s.host, username:s.username + '@' + s.domain, password:s.password })
51 - client.on('error', std.bind(function(err) {
52 - this._consoleLog(this._message('EMAIL ALERT ERROR ' + err + ' ' + err.stack))
53 - client.end()
54 - }))
55 -
56 - var transactionID = new Date().getTime()
57 - this._consoleLog(this._message('START ALERT EMAIL TRANSACTION ' + transactionID))
58 - var transaction = client.mail(message.sender(), message.recipients())
59 - transaction.on('ready', std.bind(this, function() {
60 - transaction.end(message.toString())
61 - this._consoleLog(this._message('END ALERT EMAIL TRANSACTION ' + transactionID))
62 - transaction.on('end', std.bind(this, function() {
63 - this._consoleLog(this._message('ALERT EMAIL TRANSACTION ' + transactionID + ' COMPLETED'))
64 - client.quit()
65 - }))
66 - }))
67 - }, 10000) // Send at most one email per 10 seconds
68 -})
69 -
70 -function joinParts(arr) { return arr.join(' | ') }
71 -
72 -var emailAlertSettings = null
73 -module.exports.setupAlerts = function(s) {
74 - emailAlertSettings = {
75 - domain: s.domain,
76 - host: s.host,
77 - username: s.username,
78 - password: s.password,
79 - alert: s.alert
80 - }
81 -}
1 -var Class = require('./Class'),
2 - invokeWith = require('./invokeWith'),
3 - slice = require('./slice'),
4 - each = require('./each'),
5 - bind = require('./bind')
6 -
7 -module.exports = Class(function() {
8 - this.init = function(callback) {
9 - this._dependants = []
10 - this._fulfillment = null
11 - if (callback) { this.add(callback) }
12 - }
13 -
14 - this.add = function(callback) {
15 - if (this._fulfillment) { callback.apply(this, this._fulfillment) }
16 - else { this._dependants.push(callback) }
17 - return this
18 - }
19 -
20 - this.fulfill = function(/* arg1, arg2, ...*/) {
21 - if (this._fulfillment) { throw new Error('Promise fulfilled twice') }
22 - this._fulfillment = slice(arguments)
23 - each(this._dependants, invokeWith.apply(this, this._fulfillment))
24 - delete this._dependants
25 - return this
26 - }
27 -
28 - this.nextTickAdd = function(callback) {
29 - setTimeout(bind(this, this.add, callback), 0)
30 - }
31 -
32 - this.getCallback = function() {
33 - return this._callback || (this._callback = bind(this, this.handle))
34 - }
35 -
36 - this.handle = function(err, result) {
37 - if (err) { this.fail(err) }
38 - else { this.fulfill(result) }
39 - }
40 -})
1 -var Class = require('./Class'),
2 - bind = require('./bind'),
3 - slice = require('./slice')
4 -
5 -module.exports = Class(function() {
6 -
7 - this.init = function() {
8 - this._subscribers = {}
9 - }
10 -
11 - this.on = this.subscribe = function(signal, fn) {
12 - var subscribers = this._subscribers[signal]
13 - if (!subscribers) { subscribers = this._subscribers[signal] = [] }
14 - subscribers.push(fn)
15 - return this
16 - }
17 -
18 - this._publish = function(signal) {
19 - var args = slice(arguments, 1),
20 - subscribers = this._subscribers[signal]
21 - if (!signal || !subscribers) { return this }
22 - for (var i=0; i<subscribers.length; i++) {
23 - subscribers[i].apply(this, args)
24 - }
25 - return this
26 - }
27 -})
28 -
1 -std
2 -===
3 -
4 -Standard library javascript functionality
5 -
6 -Acknowledgements
7 -----------------
8 -
9 -- The following functions are taken from phpjs - https://github.com/kvz/phpjs, http://phpjs.org/pages/license: pack, unpack, crc32, utf8_encode
10 -- dom.getOffset is lifted from jQuery with some modification
11 -- dom.getWindowScroll is modified from http://stackoverflow.com/questions/1567327/using-jquery-to-get-elements-position-relative-to-viewport, which is based on a quirksmode.org snippet
12 -- json.js taken from https://github.com/douglascrockford/JSON-js
13 -- trim taken from http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/string/string.js?r=2
14 -- The following functions are taken from nodeunit - https://github.com/caolan/nodeunit, https://github.com/caolan/nodeunit/blob/master/LICENSE: deepEqual
15 -- base64.js implementation taken from @dankogai's https://github.com/dankogai/js-base64, MIT licensed
16 -
1 -module.exports = function arrayToObject(arr) {
2 - var obj = {}
3 - for (var i=0; i<arr.length; i++) { obj[arr[i]] = true }
4 - return obj
5 -}
...\ No newline at end of file ...\ No newline at end of file
1 -// Largely adapted from nodeunit
2 -/*!
3 - * Nodeunit
4 - * https://github.com/caolan/nodeunit
5 - * Copyright (c) 2010 Caolan McMahon
6 - * MIT Licensed
7 - *
8 - * json2.js
9 - * http://www.JSON.org/json2.js
10 - * Public Domain.
11 - * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
12 - */
13 -
14 -var isArguments = require('../isArguments'),
15 - slice = require('../slice'),
16 - keys = require('../keys')
17 -
18 -var deepEqual = module.exports = function(actual, expected) {
19 - // 7.1. All identical values are equivalent, as determined by ===.
20 - if (actual === expected) {
21 - return true;
22 - // 7.2. If the expected value is a Date object, the actual value is
23 - // equivalent if it is also a Date object that refers to the same time.
24 - } else if (actual instanceof Date && expected instanceof Date) {
25 - return actual.getTime() === expected.getTime();
26 -
27 - // 7.3. Other pairs that do not both pass typeof value == "object",
28 - // equivalence is determined by ==.
29 - } else if (typeof actual != 'object' && typeof expected != 'object') {
30 - return actual == expected;
31 -
32 - // 7.4. For all other Object pairs, including Array objects, equivalence is
33 - // determined by having the same number of owned properties (as verified
34 - // with Object.prototype.hasOwnProperty.call), the same set of keys
35 - // (although not necessarily the same order), equivalent values for every
36 - // corresponding key, and an identical "prototype" property. Note: this
37 - // accounts for both named and indexed properties on Arrays.
38 - } else {
39 - return objEquiv(actual, expected);
40 - }
41 -}
42 -
43 -function isUndefinedOrNull (value) {
44 - return value === null || value === undefined;
45 -}
46 -
47 -function objEquiv (a, b) {
48 - if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
49 - return false;
50 - // an identical "prototype" property.
51 - if (a.prototype !== b.prototype) return false;
52 - //~~~I've managed to break Object.keys through screwy arguments passing.
53 - // Converting to array solves the problem.
54 - if (isArguments(a)) {
55 - if (!isArguments(b)) {
56 - return false;
57 - }
58 - a = slice(a, 0);
59 - b = slice(b, 0);
60 - return deepEqual(a, b);
61 - }
62 - try{
63 - var ka = keys(a),
64 - kb = keys(b),
65 - key, i;
66 - } catch (e) {//happens when one is a string literal and the other isn't
67 - return false;
68 - }
69 - // having the same number of owned properties (keys incorporates hasOwnProperty)
70 - if (ka.length != kb.length)
71 - return false;
72 - //the same set of keys (although not necessarily the same order),
73 - ka.sort();
74 - kb.sort();
75 - //~~~cheap key test
76 - for (i = ka.length - 1; i >= 0; i--) {
77 - if (ka[i] != kb[i])
78 - return false;
79 - }
80 - //equivalent values for every corresponding key, and
81 - //~~~possibly expensive deep test
82 - for (i = ka.length - 1; i >= 0; i--) {
83 - key = ka[i];
84 - if (!deepEqual(a[key], b[key] ))
85 - return false;
86 - }
87 - return true;
88 -}
1 -var nextTick = require('std/nextTick')
2 -
3 -module.exports = function asyncEach(items, opts) {
4 - var finish = opts.finish
5 - if (!items.length) { return finish(null, []) }
6 -
7 - var parallel = opts.parallel
8 - if (parallel === true) { parallel = items.length }
9 - if (!parallel) { parallel = 1 }
10 - if (parallel > waitingFor) { parallel = waitingFor }
11 -
12 - var nextIndex = 0
13 - var result = []
14 - var errorResult = null
15 - var waitingFor = items.length
16 - var context = opts.context || this
17 -
18 - var iterator = module.exports.makeIterator(context, opts.iterate)
19 -
20 - function processNextItem() {
21 - if (!waitingFor) {
22 - return finish.call(context, null)
23 - }
24 - var iterationIndex = nextIndex
25 - if (iterationIndex == items.length) {
26 - // no more processing to be done - just wait for the remaining parallel requests to finish
27 - return
28 - }
29 - nextIndex += 1
30 - nextTick(function() {
31 - iterator(items[iterationIndex], iterationIndex, iteratorCallback)
32 - })
33 - }
34 -
35 - function iteratorCallback(err) {
36 - if (errorResult) { return }
37 - if (err) {
38 - errorResult = err
39 - finish.call(context, err, null)
40 - } else {
41 - waitingFor -= 1
42 - processNextItem()
43 - }
44 - }
45 -
46 - // starts `parallel` number of functions processing the array
47 - for (var parallelI=0; parallelI<parallel; parallelI++) {
48 - processNextItem()
49 - }
50 -}
51 -
52 -module.exports.makeIterator = function(context, iterate) {
53 - // the given iterator may expect arguments (item + i + next), or just (item + i)
54 - if (iterate.length == 3) {
55 - return function iterator3(item, i, next) {
56 - iterate.call(context, item, i, next)
57 - }
58 - } else {
59 - return function iterator2(item, i, next) {
60 - iterate.call(context, item, next)
61 - }
62 - }
63 -}
1 -var asyncEach = require('std/asyncEach')
2 -
3 -module.exports = function asyncMap(items, opts) {
4 - var result = []
5 - result.length = items.length
6 - var includeNullValues = !opts.filterNulls
7 - var context = opts.context || this
8 -
9 - var originalIterate = asyncEach.makeIterator(context, opts.iterate)
10 - opts.iterate = function(value, index, next) {
11 - originalIterate(value, index, function(err, iterationResult) {
12 - if (err) { return next(err) }
13 - if (includeNullValues || (iterationResult != null)) {
14 - result[index] = iterationResult
15 - }
16 - next()
17 - })
18 - }
19 -
20 - var originalFinish = opts.finish
21 - opts.finish = function(err) {
22 - if (err) { return originalFinish.call(context, err) }
23 - originalFinish.call(context, null, result)
24 - }
25 -
26 - asyncEach(items, opts)
27 -}
1 -/*
2 - * $Id: base64.js,v 1.2 2011/12/27 14:34:49 dankogai Exp dankogai $
3 - *
4 - * Licensed under the MIT license.
5 - * http://www.opensource.org/licenses/mit-license.php
6 - *
7 - */
8 -
9 -(function(global){
10 -
11 -if (global.Base64) return;
12 -
13 -var b64chars
14 - = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
15 -var b64tab = function(bin){
16 - var t = {};
17 - for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
18 - return t;
19 -}(b64chars);
20 -
21 -var sub_toBase64 = function(m){
22 - var n = (m.charCodeAt(0) << 16)
23 - | (m.charCodeAt(1) << 8)
24 - | (m.charCodeAt(2) );
25 - return b64chars.charAt( n >>> 18)
26 - + b64chars.charAt((n >>> 12) & 63)
27 - + b64chars.charAt((n >>> 6) & 63)
28 - + b64chars.charAt( n & 63);
29 -};
30 -
31 -var toBase64 = function(bin){
32 - if (bin.match(/[^\x00-\xFF]/)) throw 'unsupported character found' ;
33 - var padlen = 0;
34 - while(bin.length % 3) {
35 - bin += '\0';
36 - padlen++;
37 - };
38 - var b64 = bin.replace(/[\x00-\xFF]{3}/g, sub_toBase64);
39 - if (!padlen) return b64;
40 - b64 = b64.substr(0, b64.length - padlen);
41 - while(padlen--) b64 += '=';
42 - return b64;
43 -};
44 -
45 -var btoa = global.btoa || toBase64;
46 -
47 -var sub_fromBase64 = function(m){
48 - var n = (b64tab[ m.charAt(0) ] << 18)
49 - | (b64tab[ m.charAt(1) ] << 12)
50 - | (b64tab[ m.charAt(2) ] << 6)
51 - | (b64tab[ m.charAt(3) ]);
52 - return String.fromCharCode( n >> 16 )
53 - + String.fromCharCode( (n >> 8) & 0xff )
54 - + String.fromCharCode( n & 0xff );
55 -};
56 -
57 -var fromBase64 = function(b64){
58 - b64 = b64.replace(/[^A-Za-z0-9\+\/]/g, '');
59 - var padlen = 0;
60 - while(b64.length % 4){
61 - b64 += 'A';
62 - padlen++;
63 - }
64 - var bin = b64.replace(/[A-Za-z0-9\+\/]{4}/g, sub_fromBase64);
65 - if (padlen >= 2)
66 - bin = bin.substring(0, bin.length - [0,0,2,1][padlen]);
67 - return bin;
68 -};
69 -
70 -var atob = global.atob || fromBase64;
71 -
72 -var re_char_nonascii = /[^\x00-\x7F]/g;
73 -
74 -var sub_char_nonascii = function(m){
75 - var n = m.charCodeAt(0);
76 - return n < 0x800 ? String.fromCharCode(0xc0 | (n >>> 6))
77 - + String.fromCharCode(0x80 | (n & 0x3f))
78 - : String.fromCharCode(0xe0 | ((n >>> 12) & 0x0f))
79 - + String.fromCharCode(0x80 | ((n >>> 6) & 0x3f))
80 - + String.fromCharCode(0x80 | (n & 0x3f))
81 - ;
82 -};
83 -
84 -var utob = function(uni){
85 - return uni.replace(re_char_nonascii, sub_char_nonascii);
86 -};
87 -
88 -var re_bytes_nonascii
89 - = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
90 -
91 -var sub_bytes_nonascii = function(m){
92 - var c0 = m.charCodeAt(0);
93 - var c1 = m.charCodeAt(1);
94 - if(c0 < 0xe0){
95 - return String.fromCharCode(((c0 & 0x1f) << 6) | (c1 & 0x3f));
96 - }else{
97 - var c2 = m.charCodeAt(2);
98 - return String.fromCharCode(
99 - ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f)
100 - );
101 - }
102 -};
103 -
104 -var btou = function(bin){
105 - return bin.replace(re_bytes_nonascii, sub_bytes_nonascii);
106 -};
107 -
108 -global.exports = {
109 - fromBase64:fromBase64,
110 - toBase64:toBase64,
111 - atob:atob,
112 - btoa:btoa,
113 - utob:utob,
114 - btou:btou,
115 - encode:function(u){ return btoa(utob(u)) },
116 - encodeURI:function(u){
117 - return btoa(utob(u)).replace(/[+\/]/g, function(m0){
118 - return m0 == '+' ? '-' : '_';
119 - }).replace(/=+$/, '');
120 - },
121 - decode:function(a){
122 - return btou(atob(a.replace(/[-_]/g, function(m0){
123 - return m0 == '-' ? '+' : '/';
124 - })));
125 - }
126 -};
127 -
128 -})(module);
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - Example usage:
3 -
4 - function Client() {
5 - this._socket = new Connection()
6 - this._socket.open()
7 - this._socket.on('connected', bind(this, '_log', 'connected!'))
8 - this._socket.on('connected', bind(this, 'disconnect'))
9 - }
10 -
11 - Client.prototype._log = function(message) {
12 - console.log('client says:', message)
13 - }
14 -
15 - Client.prototype.disconnect = function() {
16 - this._socket.disconnect()
17 - }
18 -
19 - Example usage:
20 -
21 - var Toolbar = Class(function() {
22 -
23 - this.init = function() {
24 - this._buttonWasClicked = false
25 - }
26 -
27 - this.addButton = function(clickHandler) {
28 - this._button = new Button()
29 - this._button.on('Click', bind(this, '_onButtonClick', clickHandler))
30 - }
31 -
32 - this._onButtonClick = function(clickHandler) {
33 - this._buttonWasClicked = true
34 - clickHandler()
35 - }
36 -
37 - })
38 -
39 -*/
40 -var slice = require('./slice')
41 -
42 -module.exports = function bind(context, method /* curry1, curry2, ... curryN */) {
43 - if (typeof method == 'string') { method = context[method] }
44 - var curryArgs = slice(arguments, 2)
45 - return function bound() {
46 - var invocationArgs = slice(arguments)
47 - return method.apply(context, curryArgs.concat(invocationArgs))
48 - }
49 -}
50 -
1 -/*
2 - Block a function from being called by adding and removing any number of blocks.
3 - Excellent for waiting on parallel asynchronous operations.
4 - A blocked function starts out with exactly one block
5 -
6 - Example usage:
7 -
8 - http.createServer(function(req, res) {
9 - var sendResponse = blockFunction(function() {
10 - res.writeHead(204)
11 - res.end()
12 - })
13 - var queries = parseQueries(req.url)
14 - for (var i=0; i<queries.length; i++) {
15 - sendResponse.addBlock()
16 - handleQuery(queries[i]; function() {
17 - sendResponse.removeBlock()
18 - })
19 - }
20 - })
21 -*/
22 -
23 -module.exports = function blockFunction(fn) {
24 - var numBlocks = 0
25 - return {
26 - addBlock:function() {
27 - numBlocks++
28 - return this
29 - },
30 - removeBlock:function() {
31 - if (!fn) { throw new Error("Block removed after function was unblocked") }
32 - if (!numBlocks) { throw new Error("Tried to remove a block that was never added") }
33 - if (--numBlocks) { return }
34 - fn(null)
35 - delete fn
36 - return this
37 - },
38 - fail:function(error) {
39 - fn(error)
40 - delete fn
41 - return this
42 - }
43 - }
44 -}
1 -// From http://www.quirksmode.org/js/detect.html - thanks PPK!
2 -module.exports = {
3 - init: function () {
4 - this.name = this.searchString(this.dataBrowser) || "An unknown browser";
5 - this.version = this.searchVersion(navigator.userAgent)
6 - || this.searchVersion(navigator.appVersion)
7 - || "unknown";
8 - this.OS = this.searchString(this.dataOS) || "unknown";
9 - this["is" + this.name] = this.version
10 - },
11 - searchString: function (data) {
12 - for (var i=0;i<data.length;i++) {
13 - var dataString = data[i].string;
14 - var dataProp = data[i].prop;
15 - this.versionSearchString = data[i].versionSearch || data[i].identity;
16 - if (dataString) {
17 - if (dataString.indexOf(data[i].subString) != -1)
18 - return data[i].identity;
19 - }
20 - else if (dataProp)
21 - return data[i].identity;
22 - }
23 - },
24 - searchVersion: function (dataString) {
25 - var index = dataString.indexOf(this.versionSearchString);
26 - if (index == -1) return;
27 - return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
28 - },
29 - dataBrowser: [
30 - {
31 - string: navigator.userAgent,
32 - subString: "Chrome",
33 - identity: "Chrome"
34 - },
35 - { string: navigator.userAgent,
36 - subString: "OmniWeb",
37 - versionSearch: "OmniWeb/",
38 - identity: "OmniWeb"
39 - },
40 - {
41 - string: navigator.vendor,
42 - subString: "Apple",
43 - identity: "Safari",
44 - versionSearch: "Version"
45 - },
46 - {
47 - prop: window.opera,
48 - identity: "Opera"
49 - },
50 - {
51 - string: navigator.vendor,
52 - subString: "iCab",
53 - identity: "iCab"
54 - },
55 - {
56 - string: navigator.vendor,
57 - subString: "KDE",
58 - identity: "Konqueror"
59 - },
60 - {
61 - string: navigator.userAgent,
62 - subString: "Firefox",
63 - identity: "Firefox"
64 - },
65 - {
66 - string: navigator.vendor,
67 - subString: "Camino",
68 - identity: "Camino"
69 - },
70 - { // for newer Netscapes (6+)
71 - string: navigator.userAgent,
72 - subString: "Netscape",
73 - identity: "Netscape"
74 - },
75 - {
76 - string: navigator.userAgent,
77 - subString: "MSIE",
78 - identity: "Explorer",
79 - versionSearch: "MSIE"
80 - },
81 - {
82 - string: navigator.userAgent,
83 - subString: "Gecko",
84 - identity: "Mozilla",
85 - versionSearch: "rv"
86 - },
87 - { // for older Netscapes (4-)
88 - string: navigator.userAgent,
89 - subString: "Mozilla",
90 - identity: "Netscape",
91 - versionSearch: "Mozilla"
92 - }
93 - ],
94 - dataOS : [
95 - {
96 - string: navigator.platform,
97 - subString: "Win",
98 - identity: "Windows"
99 - },
100 - {
101 - string: navigator.platform,
102 - subString: "Mac",
103 - identity: "Mac"
104 - },
105 - {
106 - string: navigator.userAgent,
107 - subString: "iPhone",
108 - identity: "iPhone/iPod"
109 - },
110 - {
111 - string: navigator.platform,
112 - subString: "Linux",
113 - identity: "Linux"
114 - }
115 - ]
116 -
117 -};
118 -
119 -module.exports.init();
1 -module.exports = function check(a, b) {
2 - if (a != b) { throw new Error("Not equal " + a + " & " + b) }
3 -}
...\ No newline at end of file ...\ No newline at end of file
1 -var Class = require('./Class')
2 -
3 -var mobileRegex = /mobile/i;
4 -
5 -var Client = Class(function() {
6 -
7 - this.init = function(userAgent) {
8 - this._userAgent = userAgent
9 - this._parseBrowser()
10 - this._parseDevice()
11 - }
12 -
13 - this._parseBrowser = function() {
14 - (this.isChrome = this._isBrowser('Chrome'))
15 - || (this.isFirefox = this._isBrowser('Firefox'))
16 - || (this.isIE = this._isBrowser('MSIE'))
17 - || (this.isSkyfire = this._isBrowser('Skyfire', 'Skyfire')) // Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17 Skyfire/2.0
18 - || (this.isSafari = this._isBrowser('Safari', 'Version'))
19 - || (this.isOpera = this._isBrowser('Opera', 'Version'))
20 -
21 - if (this.isOpera) {
22 - if (this._userAgent.match('Opera Mini')) { this.isOperaMini = true } // Opera mini is a cloud browser - Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/ADR-1110171336; U; en) Presto/2.9.201 Version/11.50
23 - }
24 -
25 - if (this.isIE) {
26 - this.isChromeFrame = !!this._userAgent.match('chromeframe')
27 - }
28 -
29 - try {
30 - document.createEvent("TouchEvent")
31 - this.isTouch = ('ontouchstart' in window)
32 - } catch (e) {
33 - this.isTouch = false
34 - }
35 - }
36 -
37 - this._parseDevice = function() {
38 - ((this.isIPhone = this._is('iPhone'))
39 - || (this.isIPad = this._is('iPad'))
40 - || (this.isIPod = this._is('iPod')))
41 -
42 - this.isAndroid = this._isBrowser('Android', 'Version')
43 - this.isIOS = (this.isIPhone || this.isIPad || this.isIPod)
44 -
45 - if (this.isIOS) {
46 - var osVersionMatch = this._userAgent.match(/ OS ([\d_]+) /),
47 - osVersion = osVersionMatch ? osVersionMatch[1] : '',
48 - parts = osVersion.split('_'),
49 - version = { major:parseInt(parts[0]), minor:parseInt(parts[1]), patch:parseInt(parts[2]) }
50 -
51 - this.os = { version:version }
52 - }
53 -
54 - if (this.isOpera && this._userAgent.match('Opera Mobi')) { this.isMobile = true } // Opera mobile is a proper mobile browser - Opera/9.80 (Android; Opera Mini/6.5.26571/ 26.1069; U; en) Presto/2.8.119 Version/10.54
55 - if (this.isSkyfire) { this.isMobile = true }
56 - if (this.isIPhone) { this.isMobile = true }
57 - if (this.isAndroid) {
58 - if (this._userAgent.match(mobileRegex)) { this.isMobile = true }
59 - if (this.isFirefox) { this.isMobile = true } // Firefox Android browsers do not seem to have an indication that it's a phone vs a tablet: Mozilla/5.0 (Android; Linux armv7l; rv:7.0.1) Gecko/20110928 Firefox/7.0.1 Fennec/7.0.1
60 - }
61 -
62 - this.isTablet = this.isIPad
63 - }
64 -
65 - this.isQuirksMode = function(doc) {
66 - // in IE, if compatMode is undefined (early ie) or explicitly set to BackCompat, we're in quirks
67 - return this.isIE && (!doc.compatMode || doc.compatMode == 'BackCompat')
68 - }
69 -
70 - this._isBrowser = function(name, versionString) {
71 - if (!this._is(name)) { return false }
72 - var agent = this._userAgent,
73 - index = agent.indexOf(versionString || name)
74 - this.version = parseFloat(agent.substr(index + (versionString || name).length + 1))
75 - this.name = name
76 - return true
77 - }
78 -
79 - this._is = function(name) {
80 - return (this._userAgent.indexOf(name) >= 0)
81 - }
82 -})
83 -
84 -if (typeof window != 'undefined') { module.exports = new Client(window.navigator.userAgent) }
85 -else { module.exports = {} }
86 -
87 -module.exports.parse = function(userAgent) { return new Client(userAgent) }
1 -module.exports = function clip(val, min, max) {
2 - return Math.max(Math.min(val, max), min)
3 -}
1 -module.exports.get = function(name) {
2 - var regex = new RegExp(
3 - '(^|(; ))' + // beginning of document.cookie, or "; " which signifies the beginning of a new cookie
4 - name +
5 - '=([^;]*)') // the value of the cookie, matched up until a ";" or the end of the string
6 -
7 - var match = document.cookie.match(regex),
8 - value = match && match[3]
9 - return value && decodeURIComponent(value)
10 -}
11 -
12 -module.exports.set = function(name, value, duration) {
13 - if (duration === undefined) { duration = (365 * 24 * 60 * 60 * 1000) } // one year
14 - var date = (duration instanceof Date ? duration : (duration < 0 ? null : new Date(new Date().getTime() + duration))),
15 - expires = date ? "expires=" + date.toGMTString() + '; ' : '',
16 - cookieName = name + '=' + encodeURIComponent(value) + '; ',
17 - domain = 'domain='+document.domain+'; ',
18 - path = 'path=/; '
19 -
20 - document.cookie = cookieName + expires + domain + path
21 -}
22 -
23 -module.exports.isEnabled = function() {
24 - var name = '__test__cookie' + new Date().getTime()
25 - module.exports.set(name, 1)
26 - var isEnabled = !!module.exports.get(name)
27 - module.exports.remove(name)
28 - return isEnabled
29 -}
30 -
31 -module.exports.remove = function(name) {
32 - module.exports.set(name, "", new Date(1))
33 -}
1 -var each = require('./each'),
2 - isArray = require('./isArray')
3 -
4 -module.exports = function copy(obj, deep) {
5 - var result = isArray(obj) ? [] : {}
6 - each(obj, function(val, key) {
7 - result[key] = (deep && typeof val == 'object') ? copy(val, deep) : val
8 - })
9 - return result
10 -}
1 -// https://github.com/kvz/phpjs/raw/2ae4292a8629d6007eae26298bd19339ef97957e/functions/strings/crc32.js
2 -// MIT License http://phpjs.org/pages/license
3 -
4 -var utf8_encode = require('./utf8_encode')
5 -
6 -module.exports = function crc32 (str) {
7 - // http://kevin.vanzonneveld.net
8 - // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
9 - // + improved by: T0bsn
10 - // - depends on: utf8_encode
11 - // * example 1: crc32('Kevin van Zonneveld');
12 - // * returns 1: 1249991249
13 - str = utf8_encode(str);
14 - var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";
15 -
16 - var crc = 0;
17 - var x = 0;
18 - var y = 0;
19 -
20 - crc = crc ^ (-1);
21 - for (var i = 0, iTop = str.length; i < iTop; i++) {
22 - y = (crc ^ str.charCodeAt(i)) & 0xFF;
23 - x = "0x" + table.substr(y * 9, 8);
24 - crc = (crc >>> 8) ^ x;
25 - }
26 -
27 - return crc ^ (-1);
28 -}
1 -// Thanks Douglas Crockford! http://javascript.crockford.com/prototypal.html
2 -module.exports = function create(obj, extendWithProperties) {
3 - function extendObject(result, props) {
4 - for (var key in props) {
5 - if (!props.hasOwnProperty(key)) { continue }
6 - result[key] = props[key]
7 - }
8 - return result
9 - }
10 - if (typeof Object.create == 'function') {
11 - module.exports = function nativeCreate(obj, extendWithProperties) {
12 - return extendObject(Object.create(obj), extendWithProperties)
13 - }
14 - } else {
15 - module.exports = function shimCreate(obj, extendWithProperties) {
16 - function F() {}
17 - F.prototype = obj
18 - return extendObject(new F(), extendWithProperties)
19 - }
20 - }
21 - return module.exports(obj, extendWithProperties)
22 -}
1 -var slice = require('./slice')
2 -
3 -module.exports = function curry(fn /* arg1, arg2, ... argN */) {
4 - var curryArgs = slice(arguments, 1)
5 - return function curried() {
6 - var invocationArgs = slice(arguments)
7 - return fn.apply(this, curryArgs.concat(invocationArgs))
8 - }
9 -}
10 -
1 -module.exports = function(object, propertyName, getter) {
2 - module.exports = object.defineGetter ? _w3cDefineGetter
3 - : object.__defineGetter__ ? _interimDefineGetter
4 - : Object.defineProperty ? _ie8DefineGetter
5 - : function() { throw 'defineGetter not supported' }
6 - return module.exports(object, propertyName, getter)
7 -}
8 -
9 -function defineGetter(object, propertyName, getter) {
10 - var fn = object.defineGetter ? _w3cDefineGetter
11 - : object.__defineGetter__ ? _interimDefineGetter
12 - : Object.defineProperty ? _ie8DefineGetter
13 - : function() { throw new Error('defineGetter is not supported') }
14 -
15 - module.exports.defineGetter = fn
16 - fn.apply(this, arguments)
17 -}
18 -
19 -var _w3cDefineGetter = function(object, propertyName, getter) {
20 - object.defineGetter(propertyName, getter)
21 -}
22 -
23 -var _interimDefineGetter = function(object, propertyName, getter) {
24 - object.__defineGetter__(propertyName, getter)
25 -}
26 -
27 -var _ie8DefineGetter = function(object, propertyName, getter) {
28 - Object.defineProperty(object, propertyName, { value:getter, enumerable:true, configurable:true })
29 -}
1 -/*
2 - Delay the execution of a function.
3 - If the function gets called multiple times during a delay, the delayed function gets invoced only once,
4 - with the arguments of the most recent invocation. This is useful for expensive functions that should
5 - not be called multiple times during a short time interval, e.g. rendering
6 -
7 - Example usage:
8 -
9 - Class(UIComponent, function() {
10 - this.render = delay(function() {
11 - ...
12 - }, 250) // render at most 4 times per second
13 - })
14 -
15 - // Bath messages into a single email
16 - var EmailBatcher = Class(function() {
17 - this.init = function() {
18 - this._queue = []
19 - }
20 -
21 - this.send = function(email) {
22 - this._queue.push(email)
23 - this._scheduleDispatch()
24 - }
25 -
26 - this._scheduleDispatch = delay(function() {
27 - smtp.send(this._queue.join('\n\n'))
28 - this._queue = []
29 - }, 5000) // send emails at most once every 5 seconds
30 - })
31 -*/
32 -module.exports = function delay(fn, delayBy) {
33 - if (typeof delayBy != 'number') { delayBy = 50 }
34 - var timeoutName = '__delayTimeout__' + (++module.exports._unique)
35 - var delayedFunction = function delayed() {
36 - if (this[timeoutName]) {
37 - clearTimeout(this[timeoutName])
38 - }
39 - var args = arguments, self = this
40 - this[timeoutName] = setTimeout(function fireDelayed() {
41 - clearTimeout(self[timeoutName])
42 - delete self[timeoutName]
43 - fn.apply(self, args)
44 - }, delayBy)
45 - }
46 - delayedFunction.cancel = function() {
47 - clearTimeout(this[timeoutName])
48 - }
49 - return delayedFunction
50 -}
51 -module.exports._unique = 0
1 -module.exports = function delayed(amount, fn) {
2 - if (!fn) {
3 - fn = amount
4 - amount = 0
5 - }
6 - return function() {
7 - var self = this
8 - var args = arguments
9 - setTimeout(function() { fn.apply(self, args) }, amount)
10 - }
11 -}
1 -var isArray = require('./isArray'),
2 - isArguments = require('./isArguments')
3 -
4 -module.exports = function(items, ctx, fn) {
5 - if (!items) { return }
6 - if (!fn) {
7 - fn = ctx
8 - ctx = this
9 - }
10 - if (isArray(items) || isArguments(items)) {
11 - for (var i=0; i < items.length; i++) {
12 - fn.call(ctx, items[i], i)
13 - }
14 - } else {
15 - for (var key in items) {
16 - if (!items.hasOwnProperty(key)) { continue }
17 - fn.call(ctx, items[key], key)
18 - }
19 - }
20 -}
1 -/*
2 - Example usage:
3 -
4 - var A = Class(function() {
5 -
6 - var defaults = {
7 - foo: 'cat',
8 - bar: 'dum'
9 - }
10 -
11 - this.init = function(opts) {
12 - opts = std.extend(opts, defaults)
13 - this._foo = opts.foo
14 - this._bar = opts.bar
15 - }
16 -
17 - this.getFoo = function() {
18 - return this._foo
19 - }
20 -
21 - this.getBar = function() {
22 - return this._bar
23 - }
24 - })
25 -
26 - var a = new A({ bar:'sim' })
27 - a.getFoo() == 'cat'
28 - a.getBar() == 'sim'
29 -*/
30 -
31 -var copy = require('./copy')
32 -
33 -module.exports = function extend(target, extendWith) {
34 - target = copy(target)
35 - for (var key in extendWith) {
36 - if (typeof target[key] != 'undefined') { continue }
37 - target[key] = extendWith[key]
38 - }
39 - return target
40 -}
1 -/*
2 - Example usage:
3 - filter([1,2,0,'',false,null,undefined]) // -> [1,2,0,'',false]
4 - filter([1,2,3], this, function(val, index) { val == 1 }) // -> [1]
5 -*/
6 -var each = require('./each')
7 -var isArray = require('./isArray')
8 -
9 -module.exports = function filter(arr, ctx, fn) {
10 - if (arguments.length == 2) {
11 - fn = ctx
12 - ctx = this
13 - }
14 - if (!fn) {
15 - fn = falseOrTruthy
16 - }
17 -
18 - var result
19 - if (isArray(arr)) {
20 - result = []
21 - each(arr, function(value, index) {
22 - if (!fn.call(ctx, value, index)) { return }
23 - result.push(value)
24 - })
25 - } else {
26 - result = {}
27 - each(arr, function(value, key) {
28 - if (!fn.call(ctx, value, key)) { return }
29 - result[key] = value
30 - })
31 - }
32 - return result
33 -}
34 -
35 -function falseOrTruthy(arg) {
36 - return !!arg || arg === false
37 -}
38 -
1 -module.exports = function find(items, fn) {
2 - if (!items) { return null }
3 - for (var i=0; i<items.length; i++) {
4 - if (fn(items[i], i)) { return items[i] }
5 - }
6 - return null
7 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = function flatten(arr) {
2 - return Array.prototype.concat.apply([], arr)
3 -}
1 -module.exports = function flip(obj) {
2 - var res = {}
3 - for (var key in obj) { res[obj[key]] = key }
4 - return res
5 -}
1 -module.exports = {
2 - Class: require('./Class'),
3 - bind: require('./bind'),
4 - curry: require('./curry'),
5 - throttle: require('./throttle'),
6 - delay: require('./delay'),
7 - invoke: require('./invoke'),
8 - isArray: require('./isArray'),
9 - each: require('./each'),
10 - map: require('./map'),
11 - pick: require('./filter'), // deprecated in favor of filter
12 - filter: require('./filter'),
13 - flatten: require('./flatten'),
14 - extend: require('./extend'),
15 - slice: require('./slice'),
16 - pack: require('./pack'),
17 - unpack: require('./unpack'),
18 - crc32: require('./crc32'),
19 - strip: require('./strip')
20 -}
1 -var each = require('std/each')
2 -
3 -module.exports = function inverse(obj) {
4 - var result = {}
5 - each(obj, function(val, key) { result[val] = key })
6 - return result
7 -}
1 -/*
2 - Example usage:
3 -
4 - var obj = {
5 - setTime: function(ts) { this._time = ts }
6 - }
7 - each([obj], call('setTime', 1000))
8 -*/
9 -
10 -var slice = require('./slice')
11 -module.exports = function call(methodName /*, curry1, ..., curryN */) {
12 - var curryArgs = slice(arguments, 1)
13 - return function futureCall(obj) {
14 - var fn = obj[methodName],
15 - args = curryArgs.concat(slice(arguments, 1))
16 - return fn.apply(obj, args)
17 - }
18 -}
19 -
1 -/*
2 - Example usage:
3 -
4 - var callbacks = [...],
5 - result = { ... }
6 - each(callbacks, invokeWith(result))
7 -*/
8 -
9 -var slice = require('./slice')
10 -module.exports = function invokeWith(/*, curry1, ..., curryN */) {
11 - var curryArgs = slice(arguments, 0)
12 - return function futureInvocation(fn) {
13 - var args = curryArgs.concat(slice(arguments, 1))
14 - return fn.apply(this, args)
15 - }
16 -}
17 -
1 -module.exports = function isArguments(obj) {
2 - return Object.prototype.toString.call(obj) == '[object Arguments]'
3 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = (function() {
2 - if (Array.isArray && Array.isArray.toString().match('\\[native code\\]')) {
3 - return function(obj) {
4 - return Array.isArray(obj)
5 - }
6 - } else {
7 - // thanks @kangax http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
8 - return function(obj) {
9 - return Object.prototype.toString.call(obj) == '[object Array]'
10 - }
11 - }
12 -})();
1 -module.exports = function isFunction(fn) {
2 - return Object.prototype.toString.call(fn) == '[object Function]'
3 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = function isObject(obj) {
2 - return Object.prototype.toString.call(obj) == '[object Object]'
3 -}
1 -/*
2 - http://www.JSON.org/json2.js
3 - 2011-02-23
4 -
5 - Public Domain.
6 -
7 - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
8 -
9 - See http://www.JSON.org/js.html
10 -
11 -
12 - This code should be minified before deployment.
13 - See http://javascript.crockford.com/jsmin.html
14 -
15 - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
16 - NOT CONTROL.
17 -
18 -
19 - This file creates a global JSON object containing two methods: stringify
20 - and parse.
21 -
22 - JSON.stringify(value, replacer, space)
23 - value any JavaScript value, usually an object or array.
24 -
25 - replacer an optional parameter that determines how object
26 - values are stringified for objects. It can be a
27 - function or an array of strings.
28 -
29 - space an optional parameter that specifies the indentation
30 - of nested structures. If it is omitted, the text will
31 - be packed without extra whitespace. If it is a number,
32 - it will specify the number of spaces to indent at each
33 - level. If it is a string (such as '\t' or '&nbsp;'),
34 - it contains the characters used to indent at each level.
35 -
36 - This method produces a JSON text from a JavaScript value.
37 -
38 - When an object value is found, if the object contains a toJSON
39 - method, its toJSON method will be called and the result will be
40 - stringified. A toJSON method does not serialize: it returns the
41 - value represented by the name/value pair that should be serialized,
42 - or undefined if nothing should be serialized. The toJSON method
43 - will be passed the key associated with the value, and this will be
44 - bound to the value
45 -
46 - For example, this would serialize Dates as ISO strings.
47 -
48 - Date.prototype.toJSON = function (key) {
49 - function f(n) {
50 - // Format integers to have at least two digits.
51 - return n < 10 ? '0' + n : n;
52 - }
53 -
54 - return this.getUTCFullYear() + '-' +
55 - f(this.getUTCMonth() + 1) + '-' +
56 - f(this.getUTCDate()) + 'T' +
57 - f(this.getUTCHours()) + ':' +
58 - f(this.getUTCMinutes()) + ':' +
59 - f(this.getUTCSeconds()) + 'Z';
60 - };
61 -
62 - You can provide an optional replacer method. It will be passed the
63 - key and value of each member, with this bound to the containing
64 - object. The value that is returned from your method will be
65 - serialized. If your method returns undefined, then the member will
66 - be excluded from the serialization.
67 -
68 - If the replacer parameter is an array of strings, then it will be
69 - used to select the members to be serialized. It filters the results
70 - such that only members with keys listed in the replacer array are
71 - stringified.
72 -
73 - Values that do not have JSON representations, such as undefined or
74 - functions, will not be serialized. Such values in objects will be
75 - dropped; in arrays they will be replaced with null. You can use
76 - a replacer function to replace those with JSON values.
77 - JSON.stringify(undefined) returns undefined.
78 -
79 - The optional space parameter produces a stringification of the
80 - value that is filled with line breaks and indentation to make it
81 - easier to read.
82 -
83 - If the space parameter is a non-empty string, then that string will
84 - be used for indentation. If the space parameter is a number, then
85 - the indentation will be that many spaces.
86 -
87 - Example:
88 -
89 - text = JSON.stringify(['e', {pluribus: 'unum'}]);
90 - // text is '["e",{"pluribus":"unum"}]'
91 -
92 -
93 - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
94 - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
95 -
96 - text = JSON.stringify([new Date()], function (key, value) {
97 - return this[key] instanceof Date ?
98 - 'Date(' + this[key] + ')' : value;
99 - });
100 - // text is '["Date(---current time---)"]'
101 -
102 -
103 - JSON.parse(text, reviver)
104 - This method parses a JSON text to produce an object or array.
105 - It can throw a SyntaxError exception.
106 -
107 - The optional reviver parameter is a function that can filter and
108 - transform the results. It receives each of the keys and values,
109 - and its return value is used instead of the original value.
110 - If it returns what it received, then the structure is not modified.
111 - If it returns undefined then the member is deleted.
112 -
113 - Example:
114 -
115 - // Parse the text. Values that look like ISO date strings will
116 - // be converted to Date objects.
117 -
118 - myData = JSON.parse(text, function (key, value) {
119 - var a;
120 - if (typeof value === 'string') {
121 - a =
122 -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
123 - if (a) {
124 - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
125 - +a[5], +a[6]));
126 - }
127 - }
128 - return value;
129 - });
130 -
131 - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
132 - var d;
133 - if (typeof value === 'string' &&
134 - value.slice(0, 5) === 'Date(' &&
135 - value.slice(-1) === ')') {
136 - d = new Date(value.slice(5, -1));
137 - if (d) {
138 - return d;
139 - }
140 - }
141 - return value;
142 - });
143 -
144 -
145 - This is a reference implementation. You are free to copy, modify, or
146 - redistribute.
147 -*/
148 -
149 -/*jslint evil: true, strict: false, regexp: false */
150 -
151 -/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
152 - call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
153 - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
154 - lastIndex, length, parse, prototype, push, replace, slice, stringify,
155 - test, toJSON, toString, valueOf
156 -*/
157 -
158 -
159 -// Create a JSON object only if one does not already exist. We create the
160 -// methods in a closure to avoid creating global variables.
161 -
162 -var JSON;
163 -if (!JSON) {
164 - JSON = {};
165 -}
166 -
167 -(function () {
168 - "use strict";
169 -
170 - function f(n) {
171 - // Format integers to have at least two digits.
172 - return n < 10 ? '0' + n : n;
173 - }
174 -
175 - if (typeof Date.prototype.toJSON !== 'function') {
176 -
177 - Date.prototype.toJSON = function (key) {
178 -
179 - return isFinite(this.valueOf()) ?
180 - this.getUTCFullYear() + '-' +
181 - f(this.getUTCMonth() + 1) + '-' +
182 - f(this.getUTCDate()) + 'T' +
183 - f(this.getUTCHours()) + ':' +
184 - f(this.getUTCMinutes()) + ':' +
185 - f(this.getUTCSeconds()) + 'Z' : null;
186 - };
187 -
188 - String.prototype.toJSON =
189 - Number.prototype.toJSON =
190 - Boolean.prototype.toJSON = function (key) {
191 - return this.valueOf();
192 - };
193 - }
194 -
195 - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
196 - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
197 - gap,
198 - indent,
199 - meta = { // table of character substitutions
200 - '\b': '\\b',
201 - '\t': '\\t',
202 - '\n': '\\n',
203 - '\f': '\\f',
204 - '\r': '\\r',
205 - '"' : '\\"',
206 - '\\': '\\\\'
207 - },
208 - rep;
209 -
210 -
211 - function quote(string) {
212 -
213 -// If the string contains no control characters, no quote characters, and no
214 -// backslash characters, then we can safely slap some quotes around it.
215 -// Otherwise we must also replace the offending characters with safe escape
216 -// sequences.
217 -
218 - escapable.lastIndex = 0;
219 - return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
220 - var c = meta[a];
221 - return typeof c === 'string' ? c :
222 - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
223 - }) + '"' : '"' + string + '"';
224 - }
225 -
226 -
227 - function str(key, holder) {
228 -
229 -// Produce a string from holder[key].
230 -
231 - var i, // The loop counter.
232 - k, // The member key.
233 - v, // The member value.
234 - length,
235 - mind = gap,
236 - partial,
237 - value = holder[key];
238 -
239 -// If the value has a toJSON method, call it to obtain a replacement value.
240 -
241 - if (value && typeof value === 'object' &&
242 - typeof value.toJSON === 'function') {
243 - value = value.toJSON(key);
244 - }
245 -
246 -// If we were called with a replacer function, then call the replacer to
247 -// obtain a replacement value.
248 -
249 - if (typeof rep === 'function') {
250 - value = rep.call(holder, key, value);
251 - }
252 -
253 -// What happens next depends on the value's type.
254 -
255 - switch (typeof value) {
256 - case 'string':
257 - return quote(value);
258 -
259 - case 'number':
260 -
261 -// JSON numbers must be finite. Encode non-finite numbers as null.
262 -
263 - return isFinite(value) ? String(value) : 'null';
264 -
265 - case 'boolean':
266 - case 'null':
267 -
268 -// If the value is a boolean or null, convert it to a string. Note:
269 -// typeof null does not produce 'null'. The case is included here in
270 -// the remote chance that this gets fixed someday.
271 -
272 - return String(value);
273 -
274 -// If the type is 'object', we might be dealing with an object or an array or
275 -// null.
276 -
277 - case 'object':
278 -
279 -// Due to a specification blunder in ECMAScript, typeof null is 'object',
280 -// so watch out for that case.
281 -
282 - if (!value) {
283 - return 'null';
284 - }
285 -
286 -// Make an array to hold the partial results of stringifying this object value.
287 -
288 - gap += indent;
289 - partial = [];
290 -
291 -// Is the value an array?
292 -
293 - if (Object.prototype.toString.apply(value) === '[object Array]') {
294 -
295 -// The value is an array. Stringify every element. Use null as a placeholder
296 -// for non-JSON values.
297 -
298 - length = value.length;
299 - for (i = 0; i < length; i += 1) {
300 - partial[i] = str(i, value) || 'null';
301 - }
302 -
303 -// Join all of the elements together, separated with commas, and wrap them in
304 -// brackets.
305 -
306 - v = partial.length === 0 ? '[]' : gap ?
307 - '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
308 - '[' + partial.join(',') + ']';
309 - gap = mind;
310 - return v;
311 - }
312 -
313 -// If the replacer is an array, use it to select the members to be stringified.
314 -
315 - if (rep && typeof rep === 'object') {
316 - length = rep.length;
317 - for (i = 0; i < length; i += 1) {
318 - if (typeof rep[i] === 'string') {
319 - k = rep[i];
320 - v = str(k, value);
321 - if (v) {
322 - partial.push(quote(k) + (gap ? ': ' : ':') + v);
323 - }
324 - }
325 - }
326 - } else {
327 -
328 -// Otherwise, iterate through all of the keys in the object.
329 -
330 - for (k in value) {
331 - if (Object.prototype.hasOwnProperty.call(value, k)) {
332 - v = str(k, value);
333 - if (v) {
334 - partial.push(quote(k) + (gap ? ': ' : ':') + v);
335 - }
336 - }
337 - }
338 - }
339 -
340 -// Join all of the member texts together, separated with commas,
341 -// and wrap them in braces.
342 -
343 - v = partial.length === 0 ? '{}' : gap ?
344 - '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
345 - '{' + partial.join(',') + '}';
346 - gap = mind;
347 - return v;
348 - }
349 - }
350 -
351 -// If the JSON object does not yet have a stringify method, give it one.
352 -
353 - if (typeof JSON.stringify !== 'function') {
354 - JSON.stringify = function (value, replacer, space) {
355 -
356 -// The stringify method takes a value and an optional replacer, and an optional
357 -// space parameter, and returns a JSON text. The replacer can be a function
358 -// that can replace values, or an array of strings that will select the keys.
359 -// A default replacer method can be provided. Use of the space parameter can
360 -// produce text that is more easily readable.
361 -
362 - var i;
363 - gap = '';
364 - indent = '';
365 -
366 -// If the space parameter is a number, make an indent string containing that
367 -// many spaces.
368 -
369 - if (typeof space === 'number') {
370 - for (i = 0; i < space; i += 1) {
371 - indent += ' ';
372 - }
373 -
374 -// If the space parameter is a string, it will be used as the indent string.
375 -
376 - } else if (typeof space === 'string') {
377 - indent = space;
378 - }
379 -
380 -// If there is a replacer, it must be a function or an array.
381 -// Otherwise, throw an error.
382 -
383 - rep = replacer;
384 - if (replacer && typeof replacer !== 'function' &&
385 - (typeof replacer !== 'object' ||
386 - typeof replacer.length !== 'number')) {
387 - throw new Error('JSON.stringify');
388 - }
389 -
390 -// Make a fake root object containing our value under the key of ''.
391 -// Return the result of stringifying the value.
392 -
393 - return str('', {'': value});
394 - };
395 - }
396 -
397 -
398 -// If the JSON object does not yet have a parse method, give it one.
399 -
400 - if (typeof JSON.parse !== 'function') {
401 - JSON.parse = function (text, reviver) {
402 -
403 -// The parse method takes a text and an optional reviver function, and returns
404 -// a JavaScript value if the text is a valid JSON text.
405 -
406 - var j;
407 -
408 - function walk(holder, key) {
409 -
410 -// The walk method is used to recursively walk the resulting structure so
411 -// that modifications can be made.
412 -
413 - var k, v, value = holder[key];
414 - if (value && typeof value === 'object') {
415 - for (k in value) {
416 - if (Object.prototype.hasOwnProperty.call(value, k)) {
417 - v = walk(value, k);
418 - if (v !== undefined) {
419 - value[k] = v;
420 - } else {
421 - delete value[k];
422 - }
423 - }
424 - }
425 - }
426 - return reviver.call(holder, key, value);
427 - }
428 -
429 -
430 -// Parsing happens in four stages. In the first stage, we replace certain
431 -// Unicode characters with escape sequences. JavaScript handles many characters
432 -// incorrectly, either silently deleting them, or treating them as line endings.
433 -
434 - text = String(text);
435 - cx.lastIndex = 0;
436 - if (cx.test(text)) {
437 - text = text.replace(cx, function (a) {
438 - return '\\u' +
439 - ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
440 - });
441 - }
442 -
443 -// In the second stage, we run the text against regular expressions that look
444 -// for non-JSON patterns. We are especially concerned with '()' and 'new'
445 -// because they can cause invocation, and '=' because it can cause mutation.
446 -// But just to be safe, we want to reject all unexpected forms.
447 -
448 -// We split the second stage into 4 regexp operations in order to work around
449 -// crippling inefficiencies in IE's and Safari's regexp engines. First we
450 -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
451 -// replace all simple value tokens with ']' characters. Third, we delete all
452 -// open brackets that follow a colon or comma or that begin the text. Finally,
453 -// we look to see that the remaining characters are only whitespace or ']' or
454 -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
455 -
456 - if (/^[\],:{}\s]*$/
457 - .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
458 - .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
459 - .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
460 -
461 -// In the third stage we use the eval function to compile the text into a
462 -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
463 -// in JavaScript: it can begin a block or an object literal. We wrap the text
464 -// in parens to eliminate the ambiguity.
465 -
466 - j = eval('(' + text + ')');
467 -
468 -// In the optional fourth stage, we recursively walk the new structure, passing
469 -// each name/value pair to a reviver function for possible transformation.
470 -
471 - return typeof reviver === 'function' ?
472 - walk({'': j}, '') : j;
473 - }
474 -
475 -// If the text is not JSON parseable, then a SyntaxError is thrown.
476 -
477 - throw new SyntaxError('JSON.parse');
478 - };
479 - }
480 -}());
481 -
482 -module.exports = JSON
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = function keys(obj) {
2 - if (Object.keys) {
3 - module.exports = function(obj) {
4 - return Object.keys(obj)
5 - }
6 - } else {
7 - module.exports = function(obj) {
8 - for (var k in obj) {
9 - if (obj.hasOwnProperty(k)) { keys.push(k) }
10 - }
11 - }
12 - }
13 - return module.exports(obj)
14 -}
1 -var isArray = require('./isArray')
2 -
3 -module.exports = function(arr) {
4 - if (!isArray(arr)) { return null }
5 - return arr[arr.length - 1]
6 -}
...\ No newline at end of file ...\ No newline at end of file
1 -var each = require('./each')
2 -
3 -module.exports = function(items, ctx, fn) {
4 - var result = []
5 - if (!fn) {
6 - fn = ctx
7 - ctx = this
8 - }
9 - each(items, ctx, function(item, key) {
10 - result.push(fn.call(ctx, item, key))
11 - })
12 - return result
13 -}
1 -module.exports = function merge(objA, objB) {
2 - var result = {},
3 - key
4 - for (key in objA) { result[key] = objA[key] }
5 - for (key in objB) { result[key] = objB[key] }
6 - return result
7 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = (function(global) {
2 - if (typeof process != 'undefined' && process.nextTick) { return process.nextTick }
3 -
4 - var requestAnimationFrame = global.requestAnimationFrame || global.mozRequestAnimationFrame || global.webkitRequestAnimationFrame || global.msRequestAnimationFrame
5 - if (requestAnimationFrame) { return makeTicker(requestAnimationFrame) }
6 -
7 - return makeTicker(setTimeout)
8 -
9 - function makeTicker(tickFn) {
10 - return function nextTick(callback) {
11 - tickFn(function() { callback() }) // Do not pass through arguments from setTimeout/requestAnimationFrame
12 - }
13 - }
14 -}(this))
1 -module.exports = function once(fn) {
2 - var timeout
3 - var args
4 - return function() {
5 - args = arguments
6 - if (timeout) { return }
7 - timeout = setTimeout(function() {
8 - fn.apply(this, args)
9 - timeout = null
10 - args = null
11 - }, 0)
12 - }
13 -}
1 -module.exports = function options(opts, defaults) {
2 - if (!opts) { opts = {} }
3 - var result = {}
4 - if (!opts) { opts = {} }
5 - for (var key in defaults) {
6 - result[key] = typeof opts[key] != 'undefined' ? opts[key] : defaults[key]
7 - }
8 - return result
9 -}
1 -// https://github.com/kvz/phpjs/raw/2ae4292a8629d6007eae26298bd19339ef97957e/functions/misc/pack.js
2 -// MIT License http://phpjs.org/pages/license
3 -
4 -module.exports = function pack (format) {
5 - // http://kevin.vanzonneveld.net
6 - // + original by: Tim de Koning (http://www.kingsquare.nl)
7 - // + parts by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
8 - // + bugfixed by: Tim de Koning (http://www.kingsquare.nl)
9 - // % note 1: Float encoding by: Jonas Raoni Soares Silva
10 - // % note 2: Home: http://www.kingsquare.nl/blog/12-12-2009/13507444
11 - // % note 3: Feedback: phpjs-pack@kingsquare.nl
12 - // % note 4: 'machine dependent byte order and size' aren't
13 - // % note 4: applicable for JavaScript; pack works as on a 32bit,
14 - // % note 4: little endian machine
15 - // * example 1: pack('nvc*', 0x1234, 0x5678, 65, 66);
16 - // * returns 1: '4xVAB'
17 - var formatPointer = 0,
18 - argumentPointer = 1,
19 - result = '',
20 - argument = '',
21 - i = 0,
22 - r = [],
23 - instruction, quantifier, word, precisionBits, exponentBits, extraNullCount;
24 -
25 - // vars used by float encoding
26 - var bias, minExp, maxExp, minUnnormExp, status, exp, len, bin, signal, n, intPart, floatPart, lastBit, rounded, j, k, tmpResult;
27 -
28 - while (formatPointer < format.length) {
29 - instruction = format[formatPointer];
30 - quantifier = '';
31 - formatPointer++;
32 - while ((formatPointer < format.length) && (format[formatPointer].match(/[\d\*]/) !== null)) {
33 - quantifier += format[formatPointer];
34 - formatPointer++;
35 - }
36 - if (quantifier === '') {
37 - quantifier = '1';
38 - }
39 -
40 - // Now pack variables: 'quantifier' times 'instruction'
41 - switch (instruction) {
42 - case 'a':
43 - // NUL-padded string
44 - case 'A':
45 - // SPACE-padded string
46 - if (typeof arguments[argumentPointer] === 'undefined') {
47 - throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments');
48 - } else {
49 - argument = String(arguments[argumentPointer]);
50 - }
51 - if (quantifier === '*') {
52 - quantifier = argument.length;
53 - }
54 - for (i = 0; i < quantifier; i++) {
55 - if (typeof argument[i] === 'undefined') {
56 - if (instruction === 'a') {
57 - result += String.fromCharCode(0);
58 - } else {
59 - result += ' ';
60 - }
61 - } else {
62 - result += argument[i];
63 - }
64 - }
65 - argumentPointer++;
66 - break;
67 - case 'h':
68 - // Hex string, low nibble first
69 - case 'H':
70 - // Hex string, high nibble first
71 - if (typeof arguments[argumentPointer] === 'undefined') {
72 - throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments');
73 - } else {
74 - argument = arguments[argumentPointer];
75 - }
76 - if (quantifier === '*') {
77 - quantifier = argument.length;
78 - }
79 - if (quantifier > argument.length) {
80 - throw new Error('Warning: pack() Type ' + instruction + ': not enough characters in string');
81 - }
82 - for (i = 0; i < quantifier; i += 2) {
83 - // Always get per 2 bytes...
84 - word = argument[i];
85 - if (((i + 1) >= quantifier) || typeof(argument[i + 1]) === 'undefined') {
86 - word += '0';
87 - } else {
88 - word += argument[i + 1];
89 - }
90 - // The fastest way to reverse?
91 - if (instruction === 'h') {
92 - word = word[1] + word[0];
93 - }
94 - result += String.fromCharCode(parseInt(word, 16));
95 - }
96 - argumentPointer++;
97 - break;
98 -
99 - case 'c':
100 - // signed char
101 - case 'C':
102 - // unsigned char
103 - // c and C is the same in pack
104 - if (quantifier === '*') {
105 - quantifier = arguments.length - argumentPointer;
106 - }
107 - if (quantifier > (arguments.length - argumentPointer)) {
108 - throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
109 - }
110 -
111 - for (i = 0; i < quantifier; i++) {
112 - result += String.fromCharCode(arguments[argumentPointer]);
113 - argumentPointer++;
114 - }
115 - break;
116 -
117 - case 's':
118 - // signed short (always 16 bit, machine byte order)
119 - case 'S':
120 - // unsigned short (always 16 bit, machine byte order)
121 - case 'v':
122 - // s and S is the same in pack
123 - if (quantifier === '*') {
124 - quantifier = arguments.length - argumentPointer;
125 - }
126 - if (quantifier > (arguments.length - argumentPointer)) {
127 - throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
128 - }
129 -
130 - for (i = 0; i < quantifier; i++) {
131 - result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
132 - result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
133 - argumentPointer++;
134 - }
135 - break;
136 -
137 - case 'n':
138 - // unsigned short (always 16 bit, big endian byte order)
139 - if (quantifier === '*') {
140 - quantifier = arguments.length - argumentPointer;
141 - }
142 - if (quantifier > (arguments.length - argumentPointer)) {
143 - throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
144 - }
145 -
146 - for (i = 0; i < quantifier; i++) {
147 - result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
148 - result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
149 - argumentPointer++;
150 - }
151 - break;
152 -
153 - case 'i':
154 - // signed integer (machine dependent size and byte order)
155 - case 'I':
156 - // unsigned integer (machine dependent size and byte order)
157 - case 'l':
158 - // signed long (always 32 bit, machine byte order)
159 - case 'L':
160 - // unsigned long (always 32 bit, machine byte order)
161 - case 'V':
162 - // unsigned long (always 32 bit, little endian byte order)
163 - if (quantifier === '*') {
164 - quantifier = arguments.length - argumentPointer;
165 - }
166 - if (quantifier > (arguments.length - argumentPointer)) {
167 - throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
168 - }
169 -
170 - for (i = 0; i < quantifier; i++) {
171 - result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
172 - result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
173 - result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF);
174 - result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF);
175 - argumentPointer++;
176 - }
177 -
178 - break;
179 - case 'N':
180 - // unsigned long (always 32 bit, big endian byte order)
181 - if (quantifier === '*') {
182 - quantifier = arguments.length - argumentPointer;
183 - }
184 - if (quantifier > (arguments.length - argumentPointer)) {
185 - throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
186 - }
187 -
188 - for (i = 0; i < quantifier; i++) {
189 - result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF);
190 - result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF);
191 - result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
192 - result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
193 - argumentPointer++;
194 - }
195 - break;
196 -
197 - case 'f':
198 - // float (machine dependent size and representation)
199 - case 'd':
200 - // double (machine dependent size and representation)
201 - // version based on IEEE754
202 - precisionBits = 23;
203 - exponentBits = 8;
204 - if (instruction === 'd') {
205 - precisionBits = 52;
206 - exponentBits = 11;
207 - }
208 -
209 - if (quantifier === '*') {
210 - quantifier = arguments.length - argumentPointer;
211 - }
212 - if (quantifier > (arguments.length - argumentPointer)) {
213 - throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
214 - }
215 - for (i = 0; i < quantifier; i++) {
216 - argument = arguments[argumentPointer];
217 - bias = Math.pow(2, exponentBits - 1) - 1;
218 - minExp = -bias + 1;
219 - maxExp = bias;
220 - minUnnormExp = minExp - precisionBits;
221 - status = isNaN(n = parseFloat(argument)) || n === -Infinity || n === +Infinity ? n : 0;
222 - exp = 0;
223 - len = 2 * bias + 1 + precisionBits + 3;
224 - bin = new Array(len);
225 - signal = (n = status !== 0 ? 0 : n) < 0;
226 - n = Math.abs(n);
227 - intPart = Math.floor(n);
228 - floatPart = n - intPart;
229 -
230 - for (k = len; k;) {
231 - bin[--k] = 0;
232 - }
233 - for (k = bias + 2; intPart && k;) {
234 - bin[--k] = intPart % 2;
235 - intPart = Math.floor(intPart / 2);
236 - }
237 - for (k = bias + 1; floatPart > 0 && k; --floatPart) {
238 - (bin[++k] = ((floatPart *= 2) >= 1) - 0);
239 - }
240 - for (k = -1; ++k < len && !bin[k];) {}
241 -
242 - if (bin[(lastBit = precisionBits - 1 + (k = (exp = bias + 1 - k) >= minExp && exp <= maxExp ? k + 1 : bias + 1 - (exp = minExp - 1))) + 1]) {
243 - if (!(rounded = bin[lastBit])) {
244 - for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]) {}
245 - }
246 - for (j = lastBit + 1; rounded && --j >= 0;
247 - (bin[j] = !bin[j] - 0) && (rounded = 0)) {}
248 - }
249 -
250 - for (k = k - 2 < 0 ? -1 : k - 3; ++k < len && !bin[k];) {}
251 -
252 - if ((exp = bias + 1 - k) >= minExp && exp <= maxExp) {
253 - ++k;
254 - } else {
255 - if (exp < minExp) {
256 - if (exp !== bias + 1 - len && exp < minUnnormExp) { /*"encodeFloat::float underflow" */
257 - }
258 - k = bias + 1 - (exp = minExp - 1);
259 - }
260 - }
261 -
262 - if (intPart || status !== 0) {
263 - exp = maxExp + 1;
264 - k = bias + 2;
265 - if (status === -Infinity) {
266 - signal = 1;
267 - } else if (isNaN(status)) {
268 - bin[k] = 1;
269 - }
270 - }
271 -
272 - n = Math.abs(exp + bias);
273 - tmpResult = '';
274 -
275 - for (j = exponentBits + 1; --j;) {
276 - tmpResult = (n % 2) + tmpResult;
277 - n = n >>= 1;
278 - }
279 -
280 - n = 0;
281 - j = 0;
282 - k = (tmpResult = (signal ? '1' : '0') + tmpResult + bin.slice(k, k + precisionBits).join('')).length;
283 - r = [];
284 -
285 - for (; k;) {
286 - n += (1 << j) * tmpResult.charAt(--k);
287 - if (j === 7) {
288 - r[r.length] = String.fromCharCode(n);
289 - n = 0;
290 - }
291 - j = (j + 1) % 8;
292 - }
293 -
294 - r[r.length] = n ? String.fromCharCode(n) : '';
295 - result += r.join('');
296 - argumentPointer++;
297 - }
298 - break;
299 -
300 - case 'x':
301 - // NUL byte
302 - if (quantifier === '*') {
303 - throw new Error('Warning: pack(): Type x: \'*\' ignored');
304 - }
305 - for (i = 0; i < quantifier; i++) {
306 - result += String.fromCharCode(0);
307 - }
308 - break;
309 -
310 - case 'X':
311 - // Back up one byte
312 - if (quantifier === '*') {
313 - throw new Error('Warning: pack(): Type X: \'*\' ignored');
314 - }
315 - for (i = 0; i < quantifier; i++) {
316 - if (result.length === 0) {
317 - throw new Error('Warning: pack(): Type X:' + ' outside of string');
318 - } else {
319 - result = result.substring(0, result.length - 1);
320 - }
321 - }
322 - break;
323 -
324 - case '@':
325 - // NUL-fill to absolute position
326 - if (quantifier === '*') {
327 - throw new Error('Warning: pack(): Type X: \'*\' ignored');
328 - }
329 - if (quantifier > result.length) {
330 - extraNullCount = quantifier - result.length;
331 - for (i = 0; i < extraNullCount; i++) {
332 - result += String.fromCharCode(0);
333 - }
334 - }
335 - if (quantifier < result.length) {
336 - result = result.substring(0, quantifier);
337 - }
338 - break;
339 -
340 - default:
341 - throw new Error('Warning: pack() Type ' + instruction + ': unknown format code');
342 - }
343 - }
344 - if (argumentPointer < arguments.length) {
345 - throw new Error('Warning: pack(): ' + (arguments.length - argumentPointer) + ' arguments unused');
346 - }
347 -
348 - return result;
349 -}
1 -{
2 - "_from": "std@0.1.40",
3 - "_id": "std@0.1.40",
4 - "_inBundle": false,
5 - "_integrity": "sha1-Nnil9lCU2eG2teJu2/wCErg0K3E=",
6 - "_location": "/std",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "version",
10 - "registry": true,
11 - "raw": "std@0.1.40",
12 - "name": "std",
13 - "escapedName": "std",
14 - "rawSpec": "0.1.40",
15 - "saveSpec": null,
16 - "fetchSpec": "0.1.40"
17 - },
18 - "_requiredBy": [
19 - "/require"
20 - ],
21 - "_resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz",
22 - "_shasum": "3678a5f65094d9e1b6b5e26edbfc0212b8342b71",
23 - "_spec": "std@0.1.40",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\require",
25 - "author": {
26 - "name": "@marcuswestin"
27 - },
28 - "bugs": {
29 - "url": "https://github.com/marcuswestin/std.js/issues"
30 - },
31 - "bundleDependencies": false,
32 - "contributors": [
33 - {
34 - "name": "@kaleb"
35 - }
36 - ],
37 - "deprecated": false,
38 - "description": "javascript standard library",
39 - "directories": {
40 - "lib": "lib"
41 - },
42 - "engines": {
43 - "node": "*"
44 - },
45 - "homepage": "https://github.com/marcuswestin/std.js#readme",
46 - "name": "std",
47 - "repository": {
48 - "type": "git",
49 - "url": "git://github.com/marcuswestin/std.js.git"
50 - },
51 - "version": "0.1.40"
52 -}
1 -var asyncMap = require('std/asyncMap')
2 -var slice = require('std/slice')
3 -
4 -module.exports = function parallel(/* fn1, fn2, ..., finishFn */) {
5 - var parallelFunctions = slice(arguments)
6 - var finish = parallelFunctions.pop()
7 - asyncMap(parallelFunctions, {
8 - parallel:parallelFunctions.length,
9 - iterate:function(parallelFn, done) {
10 - parallelFn(done)
11 - },
12 - finish:function(err, mapResults) {
13 - if (err) { return finish(err) }
14 - finish.apply(this, [null].concat(mapResults))
15 - }
16 - })
17 -}
1 -var extend = require('./extend'),
2 - map = require('./map')
3 -
4 -module.exports = function(url, winID, opts) {
5 - opts = extend(opts, module.exports.defaults)
6 - if (!opts['left']) { opts['left'] = Math.round((screen.width - opts['width']) / 2) }
7 - if (!opts['top']) { opts['top'] = Math.round((screen.height - opts['height']) / 2) }
8 -
9 - var popupStr = map(opts, function(val, key) { return key+'='+val }).join(',')
10 -
11 - return window.open(url, winID, popupStr)
12 -}
13 -
14 -module.exports.defaults = {
15 - 'width': 600,
16 - 'height': 400,
17 - 'left': null,
18 - 'top': null,
19 - 'directories': 0,
20 - 'location': 1,
21 - 'menubar': 0,
22 - 'resizable': 0,
23 - 'scrollbars': 1,
24 - 'titlebar': 0,
25 - 'toolbar': 0
26 -}
1 -/*
2 - // Usage: proto(prototypeObj, intantiatingFn, properties)
3 -
4 - var base = {
5 - say:function(arg) { alert(arg) }
6 - }
7 -
8 - var person = proto(base,
9 - function(name) {
10 - this.name = name
11 - }, {
12 - greet:function(other) {
13 - this.say("hello "+other.name+", I'm "+this.name)
14 - }
15 - }
16 - )
17 -
18 - var marcus = person("marcus"),
19 - john = person("john")
20 -
21 - marcus.greet(john)
22 -*/
23 -
24 -var create = require('./create')
25 -
26 -var proto = module.exports = function proto(prototypeObject, instantiationFunction, propertiesToAdd) {
27 - // F is the function that is required in order to implement JS prototypical inheritence
28 - function F(args) {
29 - // When a new object is created, call the instantiation function
30 - return instantiationFunction.apply(this, args)
31 - }
32 - // The prototype object itself points to the passed-in prototypeObject,
33 - // but also has all the properties enumerated in propertiesToAdd
34 - F.prototype = prototypeObject ? create(prototypeObject, propertiesToAdd) : propertiesToAdd
35 -
36 - return function() {
37 - return new F(arguments)
38 - }
39 -}
1 -module.exports = function rand(floor, ceil) {
2 - return Math.floor(Math.random() * (ceil - floor + 1)) + floor
3 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = function recall(context, args) {
2 - var fn = args.callee
3 - return function() { return fn.apply(context, args); }
4 -}
1 -module.exports = function remove(arr, item) {
2 - if (!arr) { return }
3 - for (var i=0; i<arr.length; i++) {
4 - if (arr[i] != item) { continue }
5 - arr.splice(i, 1)
6 - return
7 - }
8 -}
1 -module.exports = function repeat(str, times) {
2 - if (times < 0) { return '' }
3 - return new Array(times + 1).join(str)
4 -}
1 -module.exports = function round(value, decimalPoints) {
2 - if (!(decimalPoints > 0)) { // (undefined < 0) == false, but (!(undefined > 0)) == true
3 - return Math.round(value)
4 - }
5 - var granularity = Math.pow(10, decimalPoints)
6 - return Math.round(value * granularity) / granularity
7 -}
1 -var create = require('./create'),
2 - options = require('./options'),
3 - parseUrl = require('./url').parse
4 -
5 -module.exports = function(opts) {
6 - opts = options(opts, { prefix:'/', default:'/' })
7 - opts.prefix = new RegExp('^'+opts.prefix)
8 - return create(router, {
9 - routes:{},
10 - errorHandlers:[],
11 - opts:opts
12 - })
13 -}
14 -
15 -var router = {
16 - add:function(routeName, handler) {
17 - var route = this.routes
18 - var parts = routeName.split('/')
19 - if (parts[0] != '') { throw new Error('Route much start with "/": '+ routeName) }
20 - parts.shift()
21 - for (var i=0; i<parts.length; i++) {
22 - var name = parts[i]
23 - var isVariable = (name[0] == ':')
24 - var key = isVariable ? ':' : name
25 - if (!route[key]) { route[key] = {} }
26 - route = route[key]
27 - if (i == parts.length - 1) {
28 - route.handler = handler
29 - }
30 - if (isVariable) {
31 - route.__paramName = name.substr(1)
32 - }
33 - }
34 - return this
35 - },
36 - error:function(handler) {
37 - this.errorHandlers.push(handler)
38 - return this
39 - },
40 - route:function(url) {
41 - url = parseUrl(url)
42 - var path = url.pathname
43 - if (this.opts.prefix) {
44 - path = path.replace(this.opts.prefix, '')
45 - }
46 - var params = url.getSearchParams()
47 - var route = this.routes
48 - var parts = path.split('/')
49 - parts.shift()
50 - for (var i=0; i<parts.length; i++) {
51 - var name = parts[i]
52 - if (route[':']) {
53 - route = route[':']
54 - params[route.__paramName] = name
55 - } else if (route[name]) {
56 - route = route[name]
57 - } else {
58 - return this._onError(path)
59 - }
60 - }
61 -
62 - if (typeof route.handler != 'function') {
63 - this._onError(path)
64 - } else {
65 - route.handler(params)
66 - }
67 - },
68 - _onError:function(url) {
69 - this.errorHandlers.forEach(function(handler) { handler(url) })
70 - }
71 -}
1 -/*
2 - Example usage:
3 -
4 - function log(category, arg1, arg2) { // arg3, arg4, ..., argN
5 - console.log('log category', category, std.slice(arguments, 1))
6 - }
7 -*/
8 -module.exports = function args(args, offset, length) {
9 - if (typeof length == 'undefined') { length = args.length }
10 - return Array.prototype.slice.call(args, offset || 0, length)
11 -}
12 -
1 -var stripRegex = /^\s*(.*?)\s*$/
2 -module.exports = function(str) {
3 - return str.match(stripRegex)[1]
4 -}
5 -
1 -module.exports = function sum(list, fn) {
2 - if (!list) { return 0 }
3 - var total = 0
4 - for (var i=0; i<list.length; i++) {
5 - total += fn(list[i])
6 - }
7 - return total
8 -}
1 -var unique = 0
2 -module.exports = function throttle(fn, delay) {
3 - if (typeof delay != 'number') { delay = 50 }
4 - var timeoutName = '__throttleTimeout__' + (++unique)
5 - return function throttled() {
6 - if (this[timeoutName]) { return }
7 - var args = arguments, self = this
8 - this[timeoutName] = setTimeout(function fireDelayed() {
9 - delete self[timeoutName]
10 - fn.apply(self, args)
11 - }, delay)
12 - fn.apply(self, args)
13 - }
14 -}
1 -var curry = require('./curry')
2 -var slice = require('./slice')
3 -var each = require('./each')
4 -
5 -var time = module.exports = timeWithBase(1) // millisecond
6 -
7 -function inMilliseconds() { return timeWithBase(time.milliseconds) }
8 -function inSeconds() { return timeWithBase(time.seconds) }
9 -function inMinutes() { return timeWithBase(time.minutes) }
10 -function inHours() { return timeWithBase(time.hours) }
11 -function inDays() { return timeWithBase(time.days) }
12 -function inWeeks() { return timeWithBase(time.weeks) }
13 -
14 -function timeWithBase(base) {
15 - var time = {
16 - now: now,
17 - ago: ago,
18 - // for creating instances of time in a different base
19 - inMilliseconds: inMilliseconds,
20 - inSeconds: inSeconds,
21 - inMinutes: inMinutes,
22 - inHours: inHours,
23 - inDays: inDays,
24 - inWeeks: inWeeks
25 - }
26 -
27 - time.millisecond = time.milliseconds = 1 / base
28 - time.second = time.seconds = 1000 * time.millisecond
29 - time.minute = time.minutes = 60 * time.second
30 - time.hour = time.hours = 60 * time.minute
31 - time.day = time.days = 24 * time.hour
32 - time.week = time.weeks = 7 * time.day
33 -
34 - function now(_base) { return Math.round(new Date().getTime() / (_base || base)) }
35 -
36 - function ago(ts, yield) { return ago.stepFunction(ts, yield) }
37 - ago.stepFunction = _stepFunction(
38 - 10 * time.second, 'just now', null,
39 - time.minute, 'less than a minute ago', null,
40 - 2 * time.minute, 'one minute ago', null,
41 - time.hour, '%N minutes ago', [time.minute],
42 - 2 * time.hour, 'one hour ago', null,
43 - time.day, '%N hours ago', [time.hour],
44 - time.day * 2, 'one day ago', null,
45 - time.week, '%N days ago', [time.day],
46 - 2 * time.week, '1 week ago', [time.week],
47 - Infinity, '%N weeks ago', [time.week])
48 -
49 - ago.precise = _stepFunction(
50 - time.minute, '%N seconds ago', [time.second],
51 - time.hour, '%N minutes, %N seconds ago', [time.minute, time.second],
52 - time.day, '%N hours, %N minutes ago', [time.hour, time.minute],
53 - time.week, '%N days, %N hours ago', [time.day, time.hour],
54 - Infinity, '%N weeks, %N days ago', [time.week, time.day])
55 -
56 - ago.brief = _stepFunction(
57 - 20 * time.second, 'now', null,
58 - time.minute, '1 min', null,
59 - time.hour, '%N min', [time.minute],
60 - 2 * time.hour, '1 hr', null,
61 - time.day, '%N hrs', [time.hour],
62 - time.day * 2, '1 day', null,
63 - time.week, '%N days', [time.day],
64 - 2 * time.week, '1 week', null,
65 - 30 * time.day, '%N weeks', [time.week],
66 - 60 * time.day, '1 month', null,
67 - Infinity, '%N months', [time.day * 30])
68 -
69 - var MAX_TIMEOUT_VALUE = 2147483647
70 - function _stepFunction() {
71 - var steps = arguments
72 - var stepFn = function(unbasedTimestamp, yield) {
73 - var millisecondsAgo = (now(time.milliseconds) - unbasedTimestamp)
74 - for (var i=0; i < steps.length; i+=3) {
75 - if (millisecondsAgo > steps[i]) { continue }
76 - var result = _getStepResult(millisecondsAgo, steps, i)
77 - if (yield) {
78 - yield(result.payload)
79 - if (result.smallestGranularity) {
80 - var timeoutIn = Math.min(result.smallestGranularity - (millisecondsAgo % result.smallestGranularity), MAX_TIMEOUT_VALUE)
81 - setTimeout(curry(stepFn, unbasedTimestamp, yield), timeoutIn * base)
82 - }
83 - }
84 - return result.payload
85 - }
86 - return _getStepResult(millisecondsAgo, steps, i - 3).payload // the last one
87 - }
88 - return stepFn
89 - }
90 -
91 - function _getStepResult(millisecondsAgo, steps, i) {
92 - var stepSize = steps[i]
93 - var stepPayload = steps[i+1]
94 - var stepGranularities = steps[i+2]
95 - var smallestGranularity = stepSize
96 - var untakenTime = millisecondsAgo
97 - each(stepGranularities, function(granularity) {
98 - var granAmount = Math.floor(untakenTime / granularity)
99 - untakenTime -= granAmount * granularity
100 - stepPayload = stepPayload.replace('%N', granAmount)
101 - if (granularity < smallestGranularity) {
102 - smallestGranularity = granularity
103 - }
104 - })
105 - return { payload:stepPayload, smallestGranularity:smallestGranularity }
106 - }
107 -
108 - return time
109 -}
1 -// Thanks goog! http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/string/string.js?r=2
2 -module.exports = function(str) {
3 - return str ? str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '') : ''
4 -}
1 -var identity = function(item) { return item }
2 -var itemId = function(item) { return item.id }
3 -
4 -/*
5 - * Filters a list to unique items
6 - */
7 -module.exports = function(list, getId) {
8 - if (!list || !list.length) { return [] }
9 - if (!getId) {
10 - getId = (list[0].id ? itemId : identity)
11 - }
12 - var seen = {}
13 - var result = []
14 - for (var i=0; i<list.length; i++) {
15 - var item = list[i]
16 - var id = getId(item)
17 - if (seen[id]) { continue }
18 - seen[id] = true
19 - result.push(item)
20 - }
21 - return result
22 -}
1 -// https://github.com/marcuswestin/phpjs/raw/master/_workbench/misc/unpack.js
2 -// Original repo https://github.com/kvz/phpjs/blob/master/_workbench/misc/unpack.js
3 -// MIT license
4 -
5 -module.exports = function unpack(format, data) {
6 - // http://kevin.vanzonneveld.net
7 - // + original by: Tim de Koning (http://www.kingsquare.nl)
8 - // + parts by: Jonas Raoni Soares Silva
9 - // + http://www.jsfromhell.com
10 - // % note 1: Float decoding by: Jonas Raoni Soares Silva
11 - // % note 2: Home: http://www.kingsquare.nl/blog/22-12-2009/13650536
12 - // % note 3: Feedback: phpjs-unpack@kingsquare.nl
13 - // % note 4: 'machine dependant byte order and size' aren't
14 - // % note 5: applicable for JavaScript unpack works as on a 32bit,
15 - // % note 6: little endian machine
16 - // * example 1: unpack('f2test', 'abcddbca');
17 - // * returns 1: { 'test1': 1.6777999408082E+22.
18 - // * returns 2: 'test2': 2.6100787562286E+20 }
19 -
20 - var formatPointer = 0, dataPointer = 0, result = {}, instruction = '',
21 - quantifier = '', label = '', currentData = '', i = 0, j = 0,
22 - word = '', precisionBits = 0, exponentBits = 0, dataByteLength = 0;
23 -
24 - // Used by float decoding
25 - var b = [], bias, signal, exponent, significand, divisor, curByte,
26 - byteValue, startBit = 0, mask, currentResult;
27 -
28 - var readBits = function(start, length, byteArray){
29 - var offsetLeft, offsetRight, curByte, lastByte, diff, sum;
30 -
31 - function shl(a, b){
32 - for(++b; --b;) {
33 - a = ((a %= 0x7fffffff + 1) & 0x40000000) === 0x40000000 ?
34 - a * 2 :
35 - (a - 0x40000000) * 2 + 0x7fffffff + 1;
36 - }
37 - return a;
38 - }
39 - if(start < 0 || length <= 0) {
40 - return 0;
41 - }
42 -
43 - offsetRight = start % 8;
44 - curByte = byteArray.length - (start >> 3) - 1;
45 - lastByte = byteArray.length + (-(start + length) >> 3);
46 - diff = curByte - lastByte;
47 - sum = (
48 - (byteArray[ curByte ] >> offsetRight) &
49 - ((1 << (diff ? 8 - offsetRight : length)) - 1)
50 - ) + (
51 - diff && (offsetLeft = (start + length) % 8) ?
52 - (byteArray[ lastByte++ ] & ((1 << offsetLeft) - 1)) <<
53 - (diff-- << 3) - offsetRight :
54 - 0
55 - );
56 -
57 - for(; diff;) {
58 - sum += shl(byteArray[ lastByte++ ], (diff-- << 3) - offsetRight);
59 - }
60 - return sum;
61 - };
62 -
63 - while (formatPointer < format.length) {
64 - instruction = format[formatPointer];
65 -
66 - // Start reading 'quantifier'
67 - quantifier = '';
68 - formatPointer++;
69 - while ((formatPointer < format.length) &&
70 - (format[formatPointer].match(/[\d\*]/) !== null)) {
71 - quantifier += format[formatPointer];
72 - formatPointer++;
73 - }
74 - if (quantifier === '') {
75 - quantifier = '1';
76 - }
77 -
78 -
79 - // Start reading label
80 - label = '';
81 - while ((formatPointer < format.length) &&
82 - (format[formatPointer] !== '/')) {
83 - label += format[formatPointer];
84 - formatPointer++;
85 - }
86 - if (format[formatPointer] === '/') {
87 - formatPointer++;
88 - }
89 -
90 - // Process given instruction
91 - switch (instruction) {
92 - case 'a': // NUL-padded string
93 - case 'A': // SPACE-padded string
94 - if (quantifier === '*') {
95 - quantifier = data.length - dataPointer;
96 - } else {
97 - quantifier = parseInt(quantifier, 10);
98 - }
99 - currentData = data.substr(dataPointer, quantifier);
100 - dataPointer += quantifier;
101 -
102 - if (instruction === 'a') {
103 - currentResult = currentData.replace(/\0+$/, '');
104 - } else {
105 - currentResult = currentData.replace(/ +$/, '');
106 - }
107 - result[label] = currentResult;
108 - break;
109 -
110 - case 'h': // Hex string, low nibble first
111 - case 'H': // Hex string, high nibble first
112 - if (quantifier === '*') {
113 - quantifier = data.length - dataPointer;
114 - } else {
115 - quantifier = parseInt(quantifier, 10);
116 - }
117 - currentData = data.substr(dataPointer, quantifier);
118 - dataPointer += quantifier;
119 -
120 - if (quantifier>currentData.length) {
121 - throw new Error('Warning: unpack(): Type ' + instruction +
122 - ': not enough input, need ' + quantifier);
123 - }
124 -
125 - currentResult = '';
126 - for(i=0;i<currentData.length;i++) {
127 - word = currentData.charCodeAt(i).toString(16);
128 - if (instruction === 'h') {
129 - word = word[1]+word[0];
130 - }
131 - currentResult += word;
132 - }
133 - result[label] = currentResult;
134 - break;
135 -
136 - case 'c': // signed char
137 - case 'C': // unsigned c
138 - if (quantifier === '*') {
139 - quantifier = data.length - dataPointer;
140 - } else {
141 - quantifier = parseInt(quantifier, 10);
142 - }
143 -
144 - currentData = data.substr(dataPointer, quantifier);
145 - dataPointer += quantifier;
146 -
147 - for (i=0;i<currentData.length;i++) {
148 - currentResult = currentData.charCodeAt(i);
149 - if ((instruction === 'c') && (currentResult >= 128)) {
150 - currentResult -= 256;
151 - }
152 - result[label+(quantifier>1?
153 - (i+1):
154 - '')] = currentResult;
155 - }
156 - break;
157 -
158 - case 'S': // unsigned short (always 16 bit, machine byte order)
159 - case 's': // signed short (always 16 bit, machine byte order)
160 - case 'v': // unsigned short (always 16 bit, little endian byte order)
161 - if (quantifier === '*') {
162 - quantifier = (data.length - dataPointer) / 2;
163 - } else {
164 - quantifier = parseInt(quantifier, 10);
165 - }
166 -
167 - currentData = data.substr(dataPointer, quantifier * 2);
168 - dataPointer += quantifier * 2;
169 -
170 - for (i=0;i<currentData.length;i+=2) {
171 - // sum per word;
172 - currentResult = (currentData.charCodeAt(i+1) & 0xFF) << 8 +
173 - (currentData.charCodeAt(i) & 0xFF);
174 - if ((instruction === 's') && (currentResult >= 32768)) {
175 - currentResult -= 65536;
176 - }
177 - result[label+(quantifier>1?
178 - ((i/2)+1):
179 - '')] = currentResult;
180 - }
181 - break;
182 -
183 - case 'n': // unsigned short (always 16 bit, big endian byte order)
184 - if (quantifier === '*') {
185 - quantifier = (data.length - dataPointer) / 2;
186 - } else {
187 - quantifier = parseInt(quantifier, 10);
188 - }
189 -
190 - currentData = data.substr(dataPointer, quantifier * 2);
191 - dataPointer += quantifier * 2;
192 -
193 - for (i=0;i<currentData.length;i+=2) {
194 - // sum per word;
195 - currentResult = ((currentData.charCodeAt(i) & 0xFF) << 8) +
196 - (currentData.charCodeAt(i+1) & 0xFF);
197 - result[label+(quantifier>1?
198 - ((i/2)+1):
199 - '')] = currentResult;
200 - }
201 - break;
202 -
203 - case 'i': // signed integer (machine dependent size and byte order)
204 - case 'I': // unsigned integer (machine dependent size & byte order)
205 - case 'l': // signed long (always 32 bit, machine byte order)
206 - case 'L': // unsigned long (always 32 bit, machine byte order)
207 - case 'V': // unsigned long (always 32 bit, little endian byte order)
208 - if (quantifier === '*') {
209 - quantifier = (data.length - dataPointer) / 4;
210 - } else {
211 - quantifier = parseInt(quantifier, 10);
212 - }
213 -
214 - currentData = data.substr(dataPointer, quantifier * 4);
215 - dataPointer += quantifier * 4;
216 -
217 - for (i=0;i<currentData.length;i+=4) {
218 - currentResult =
219 - ((currentData.charCodeAt(i+3) & 0xFF) << 24) +
220 - ((currentData.charCodeAt(i+2) & 0xFF) << 16) +
221 - ((currentData.charCodeAt(i+1) & 0xFF) << 8) +
222 - ((currentData.charCodeAt(i) & 0xFF));
223 - result[label+(quantifier>1?
224 - ((i/4)+1):
225 - '')] = currentResult;
226 - }
227 -
228 - break;
229 -
230 - case 'N': // unsigned long (always 32 bit, little endian byte order)
231 - if (quantifier === '*') {
232 - quantifier = (data.length - dataPointer) / 4;
233 - } else {
234 - quantifier = parseInt(quantifier, 10);
235 - }
236 -
237 - currentData = data.substr(dataPointer, quantifier * 4);
238 - dataPointer += quantifier * 4;
239 -
240 - for (i=0;i<currentData.length;i+=4) {
241 - currentResult =
242 - ((currentData.charCodeAt(i) & 0xFF) << 24) +
243 - ((currentData.charCodeAt(i+1) & 0xFF) << 16) +
244 - ((currentData.charCodeAt(i+2) & 0xFF) << 8) +
245 - ((currentData.charCodeAt(i+3) & 0xFF));
246 - result[label+(quantifier>1?
247 - ((i/4)+1):
248 - '')] = currentResult;
249 - }
250 -
251 - break;
252 -
253 - case 'f':
254 - case 'd':
255 - exponentBits = 8;
256 - dataByteLength = 4;
257 - if (instruction === 'd') {
258 - exponentBits = 11;
259 - dataByteLength = 8;
260 - }
261 -
262 - if (quantifier === '*') {
263 - quantifier = (data.length - dataPointer) / dataByteLength;
264 - } else {
265 - quantifier = parseInt(quantifier, 10);
266 - }
267 -
268 - currentData = data.substr(dataPointer,
269 - quantifier * dataByteLength);
270 - dataPointer += quantifier * dataByteLength;
271 -
272 - for (i=0;i<currentData.length;i+=dataByteLength) {
273 - data = currentData.substr(i, dataByteLength);
274 -
275 - b = [];
276 - for(j = data.length-1; j >= 0 ; --j) {
277 - b.push(data.charCodeAt(j));
278 - }
279 -
280 - precisionBits = (instruction === 'f')?23:52;
281 -
282 - bias = Math.pow(2, exponentBits - 1) - 1;
283 - signal = readBits(precisionBits + exponentBits, 1, b);
284 - exponent = readBits(precisionBits, exponentBits, b);
285 - significand = 0;
286 - divisor = 2;
287 - curByte = b.length + (-precisionBits >> 3) - 1;
288 - startBit = 0;
289 -
290 - do {
291 - byteValue = b[ ++curByte ];
292 - startBit = precisionBits % 8 || 8;
293 - mask = 1 << startBit;
294 - for(; (mask >>= 1);) {
295 - if (byteValue & mask) {
296 - significand += 1 / divisor;
297 - }
298 - divisor *= 2;
299 - }
300 - } while ((precisionBits -= startBit));
301 -
302 - if (exponent === (bias << 1) + 1) {
303 - if (significand) {
304 - currentResult = NaN;
305 - } else {
306 - if (signal) {
307 - currentResult = -Infinity;
308 - } else {
309 - currentResult = +Infinity;
310 - }
311 - }
312 - } else {
313 - if ((1 + signal * -2) * (exponent || significand)) {
314 - if (!exponent) {
315 - currentResult = Math.pow(2, -bias + 1) *
316 - significand;
317 - } else {
318 - currentResult = Math.pow(2,
319 - exponent - bias) *
320 - (1 + significand);
321 - }
322 - } else {
323 - currentResult = 0;
324 - }
325 - }
326 - result[label+(quantifier>1?
327 - ((i/4)+1):
328 - '')] = currentResult;
329 - }
330 -
331 - break;
332 -
333 - case 'x': // NUL byte
334 - case 'X': // Back up one byte
335 - case '@': // NUL byte
336 - if (quantifier === '*') {
337 - quantifier = data.length - dataPointer;
338 - } else {
339 - quantifier = parseInt(quantifier, 10);
340 - }
341 -
342 - if (quantifier > 0) {
343 - if (instruction === 'X') {
344 - dataPointer -= quantifier;
345 - } else {
346 - if (instruction === 'x') {
347 - dataPointer += quantifier;
348 - } else {
349 - dataPointer = quantifier;
350 - }
351 - }
352 - }
353 - break;
354 -
355 - default:
356 - throw new Error('Warning: unpack() Type ' + instruction +
357 - ': unknown format code');
358 - }
359 - }
360 - return result;
361 -}
1 -var Class = require('./Class')
2 -var map = require('./map')
3 -var isArray = require('std/isArray')
4 -
5 -var URL = Class(function() {
6 -
7 - this._extractionRegex = new RegExp([
8 - '^', // start at the beginning of the string
9 - '((\\w+:)?//)?', // match a possible protocol, like http://, ftp://, or // for a relative url
10 - '(\\w[\\w\\.\\-]+)?', // match a possible domain
11 - '(:\\d+)?', // match a possible port
12 - '(\\/[^\\?#]+)?', // match a possible path
13 - '(\\?[^#]+)?', // match possible GET parameters
14 - '(#.*)?' // match the rest of the URL as the hash
15 - ].join(''), 'i')
16 -
17 - this.init = function(url) {
18 - var match = (url || '').toString().match(this._extractionRegex) || []
19 - this.protocol = match[2] || ''
20 - this.hostname = match[3] || ''
21 - this.port = (match[4] || '').substr(1)
22 - this.host = (this.hostname ? this.hostname : '') + (this.port ? ':' + this.port : '')
23 - this.pathname = match[5] || ''
24 - this.search = (match[6]||'').substr(1)
25 - this.hash = (match[7]||'').substr(1)
26 - }
27 -
28 - this.setProtocol = function(protocol) {
29 - this.protocol = protocol
30 - return this
31 - }
32 -
33 - this.toString = function() {
34 - return [
35 - this.protocol || '//',
36 - this.host,
37 - this.pathname,
38 - this.getSearch(),
39 - this.getHash()
40 - ].join('')
41 - }
42 -
43 - this.toJSON = this.toString
44 -
45 - this.getTopLevelDomain = function() {
46 - if (!this.host) { return '' }
47 - var parts = this.host.split('.')
48 - return parts.slice(parts.length - 2).join('.')
49 - }
50 -
51 - this.getSearchParams = function() {
52 - if (this._searchParams) { return this._searchParams }
53 - return this._searchParams = url.query.parse(this.search) || {}
54 - }
55 -
56 - this.getHashParams = function() {
57 - if (this._hashParams) { return this._hashParams }
58 - return this._hashParams = url.query.parse(this.hash) || {}
59 - }
60 -
61 - this.addToSearch = function(key, val) { this.getSearchParams()[key] = val; return this }
62 - this.addToHash = function(key, val) { this.getHashParams()[key] = val; return this }
63 - this.removeFromSearch = function(key) { delete this.getSearchParams()[key]; return this }
64 - this.removeFromHash = function(key) { delete this.getHashParams()[key]; return this }
65 -
66 - this.getSearch = function() {
67 - return (
68 - this._searchParams ? '?' + url.query.string(this._searchParams)
69 - : this.search ? '?' + this.search
70 - : '')
71 - }
72 -
73 - this.getHash = function() {
74 - return (
75 - this._hashParams ? '#' + url.query.string(this._hashParams)
76 - : this.hash ? '?' + this.hash
77 - : '')
78 - }
79 -
80 - this.getSearchParam = function(key) { return this.getSearchParams()[key] }
81 - this.getHashParam = function(key) { return this.getHashParams()[key] }
82 -})
83 -
84 -var url = module.exports = function url(url) { return new URL(url) }
85 -url.parse = url
86 -
87 -url.query = {
88 - parse:function(paramString) {
89 - var parts = paramString.split('&'),
90 - params = {}
91 - for (var i=0; i<parts.length; i++) {
92 - var kvp = parts[i].split('=')
93 - if (kvp.length != 2) { continue }
94 - params[decodeURIComponent(kvp[0])] = decodeURIComponent(kvp[1])
95 - }
96 - return params
97 - },
98 - string:function(params) {
99 - return map(params, function(val, key) {
100 - return encodeURIComponent(key) + '=' + url.query.encodeValue(val)
101 - }).join('&')
102 - },
103 - encodeValue:function(val) {
104 - if (isArray(val)) {
105 - return map(val, function(v) {
106 - return encodeURIComponent(v)
107 - }).join(',')
108 - } else {
109 - return encodeURIComponent(val)
110 - }
111 - }
112 -}
1 -// https://github.com/kvz/phpjs/raw/2ae4292a8629d6007eae26298bd19339ef97957e/functions/xml/utf8_encode.js
2 -// MIT License http://phpjs.org/pages/license
3 -
4 -module.exports = function utf8_encode (argString) {
5 - // http://kevin.vanzonneveld.net
6 - // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
7 - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
8 - // + improved by: sowberry
9 - // + tweaked by: Jack
10 - // + bugfixed by: Onno Marsman
11 - // + improved by: Yves Sucaet
12 - // + bugfixed by: Onno Marsman
13 - // + bugfixed by: Ulrich
14 - // * example 1: utf8_encode('Kevin van Zonneveld');
15 - // * returns 1: 'Kevin van Zonneveld'
16 - var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
17 - var utftext = "",
18 - start, end, stringl = 0;
19 -
20 - start = end = 0;
21 - stringl = string.length;
22 - for (var n = 0; n < stringl; n++) {
23 - var c1 = string.charCodeAt(n);
24 - var enc = null;
25 -
26 - if (c1 < 128) {
27 - end++;
28 - } else if (c1 > 127 && c1 < 2048) {
29 - enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
30 - } else {
31 - enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
32 - }
33 - if (enc !== null) {
34 - if (end > start) {
35 - utftext += string.slice(start, end);
36 - }
37 - utftext += enc;
38 - start = end = n + 1;
39 - }
40 - }
41 -
42 - if (end > start) {
43 - utftext += string.slice(start, stringl);
44 - }
45 -
46 - return utftext;
47 -}
1 -module.exports = function waitFor(num, callback) {
2 - var seenError
3 - return function(err, res) {
4 - if (num == 0) { return log.warn("waitFor was called more than the expected number of times") }
5 - if (seenError) { return }
6 - if (err) {
7 - seenError = true
8 - return callback(err)
9 - }
10 - num -= 1
11 - if (num == 0) { callback(null) }
12 - }
13 -}
1 -var curry = require('./curry'),
2 - map = require('./map'),
3 - each = require('./each'),
4 - json = require('./json')
5 -
6 -module.exports = {
7 - request: request,
8 - get: curry(request, 'get'),
9 - post: curry(request, 'post'),
10 - jsonGet: curry(sendJSON, 'get'),
11 - jsonPost: curry(sendJSON, 'post')
12 -}
13 -
14 -var XHR = window.XMLHttpRequest || function() { return new ActiveXObject("Msxml2.XMLHTTP"); }
15 -
16 -var onBeforeUnloadFired = false
17 -function onBeforeUnload() {
18 - onBeforeUnloadFired = true
19 - setTimeout(function(){ onBeforeUnloadFired = false }, 100)
20 -}
21 -
22 -if (window.addEventListener) { window.addEventListener('beforeunload', onBeforeUnload, false) }
23 -else { window.attachEvent('onbeforeunload', onBeforeUnload) }
24 -
25 -function request(method, url, params, callback, headers, opts) {
26 - var xhr = new XHR()
27 - method = method.toUpperCase()
28 - headers = headers || {}
29 - opts = opts || {}
30 - xhr.onreadystatechange = function() {
31 - var err, result
32 - try {
33 - if (xhr.readyState != 4) { return }
34 - if (onBeforeUnloadFired) { return }
35 - var text = xhr.responseText,
36 - isJson = xhr.getResponseHeader('Content-Type') == 'application/json'
37 - if (xhr.status == 200 || xhr.status == 204) {
38 - result = isJson ? json.parse(text) : text
39 - } else {
40 - try { err = isJson ? json.parse(text) : new Error(text) }
41 - catch (e) { err = new Error(text) }
42 - }
43 - } catch(e) {
44 - err = e
45 - }
46 - if (err || typeof result != undefined) {
47 - _abortXHR(xhr)
48 - callback(err, result)
49 - }
50 - }
51 -
52 - var uriEncode = (opts.encode === false
53 - ? function(params) { return map(params, function(val, key) { return key+'='+val }).join('&') }
54 - : function(params) { return map(params, function(val, key) { return encodeURIComponent(key)+'='+encodeURIComponent(val) }).join('&') })
55 -
56 - var data = ''
57 - if (method == 'GET') {
58 - var queryParams = uriEncode(params)
59 - url += (url.indexOf('?') == -1 && queryParams ? '?' : '') + queryParams
60 - } else if (method == 'POST') {
61 - var contentType = headers['Content-Type']
62 - if (!contentType) {
63 - contentType = headers['Content-Type'] = 'application/x-www-form-urlencoded'
64 - }
65 - if (contentType == 'application/x-www-form-urlencoded') {
66 - data = uriEncode(params)
67 - } else if (contentType == 'application/json') {
68 - data = json.stringify(params)
69 - }
70 - }
71 - xhr.open(method, url, true)
72 - each(headers, function(val, key) { xhr.setRequestHeader(key, val) })
73 - xhr.send(data)
74 -}
75 -
76 -function sendJSON(method, url, params, callback) {
77 - return request(method, url, params, callback, { 'Content-Type':'application/json' })
78 -}
79 -
80 -function _abortXHR(xhr) {
81 - try {
82 - if('onload' in xhr) {
83 - xhr.onload = xhr.onerror = xhr.ontimeout = null;
84 - } else if('onreadystatechange' in xhr) {
85 - xhr.onreadystatechange = null;
86 - }
87 - if(xhr.abort) { xhr.abort(); }
88 - } catch(e) {}
89 -}
1 -UglifyJS is released under the BSD license:
2 -
3 -Copyright 2012-2013 (c) Mihai Bazon <mihai.bazon@gmail.com>
4 -
5 -Redistribution and use in source and binary forms, with or without
6 -modification, are permitted provided that the following conditions
7 -are met:
8 -
9 - * Redistributions of source code must retain the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer.
12 -
13 - * Redistributions in binary form must reproduce the above
14 - copyright notice, this list of conditions and the following
15 - disclaimer in the documentation and/or other materials
16 - provided with the distribution.
17 -
18 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
19 -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
22 -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23 -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 -SUCH DAMAGE.
1 -UglifyJS 2
2 -==========
3 -
4 -UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.
5 -
6 -This page documents the command line utility. For
7 -[API and internals documentation see my website](http://lisperator.net/uglifyjs/).
8 -There's also an
9 -[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
10 -Chrome and probably Safari).
11 -
12 -Install
13 --------
14 -
15 -First make sure you have installed the latest version of [node.js](http://nodejs.org/)
16 -(You may need to restart your computer after this step).
17 -
18 -From NPM for use as a command line app:
19 -
20 - npm install uglify-js -g
21 -
22 -From NPM for programmatic use:
23 -
24 - npm install uglify-js
25 -
26 -From Git:
27 -
28 - git clone git://github.com/mishoo/UglifyJS2.git
29 - cd UglifyJS2
30 - npm link .
31 -
32 -Usage
33 ------
34 -
35 - uglifyjs [input files] [options]
36 -
37 -UglifyJS2 can take multiple input files. It's recommended that you pass the
38 -input files first, then pass the options. UglifyJS will parse input files
39 -in sequence and apply any compression options. The files are parsed in the
40 -same global scope, that is, a reference from a file to some
41 -variable/function declared in another file will be matched properly.
42 -
43 -If you want to read from STDIN instead, pass a single dash instead of input
44 -files.
45 -
46 -The available options are:
47 -
48 - --source-map Specify an output file where to generate source map.
49 - [string]
50 - --source-map-root The path to the original source to be included in the
51 - source map. [string]
52 - --source-map-url The path to the source map to be added in //@
53 - sourceMappingURL. Defaults to the value passed with
54 - --source-map. [string]
55 - --in-source-map Input source map, useful if you're compressing JS that was
56 - generated from some other original code.
57 - --screw-ie8 Pass this flag if you don't care about full compliance with
58 - Internet Explorer 6-8 quirks (by default UglifyJS will try
59 - to be IE-proof).
60 - -p, --prefix Skip prefix for original filenames that appear in source
61 - maps. For example -p 3 will drop 3 directories from file
62 - names and ensure they are relative paths.
63 - -o, --output Output file (default STDOUT).
64 - -b, --beautify Beautify output/specify output options. [string]
65 - -m, --mangle Mangle names/pass mangler options. [string]
66 - -r, --reserved Reserved names to exclude from mangling.
67 - -c, --compress Enable compressor/pass compressor options. Pass options
68 - like -c hoist_vars=false,if_return=false. Use -c with no
69 - argument to use the default compression options. [string]
70 - -d, --define Global definitions [string]
71 - --comments Preserve copyright comments in the output. By default this
72 - works like Google Closure, keeping JSDoc-style comments
73 - that contain "@license" or "@preserve". You can optionally
74 - pass one of the following arguments to this flag:
75 - - "all" to keep all comments
76 - - a valid JS regexp (needs to start with a slash) to keep
77 - only comments that match.
78 - Note that currently not *all* comments can be kept when
79 - compression is on, because of dead code removal or
80 - cascading statements into sequences. [string]
81 - --stats Display operations run time on STDERR. [boolean]
82 - --acorn Use Acorn for parsing. [boolean]
83 - --spidermonkey Assume input fles are SpiderMonkey AST format (as JSON).
84 - [boolean]
85 - --self Build itself (UglifyJS2) as a library (implies
86 - --wrap=UglifyJS --export-all) [boolean]
87 - --wrap Embed everything in a big function, making the “exports”
88 - and “global” variables available. You need to pass an
89 - argument to this option to specify the name that your
90 - module will take when included in, say, a browser.
91 - [string]
92 - --export-all Only used when --wrap, this tells UglifyJS to add code to
93 - automatically export all globals. [boolean]
94 - --lint Display some scope warnings [boolean]
95 - -v, --verbose Verbose [boolean]
96 - -V, --version Print version number and exit. [boolean]
97 -
98 -Specify `--output` (`-o`) to declare the output file. Otherwise the output
99 -goes to STDOUT.
100 -
101 -## Source map options
102 -
103 -UglifyJS2 can generate a source map file, which is highly useful for
104 -debugging your compressed JavaScript. To get a source map, pass
105 -`--source-map output.js.map` (full path to the file where you want the
106 -source map dumped).
107 -
108 -Additionally you might need `--source-map-root` to pass the URL where the
109 -original files can be found. In case you are passing full paths to input
110 -files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of
111 -directories to drop from the path prefix when declaring files in the source
112 -map.
113 -
114 -For example:
115 -
116 - uglifyjs /home/doe/work/foo/src/js/file1.js \
117 - /home/doe/work/foo/src/js/file2.js \
118 - -o foo.min.js \
119 - --source-map foo.min.js.map \
120 - --source-map-root http://foo.com/src \
121 - -p 5 -c -m
122 -
123 -The above will compress and mangle `file1.js` and `file2.js`, will drop the
124 -output in `foo.min.js` and the source map in `foo.min.js.map`. The source
125 -mapping will refer to `http://foo.com/src/js/file1.js` and
126 -`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`
127 -as the source map root, and the original files as `js/file1.js` and
128 -`js/file2.js`).
129 -
130 -### Composed source map
131 -
132 -When you're compressing JS code that was output by a compiler such as
133 -CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd
134 -like to map back to the original code (i.e. CoffeeScript). UglifyJS has an
135 -option to take an input source map. Assuming you have a mapping from
136 -CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
137 -compressed JS by mapping every token in the compiled JS to its original
138 -location.
139 -
140 -To use this feature you need to pass `--in-source-map
141 -/path/to/input/source.map`. Normally the input source map should also point
142 -to the file containing the generated JS, so if that's correct you can omit
143 -input files from the command line.
144 -
145 -## Mangler options
146 -
147 -To enable the mangler you need to pass `--mangle` (`-m`). The following
148 -(comma-separated) options are supported:
149 -
150 -- `sort` — to assign shorter names to most frequently used variables. This
151 - saves a few hundred bytes on jQuery before gzip, but the output is
152 - _bigger_ after gzip (and seems to happen for other libraries I tried it
153 - on) therefore it's not enabled by default.
154 -
155 -- `toplevel` — mangle names declared in the toplevel scope (disabled by
156 - default).
157 -
158 -- `eval` — mangle names visible in scopes where `eval` or `when` are used
159 - (disabled by default).
160 -
161 -When mangling is enabled but you want to prevent certain names from being
162 -mangled, you can declare those names with `--reserved` (`-r`) — pass a
163 -comma-separated list of names. For example:
164 -
165 - uglifyjs ... -m -r '$,require,exports'
166 -
167 -to prevent the `require`, `exports` and `$` names from being changed.
168 -
169 -## Compressor options
170 -
171 -You need to pass `--compress` (`-c`) to enable the compressor. Optionally
172 -you can pass a comma-separated list of options. Options are in the form
173 -`foo=bar`, or just `foo` (the latter implies a boolean option that you want
174 -to set `true`; it's effectively a shortcut for `foo=true`).
175 -
176 -- `sequences` -- join consecutive simple statements using the comma operator
177 -- `properties` -- rewrite property access using the dot notation, for
178 - example `foo["bar"] → foo.bar`
179 -- `dead_code` -- remove unreachable code
180 -- `drop_debugger` -- remove `debugger;` statements
181 -- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below)
182 -- `conditionals` -- apply optimizations for `if`-s and conditional
183 - expressions
184 -- `comparisons` -- apply certain optimizations to binary nodes, for example:
185 - `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,
186 - e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
187 -- `evaluate` -- attempt to evaluate constant expressions
188 -- `booleans` -- various optimizations for boolean context, for example `!!a
189 - ? b : c → a ? b : c`
190 -- `loops` -- optimizations for `do`, `while` and `for` loops when we can
191 - statically determine the condition
192 -- `unused` -- drop unreferenced functions and variables
193 -- `hoist_funs` -- hoist function declarations
194 -- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
195 - by default because it seems to increase the size of the output in general)
196 -- `if_return` -- optimizations for if/return and if/continue
197 -- `join_vars` -- join consecutive `var` statements
198 -- `cascade` -- small optimization for sequences, transform `x, x` into `x`
199 - and `x = something(), x` into `x = something()`
200 -- `warnings` -- display warnings when dropping unreachable code or unused
201 - declarations etc.
202 -
203 -### The `unsafe` option
204 -
205 -It enables some transformations that *might* break code logic in certain
206 -contrived cases, but should be fine for most code. You might want to try it
207 -on your own code, it should reduce the minified size. Here's what happens
208 -when this flag is on:
209 -
210 -- `new Array(1, 2, 3)` or `Array(1, 2, 3)``[1, 2, 3 ]`
211 -- `new Object()``{}`
212 -- `String(exp)` or `exp.toString()``"" + exp`
213 -- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
214 -- `typeof foo == "undefined"``foo === void 0`
215 -- `void 0``"undefined"` (if there is a variable named "undefined" in
216 - scope; we do it because the variable name will be mangled, typically
217 - reduced to a single character).
218 -
219 -### Conditional compilation
220 -
221 -You can use the `--define` (`-d`) switch in order to declare global
222 -variables that UglifyJS will assume to be constants (unless defined in
223 -scope). For example if you pass `--define DEBUG=false` then, coupled with
224 -dead code removal UglifyJS will discard the following from the output:
225 -
226 - if (DEBUG) {
227 - console.log("debug stuff");
228 - }
229 -
230 -UglifyJS will warn about the condition being always false and about dropping
231 -unreachable code; for now there is no option to turn off only this specific
232 -warning, you can pass `warnings=false` to turn off *all* warnings.
233 -
234 -Another way of doing that is to declare your globals as constants in a
235 -separate file and include it into the build. For example you can have a
236 -`build/defines.js` file with the following:
237 -
238 - const DEBUG = false;
239 - const PRODUCTION = true;
240 - // etc.
241 -
242 -and build your code like this:
243 -
244 - uglifyjs build/defines.js js/foo.js js/bar.js... -c
245 -
246 -UglifyJS will notice the constants and, since they cannot be altered, it
247 -will evaluate references to them to the value itself and drop unreachable
248 -code as usual. The possible downside of this approach is that the build
249 -will contain the `const` declarations.
250 -
251 -<a name="codegen-options"></a>
252 -## Beautifier options
253 -
254 -The code generator tries to output shortest code possible by default. In
255 -case you want beautified output, pass `--beautify` (`-b`). Optionally you
256 -can pass additional arguments that control the code output:
257 -
258 -- `beautify` (default `true`) -- whether to actually beautify the output.
259 - Passing `-b` will set this to true, but you might need to pass `-b` even
260 - when you want to generate minified code, in order to specify additional
261 - arguments, so you can use `-b beautify=false` to override it.
262 -- `indent-level` (default 4)
263 -- `indent-start` (default 0) -- prefix all lines by that many spaces
264 -- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal
265 - objects
266 -- `space-colon` (default `true`) -- insert a space after the colon signs
267 -- `ascii-only` (default `false`) -- escape Unicode characters in strings and
268 - regexps
269 -- `inline-script` (default `false`) -- escape the slash in occurrences of
270 - `</script` in strings
271 -- `width` (default 80) -- only takes effect when beautification is on, this
272 - specifies an (orientative) line width that the beautifier will try to
273 - obey. It refers to the width of the line text (excluding indentation).
274 - It doesn't work very well currently, but it does make the code generated
275 - by UglifyJS more readable.
276 -- `max-line-len` (default 32000) -- maximum line length (for uglified code)
277 -- `ie-proof` (default `true`) -- generate “IE-proof” code (for now this
278 - means add brackets around the do/while in code like this: `if (foo) do
279 - something(); while (bar); else ...`.
280 -- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
281 - `do`, `while` or `with` statements, even if their body is a single
282 - statement.
283 -- `semicolons` (default `true`) -- separate statements with semicolons. If
284 - you pass `false` then whenever possible we will use a newline instead of a
285 - semicolon, leading to more readable output of uglified code (size before
286 - gzip could be smaller; size after gzip insignificantly larger).
287 -
288 -### Keeping copyright notices or other comments
289 -
290 -You can pass `--comments` to retain certain comments in the output. By
291 -default it will keep JSDoc-style comments that contain "@preserve",
292 -"@license" or "@cc_on" (conditional compilation for IE). You can pass
293 -`--comments all` to keep all the comments, or a valid JavaScript regexp to
294 -keep only comments that match this regexp. For example `--comments
295 -'/foo|bar/'` will keep only comments that contain "foo" or "bar".
296 -
297 -Note, however, that there might be situations where comments are lost. For
298 -example:
299 -
300 - function f() {
301 - /** @preserve Foo Bar */
302 - function g() {
303 - // this function is never called
304 - }
305 - return something();
306 - }
307 -
308 -Even though it has "@preserve", the comment will be lost because the inner
309 -function `g` (which is the AST node to which the comment is attached to) is
310 -discarded by the compressor as not referenced.
311 -
312 -The safest comments where to place copyright information (or other info that
313 -needs to be kept in the output) are comments attached to toplevel nodes.
314 -
315 -## Support for the SpiderMonkey AST
316 -
317 -UglifyJS2 has its own abstract syntax tree format; for
318 -[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
319 -we can't easily change to using the SpiderMonkey AST internally. However,
320 -UglifyJS now has a converter which can import a SpiderMonkey AST.
321 -
322 -For example [Acorn][acorn] is a super-fast parser that produces a
323 -SpiderMonkey AST. It has a small CLI utility that parses one file and dumps
324 -the AST in JSON on the standard output. To use UglifyJS to mangle and
325 -compress that:
326 -
327 - acorn file.js | uglifyjs --spidermonkey -m -c
328 -
329 -The `--spidermonkey` option tells UglifyJS that all input files are not
330 -JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
331 -don't use our own parser in this case, but just transform that AST into our
332 -internal AST.
333 -
334 -### Use Acorn for parsing
335 -
336 -More for fun, I added the `--acorn` option which will use Acorn to do all
337 -the parsing. If you pass this option, UglifyJS will `require("acorn")`.
338 -
339 -Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
340 -converting the SpiderMonkey tree that Acorn produces takes another 150ms so
341 -in total it's a bit more than just using UglifyJS's own parser.
342 -
343 -API Reference
344 --------------
345 -
346 -Assuming installation via NPM, you can load UglifyJS in your application
347 -like this:
348 -
349 - var UglifyJS = require("uglify-js");
350 -
351 -It exports a lot of names, but I'll discuss here the basics that are needed
352 -for parsing, mangling and compressing a piece of code. The sequence is (1)
353 -parse, (2) compress, (3) mangle, (4) generate output code.
354 -
355 -### The simple way
356 -
357 -There's a single toplevel function which combines all the steps. If you
358 -don't need additional customization, you might want to go with `minify`.
359 -Example:
360 -
361 - var result = UglifyJS.minify("/path/to/file.js");
362 - console.log(result.code); // minified output
363 - // if you need to pass code instead of file name
364 - var result = UglifyJS.minify("var b = function () {};", {fromString: true});
365 -
366 -You can also compress multiple files:
367 -
368 - var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ]);
369 - console.log(result.code);
370 -
371 -To generate a source map:
372 -
373 - var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
374 - outSourceMap: "out.js.map"
375 - });
376 - console.log(result.code); // minified output
377 - console.log(result.map);
378 -
379 -Note that the source map is not saved in a file, it's just returned in
380 -`result.map`. The value passed for `outSourceMap` is only used to set the
381 -`file` attribute in the source map (see [the spec][sm-spec]).
382 -
383 -You can also specify sourceRoot property to be included in source map:
384 -
385 - var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
386 - outSourceMap: "out.js.map",
387 - sourceRoot: "http://example.com/src"
388 - });
389 -
390 -
391 -If you're compressing compiled JavaScript and have a source map for it, you
392 -can use the `inSourceMap` argument:
393 -
394 - var result = UglifyJS.minify("compiled.js", {
395 - inSourceMap: "compiled.js.map",
396 - outSourceMap: "minified.js.map"
397 - });
398 - // same as before, it returns `code` and `map`
399 -
400 -The `inSourceMap` is only used if you also request `outSourceMap` (it makes
401 -no sense otherwise).
402 -
403 -Other options:
404 -
405 -- `warnings` (default `false`) — pass `true` to display compressor warnings.
406 -
407 -- `fromString` (default `false`) — if you pass `true` then you can pass
408 - JavaScript source code, rather than file names.
409 -
410 -- `mangle` — pass `false` to skip mangling names.
411 -
412 -- `output` (default `null`) — pass an object if you wish to specify
413 - additional [output options][codegen]. The defaults are optimized
414 - for best compression.
415 -
416 -- `compress` (default `{}`) — pass `false` to skip compressing entirely.
417 - Pass an object to specify custom [compressor options][compressor].
418 -
419 -We could add more options to `UglifyJS.minify` — if you need additional
420 -functionality please suggest!
421 -
422 -### The hard way
423 -
424 -Following there's more detailed API info, in case the `minify` function is
425 -too simple for your needs.
426 -
427 -#### The parser
428 -
429 - var toplevel_ast = UglifyJS.parse(code, options);
430 -
431 -`options` is optional and if present it must be an object. The following
432 -properties are available:
433 -
434 -- `strict` — disable automatic semicolon insertion and support for trailing
435 - comma in arrays and objects
436 -- `filename` — the name of the file where this code is coming from
437 -- `toplevel` — a `toplevel` node (as returned by a previous invocation of
438 - `parse`)
439 -
440 -The last two options are useful when you'd like to minify multiple files and
441 -get a single file as the output and a proper source map. Our CLI tool does
442 -something like this:
443 -
444 - var toplevel = null;
445 - files.forEach(function(file){
446 - var code = fs.readFileSync(file);
447 - toplevel = UglifyJS.parse(code, {
448 - filename: file,
449 - toplevel: toplevel
450 - });
451 - });
452 -
453 -After this, we have in `toplevel` a big AST containing all our files, with
454 -each token having proper information about where it came from.
455 -
456 -#### Scope information
457 -
458 -UglifyJS contains a scope analyzer that you need to call manually before
459 -compressing or mangling. Basically it augments various nodes in the AST
460 -with information about where is a name defined, how many times is a name
461 -referenced, if it is a global or not, if a function is using `eval` or the
462 -`with` statement etc. I will discuss this some place else, for now what's
463 -important to know is that you need to call the following before doing
464 -anything with the tree:
465 -
466 - toplevel.figure_out_scope()
467 -
468 -#### Compression
469 -
470 -Like this:
471 -
472 - var compressor = UglifyJS.Compressor(options);
473 - var compressed_ast = toplevel.transform(compressor);
474 -
475 -The `options` can be missing. Available options are discussed above in
476 -“Compressor options”. Defaults should lead to best compression in most
477 -scripts.
478 -
479 -The compressor is destructive, so don't rely that `toplevel` remains the
480 -original tree.
481 -
482 -#### Mangling
483 -
484 -After compression it is a good idea to call again `figure_out_scope` (since
485 -the compressor might drop unused variables / unreachable code and this might
486 -change the number of identifiers or their position). Optionally, you can
487 -call a trick that helps after Gzip (counting character frequency in
488 -non-mangleable words). Example:
489 -
490 - compressed_ast.figure_out_scope();
491 - compressed_ast.compute_char_frequency();
492 - compressed_ast.mangle_names();
493 -
494 -#### Generating output
495 -
496 -AST nodes have a `print` method that takes an output stream. Essentially,
497 -to generate code you do this:
498 -
499 - var stream = UglifyJS.OutputStream(options);
500 - compressed_ast.print(stream);
501 - var code = stream.toString(); // this is your minified code
502 -
503 -or, for a shortcut you can do:
504 -
505 - var code = compressed_ast.print_to_string(options);
506 -
507 -As usual, `options` is optional. The output stream accepts a lot of otions,
508 -most of them documented above in section “Beautifier options”. The two
509 -which we care about here are `source_map` and `comments`.
510 -
511 -#### Keeping comments in the output
512 -
513 -In order to keep certain comments in the output you need to pass the
514 -`comments` option. Pass a RegExp or a function. If you pass a RegExp, only
515 -those comments whose body matches the regexp will be kept. Note that body
516 -means without the initial `//` or `/*`. If you pass a function, it will be
517 -called for every comment in the tree and will receive two arguments: the
518 -node that the comment is attached to, and the comment token itself.
519 -
520 -The comment token has these properties:
521 -
522 -- `type`: "comment1" for single-line comments or "comment2" for multi-line
523 - comments
524 -- `value`: the comment body
525 -- `pos` and `endpos`: the start/end positions (zero-based indexes) in the
526 - original code where this comment appears
527 -- `line` and `col`: the line and column where this comment appears in the
528 - original code
529 -- `file` — the file name of the original file
530 -- `nlb` — true if there was a newline before this comment in the original
531 - code, or if this comment contains a newline.
532 -
533 -Your function should return `true` to keep the comment, or a falsy value
534 -otherwise.
535 -
536 -#### Generating a source mapping
537 -
538 -You need to pass the `source_map` argument when calling `print`. It needs
539 -to be a `SourceMap` object (which is a thin wrapper on top of the
540 -[source-map][source-map] library).
541 -
542 -Example:
543 -
544 - var source_map = UglifyJS.SourceMap(source_map_options);
545 - var stream = UglifyJS.OutputStream({
546 - ...
547 - source_map: source_map
548 - });
549 - compressed_ast.print(stream);
550 -
551 - var code = stream.toString();
552 - var map = source_map.toString(); // json output for your source map
553 -
554 -The `source_map_options` (optional) can contain the following properties:
555 -
556 -- `file`: the name of the JavaScript output file that this mapping refers to
557 -- `root`: the `sourceRoot` property (see the [spec][sm-spec])
558 -- `orig`: the "original source map", handy when you compress generated JS
559 - and want to map the minified output back to the original code where it
560 - came from. It can be simply a string in JSON, or a JSON object containing
561 - the original source map.
562 -
563 - [acorn]: https://github.com/marijnh/acorn
564 - [source-map]: https://github.com/mozilla/source-map
565 - [sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
566 - [codegen]: http://lisperator.net/uglifyjs/codegen
567 - [compressor]: http://lisperator.net/uglifyjs/compress
1 -#! /usr/bin/env node
2 -// -*- js -*-
3 -
4 -"use strict";
5 -
6 -var UglifyJS = require("../tools/node");
7 -var sys = require("util");
8 -var optimist = require("optimist");
9 -var fs = require("fs");
10 -var async = require("async");
11 -var acorn;
12 -var ARGS = optimist
13 - .usage("$0 input1.js [input2.js ...] [options]\n\
14 -Use a single dash to read input from the standard input.\
15 -\n\n\
16 -NOTE: by default there is no mangling/compression.\n\
17 -Without [options] it will simply parse input files and dump the AST\n\
18 -with whitespace and comments discarded. To achieve compression and\n\
19 -mangling you need to use `-c` and `-m`.\
20 -")
21 - .describe("source-map", "Specify an output file where to generate source map.")
22 - .describe("source-map-root", "The path to the original source to be included in the source map.")
23 - .describe("source-map-url", "The path to the source map to be added in //@ sourceMappingURL. Defaults to the value passed with --source-map.")
24 - .describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
25 - .describe("screw-ie8", "Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof).")
26 - .describe("p", "Skip prefix for original filenames that appear in source maps. \
27 -For example -p 3 will drop 3 directories from file names and ensure they are relative paths.")
28 - .describe("o", "Output file (default STDOUT).")
29 - .describe("b", "Beautify output/specify output options.")
30 - .describe("m", "Mangle names/pass mangler options.")
31 - .describe("r", "Reserved names to exclude from mangling.")
32 - .describe("c", "Enable compressor/pass compressor options. \
33 -Pass options like -c hoist_vars=false,if_return=false. \
34 -Use -c with no argument to use the default compression options.")
35 - .describe("d", "Global definitions")
36 - .describe("e", "Embed everything in a big function, with a configurable parameter/argument list.")
37 -
38 - .describe("comments", "Preserve copyright comments in the output. \
39 -By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
40 -You can optionally pass one of the following arguments to this flag:\n\
41 -- \"all\" to keep all comments\n\
42 -- a valid JS regexp (needs to start with a slash) to keep only comments that match.\n\
43 -\
44 -Note that currently not *all* comments can be kept when compression is on, \
45 -because of dead code removal or cascading statements into sequences.")
46 -
47 - .describe("stats", "Display operations run time on STDERR.")
48 - .describe("acorn", "Use Acorn for parsing.")
49 - .describe("spidermonkey", "Assume input fles are SpiderMonkey AST format (as JSON).")
50 - .describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)")
51 - .describe("wrap", "Embed everything in a big function, making the “exports” and “global” variables available. \
52 -You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.")
53 - .describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
54 - .describe("lint", "Display some scope warnings")
55 - .describe("v", "Verbose")
56 - .describe("V", "Print version number and exit.")
57 -
58 - .alias("p", "prefix")
59 - .alias("o", "output")
60 - .alias("v", "verbose")
61 - .alias("b", "beautify")
62 - .alias("m", "mangle")
63 - .alias("c", "compress")
64 - .alias("d", "define")
65 - .alias("r", "reserved")
66 - .alias("V", "version")
67 - .alias("e", "enclose")
68 -
69 - .string("source-map")
70 - .string("source-map-root")
71 - .string("source-map-url")
72 - .string("b")
73 - .string("m")
74 - .string("c")
75 - .string("d")
76 - .string("e")
77 - .string("comments")
78 - .string("wrap")
79 - .boolean("screw-ie8")
80 - .boolean("export-all")
81 - .boolean("self")
82 - .boolean("v")
83 - .boolean("stats")
84 - .boolean("acorn")
85 - .boolean("spidermonkey")
86 - .boolean("lint")
87 - .boolean("V")
88 -
89 - .wrap(80)
90 -
91 - .argv
92 -;
93 -
94 -normalize(ARGS);
95 -
96 -if (ARGS.version || ARGS.V) {
97 - var json = require("../package.json");
98 - sys.puts(json.name + ' ' + json.version);
99 - process.exit(0);
100 -}
101 -
102 -if (ARGS.ast_help) {
103 - var desc = UglifyJS.describe_ast();
104 - sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
105 - process.exit(0);
106 -}
107 -
108 -if (ARGS.h || ARGS.help) {
109 - sys.puts(optimist.help());
110 - process.exit(0);
111 -}
112 -
113 -if (ARGS.acorn) {
114 - acorn = require("acorn");
115 -}
116 -
117 -var COMPRESS = getOptions("c", true);
118 -var MANGLE = getOptions("m", true);
119 -var BEAUTIFY = getOptions("b", true);
120 -
121 -if (ARGS.d) {
122 - if (COMPRESS) COMPRESS.global_defs = getOptions("d");
123 -}
124 -
125 -if (ARGS.screw_ie8) {
126 - if (COMPRESS) COMPRESS.screw_ie8 = true;
127 - if (MANGLE) MANGLE.screw_ie8 = true;
128 -}
129 -
130 -if (ARGS.r) {
131 - if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
132 -}
133 -
134 -var OUTPUT_OPTIONS = {
135 - beautify: BEAUTIFY ? true : false
136 -};
137 -
138 -if (BEAUTIFY)
139 - UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
140 -
141 -if (ARGS.comments) {
142 - if (/^\//.test(ARGS.comments)) {
143 - OUTPUT_OPTIONS.comments = new Function("return(" + ARGS.comments + ")")();
144 - } else if (ARGS.comments == "all") {
145 - OUTPUT_OPTIONS.comments = true;
146 - } else {
147 - OUTPUT_OPTIONS.comments = function(node, comment) {
148 - var text = comment.value;
149 - var type = comment.type;
150 - if (type == "comment2") {
151 - // multiline comment
152 - return /@preserve|@license|@cc_on/i.test(text);
153 - }
154 - }
155 - }
156 -}
157 -
158 -var files = ARGS._.slice();
159 -
160 -if (ARGS.self) {
161 - if (files.length > 0) {
162 - sys.error("WARN: Ignoring input files since --self was passed");
163 - }
164 - files = UglifyJS.FILES;
165 - if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
166 - ARGS.export_all = true;
167 -}
168 -
169 -var ORIG_MAP = ARGS.in_source_map;
170 -
171 -if (ORIG_MAP) {
172 - ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
173 - if (files.length == 0) {
174 - sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file);
175 - files = [ ORIG_MAP.file ];
176 - }
177 - if (ARGS.source_map_root == null) {
178 - ARGS.source_map_root = ORIG_MAP.sourceRoot;
179 - }
180 -}
181 -
182 -if (files.length == 0) {
183 - files = [ "-" ];
184 -}
185 -
186 -if (files.indexOf("-") >= 0 && ARGS.source_map) {
187 - sys.error("ERROR: Source map doesn't work with input from STDIN");
188 - process.exit(1);
189 -}
190 -
191 -if (files.filter(function(el){ return el == "-" }).length > 1) {
192 - sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
193 - process.exit(1);
194 -}
195 -
196 -var STATS = {};
197 -var OUTPUT_FILE = ARGS.o;
198 -var TOPLEVEL = null;
199 -
200 -var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
201 - file: OUTPUT_FILE,
202 - root: ARGS.source_map_root,
203 - orig: ORIG_MAP,
204 -}) : null;
205 -
206 -OUTPUT_OPTIONS.source_map = SOURCE_MAP;
207 -
208 -try {
209 - var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
210 - var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
211 -} catch(ex) {
212 - if (ex instanceof UglifyJS.DefaultsError) {
213 - sys.error(ex.msg);
214 - sys.error("Supported options:");
215 - sys.error(sys.inspect(ex.defs));
216 - process.exit(1);
217 - }
218 -}
219 -
220 -async.eachLimit(files, 1, function (file, cb) {
221 - read_whole_file(file, function (err, code) {
222 - if (err) {
223 - sys.error("ERROR: can't read file: " + filename);
224 - process.exit(1);
225 - }
226 - if (ARGS.p != null) {
227 - file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
228 - }
229 - time_it("parse", function(){
230 - if (ARGS.spidermonkey) {
231 - var program = JSON.parse(code);
232 - if (!TOPLEVEL) TOPLEVEL = program;
233 - else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
234 - }
235 - else if (ARGS.acorn) {
236 - TOPLEVEL = acorn.parse(code, {
237 - locations : true,
238 - trackComments : true,
239 - sourceFile : file,
240 - program : TOPLEVEL
241 - });
242 - }
243 - else {
244 - TOPLEVEL = UglifyJS.parse(code, {
245 - filename: file,
246 - toplevel: TOPLEVEL
247 - });
248 - };
249 - });
250 - cb();
251 - });
252 -}, function () {
253 - if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
254 - TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
255 - });
256 -
257 - if (ARGS.wrap) {
258 - TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
259 - }
260 -
261 - if (ARGS.enclose) {
262 - var arg_parameter_list = ARGS.enclose;
263 -
264 - if (!(arg_parameter_list instanceof Array)) {
265 - arg_parameter_list = [arg_parameter_list];
266 - }
267 -
268 - TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
269 - }
270 -
271 - var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
272 -
273 - if (SCOPE_IS_NEEDED) {
274 - time_it("scope", function(){
275 - TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
276 - if (ARGS.lint) {
277 - TOPLEVEL.scope_warnings();
278 - }
279 - });
280 - }
281 -
282 - if (COMPRESS) {
283 - time_it("squeeze", function(){
284 - TOPLEVEL = TOPLEVEL.transform(compressor);
285 - });
286 - }
287 -
288 - if (SCOPE_IS_NEEDED) {
289 - time_it("scope", function(){
290 - TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
291 - if (MANGLE) {
292 - TOPLEVEL.compute_char_frequency(MANGLE);
293 - }
294 - });
295 - }
296 -
297 - if (MANGLE) time_it("mangle", function(){
298 - TOPLEVEL.mangle_names(MANGLE);
299 - });
300 - time_it("generate", function(){
301 - TOPLEVEL.print(output);
302 - });
303 -
304 - output = output.get();
305 -
306 - if (SOURCE_MAP) {
307 - fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
308 - output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/";
309 - }
310 -
311 - if (OUTPUT_FILE) {
312 - fs.writeFileSync(OUTPUT_FILE, output, "utf8");
313 - } else {
314 - sys.print(output);
315 - sys.error("\n");
316 - }
317 -
318 - if (ARGS.stats) {
319 - sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", {
320 - count: files.length
321 - }));
322 - for (var i in STATS) if (STATS.hasOwnProperty(i)) {
323 - sys.error(UglifyJS.string_template("- {name}: {time}s", {
324 - name: i,
325 - time: (STATS[i] / 1000).toFixed(3)
326 - }));
327 - }
328 - }
329 -});
330 -
331 -/* -----[ functions ]----- */
332 -
333 -function normalize(o) {
334 - for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
335 - o[i.replace(/-/g, "_")] = o[i];
336 - delete o[i];
337 - }
338 -}
339 -
340 -function getOptions(x, constants) {
341 - x = ARGS[x];
342 - if (!x) return null;
343 - var ret = {};
344 - if (x !== true) {
345 - var ast;
346 - try {
347 - ast = UglifyJS.parse(x);
348 - } catch(ex) {
349 - if (ex instanceof UglifyJS.JS_Parse_Error) {
350 - sys.error("Error parsing arguments in: " + x);
351 - process.exit(1);
352 - }
353 - }
354 - ast.walk(new UglifyJS.TreeWalker(function(node){
355 - if (node instanceof UglifyJS.AST_Toplevel) return; // descend
356 - if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend
357 - if (node instanceof UglifyJS.AST_Seq) return; // descend
358 - if (node instanceof UglifyJS.AST_Assign) {
359 - var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_");
360 - var value = node.right;
361 - if (constants)
362 - value = new Function("return (" + value.print_to_string() + ")")();
363 - ret[name] = value;
364 - return true; // no descend
365 - }
366 - sys.error(node.TYPE)
367 - sys.error("Error parsing arguments in: " + x);
368 - process.exit(1);
369 - }));
370 - }
371 - return ret;
372 -}
373 -
374 -function read_whole_file(filename, cb) {
375 - if (filename == "-") {
376 - var chunks = [];
377 - process.stdin.setEncoding('utf-8');
378 - process.stdin.on('data', function (chunk) {
379 - chunks.push(chunk);
380 - }).on('end', function () {
381 - cb(null, chunks.join(""));
382 - });
383 - process.openStdin();
384 - } else {
385 - fs.readFile(filename, "utf-8", cb);
386 - }
387 -}
388 -
389 -function time_it(name, cont) {
390 - var t1 = new Date().getTime();
391 - var ret = cont();
392 - if (ARGS.stats) {
393 - var spent = new Date().getTime() - t1;
394 - if (STATS[name]) STATS[name] += spent;
395 - else STATS[name] = spent;
396 - }
397 - return ret;
398 -}
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -function DEFNODE(type, props, methods, base) {
47 - if (arguments.length < 4) base = AST_Node;
48 - if (!props) props = [];
49 - else props = props.split(/\s+/);
50 - var self_props = props;
51 - if (base && base.PROPS)
52 - props = props.concat(base.PROPS);
53 - var code = "return function AST_" + type + "(props){ if (props) { ";
54 - for (var i = props.length; --i >= 0;) {
55 - code += "this." + props[i] + " = props." + props[i] + ";";
56 - }
57 - var proto = base && new base;
58 - if (proto && proto.initialize || (methods && methods.initialize))
59 - code += "this.initialize();";
60 - code += "}}";
61 - var ctor = new Function(code)();
62 - if (proto) {
63 - ctor.prototype = proto;
64 - ctor.BASE = base;
65 - }
66 - if (base) base.SUBCLASSES.push(ctor);
67 - ctor.prototype.CTOR = ctor;
68 - ctor.PROPS = props || null;
69 - ctor.SELF_PROPS = self_props;
70 - ctor.SUBCLASSES = [];
71 - if (type) {
72 - ctor.prototype.TYPE = ctor.TYPE = type;
73 - }
74 - if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
75 - if (/^\$/.test(i)) {
76 - ctor[i.substr(1)] = methods[i];
77 - } else {
78 - ctor.prototype[i] = methods[i];
79 - }
80 - }
81 - ctor.DEFMETHOD = function(name, method) {
82 - this.prototype[name] = method;
83 - };
84 - return ctor;
85 -};
86 -
87 -var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {
88 -}, null);
89 -
90 -var AST_Node = DEFNODE("Node", "start end", {
91 - clone: function() {
92 - return new this.CTOR(this);
93 - },
94 - $documentation: "Base class of all AST nodes",
95 - $propdoc: {
96 - start: "[AST_Token] The first token of this node",
97 - end: "[AST_Token] The last token of this node"
98 - },
99 - _walk: function(visitor) {
100 - return visitor._visit(this);
101 - },
102 - walk: function(visitor) {
103 - return this._walk(visitor); // not sure the indirection will be any help
104 - }
105 -}, null);
106 -
107 -AST_Node.warn_function = null;
108 -AST_Node.warn = function(txt, props) {
109 - if (AST_Node.warn_function)
110 - AST_Node.warn_function(string_template(txt, props));
111 -};
112 -
113 -/* -----[ statements ]----- */
114 -
115 -var AST_Statement = DEFNODE("Statement", null, {
116 - $documentation: "Base class of all statements",
117 -});
118 -
119 -var AST_Debugger = DEFNODE("Debugger", null, {
120 - $documentation: "Represents a debugger statement",
121 -}, AST_Statement);
122 -
123 -var AST_Directive = DEFNODE("Directive", "value scope", {
124 - $documentation: "Represents a directive, like \"use strict\";",
125 - $propdoc: {
126 - value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
127 - scope: "[AST_Scope/S] The scope that this directive affects"
128 - },
129 -}, AST_Statement);
130 -
131 -var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
132 - $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
133 - $propdoc: {
134 - body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
135 - },
136 - _walk: function(visitor) {
137 - return visitor._visit(this, function(){
138 - this.body._walk(visitor);
139 - });
140 - }
141 -}, AST_Statement);
142 -
143 -function walk_body(node, visitor) {
144 - if (node.body instanceof AST_Statement) {
145 - node.body._walk(visitor);
146 - }
147 - else node.body.forEach(function(stat){
148 - stat._walk(visitor);
149 - });
150 -};
151 -
152 -var AST_Block = DEFNODE("Block", "body", {
153 - $documentation: "A body of statements (usually bracketed)",
154 - $propdoc: {
155 - body: "[AST_Statement*] an array of statements"
156 - },
157 - _walk: function(visitor) {
158 - return visitor._visit(this, function(){
159 - walk_body(this, visitor);
160 - });
161 - }
162 -}, AST_Statement);
163 -
164 -var AST_BlockStatement = DEFNODE("BlockStatement", null, {
165 - $documentation: "A block statement",
166 -}, AST_Block);
167 -
168 -var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
169 - $documentation: "The empty statement (empty block or simply a semicolon)",
170 - _walk: function(visitor) {
171 - return visitor._visit(this);
172 - }
173 -}, AST_Statement);
174 -
175 -var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
176 - $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
177 - $propdoc: {
178 - body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
179 - },
180 - _walk: function(visitor) {
181 - return visitor._visit(this, function(){
182 - this.body._walk(visitor);
183 - });
184 - }
185 -}, AST_Statement);
186 -
187 -var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
188 - $documentation: "Statement with a label",
189 - $propdoc: {
190 - label: "[AST_Label] a label definition"
191 - },
192 - _walk: function(visitor) {
193 - return visitor._visit(this, function(){
194 - this.label._walk(visitor);
195 - this.body._walk(visitor);
196 - });
197 - }
198 -}, AST_StatementWithBody);
199 -
200 -var AST_DWLoop = DEFNODE("DWLoop", "condition", {
201 - $documentation: "Base class for do/while statements",
202 - $propdoc: {
203 - condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
204 - },
205 - _walk: function(visitor) {
206 - return visitor._visit(this, function(){
207 - this.condition._walk(visitor);
208 - this.body._walk(visitor);
209 - });
210 - }
211 -}, AST_StatementWithBody);
212 -
213 -var AST_Do = DEFNODE("Do", null, {
214 - $documentation: "A `do` statement",
215 -}, AST_DWLoop);
216 -
217 -var AST_While = DEFNODE("While", null, {
218 - $documentation: "A `while` statement",
219 -}, AST_DWLoop);
220 -
221 -var AST_For = DEFNODE("For", "init condition step", {
222 - $documentation: "A `for` statement",
223 - $propdoc: {
224 - init: "[AST_Node?] the `for` initialization code, or null if empty",
225 - condition: "[AST_Node?] the `for` termination clause, or null if empty",
226 - step: "[AST_Node?] the `for` update clause, or null if empty"
227 - },
228 - _walk: function(visitor) {
229 - return visitor._visit(this, function(){
230 - if (this.init) this.init._walk(visitor);
231 - if (this.condition) this.condition._walk(visitor);
232 - if (this.step) this.step._walk(visitor);
233 - this.body._walk(visitor);
234 - });
235 - }
236 -}, AST_StatementWithBody);
237 -
238 -var AST_ForIn = DEFNODE("ForIn", "init name object", {
239 - $documentation: "A `for ... in` statement",
240 - $propdoc: {
241 - init: "[AST_Node] the `for/in` initialization code",
242 - name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
243 - object: "[AST_Node] the object that we're looping through"
244 - },
245 - _walk: function(visitor) {
246 - return visitor._visit(this, function(){
247 - this.init._walk(visitor);
248 - this.object._walk(visitor);
249 - this.body._walk(visitor);
250 - });
251 - }
252 -}, AST_StatementWithBody);
253 -
254 -var AST_With = DEFNODE("With", "expression", {
255 - $documentation: "A `with` statement",
256 - $propdoc: {
257 - expression: "[AST_Node] the `with` expression"
258 - },
259 - _walk: function(visitor) {
260 - return visitor._visit(this, function(){
261 - this.expression._walk(visitor);
262 - this.body._walk(visitor);
263 - });
264 - }
265 -}, AST_StatementWithBody);
266 -
267 -/* -----[ scope and functions ]----- */
268 -
269 -var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
270 - $documentation: "Base class for all statements introducing a lexical scope",
271 - $propdoc: {
272 - directives: "[string*/S] an array of directives declared in this scope",
273 - variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
274 - functions: "[Object/S] like `variables`, but only lists function declarations",
275 - uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
276 - uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
277 - parent_scope: "[AST_Scope?/S] link to the parent scope",
278 - enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
279 - cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
280 - },
281 -}, AST_Block);
282 -
283 -var AST_Toplevel = DEFNODE("Toplevel", "globals", {
284 - $documentation: "The toplevel scope",
285 - $propdoc: {
286 - globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
287 - },
288 - wrap_enclose: function(arg_parameter_pairs) {
289 - var self = this;
290 - var args = [];
291 - var parameters = [];
292 -
293 - arg_parameter_pairs.forEach(function(pair) {
294 - var split = pair.split(":");
295 -
296 - args.push(split[0]);
297 - parameters.push(split[1]);
298 - });
299 -
300 - var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
301 - wrapped_tl = parse(wrapped_tl);
302 - wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
303 - if (node instanceof AST_Directive && node.value == "$ORIG") {
304 - return MAP.splice(self.body);
305 - }
306 - }));
307 - return wrapped_tl;
308 - },
309 - wrap_commonjs: function(name, export_all) {
310 - var self = this;
311 - var to_export = [];
312 - if (export_all) {
313 - self.figure_out_scope();
314 - self.walk(new TreeWalker(function(node){
315 - if (node instanceof AST_SymbolDeclaration && node.definition().global) {
316 - if (!find_if(function(n){ return n.name == node.name }, to_export))
317 - to_export.push(node);
318 - }
319 - }));
320 - }
321 - var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
322 - wrapped_tl = parse(wrapped_tl);
323 - wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
324 - if (node instanceof AST_SimpleStatement) {
325 - node = node.body;
326 - if (node instanceof AST_String) switch (node.getValue()) {
327 - case "$ORIG":
328 - return MAP.splice(self.body);
329 - case "$EXPORTS":
330 - var body = [];
331 - to_export.forEach(function(sym){
332 - body.push(new AST_SimpleStatement({
333 - body: new AST_Assign({
334 - left: new AST_Sub({
335 - expression: new AST_SymbolRef({ name: "exports" }),
336 - property: new AST_String({ value: sym.name }),
337 - }),
338 - operator: "=",
339 - right: new AST_SymbolRef(sym),
340 - }),
341 - }));
342 - });
343 - return MAP.splice(body);
344 - }
345 - }
346 - }));
347 - return wrapped_tl;
348 - }
349 -}, AST_Scope);
350 -
351 -var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
352 - $documentation: "Base class for functions",
353 - $propdoc: {
354 - name: "[AST_SymbolDeclaration?] the name of this function",
355 - argnames: "[AST_SymbolFunarg*] array of function arguments",
356 - uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
357 - },
358 - _walk: function(visitor) {
359 - return visitor._visit(this, function(){
360 - if (this.name) this.name._walk(visitor);
361 - this.argnames.forEach(function(arg){
362 - arg._walk(visitor);
363 - });
364 - walk_body(this, visitor);
365 - });
366 - }
367 -}, AST_Scope);
368 -
369 -var AST_Accessor = DEFNODE("Accessor", null, {
370 - $documentation: "A setter/getter function"
371 -}, AST_Lambda);
372 -
373 -var AST_Function = DEFNODE("Function", null, {
374 - $documentation: "A function expression"
375 -}, AST_Lambda);
376 -
377 -var AST_Defun = DEFNODE("Defun", null, {
378 - $documentation: "A function definition"
379 -}, AST_Lambda);
380 -
381 -/* -----[ JUMPS ]----- */
382 -
383 -var AST_Jump = DEFNODE("Jump", null, {
384 - $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
385 -}, AST_Statement);
386 -
387 -var AST_Exit = DEFNODE("Exit", "value", {
388 - $documentation: "Base class for “exits” (`return` and `throw`)",
389 - $propdoc: {
390 - value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
391 - },
392 - _walk: function(visitor) {
393 - return visitor._visit(this, this.value && function(){
394 - this.value._walk(visitor);
395 - });
396 - }
397 -}, AST_Jump);
398 -
399 -var AST_Return = DEFNODE("Return", null, {
400 - $documentation: "A `return` statement"
401 -}, AST_Exit);
402 -
403 -var AST_Throw = DEFNODE("Throw", null, {
404 - $documentation: "A `throw` statement"
405 -}, AST_Exit);
406 -
407 -var AST_LoopControl = DEFNODE("LoopControl", "label", {
408 - $documentation: "Base class for loop control statements (`break` and `continue`)",
409 - $propdoc: {
410 - label: "[AST_LabelRef?] the label, or null if none",
411 - },
412 - _walk: function(visitor) {
413 - return visitor._visit(this, this.label && function(){
414 - this.label._walk(visitor);
415 - });
416 - }
417 -}, AST_Jump);
418 -
419 -var AST_Break = DEFNODE("Break", null, {
420 - $documentation: "A `break` statement"
421 -}, AST_LoopControl);
422 -
423 -var AST_Continue = DEFNODE("Continue", null, {
424 - $documentation: "A `continue` statement"
425 -}, AST_LoopControl);
426 -
427 -/* -----[ IF ]----- */
428 -
429 -var AST_If = DEFNODE("If", "condition alternative", {
430 - $documentation: "A `if` statement",
431 - $propdoc: {
432 - condition: "[AST_Node] the `if` condition",
433 - alternative: "[AST_Statement?] the `else` part, or null if not present"
434 - },
435 - _walk: function(visitor) {
436 - return visitor._visit(this, function(){
437 - this.condition._walk(visitor);
438 - this.body._walk(visitor);
439 - if (this.alternative) this.alternative._walk(visitor);
440 - });
441 - }
442 -}, AST_StatementWithBody);
443 -
444 -/* -----[ SWITCH ]----- */
445 -
446 -var AST_Switch = DEFNODE("Switch", "expression", {
447 - $documentation: "A `switch` statement",
448 - $propdoc: {
449 - expression: "[AST_Node] the `switch` “discriminant”"
450 - },
451 - _walk: function(visitor) {
452 - return visitor._visit(this, function(){
453 - this.expression._walk(visitor);
454 - walk_body(this, visitor);
455 - });
456 - }
457 -}, AST_Block);
458 -
459 -var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
460 - $documentation: "Base class for `switch` branches",
461 -}, AST_Block);
462 -
463 -var AST_Default = DEFNODE("Default", null, {
464 - $documentation: "A `default` switch branch",
465 -}, AST_SwitchBranch);
466 -
467 -var AST_Case = DEFNODE("Case", "expression", {
468 - $documentation: "A `case` switch branch",
469 - $propdoc: {
470 - expression: "[AST_Node] the `case` expression"
471 - },
472 - _walk: function(visitor) {
473 - return visitor._visit(this, function(){
474 - this.expression._walk(visitor);
475 - walk_body(this, visitor);
476 - });
477 - }
478 -}, AST_SwitchBranch);
479 -
480 -/* -----[ EXCEPTIONS ]----- */
481 -
482 -var AST_Try = DEFNODE("Try", "bcatch bfinally", {
483 - $documentation: "A `try` statement",
484 - $propdoc: {
485 - bcatch: "[AST_Catch?] the catch block, or null if not present",
486 - bfinally: "[AST_Finally?] the finally block, or null if not present"
487 - },
488 - _walk: function(visitor) {
489 - return visitor._visit(this, function(){
490 - walk_body(this, visitor);
491 - if (this.bcatch) this.bcatch._walk(visitor);
492 - if (this.bfinally) this.bfinally._walk(visitor);
493 - });
494 - }
495 -}, AST_Block);
496 -
497 -// XXX: this is wrong according to ECMA-262 (12.4). the catch block
498 -// should introduce another scope, as the argname should be visible
499 -// only inside the catch block. However, doing it this way because of
500 -// IE which simply introduces the name in the surrounding scope. If
501 -// we ever want to fix this then AST_Catch should inherit from
502 -// AST_Scope.
503 -var AST_Catch = DEFNODE("Catch", "argname", {
504 - $documentation: "A `catch` node; only makes sense as part of a `try` statement",
505 - $propdoc: {
506 - argname: "[AST_SymbolCatch] symbol for the exception"
507 - },
508 - _walk: function(visitor) {
509 - return visitor._visit(this, function(){
510 - this.argname._walk(visitor);
511 - walk_body(this, visitor);
512 - });
513 - }
514 -}, AST_Block);
515 -
516 -var AST_Finally = DEFNODE("Finally", null, {
517 - $documentation: "A `finally` node; only makes sense as part of a `try` statement"
518 -}, AST_Block);
519 -
520 -/* -----[ VAR/CONST ]----- */
521 -
522 -var AST_Definitions = DEFNODE("Definitions", "definitions", {
523 - $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
524 - $propdoc: {
525 - definitions: "[AST_VarDef*] array of variable definitions"
526 - },
527 - _walk: function(visitor) {
528 - return visitor._visit(this, function(){
529 - this.definitions.forEach(function(def){
530 - def._walk(visitor);
531 - });
532 - });
533 - }
534 -}, AST_Statement);
535 -
536 -var AST_Var = DEFNODE("Var", null, {
537 - $documentation: "A `var` statement"
538 -}, AST_Definitions);
539 -
540 -var AST_Const = DEFNODE("Const", null, {
541 - $documentation: "A `const` statement"
542 -}, AST_Definitions);
543 -
544 -var AST_VarDef = DEFNODE("VarDef", "name value", {
545 - $documentation: "A variable declaration; only appears in a AST_Definitions node",
546 - $propdoc: {
547 - name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
548 - value: "[AST_Node?] initializer, or null of there's no initializer"
549 - },
550 - _walk: function(visitor) {
551 - return visitor._visit(this, function(){
552 - this.name._walk(visitor);
553 - if (this.value) this.value._walk(visitor);
554 - });
555 - }
556 -});
557 -
558 -/* -----[ OTHER ]----- */
559 -
560 -var AST_Call = DEFNODE("Call", "expression args", {
561 - $documentation: "A function call expression",
562 - $propdoc: {
563 - expression: "[AST_Node] expression to invoke as function",
564 - args: "[AST_Node*] array of arguments"
565 - },
566 - _walk: function(visitor) {
567 - return visitor._visit(this, function(){
568 - this.expression._walk(visitor);
569 - this.args.forEach(function(arg){
570 - arg._walk(visitor);
571 - });
572 - });
573 - }
574 -});
575 -
576 -var AST_New = DEFNODE("New", null, {
577 - $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
578 -}, AST_Call);
579 -
580 -var AST_Seq = DEFNODE("Seq", "car cdr", {
581 - $documentation: "A sequence expression (two comma-separated expressions)",
582 - $propdoc: {
583 - car: "[AST_Node] first element in sequence",
584 - cdr: "[AST_Node] second element in sequence"
585 - },
586 - $cons: function(x, y) {
587 - var seq = new AST_Seq(x);
588 - seq.car = x;
589 - seq.cdr = y;
590 - return seq;
591 - },
592 - $from_array: function(array) {
593 - if (array.length == 0) return null;
594 - if (array.length == 1) return array[0].clone();
595 - var list = null;
596 - for (var i = array.length; --i >= 0;) {
597 - list = AST_Seq.cons(array[i], list);
598 - }
599 - var p = list;
600 - while (p) {
601 - if (p.cdr && !p.cdr.cdr) {
602 - p.cdr = p.cdr.car;
603 - break;
604 - }
605 - p = p.cdr;
606 - }
607 - return list;
608 - },
609 - to_array: function() {
610 - var p = this, a = [];
611 - while (p) {
612 - a.push(p.car);
613 - if (p.cdr && !(p.cdr instanceof AST_Seq)) {
614 - a.push(p.cdr);
615 - break;
616 - }
617 - p = p.cdr;
618 - }
619 - return a;
620 - },
621 - add: function(node) {
622 - var p = this;
623 - while (p) {
624 - if (!(p.cdr instanceof AST_Seq)) {
625 - var cell = AST_Seq.cons(p.cdr, node);
626 - return p.cdr = cell;
627 - }
628 - p = p.cdr;
629 - }
630 - },
631 - _walk: function(visitor) {
632 - return visitor._visit(this, function(){
633 - this.car._walk(visitor);
634 - if (this.cdr) this.cdr._walk(visitor);
635 - });
636 - }
637 -});
638 -
639 -var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
640 - $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
641 - $propdoc: {
642 - expression: "[AST_Node] the “container” expression",
643 - property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
644 - }
645 -});
646 -
647 -var AST_Dot = DEFNODE("Dot", null, {
648 - $documentation: "A dotted property access expression",
649 - _walk: function(visitor) {
650 - return visitor._visit(this, function(){
651 - this.expression._walk(visitor);
652 - });
653 - }
654 -}, AST_PropAccess);
655 -
656 -var AST_Sub = DEFNODE("Sub", null, {
657 - $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
658 - _walk: function(visitor) {
659 - return visitor._visit(this, function(){
660 - this.expression._walk(visitor);
661 - this.property._walk(visitor);
662 - });
663 - }
664 -}, AST_PropAccess);
665 -
666 -var AST_Unary = DEFNODE("Unary", "operator expression", {
667 - $documentation: "Base class for unary expressions",
668 - $propdoc: {
669 - operator: "[string] the operator",
670 - expression: "[AST_Node] expression that this unary operator applies to"
671 - },
672 - _walk: function(visitor) {
673 - return visitor._visit(this, function(){
674 - this.expression._walk(visitor);
675 - });
676 - }
677 -});
678 -
679 -var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
680 - $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
681 -}, AST_Unary);
682 -
683 -var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
684 - $documentation: "Unary postfix expression, i.e. `i++`"
685 -}, AST_Unary);
686 -
687 -var AST_Binary = DEFNODE("Binary", "left operator right", {
688 - $documentation: "Binary expression, i.e. `a + b`",
689 - $propdoc: {
690 - left: "[AST_Node] left-hand side expression",
691 - operator: "[string] the operator",
692 - right: "[AST_Node] right-hand side expression"
693 - },
694 - _walk: function(visitor) {
695 - return visitor._visit(this, function(){
696 - this.left._walk(visitor);
697 - this.right._walk(visitor);
698 - });
699 - }
700 -});
701 -
702 -var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
703 - $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
704 - $propdoc: {
705 - condition: "[AST_Node]",
706 - consequent: "[AST_Node]",
707 - alternative: "[AST_Node]"
708 - },
709 - _walk: function(visitor) {
710 - return visitor._visit(this, function(){
711 - this.condition._walk(visitor);
712 - this.consequent._walk(visitor);
713 - this.alternative._walk(visitor);
714 - });
715 - }
716 -});
717 -
718 -var AST_Assign = DEFNODE("Assign", null, {
719 - $documentation: "An assignment expression — `a = b + 5`",
720 -}, AST_Binary);
721 -
722 -/* -----[ LITERALS ]----- */
723 -
724 -var AST_Array = DEFNODE("Array", "elements", {
725 - $documentation: "An array literal",
726 - $propdoc: {
727 - elements: "[AST_Node*] array of elements"
728 - },
729 - _walk: function(visitor) {
730 - return visitor._visit(this, function(){
731 - this.elements.forEach(function(el){
732 - el._walk(visitor);
733 - });
734 - });
735 - }
736 -});
737 -
738 -var AST_Object = DEFNODE("Object", "properties", {
739 - $documentation: "An object literal",
740 - $propdoc: {
741 - properties: "[AST_ObjectProperty*] array of properties"
742 - },
743 - _walk: function(visitor) {
744 - return visitor._visit(this, function(){
745 - this.properties.forEach(function(prop){
746 - prop._walk(visitor);
747 - });
748 - });
749 - }
750 -});
751 -
752 -var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
753 - $documentation: "Base class for literal object properties",
754 - $propdoc: {
755 - key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code",
756 - value: "[AST_Node] property value. For setters and getters this is an AST_Function."
757 - },
758 - _walk: function(visitor) {
759 - return visitor._visit(this, function(){
760 - this.value._walk(visitor);
761 - });
762 - }
763 -});
764 -
765 -var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
766 - $documentation: "A key: value object property",
767 -}, AST_ObjectProperty);
768 -
769 -var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
770 - $documentation: "An object setter property",
771 -}, AST_ObjectProperty);
772 -
773 -var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
774 - $documentation: "An object getter property",
775 -}, AST_ObjectProperty);
776 -
777 -var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
778 - $propdoc: {
779 - name: "[string] name of this symbol",
780 - scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
781 - thedef: "[SymbolDef/S] the definition of this symbol"
782 - },
783 - $documentation: "Base class for all symbols",
784 -});
785 -
786 -var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
787 - $documentation: "The name of a property accessor (setter/getter function)"
788 -}, AST_Symbol);
789 -
790 -var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
791 - $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
792 - $propdoc: {
793 - init: "[AST_Node*/S] array of initializers for this declaration."
794 - }
795 -}, AST_Symbol);
796 -
797 -var AST_SymbolVar = DEFNODE("SymbolVar", null, {
798 - $documentation: "Symbol defining a variable",
799 -}, AST_SymbolDeclaration);
800 -
801 -var AST_SymbolConst = DEFNODE("SymbolConst", null, {
802 - $documentation: "A constant declaration"
803 -}, AST_SymbolDeclaration);
804 -
805 -var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
806 - $documentation: "Symbol naming a function argument",
807 -}, AST_SymbolVar);
808 -
809 -var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
810 - $documentation: "Symbol defining a function",
811 -}, AST_SymbolDeclaration);
812 -
813 -var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
814 - $documentation: "Symbol naming a function expression",
815 -}, AST_SymbolDeclaration);
816 -
817 -var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
818 - $documentation: "Symbol naming the exception in catch",
819 -}, AST_SymbolDeclaration);
820 -
821 -var AST_Label = DEFNODE("Label", "references", {
822 - $documentation: "Symbol naming a label (declaration)",
823 - $propdoc: {
824 - references: "[AST_LabelRef*] a list of nodes referring to this label"
825 - }
826 -}, AST_Symbol);
827 -
828 -var AST_SymbolRef = DEFNODE("SymbolRef", null, {
829 - $documentation: "Reference to some symbol (not definition/declaration)",
830 -}, AST_Symbol);
831 -
832 -var AST_LabelRef = DEFNODE("LabelRef", null, {
833 - $documentation: "Reference to a label symbol",
834 -}, AST_Symbol);
835 -
836 -var AST_This = DEFNODE("This", null, {
837 - $documentation: "The `this` symbol",
838 -}, AST_Symbol);
839 -
840 -var AST_Constant = DEFNODE("Constant", null, {
841 - $documentation: "Base class for all constants",
842 - getValue: function() {
843 - return this.value;
844 - }
845 -});
846 -
847 -var AST_String = DEFNODE("String", "value", {
848 - $documentation: "A string literal",
849 - $propdoc: {
850 - value: "[string] the contents of this string"
851 - }
852 -}, AST_Constant);
853 -
854 -var AST_Number = DEFNODE("Number", "value", {
855 - $documentation: "A number literal",
856 - $propdoc: {
857 - value: "[number] the numeric value"
858 - }
859 -}, AST_Constant);
860 -
861 -var AST_RegExp = DEFNODE("RegExp", "value", {
862 - $documentation: "A regexp literal",
863 - $propdoc: {
864 - value: "[RegExp] the actual regexp"
865 - }
866 -}, AST_Constant);
867 -
868 -var AST_Atom = DEFNODE("Atom", null, {
869 - $documentation: "Base class for atoms",
870 -}, AST_Constant);
871 -
872 -var AST_Null = DEFNODE("Null", null, {
873 - $documentation: "The `null` atom",
874 - value: null
875 -}, AST_Atom);
876 -
877 -var AST_NaN = DEFNODE("NaN", null, {
878 - $documentation: "The impossible value",
879 - value: 0/0
880 -}, AST_Atom);
881 -
882 -var AST_Undefined = DEFNODE("Undefined", null, {
883 - $documentation: "The `undefined` value",
884 - value: (function(){}())
885 -}, AST_Atom);
886 -
887 -var AST_Hole = DEFNODE("Hole", null, {
888 - $documentation: "A hole in an array",
889 - value: (function(){}())
890 -}, AST_Atom);
891 -
892 -var AST_Infinity = DEFNODE("Infinity", null, {
893 - $documentation: "The `Infinity` value",
894 - value: 1/0
895 -}, AST_Atom);
896 -
897 -var AST_Boolean = DEFNODE("Boolean", null, {
898 - $documentation: "Base class for booleans",
899 -}, AST_Atom);
900 -
901 -var AST_False = DEFNODE("False", null, {
902 - $documentation: "The `false` atom",
903 - value: false
904 -}, AST_Boolean);
905 -
906 -var AST_True = DEFNODE("True", null, {
907 - $documentation: "The `true` atom",
908 - value: true
909 -}, AST_Boolean);
910 -
911 -/* -----[ TreeWalker ]----- */
912 -
913 -function TreeWalker(callback) {
914 - this.visit = callback;
915 - this.stack = [];
916 -};
917 -TreeWalker.prototype = {
918 - _visit: function(node, descend) {
919 - this.stack.push(node);
920 - var ret = this.visit(node, descend ? function(){
921 - descend.call(node);
922 - } : noop);
923 - if (!ret && descend) {
924 - descend.call(node);
925 - }
926 - this.stack.pop();
927 - return ret;
928 - },
929 - parent: function(n) {
930 - return this.stack[this.stack.length - 2 - (n || 0)];
931 - },
932 - push: function (node) {
933 - this.stack.push(node);
934 - },
935 - pop: function() {
936 - return this.stack.pop();
937 - },
938 - self: function() {
939 - return this.stack[this.stack.length - 1];
940 - },
941 - find_parent: function(type) {
942 - var stack = this.stack;
943 - for (var i = stack.length; --i >= 0;) {
944 - var x = stack[i];
945 - if (x instanceof type) return x;
946 - }
947 - },
948 - in_boolean_context: function() {
949 - var stack = this.stack;
950 - var i = stack.length, self = stack[--i];
951 - while (i > 0) {
952 - var p = stack[--i];
953 - if ((p instanceof AST_If && p.condition === self) ||
954 - (p instanceof AST_Conditional && p.condition === self) ||
955 - (p instanceof AST_DWLoop && p.condition === self) ||
956 - (p instanceof AST_For && p.condition === self) ||
957 - (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
958 - {
959 - return true;
960 - }
961 - if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
962 - return false;
963 - self = p;
964 - }
965 - },
966 - loopcontrol_target: function(label) {
967 - var stack = this.stack;
968 - if (label) {
969 - for (var i = stack.length; --i >= 0;) {
970 - var x = stack[i];
971 - if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
972 - return x.body;
973 - }
974 - }
975 - } else {
976 - for (var i = stack.length; --i >= 0;) {
977 - var x = stack[i];
978 - if (x instanceof AST_Switch
979 - || x instanceof AST_For
980 - || x instanceof AST_ForIn
981 - || x instanceof AST_DWLoop) return x;
982 - }
983 - }
984 - }
985 -};
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -function Compressor(options, false_by_default) {
47 - if (!(this instanceof Compressor))
48 - return new Compressor(options, false_by_default);
49 - TreeTransformer.call(this, this.before, this.after);
50 - this.options = defaults(options, {
51 - sequences : !false_by_default,
52 - properties : !false_by_default,
53 - dead_code : !false_by_default,
54 - drop_debugger : !false_by_default,
55 - unsafe : false,
56 - unsafe_comps : false,
57 - conditionals : !false_by_default,
58 - comparisons : !false_by_default,
59 - evaluate : !false_by_default,
60 - booleans : !false_by_default,
61 - loops : !false_by_default,
62 - unused : !false_by_default,
63 - hoist_funs : !false_by_default,
64 - hoist_vars : false,
65 - if_return : !false_by_default,
66 - join_vars : !false_by_default,
67 - cascade : !false_by_default,
68 - side_effects : !false_by_default,
69 - screw_ie8 : false,
70 -
71 - warnings : true,
72 - global_defs : {}
73 - }, true);
74 -};
75 -
76 -Compressor.prototype = new TreeTransformer;
77 -merge(Compressor.prototype, {
78 - option: function(key) { return this.options[key] },
79 - warn: function() {
80 - if (this.options.warnings)
81 - AST_Node.warn.apply(AST_Node, arguments);
82 - },
83 - before: function(node, descend, in_list) {
84 - if (node._squeezed) return node;
85 - if (node instanceof AST_Scope) {
86 - node.drop_unused(this);
87 - node = node.hoist_declarations(this);
88 - }
89 - descend(node, this);
90 - node = node.optimize(this);
91 - if (node instanceof AST_Scope) {
92 - // dead code removal might leave further unused declarations.
93 - // this'll usually save very few bytes, but the performance
94 - // hit seems negligible so I'll just drop it here.
95 -
96 - // no point to repeat warnings.
97 - var save_warnings = this.options.warnings;
98 - this.options.warnings = false;
99 - node.drop_unused(this);
100 - this.options.warnings = save_warnings;
101 - }
102 - node._squeezed = true;
103 - return node;
104 - }
105 -});
106 -
107 -(function(){
108 -
109 - function OPT(node, optimizer) {
110 - node.DEFMETHOD("optimize", function(compressor){
111 - var self = this;
112 - if (self._optimized) return self;
113 - var opt = optimizer(self, compressor);
114 - opt._optimized = true;
115 - if (opt === self) return opt;
116 - return opt.transform(compressor);
117 - });
118 - };
119 -
120 - OPT(AST_Node, function(self, compressor){
121 - return self;
122 - });
123 -
124 - AST_Node.DEFMETHOD("equivalent_to", function(node){
125 - // XXX: this is a rather expensive way to test two node's equivalence:
126 - return this.print_to_string() == node.print_to_string();
127 - });
128 -
129 - function make_node(ctor, orig, props) {
130 - if (!props) props = {};
131 - if (orig) {
132 - if (!props.start) props.start = orig.start;
133 - if (!props.end) props.end = orig.end;
134 - }
135 - return new ctor(props);
136 - };
137 -
138 - function make_node_from_constant(compressor, val, orig) {
139 - // XXX: WIP.
140 - // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){
141 - // if (node instanceof AST_SymbolRef) {
142 - // var scope = compressor.find_parent(AST_Scope);
143 - // var def = scope.find_variable(node);
144 - // node.thedef = def;
145 - // return node;
146 - // }
147 - // })).transform(compressor);
148 -
149 - if (val instanceof AST_Node) return val.transform(compressor);
150 - switch (typeof val) {
151 - case "string":
152 - return make_node(AST_String, orig, {
153 - value: val
154 - }).optimize(compressor);
155 - case "number":
156 - return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, {
157 - value: val
158 - }).optimize(compressor);
159 - case "boolean":
160 - return make_node(val ? AST_True : AST_False, orig).optimize(compressor);
161 - case "undefined":
162 - return make_node(AST_Undefined, orig).optimize(compressor);
163 - default:
164 - if (val === null) {
165 - return make_node(AST_Null, orig).optimize(compressor);
166 - }
167 - if (val instanceof RegExp) {
168 - return make_node(AST_RegExp, orig).optimize(compressor);
169 - }
170 - throw new Error(string_template("Can't handle constant of type: {type}", {
171 - type: typeof val
172 - }));
173 - }
174 - };
175 -
176 - function as_statement_array(thing) {
177 - if (thing === null) return [];
178 - if (thing instanceof AST_BlockStatement) return thing.body;
179 - if (thing instanceof AST_EmptyStatement) return [];
180 - if (thing instanceof AST_Statement) return [ thing ];
181 - throw new Error("Can't convert thing to statement array");
182 - };
183 -
184 - function is_empty(thing) {
185 - if (thing === null) return true;
186 - if (thing instanceof AST_EmptyStatement) return true;
187 - if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
188 - return false;
189 - };
190 -
191 - function loop_body(x) {
192 - if (x instanceof AST_Switch) return x;
193 - if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
194 - return (x.body instanceof AST_BlockStatement ? x.body : x);
195 - }
196 - return x;
197 - };
198 -
199 - function tighten_body(statements, compressor) {
200 - var CHANGED;
201 - do {
202 - CHANGED = false;
203 - statements = eliminate_spurious_blocks(statements);
204 - if (compressor.option("dead_code")) {
205 - statements = eliminate_dead_code(statements, compressor);
206 - }
207 - if (compressor.option("if_return")) {
208 - statements = handle_if_return(statements, compressor);
209 - }
210 - if (compressor.option("sequences")) {
211 - statements = sequencesize(statements, compressor);
212 - }
213 - if (compressor.option("join_vars")) {
214 - statements = join_consecutive_vars(statements, compressor);
215 - }
216 - } while (CHANGED);
217 - return statements;
218 -
219 - function eliminate_spurious_blocks(statements) {
220 - var seen_dirs = [];
221 - return statements.reduce(function(a, stat){
222 - if (stat instanceof AST_BlockStatement) {
223 - CHANGED = true;
224 - a.push.apply(a, eliminate_spurious_blocks(stat.body));
225 - } else if (stat instanceof AST_EmptyStatement) {
226 - CHANGED = true;
227 - } else if (stat instanceof AST_Directive) {
228 - if (seen_dirs.indexOf(stat.value) < 0) {
229 - a.push(stat);
230 - seen_dirs.push(stat.value);
231 - } else {
232 - CHANGED = true;
233 - }
234 - } else {
235 - a.push(stat);
236 - }
237 - return a;
238 - }, []);
239 - };
240 -
241 - function handle_if_return(statements, compressor) {
242 - var self = compressor.self();
243 - var in_lambda = self instanceof AST_Lambda;
244 - var ret = [];
245 - loop: for (var i = statements.length; --i >= 0;) {
246 - var stat = statements[i];
247 - switch (true) {
248 - case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0):
249 - CHANGED = true;
250 - // note, ret.length is probably always zero
251 - // because we drop unreachable code before this
252 - // step. nevertheless, it's good to check.
253 - continue loop;
254 - case stat instanceof AST_If:
255 - if (stat.body instanceof AST_Return) {
256 - //---
257 - // pretty silly case, but:
258 - // if (foo()) return; return; ==> foo(); return;
259 - if (((in_lambda && ret.length == 0)
260 - || (ret[0] instanceof AST_Return && !ret[0].value))
261 - && !stat.body.value && !stat.alternative) {
262 - CHANGED = true;
263 - var cond = make_node(AST_SimpleStatement, stat.condition, {
264 - body: stat.condition
265 - });
266 - ret.unshift(cond);
267 - continue loop;
268 - }
269 - //---
270 - // if (foo()) return x; return y; ==> return foo() ? x : y;
271 - if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
272 - CHANGED = true;
273 - stat = stat.clone();
274 - stat.alternative = ret[0];
275 - ret[0] = stat.transform(compressor);
276 - continue loop;
277 - }
278 - //---
279 - // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
280 - if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) {
281 - CHANGED = true;
282 - stat = stat.clone();
283 - stat.alternative = ret[0] || make_node(AST_Return, stat, {
284 - value: make_node(AST_Undefined, stat)
285 - });
286 - ret[0] = stat.transform(compressor);
287 - continue loop;
288 - }
289 - //---
290 - // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... }
291 - if (!stat.body.value && in_lambda) {
292 - CHANGED = true;
293 - stat = stat.clone();
294 - stat.condition = stat.condition.negate(compressor);
295 - stat.body = make_node(AST_BlockStatement, stat, {
296 - body: as_statement_array(stat.alternative).concat(ret)
297 - });
298 - stat.alternative = null;
299 - ret = [ stat.transform(compressor) ];
300 - continue loop;
301 - }
302 - //---
303 - if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
304 - && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
305 - CHANGED = true;
306 - ret.push(make_node(AST_Return, ret[0], {
307 - value: make_node(AST_Undefined, ret[0])
308 - }).transform(compressor));
309 - ret = as_statement_array(stat.alternative).concat(ret);
310 - ret.unshift(stat);
311 - continue loop;
312 - }
313 - }
314 -
315 - var ab = aborts(stat.body);
316 - var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
317 - if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
318 - || (ab instanceof AST_Continue && self === loop_body(lct))
319 - || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
320 - if (ab.label) {
321 - remove(ab.label.thedef.references, ab.label);
322 - }
323 - CHANGED = true;
324 - var body = as_statement_array(stat.body).slice(0, -1);
325 - stat = stat.clone();
326 - stat.condition = stat.condition.negate(compressor);
327 - stat.body = make_node(AST_BlockStatement, stat, {
328 - body: ret
329 - });
330 - stat.alternative = make_node(AST_BlockStatement, stat, {
331 - body: body
332 - });
333 - ret = [ stat.transform(compressor) ];
334 - continue loop;
335 - }
336 -
337 - var ab = aborts(stat.alternative);
338 - var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
339 - if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
340 - || (ab instanceof AST_Continue && self === loop_body(lct))
341 - || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
342 - if (ab.label) {
343 - remove(ab.label.thedef.references, ab.label);
344 - }
345 - CHANGED = true;
346 - stat = stat.clone();
347 - stat.body = make_node(AST_BlockStatement, stat.body, {
348 - body: as_statement_array(stat.body).concat(ret)
349 - });
350 - stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
351 - body: as_statement_array(stat.alternative).slice(0, -1)
352 - });
353 - ret = [ stat.transform(compressor) ];
354 - continue loop;
355 - }
356 -
357 - ret.unshift(stat);
358 - break;
359 - default:
360 - ret.unshift(stat);
361 - break;
362 - }
363 - }
364 - return ret;
365 - };
366 -
367 - function eliminate_dead_code(statements, compressor) {
368 - var has_quit = false;
369 - var orig = statements.length;
370 - var self = compressor.self();
371 - statements = statements.reduce(function(a, stat){
372 - if (has_quit) {
373 - extract_declarations_from_unreachable_code(compressor, stat, a);
374 - } else {
375 - if (stat instanceof AST_LoopControl) {
376 - var lct = compressor.loopcontrol_target(stat.label);
377 - if ((stat instanceof AST_Break
378 - && lct instanceof AST_BlockStatement
379 - && loop_body(lct) === self) || (stat instanceof AST_Continue
380 - && loop_body(lct) === self)) {
381 - if (stat.label) {
382 - remove(stat.label.thedef.references, stat.label);
383 - }
384 - } else {
385 - a.push(stat);
386 - }
387 - } else {
388 - a.push(stat);
389 - }
390 - if (aborts(stat)) has_quit = true;
391 - }
392 - return a;
393 - }, []);
394 - CHANGED = statements.length != orig;
395 - return statements;
396 - };
397 -
398 - function sequencesize(statements, compressor) {
399 - if (statements.length < 2) return statements;
400 - var seq = [], ret = [];
401 - function push_seq() {
402 - seq = AST_Seq.from_array(seq);
403 - if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
404 - body: seq
405 - }));
406 - seq = [];
407 - };
408 - statements.forEach(function(stat){
409 - if (stat instanceof AST_SimpleStatement) seq.push(stat.body);
410 - else push_seq(), ret.push(stat);
411 - });
412 - push_seq();
413 - ret = sequencesize_2(ret, compressor);
414 - CHANGED = ret.length != statements.length;
415 - return ret;
416 - };
417 -
418 - function sequencesize_2(statements, compressor) {
419 - function cons_seq(right) {
420 - ret.pop();
421 - var left = prev.body;
422 - if (left instanceof AST_Seq) {
423 - left.add(right);
424 - } else {
425 - left = AST_Seq.cons(left, right);
426 - }
427 - return left.transform(compressor);
428 - };
429 - var ret = [], prev = null;
430 - statements.forEach(function(stat){
431 - if (prev) {
432 - if (stat instanceof AST_For) {
433 - var opera = {};
434 - try {
435 - prev.body.walk(new TreeWalker(function(node){
436 - if (node instanceof AST_Binary && node.operator == "in")
437 - throw opera;
438 - }));
439 - if (stat.init && !(stat.init instanceof AST_Definitions)) {
440 - stat.init = cons_seq(stat.init);
441 - }
442 - else if (!stat.init) {
443 - stat.init = prev.body;
444 - ret.pop();
445 - }
446 - } catch(ex) {
447 - if (ex !== opera) throw ex;
448 - }
449 - }
450 - else if (stat instanceof AST_If) {
451 - stat.condition = cons_seq(stat.condition);
452 - }
453 - else if (stat instanceof AST_With) {
454 - stat.expression = cons_seq(stat.expression);
455 - }
456 - else if (stat instanceof AST_Exit && stat.value) {
457 - stat.value = cons_seq(stat.value);
458 - }
459 - else if (stat instanceof AST_Exit) {
460 - stat.value = cons_seq(make_node(AST_Undefined, stat));
461 - }
462 - else if (stat instanceof AST_Switch) {
463 - stat.expression = cons_seq(stat.expression);
464 - }
465 - }
466 - ret.push(stat);
467 - prev = stat instanceof AST_SimpleStatement ? stat : null;
468 - });
469 - return ret;
470 - };
471 -
472 - function join_consecutive_vars(statements, compressor) {
473 - var prev = null;
474 - return statements.reduce(function(a, stat){
475 - if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
476 - prev.definitions = prev.definitions.concat(stat.definitions);
477 - CHANGED = true;
478 - }
479 - else if (stat instanceof AST_For
480 - && prev instanceof AST_Definitions
481 - && (!stat.init || stat.init.TYPE == prev.TYPE)) {
482 - CHANGED = true;
483 - a.pop();
484 - if (stat.init) {
485 - stat.init.definitions = prev.definitions.concat(stat.init.definitions);
486 - } else {
487 - stat.init = prev;
488 - }
489 - a.push(stat);
490 - prev = stat;
491 - }
492 - else {
493 - prev = stat;
494 - a.push(stat);
495 - }
496 - return a;
497 - }, []);
498 - };
499 -
500 - };
501 -
502 - function extract_declarations_from_unreachable_code(compressor, stat, target) {
503 - compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
504 - stat.walk(new TreeWalker(function(node){
505 - if (node instanceof AST_Definitions) {
506 - compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
507 - node.remove_initializers();
508 - target.push(node);
509 - return true;
510 - }
511 - if (node instanceof AST_Defun) {
512 - target.push(node);
513 - return true;
514 - }
515 - if (node instanceof AST_Scope) {
516 - return true;
517 - }
518 - }));
519 - };
520 -
521 - /* -----[ boolean/negation helpers ]----- */
522 -
523 - // methods to determine whether an expression has a boolean result type
524 - (function (def){
525 - var unary_bool = [ "!", "delete" ];
526 - var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
527 - def(AST_Node, function(){ return false });
528 - def(AST_UnaryPrefix, function(){
529 - return member(this.operator, unary_bool);
530 - });
531 - def(AST_Binary, function(){
532 - return member(this.operator, binary_bool) ||
533 - ( (this.operator == "&&" || this.operator == "||") &&
534 - this.left.is_boolean() && this.right.is_boolean() );
535 - });
536 - def(AST_Conditional, function(){
537 - return this.consequent.is_boolean() && this.alternative.is_boolean();
538 - });
539 - def(AST_Assign, function(){
540 - return this.operator == "=" && this.right.is_boolean();
541 - });
542 - def(AST_Seq, function(){
543 - return this.cdr.is_boolean();
544 - });
545 - def(AST_True, function(){ return true });
546 - def(AST_False, function(){ return true });
547 - })(function(node, func){
548 - node.DEFMETHOD("is_boolean", func);
549 - });
550 -
551 - // methods to determine if an expression has a string result type
552 - (function (def){
553 - def(AST_Node, function(){ return false });
554 - def(AST_String, function(){ return true });
555 - def(AST_UnaryPrefix, function(){
556 - return this.operator == "typeof";
557 - });
558 - def(AST_Binary, function(compressor){
559 - return this.operator == "+" &&
560 - (this.left.is_string(compressor) || this.right.is_string(compressor));
561 - });
562 - def(AST_Assign, function(compressor){
563 - return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
564 - });
565 - def(AST_Seq, function(compressor){
566 - return this.cdr.is_string(compressor);
567 - });
568 - def(AST_Conditional, function(compressor){
569 - return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
570 - });
571 - def(AST_Call, function(compressor){
572 - return compressor.option("unsafe")
573 - && this.expression instanceof AST_SymbolRef
574 - && this.expression.name == "String"
575 - && this.expression.undeclared();
576 - });
577 - })(function(node, func){
578 - node.DEFMETHOD("is_string", func);
579 - });
580 -
581 - function best_of(ast1, ast2) {
582 - return ast1.print_to_string().length >
583 - ast2.print_to_string().length
584 - ? ast2 : ast1;
585 - };
586 -
587 - // methods to evaluate a constant expression
588 - (function (def){
589 - // The evaluate method returns an array with one or two
590 - // elements. If the node has been successfully reduced to a
591 - // constant, then the second element tells us the value;
592 - // otherwise the second element is missing. The first element
593 - // of the array is always an AST_Node descendant; when
594 - // evaluation was successful it's a node that represents the
595 - // constant; otherwise it's the original node.
596 - AST_Node.DEFMETHOD("evaluate", function(compressor){
597 - if (!compressor.option("evaluate")) return [ this ];
598 - try {
599 - var val = this._eval(), ast = make_node_from_constant(compressor, val, this);
600 - return [ best_of(ast, this), val ];
601 - } catch(ex) {
602 - if (ex !== def) throw ex;
603 - return [ this ];
604 - }
605 - });
606 - def(AST_Statement, function(){
607 - throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
608 - });
609 - def(AST_Function, function(){
610 - // XXX: AST_Function inherits from AST_Scope, which itself
611 - // inherits from AST_Statement; however, an AST_Function
612 - // isn't really a statement. This could byte in other
613 - // places too. :-( Wish JS had multiple inheritance.
614 - return [ this ];
615 - });
616 - function ev(node) {
617 - return node._eval();
618 - };
619 - def(AST_Node, function(){
620 - throw def; // not constant
621 - });
622 - def(AST_Constant, function(){
623 - return this.getValue();
624 - });
625 - def(AST_UnaryPrefix, function(){
626 - var e = this.expression;
627 - switch (this.operator) {
628 - case "!": return !ev(e);
629 - case "typeof":
630 - // Function would be evaluated to an array and so typeof would
631 - // incorrectly return 'object'. Hence making is a special case.
632 - if (e instanceof AST_Function) return typeof function(){};
633 -
634 - e = ev(e);
635 -
636 - // typeof <RegExp> returns "object" or "function" on different platforms
637 - // so cannot evaluate reliably
638 - if (e instanceof RegExp) throw def;
639 -
640 - return typeof e;
641 - case "void": return void ev(e);
642 - case "~": return ~ev(e);
643 - case "-":
644 - e = ev(e);
645 - if (e === 0) throw def;
646 - return -e;
647 - case "+": return +ev(e);
648 - }
649 - throw def;
650 - });
651 - def(AST_Binary, function(){
652 - var left = this.left, right = this.right;
653 - switch (this.operator) {
654 - case "&&" : return ev(left) && ev(right);
655 - case "||" : return ev(left) || ev(right);
656 - case "|" : return ev(left) | ev(right);
657 - case "&" : return ev(left) & ev(right);
658 - case "^" : return ev(left) ^ ev(right);
659 - case "+" : return ev(left) + ev(right);
660 - case "*" : return ev(left) * ev(right);
661 - case "/" : return ev(left) / ev(right);
662 - case "%" : return ev(left) % ev(right);
663 - case "-" : return ev(left) - ev(right);
664 - case "<<" : return ev(left) << ev(right);
665 - case ">>" : return ev(left) >> ev(right);
666 - case ">>>" : return ev(left) >>> ev(right);
667 - case "==" : return ev(left) == ev(right);
668 - case "===" : return ev(left) === ev(right);
669 - case "!=" : return ev(left) != ev(right);
670 - case "!==" : return ev(left) !== ev(right);
671 - case "<" : return ev(left) < ev(right);
672 - case "<=" : return ev(left) <= ev(right);
673 - case ">" : return ev(left) > ev(right);
674 - case ">=" : return ev(left) >= ev(right);
675 - case "in" : return ev(left) in ev(right);
676 - case "instanceof" : return ev(left) instanceof ev(right);
677 - }
678 - throw def;
679 - });
680 - def(AST_Conditional, function(){
681 - return ev(this.condition)
682 - ? ev(this.consequent)
683 - : ev(this.alternative);
684 - });
685 - def(AST_SymbolRef, function(){
686 - var d = this.definition();
687 - if (d && d.constant && d.init) return ev(d.init);
688 - throw def;
689 - });
690 - })(function(node, func){
691 - node.DEFMETHOD("_eval", func);
692 - });
693 -
694 - // method to negate an expression
695 - (function(def){
696 - function basic_negation(exp) {
697 - return make_node(AST_UnaryPrefix, exp, {
698 - operator: "!",
699 - expression: exp
700 - });
701 - };
702 - def(AST_Node, function(){
703 - return basic_negation(this);
704 - });
705 - def(AST_Statement, function(){
706 - throw new Error("Cannot negate a statement");
707 - });
708 - def(AST_Function, function(){
709 - return basic_negation(this);
710 - });
711 - def(AST_UnaryPrefix, function(){
712 - if (this.operator == "!")
713 - return this.expression;
714 - return basic_negation(this);
715 - });
716 - def(AST_Seq, function(compressor){
717 - var self = this.clone();
718 - self.cdr = self.cdr.negate(compressor);
719 - return self;
720 - });
721 - def(AST_Conditional, function(compressor){
722 - var self = this.clone();
723 - self.consequent = self.consequent.negate(compressor);
724 - self.alternative = self.alternative.negate(compressor);
725 - return best_of(basic_negation(this), self);
726 - });
727 - def(AST_Binary, function(compressor){
728 - var self = this.clone(), op = this.operator;
729 - if (compressor.option("unsafe_comps")) {
730 - switch (op) {
731 - case "<=" : self.operator = ">" ; return self;
732 - case "<" : self.operator = ">=" ; return self;
733 - case ">=" : self.operator = "<" ; return self;
734 - case ">" : self.operator = "<=" ; return self;
735 - }
736 - }
737 - switch (op) {
738 - case "==" : self.operator = "!="; return self;
739 - case "!=" : self.operator = "=="; return self;
740 - case "===": self.operator = "!=="; return self;
741 - case "!==": self.operator = "==="; return self;
742 - case "&&":
743 - self.operator = "||";
744 - self.left = self.left.negate(compressor);
745 - self.right = self.right.negate(compressor);
746 - return best_of(basic_negation(this), self);
747 - case "||":
748 - self.operator = "&&";
749 - self.left = self.left.negate(compressor);
750 - self.right = self.right.negate(compressor);
751 - return best_of(basic_negation(this), self);
752 - }
753 - return basic_negation(this);
754 - });
755 - })(function(node, func){
756 - node.DEFMETHOD("negate", function(compressor){
757 - return func.call(this, compressor);
758 - });
759 - });
760 -
761 - // determine if expression has side effects
762 - (function(def){
763 - def(AST_Node, function(){ return true });
764 -
765 - def(AST_EmptyStatement, function(){ return false });
766 - def(AST_Constant, function(){ return false });
767 - def(AST_This, function(){ return false });
768 -
769 - def(AST_Block, function(){
770 - for (var i = this.body.length; --i >= 0;) {
771 - if (this.body[i].has_side_effects())
772 - return true;
773 - }
774 - return false;
775 - });
776 -
777 - def(AST_SimpleStatement, function(){
778 - return this.body.has_side_effects();
779 - });
780 - def(AST_Defun, function(){ return true });
781 - def(AST_Function, function(){ return false });
782 - def(AST_Binary, function(){
783 - return this.left.has_side_effects()
784 - || this.right.has_side_effects();
785 - });
786 - def(AST_Assign, function(){ return true });
787 - def(AST_Conditional, function(){
788 - return this.condition.has_side_effects()
789 - || this.consequent.has_side_effects()
790 - || this.alternative.has_side_effects();
791 - });
792 - def(AST_Unary, function(){
793 - return this.operator == "delete"
794 - || this.operator == "++"
795 - || this.operator == "--"
796 - || this.expression.has_side_effects();
797 - });
798 - def(AST_SymbolRef, function(){ return false });
799 - def(AST_Object, function(){
800 - for (var i = this.properties.length; --i >= 0;)
801 - if (this.properties[i].has_side_effects())
802 - return true;
803 - return false;
804 - });
805 - def(AST_ObjectProperty, function(){
806 - return this.value.has_side_effects();
807 - });
808 - def(AST_Array, function(){
809 - for (var i = this.elements.length; --i >= 0;)
810 - if (this.elements[i].has_side_effects())
811 - return true;
812 - return false;
813 - });
814 - // def(AST_Dot, function(){
815 - // return this.expression.has_side_effects();
816 - // });
817 - // def(AST_Sub, function(){
818 - // return this.expression.has_side_effects()
819 - // || this.property.has_side_effects();
820 - // });
821 - def(AST_PropAccess, function(){
822 - return true;
823 - });
824 - def(AST_Seq, function(){
825 - return this.car.has_side_effects()
826 - || this.cdr.has_side_effects();
827 - });
828 - })(function(node, func){
829 - node.DEFMETHOD("has_side_effects", func);
830 - });
831 -
832 - // tell me if a statement aborts
833 - function aborts(thing) {
834 - return thing && thing.aborts();
835 - };
836 - (function(def){
837 - def(AST_Statement, function(){ return null });
838 - def(AST_Jump, function(){ return this });
839 - function block_aborts(){
840 - var n = this.body.length;
841 - return n > 0 && aborts(this.body[n - 1]);
842 - };
843 - def(AST_BlockStatement, block_aborts);
844 - def(AST_SwitchBranch, block_aborts);
845 - def(AST_If, function(){
846 - return this.alternative && aborts(this.body) && aborts(this.alternative);
847 - });
848 - })(function(node, func){
849 - node.DEFMETHOD("aborts", func);
850 - });
851 -
852 - /* -----[ optimizers ]----- */
853 -
854 - OPT(AST_Directive, function(self, compressor){
855 - if (self.scope.has_directive(self.value) !== self.scope) {
856 - return make_node(AST_EmptyStatement, self);
857 - }
858 - return self;
859 - });
860 -
861 - OPT(AST_Debugger, function(self, compressor){
862 - if (compressor.option("drop_debugger"))
863 - return make_node(AST_EmptyStatement, self);
864 - return self;
865 - });
866 -
867 - OPT(AST_LabeledStatement, function(self, compressor){
868 - if (self.body instanceof AST_Break
869 - && compressor.loopcontrol_target(self.body.label) === self.body) {
870 - return make_node(AST_EmptyStatement, self);
871 - }
872 - return self.label.references.length == 0 ? self.body : self;
873 - });
874 -
875 - OPT(AST_Block, function(self, compressor){
876 - self.body = tighten_body(self.body, compressor);
877 - return self;
878 - });
879 -
880 - OPT(AST_BlockStatement, function(self, compressor){
881 - self.body = tighten_body(self.body, compressor);
882 - switch (self.body.length) {
883 - case 1: return self.body[0];
884 - case 0: return make_node(AST_EmptyStatement, self);
885 - }
886 - return self;
887 - });
888 -
889 - AST_Scope.DEFMETHOD("drop_unused", function(compressor){
890 - var self = this;
891 - if (compressor.option("unused")
892 - && !(self instanceof AST_Toplevel)
893 - && !self.uses_eval
894 - ) {
895 - var in_use = [];
896 - var initializations = new Dictionary();
897 - // pass 1: find out which symbols are directly used in
898 - // this scope (not in nested scopes).
899 - var scope = this;
900 - var tw = new TreeWalker(function(node, descend){
901 - if (node !== self) {
902 - if (node instanceof AST_Defun) {
903 - initializations.add(node.name.name, node);
904 - return true; // don't go in nested scopes
905 - }
906 - if (node instanceof AST_Definitions && scope === self) {
907 - node.definitions.forEach(function(def){
908 - if (def.value) {
909 - initializations.add(def.name.name, def.value);
910 - if (def.value.has_side_effects()) {
911 - def.value.walk(tw);
912 - }
913 - }
914 - });
915 - return true;
916 - }
917 - if (node instanceof AST_SymbolRef) {
918 - push_uniq(in_use, node.definition());
919 - return true;
920 - }
921 - if (node instanceof AST_Scope) {
922 - var save_scope = scope;
923 - scope = node;
924 - descend();
925 - scope = save_scope;
926 - return true;
927 - }
928 - }
929 - });
930 - self.walk(tw);
931 - // pass 2: for every used symbol we need to walk its
932 - // initialization code to figure out if it uses other
933 - // symbols (that may not be in_use).
934 - for (var i = 0; i < in_use.length; ++i) {
935 - in_use[i].orig.forEach(function(decl){
936 - // undeclared globals will be instanceof AST_SymbolRef
937 - var init = initializations.get(decl.name);
938 - if (init) init.forEach(function(init){
939 - var tw = new TreeWalker(function(node){
940 - if (node instanceof AST_SymbolRef) {
941 - push_uniq(in_use, node.definition());
942 - }
943 - });
944 - init.walk(tw);
945 - });
946 - });
947 - }
948 - // pass 3: we should drop declarations not in_use
949 - var tt = new TreeTransformer(
950 - function before(node, descend, in_list) {
951 - if (node instanceof AST_Lambda) {
952 - for (var a = node.argnames, i = a.length; --i >= 0;) {
953 - var sym = a[i];
954 - if (sym.unreferenced()) {
955 - a.pop();
956 - compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
957 - name : sym.name,
958 - file : sym.start.file,
959 - line : sym.start.line,
960 - col : sym.start.col
961 - });
962 - }
963 - else break;
964 - }
965 - }
966 - if (node instanceof AST_Defun && node !== self) {
967 - if (!member(node.name.definition(), in_use)) {
968 - compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
969 - name : node.name.name,
970 - file : node.name.start.file,
971 - line : node.name.start.line,
972 - col : node.name.start.col
973 - });
974 - return make_node(AST_EmptyStatement, node);
975 - }
976 - return node;
977 - }
978 - if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
979 - var def = node.definitions.filter(function(def){
980 - if (member(def.name.definition(), in_use)) return true;
981 - var w = {
982 - name : def.name.name,
983 - file : def.name.start.file,
984 - line : def.name.start.line,
985 - col : def.name.start.col
986 - };
987 - if (def.value && def.value.has_side_effects()) {
988 - def._unused_side_effects = true;
989 - compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
990 - return true;
991 - }
992 - compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w);
993 - return false;
994 - });
995 - // place uninitialized names at the start
996 - def = mergeSort(def, function(a, b){
997 - if (!a.value && b.value) return -1;
998 - if (!b.value && a.value) return 1;
999 - return 0;
1000 - });
1001 - // for unused names whose initialization has
1002 - // side effects, we can cascade the init. code
1003 - // into the next one, or next statement.
1004 - var side_effects = [];
1005 - for (var i = 0; i < def.length;) {
1006 - var x = def[i];
1007 - if (x._unused_side_effects) {
1008 - side_effects.push(x.value);
1009 - def.splice(i, 1);
1010 - } else {
1011 - if (side_effects.length > 0) {
1012 - side_effects.push(x.value);
1013 - x.value = AST_Seq.from_array(side_effects);
1014 - side_effects = [];
1015 - }
1016 - ++i;
1017 - }
1018 - }
1019 - if (side_effects.length > 0) {
1020 - side_effects = make_node(AST_BlockStatement, node, {
1021 - body: [ make_node(AST_SimpleStatement, node, {
1022 - body: AST_Seq.from_array(side_effects)
1023 - }) ]
1024 - });
1025 - } else {
1026 - side_effects = null;
1027 - }
1028 - if (def.length == 0 && !side_effects) {
1029 - return make_node(AST_EmptyStatement, node);
1030 - }
1031 - if (def.length == 0) {
1032 - return side_effects;
1033 - }
1034 - node.definitions = def;
1035 - if (side_effects) {
1036 - side_effects.body.unshift(node);
1037 - node = side_effects;
1038 - }
1039 - return node;
1040 - }
1041 - if (node instanceof AST_For && node.init instanceof AST_BlockStatement) {
1042 - descend(node, this);
1043 - // certain combination of unused name + side effect leads to:
1044 - // https://github.com/mishoo/UglifyJS2/issues/44
1045 - // that's an invalid AST.
1046 - // We fix it at this stage by moving the `var` outside the `for`.
1047 - var body = node.init.body.slice(0, -1);
1048 - node.init = node.init.body.slice(-1)[0].body;
1049 - body.push(node);
1050 - return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
1051 - body: body
1052 - });
1053 - }
1054 - if (node instanceof AST_Scope && node !== self)
1055 - return node;
1056 - }
1057 - );
1058 - self.transform(tt);
1059 - }
1060 - });
1061 -
1062 - AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
1063 - var hoist_funs = compressor.option("hoist_funs");
1064 - var hoist_vars = compressor.option("hoist_vars");
1065 - var self = this;
1066 - if (hoist_funs || hoist_vars) {
1067 - var dirs = [];
1068 - var hoisted = [];
1069 - var vars = new Dictionary(), vars_found = 0, var_decl = 0;
1070 - // let's count var_decl first, we seem to waste a lot of
1071 - // space if we hoist `var` when there's only one.
1072 - self.walk(new TreeWalker(function(node){
1073 - if (node instanceof AST_Scope && node !== self)
1074 - return true;
1075 - if (node instanceof AST_Var) {
1076 - ++var_decl;
1077 - return true;
1078 - }
1079 - }));
1080 - hoist_vars = hoist_vars && var_decl > 1;
1081 - var tt = new TreeTransformer(
1082 - function before(node) {
1083 - if (node !== self) {
1084 - if (node instanceof AST_Directive) {
1085 - dirs.push(node);
1086 - return make_node(AST_EmptyStatement, node);
1087 - }
1088 - if (node instanceof AST_Defun && hoist_funs) {
1089 - hoisted.push(node);
1090 - return make_node(AST_EmptyStatement, node);
1091 - }
1092 - if (node instanceof AST_Var && hoist_vars) {
1093 - node.definitions.forEach(function(def){
1094 - vars.set(def.name.name, def);
1095 - ++vars_found;
1096 - });
1097 - var seq = node.to_assignments();
1098 - var p = tt.parent();
1099 - if (p instanceof AST_ForIn && p.init === node) {
1100 - if (seq == null) return node.definitions[0].name;
1101 - return seq;
1102 - }
1103 - if (p instanceof AST_For && p.init === node) {
1104 - return seq;
1105 - }
1106 - if (!seq) return make_node(AST_EmptyStatement, node);
1107 - return make_node(AST_SimpleStatement, node, {
1108 - body: seq
1109 - });
1110 - }
1111 - if (node instanceof AST_Scope)
1112 - return node; // to avoid descending in nested scopes
1113 - }
1114 - }
1115 - );
1116 - self = self.transform(tt);
1117 - if (vars_found > 0) {
1118 - // collect only vars which don't show up in self's arguments list
1119 - var defs = [];
1120 - vars.each(function(def, name){
1121 - if (self instanceof AST_Lambda
1122 - && find_if(function(x){ return x.name == def.name.name },
1123 - self.argnames)) {
1124 - vars.del(name);
1125 - } else {
1126 - def = def.clone();
1127 - def.value = null;
1128 - defs.push(def);
1129 - vars.set(name, def);
1130 - }
1131 - });
1132 - if (defs.length > 0) {
1133 - // try to merge in assignments
1134 - for (var i = 0; i < self.body.length;) {
1135 - if (self.body[i] instanceof AST_SimpleStatement) {
1136 - var expr = self.body[i].body, sym, assign;
1137 - if (expr instanceof AST_Assign
1138 - && expr.operator == "="
1139 - && (sym = expr.left) instanceof AST_Symbol
1140 - && vars.has(sym.name))
1141 - {
1142 - var def = vars.get(sym.name);
1143 - if (def.value) break;
1144 - def.value = expr.right;
1145 - remove(defs, def);
1146 - defs.push(def);
1147 - self.body.splice(i, 1);
1148 - continue;
1149 - }
1150 - if (expr instanceof AST_Seq
1151 - && (assign = expr.car) instanceof AST_Assign
1152 - && assign.operator == "="
1153 - && (sym = assign.left) instanceof AST_Symbol
1154 - && vars.has(sym.name))
1155 - {
1156 - var def = vars.get(sym.name);
1157 - if (def.value) break;
1158 - def.value = assign.right;
1159 - remove(defs, def);
1160 - defs.push(def);
1161 - self.body[i].body = expr.cdr;
1162 - continue;
1163 - }
1164 - }
1165 - if (self.body[i] instanceof AST_EmptyStatement) {
1166 - self.body.splice(i, 1);
1167 - continue;
1168 - }
1169 - if (self.body[i] instanceof AST_BlockStatement) {
1170 - var tmp = [ i, 1 ].concat(self.body[i].body);
1171 - self.body.splice.apply(self.body, tmp);
1172 - continue;
1173 - }
1174 - break;
1175 - }
1176 - defs = make_node(AST_Var, self, {
1177 - definitions: defs
1178 - });
1179 - hoisted.push(defs);
1180 - };
1181 - }
1182 - self.body = dirs.concat(hoisted, self.body);
1183 - }
1184 - return self;
1185 - });
1186 -
1187 - OPT(AST_SimpleStatement, function(self, compressor){
1188 - if (compressor.option("side_effects")) {
1189 - if (!self.body.has_side_effects()) {
1190 - compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
1191 - return make_node(AST_EmptyStatement, self);
1192 - }
1193 - }
1194 - return self;
1195 - });
1196 -
1197 - OPT(AST_DWLoop, function(self, compressor){
1198 - var cond = self.condition.evaluate(compressor);
1199 - self.condition = cond[0];
1200 - if (!compressor.option("loops")) return self;
1201 - if (cond.length > 1) {
1202 - if (cond[1]) {
1203 - return make_node(AST_For, self, {
1204 - body: self.body
1205 - });
1206 - } else if (self instanceof AST_While) {
1207 - if (compressor.option("dead_code")) {
1208 - var a = [];
1209 - extract_declarations_from_unreachable_code(compressor, self.body, a);
1210 - return make_node(AST_BlockStatement, self, { body: a });
1211 - }
1212 - }
1213 - }
1214 - return self;
1215 - });
1216 -
1217 - function if_break_in_loop(self, compressor) {
1218 - function drop_it(rest) {
1219 - rest = as_statement_array(rest);
1220 - if (self.body instanceof AST_BlockStatement) {
1221 - self.body = self.body.clone();
1222 - self.body.body = rest.concat(self.body.body.slice(1));
1223 - self.body = self.body.transform(compressor);
1224 - } else {
1225 - self.body = make_node(AST_BlockStatement, self.body, {
1226 - body: rest
1227 - }).transform(compressor);
1228 - }
1229 - if_break_in_loop(self, compressor);
1230 - }
1231 - var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
1232 - if (first instanceof AST_If) {
1233 - if (first.body instanceof AST_Break
1234 - && compressor.loopcontrol_target(first.body.label) === self) {
1235 - if (self.condition) {
1236 - self.condition = make_node(AST_Binary, self.condition, {
1237 - left: self.condition,
1238 - operator: "&&",
1239 - right: first.condition.negate(compressor),
1240 - });
1241 - } else {
1242 - self.condition = first.condition.negate(compressor);
1243 - }
1244 - drop_it(first.alternative);
1245 - }
1246 - else if (first.alternative instanceof AST_Break
1247 - && compressor.loopcontrol_target(first.alternative.label) === self) {
1248 - if (self.condition) {
1249 - self.condition = make_node(AST_Binary, self.condition, {
1250 - left: self.condition,
1251 - operator: "&&",
1252 - right: first.condition,
1253 - });
1254 - } else {
1255 - self.condition = first.condition;
1256 - }
1257 - drop_it(first.body);
1258 - }
1259 - }
1260 - };
1261 -
1262 - OPT(AST_While, function(self, compressor) {
1263 - if (!compressor.option("loops")) return self;
1264 - self = AST_DWLoop.prototype.optimize.call(self, compressor);
1265 - if (self instanceof AST_While) {
1266 - if_break_in_loop(self, compressor);
1267 - self = make_node(AST_For, self, self).transform(compressor);
1268 - }
1269 - return self;
1270 - });
1271 -
1272 - OPT(AST_For, function(self, compressor){
1273 - var cond = self.condition;
1274 - if (cond) {
1275 - cond = cond.evaluate(compressor);
1276 - self.condition = cond[0];
1277 - }
1278 - if (!compressor.option("loops")) return self;
1279 - if (cond) {
1280 - if (cond.length > 1 && !cond[1]) {
1281 - if (compressor.option("dead_code")) {
1282 - var a = [];
1283 - if (self.init instanceof AST_Statement) {
1284 - a.push(self.init);
1285 - }
1286 - else if (self.init) {
1287 - a.push(make_node(AST_SimpleStatement, self.init, {
1288 - body: self.init
1289 - }));
1290 - }
1291 - extract_declarations_from_unreachable_code(compressor, self.body, a);
1292 - return make_node(AST_BlockStatement, self, { body: a });
1293 - }
1294 - }
1295 - }
1296 - if_break_in_loop(self, compressor);
1297 - return self;
1298 - });
1299 -
1300 - OPT(AST_If, function(self, compressor){
1301 - if (!compressor.option("conditionals")) return self;
1302 - // if condition can be statically determined, warn and drop
1303 - // one of the blocks. note, statically determined implies
1304 - // “has no side effects”; also it doesn't work for cases like
1305 - // `x && true`, though it probably should.
1306 - var cond = self.condition.evaluate(compressor);
1307 - self.condition = cond[0];
1308 - if (cond.length > 1) {
1309 - if (cond[1]) {
1310 - compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
1311 - if (compressor.option("dead_code")) {
1312 - var a = [];
1313 - if (self.alternative) {
1314 - extract_declarations_from_unreachable_code(compressor, self.alternative, a);
1315 - }
1316 - a.push(self.body);
1317 - return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
1318 - }
1319 - } else {
1320 - compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
1321 - if (compressor.option("dead_code")) {
1322 - var a = [];
1323 - extract_declarations_from_unreachable_code(compressor, self.body, a);
1324 - if (self.alternative) a.push(self.alternative);
1325 - return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
1326 - }
1327 - }
1328 - }
1329 - if (is_empty(self.alternative)) self.alternative = null;
1330 - var negated = self.condition.negate(compressor);
1331 - var negated_is_best = best_of(self.condition, negated) === negated;
1332 - if (self.alternative && negated_is_best) {
1333 - negated_is_best = false; // because we already do the switch here.
1334 - self.condition = negated;
1335 - var tmp = self.body;
1336 - self.body = self.alternative || make_node(AST_EmptyStatement);
1337 - self.alternative = tmp;
1338 - }
1339 - if (is_empty(self.body) && is_empty(self.alternative)) {
1340 - return make_node(AST_SimpleStatement, self.condition, {
1341 - body: self.condition
1342 - }).transform(compressor);
1343 - }
1344 - if (self.body instanceof AST_SimpleStatement
1345 - && self.alternative instanceof AST_SimpleStatement) {
1346 - return make_node(AST_SimpleStatement, self, {
1347 - body: make_node(AST_Conditional, self, {
1348 - condition : self.condition,
1349 - consequent : self.body.body,
1350 - alternative : self.alternative.body
1351 - })
1352 - }).transform(compressor);
1353 - }
1354 - if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
1355 - if (negated_is_best) return make_node(AST_SimpleStatement, self, {
1356 - body: make_node(AST_Binary, self, {
1357 - operator : "||",
1358 - left : negated,
1359 - right : self.body.body
1360 - })
1361 - }).transform(compressor);
1362 - return make_node(AST_SimpleStatement, self, {
1363 - body: make_node(AST_Binary, self, {
1364 - operator : "&&",
1365 - left : self.condition,
1366 - right : self.body.body
1367 - })
1368 - }).transform(compressor);
1369 - }
1370 - if (self.body instanceof AST_EmptyStatement
1371 - && self.alternative
1372 - && self.alternative instanceof AST_SimpleStatement) {
1373 - return make_node(AST_SimpleStatement, self, {
1374 - body: make_node(AST_Binary, self, {
1375 - operator : "||",
1376 - left : self.condition,
1377 - right : self.alternative.body
1378 - })
1379 - }).transform(compressor);
1380 - }
1381 - if (self.body instanceof AST_Exit
1382 - && self.alternative instanceof AST_Exit
1383 - && self.body.TYPE == self.alternative.TYPE) {
1384 - return make_node(self.body.CTOR, self, {
1385 - value: make_node(AST_Conditional, self, {
1386 - condition : self.condition,
1387 - consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
1388 - alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
1389 - })
1390 - }).transform(compressor);
1391 - }
1392 - if (self.body instanceof AST_If
1393 - && !self.body.alternative
1394 - && !self.alternative) {
1395 - self.condition = make_node(AST_Binary, self.condition, {
1396 - operator: "&&",
1397 - left: self.condition,
1398 - right: self.body.condition
1399 - }).transform(compressor);
1400 - self.body = self.body.body;
1401 - }
1402 - if (aborts(self.body)) {
1403 - if (self.alternative) {
1404 - var alt = self.alternative;
1405 - self.alternative = null;
1406 - return make_node(AST_BlockStatement, self, {
1407 - body: [ self, alt ]
1408 - }).transform(compressor);
1409 - }
1410 - }
1411 - if (aborts(self.alternative)) {
1412 - var body = self.body;
1413 - self.body = self.alternative;
1414 - self.condition = negated_is_best ? negated : self.condition.negate(compressor);
1415 - self.alternative = null;
1416 - return make_node(AST_BlockStatement, self, {
1417 - body: [ self, body ]
1418 - }).transform(compressor);
1419 - }
1420 - return self;
1421 - });
1422 -
1423 - OPT(AST_Switch, function(self, compressor){
1424 - if (self.body.length == 0 && compressor.option("conditionals")) {
1425 - return make_node(AST_SimpleStatement, self, {
1426 - body: self.expression
1427 - }).transform(compressor);
1428 - }
1429 - for(;;) {
1430 - var last_branch = self.body[self.body.length - 1];
1431 - if (last_branch) {
1432 - var stat = last_branch.body[last_branch.body.length - 1]; // last statement
1433 - if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
1434 - last_branch.body.pop();
1435 - if (last_branch instanceof AST_Default && last_branch.body.length == 0) {
1436 - self.body.pop();
1437 - continue;
1438 - }
1439 - }
1440 - break;
1441 - }
1442 - var exp = self.expression.evaluate(compressor);
1443 - out: if (exp.length == 2) try {
1444 - // constant expression
1445 - self.expression = exp[0];
1446 - if (!compressor.option("dead_code")) break out;
1447 - var value = exp[1];
1448 - var in_if = false;
1449 - var in_block = false;
1450 - var started = false;
1451 - var stopped = false;
1452 - var ruined = false;
1453 - var tt = new TreeTransformer(function(node, descend, in_list){
1454 - if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
1455 - // no need to descend these node types
1456 - return node;
1457 - }
1458 - else if (node instanceof AST_Switch && node === self) {
1459 - node = node.clone();
1460 - descend(node, this);
1461 - return ruined ? node : make_node(AST_BlockStatement, node, {
1462 - body: node.body.reduce(function(a, branch){
1463 - return a.concat(branch.body);
1464 - }, [])
1465 - }).transform(compressor);
1466 - }
1467 - else if (node instanceof AST_If || node instanceof AST_Try) {
1468 - var save = in_if;
1469 - in_if = !in_block;
1470 - descend(node, this);
1471 - in_if = save;
1472 - return node;
1473 - }
1474 - else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
1475 - var save = in_block;
1476 - in_block = true;
1477 - descend(node, this);
1478 - in_block = save;
1479 - return node;
1480 - }
1481 - else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
1482 - if (in_if) {
1483 - ruined = true;
1484 - return node;
1485 - }
1486 - if (in_block) return node;
1487 - stopped = true;
1488 - return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
1489 - }
1490 - else if (node instanceof AST_SwitchBranch && this.parent() === self) {
1491 - if (stopped) return MAP.skip;
1492 - if (node instanceof AST_Case) {
1493 - var exp = node.expression.evaluate(compressor);
1494 - if (exp.length < 2) {
1495 - // got a case with non-constant expression, baling out
1496 - throw self;
1497 - }
1498 - if (exp[1] === value || started) {
1499 - started = true;
1500 - if (aborts(node)) stopped = true;
1501 - descend(node, this);
1502 - return node;
1503 - }
1504 - return MAP.skip;
1505 - }
1506 - descend(node, this);
1507 - return node;
1508 - }
1509 - });
1510 - tt.stack = compressor.stack.slice(); // so that's able to see parent nodes
1511 - self = self.transform(tt);
1512 - } catch(ex) {
1513 - if (ex !== self) throw ex;
1514 - }
1515 - return self;
1516 - });
1517 -
1518 - OPT(AST_Case, function(self, compressor){
1519 - self.body = tighten_body(self.body, compressor);
1520 - return self;
1521 - });
1522 -
1523 - OPT(AST_Try, function(self, compressor){
1524 - self.body = tighten_body(self.body, compressor);
1525 - return self;
1526 - });
1527 -
1528 - AST_Definitions.DEFMETHOD("remove_initializers", function(){
1529 - this.definitions.forEach(function(def){ def.value = null });
1530 - });
1531 -
1532 - AST_Definitions.DEFMETHOD("to_assignments", function(){
1533 - var assignments = this.definitions.reduce(function(a, def){
1534 - if (def.value) {
1535 - var name = make_node(AST_SymbolRef, def.name, def.name);
1536 - a.push(make_node(AST_Assign, def, {
1537 - operator : "=",
1538 - left : name,
1539 - right : def.value
1540 - }));
1541 - }
1542 - return a;
1543 - }, []);
1544 - if (assignments.length == 0) return null;
1545 - return AST_Seq.from_array(assignments);
1546 - });
1547 -
1548 - OPT(AST_Definitions, function(self, compressor){
1549 - if (self.definitions.length == 0)
1550 - return make_node(AST_EmptyStatement, self);
1551 - return self;
1552 - });
1553 -
1554 - OPT(AST_Function, function(self, compressor){
1555 - self = AST_Lambda.prototype.optimize.call(self, compressor);
1556 - if (compressor.option("unused")) {
1557 - if (self.name && self.name.unreferenced()) {
1558 - self.name = null;
1559 - }
1560 - }
1561 - return self;
1562 - });
1563 -
1564 - OPT(AST_Call, function(self, compressor){
1565 - if (compressor.option("unsafe")) {
1566 - var exp = self.expression;
1567 - if (exp instanceof AST_SymbolRef && exp.undeclared()) {
1568 - switch (exp.name) {
1569 - case "Array":
1570 - if (self.args.length != 1) {
1571 - return make_node(AST_Array, self, {
1572 - elements: self.args
1573 - });
1574 - }
1575 - break;
1576 - case "Object":
1577 - if (self.args.length == 0) {
1578 - return make_node(AST_Object, self, {
1579 - properties: []
1580 - });
1581 - }
1582 - break;
1583 - case "String":
1584 - if (self.args.length == 0) return make_node(AST_String, self, {
1585 - value: ""
1586 - });
1587 - return make_node(AST_Binary, self, {
1588 - left: self.args[0],
1589 - operator: "+",
1590 - right: make_node(AST_String, self, { value: "" })
1591 - });
1592 - }
1593 - }
1594 - else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
1595 - return make_node(AST_Binary, self, {
1596 - left: make_node(AST_String, self, { value: "" }),
1597 - operator: "+",
1598 - right: exp.expression
1599 - }).transform(compressor);
1600 - }
1601 - }
1602 - if (compressor.option("side_effects")) {
1603 - if (self.expression instanceof AST_Function
1604 - && self.args.length == 0
1605 - && !AST_Block.prototype.has_side_effects.call(self.expression)) {
1606 - return make_node(AST_Undefined, self).transform(compressor);
1607 - }
1608 - }
1609 - return self;
1610 - });
1611 -
1612 - OPT(AST_New, function(self, compressor){
1613 - if (compressor.option("unsafe")) {
1614 - var exp = self.expression;
1615 - if (exp instanceof AST_SymbolRef && exp.undeclared()) {
1616 - switch (exp.name) {
1617 - case "Object":
1618 - case "RegExp":
1619 - case "Function":
1620 - case "Error":
1621 - case "Array":
1622 - return make_node(AST_Call, self, self).transform(compressor);
1623 - }
1624 - }
1625 - }
1626 - return self;
1627 - });
1628 -
1629 - OPT(AST_Seq, function(self, compressor){
1630 - if (!compressor.option("side_effects"))
1631 - return self;
1632 - if (!self.car.has_side_effects()) {
1633 - // we shouldn't compress (1,eval)(something) to
1634 - // eval(something) because that changes the meaning of
1635 - // eval (becomes lexical instead of global).
1636 - var p;
1637 - if (!(self.cdr instanceof AST_SymbolRef
1638 - && self.cdr.name == "eval"
1639 - && self.cdr.undeclared()
1640 - && (p = compressor.parent()) instanceof AST_Call
1641 - && p.expression === self)) {
1642 - return self.cdr;
1643 - }
1644 - }
1645 - if (compressor.option("cascade")) {
1646 - if (self.car instanceof AST_Assign
1647 - && !self.car.left.has_side_effects()
1648 - && self.car.left.equivalent_to(self.cdr)) {
1649 - return self.car;
1650 - }
1651 - if (!self.car.has_side_effects()
1652 - && !self.cdr.has_side_effects()
1653 - && self.car.equivalent_to(self.cdr)) {
1654 - return self.car;
1655 - }
1656 - }
1657 - return self;
1658 - });
1659 -
1660 - AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
1661 - if (compressor.option("sequences")) {
1662 - if (this.expression instanceof AST_Seq) {
1663 - var seq = this.expression;
1664 - var x = seq.to_array();
1665 - this.expression = x.pop();
1666 - x.push(this);
1667 - seq = AST_Seq.from_array(x).transform(compressor);
1668 - return seq;
1669 - }
1670 - }
1671 - return this;
1672 - });
1673 -
1674 - OPT(AST_UnaryPostfix, function(self, compressor){
1675 - return self.lift_sequences(compressor);
1676 - });
1677 -
1678 - OPT(AST_UnaryPrefix, function(self, compressor){
1679 - self = self.lift_sequences(compressor);
1680 - var e = self.expression;
1681 - if (compressor.option("booleans") && compressor.in_boolean_context()) {
1682 - switch (self.operator) {
1683 - case "!":
1684 - if (e instanceof AST_UnaryPrefix && e.operator == "!") {
1685 - // !!foo ==> foo, if we're in boolean context
1686 - return e.expression;
1687 - }
1688 - break;
1689 - case "typeof":
1690 - // typeof always returns a non-empty string, thus it's
1691 - // always true in booleans
1692 - compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
1693 - return make_node(AST_True, self);
1694 - }
1695 - if (e instanceof AST_Binary && self.operator == "!") {
1696 - self = best_of(self, e.negate(compressor));
1697 - }
1698 - }
1699 - return self.evaluate(compressor)[0];
1700 - });
1701 -
1702 - AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
1703 - if (compressor.option("sequences")) {
1704 - if (this.left instanceof AST_Seq) {
1705 - var seq = this.left;
1706 - var x = seq.to_array();
1707 - this.left = x.pop();
1708 - x.push(this);
1709 - seq = AST_Seq.from_array(x).transform(compressor);
1710 - return seq;
1711 - }
1712 - if (this.right instanceof AST_Seq
1713 - && !(this.operator == "||" || this.operator == "&&")
1714 - && !this.left.has_side_effects()) {
1715 - var seq = this.right;
1716 - var x = seq.to_array();
1717 - this.right = x.pop();
1718 - x.push(this);
1719 - seq = AST_Seq.from_array(x).transform(compressor);
1720 - return seq;
1721 - }
1722 - }
1723 - return this;
1724 - });
1725 -
1726 - var commutativeOperators = makePredicate("== === != !== * & | ^");
1727 -
1728 - OPT(AST_Binary, function(self, compressor){
1729 - function reverse(op) {
1730 - if (!(self.left.has_side_effects() || self.right.has_side_effects())) {
1731 - if (op) self.operator = op;
1732 - var tmp = self.left;
1733 - self.left = self.right;
1734 - self.right = tmp;
1735 - }
1736 - };
1737 - if (commutativeOperators(self.operator)) {
1738 - if (self.right instanceof AST_Constant
1739 - && !(self.left instanceof AST_Constant)) {
1740 - reverse();
1741 - }
1742 - }
1743 - self = self.lift_sequences(compressor);
1744 - if (compressor.option("comparisons")) switch (self.operator) {
1745 - case "===":
1746 - case "!==":
1747 - if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
1748 - (self.left.is_boolean() && self.right.is_boolean())) {
1749 - self.operator = self.operator.substr(0, 2);
1750 - }
1751 - // XXX: intentionally falling down to the next case
1752 - case "==":
1753 - case "!=":
1754 - if (self.left instanceof AST_String
1755 - && self.left.value == "undefined"
1756 - && self.right instanceof AST_UnaryPrefix
1757 - && self.right.operator == "typeof"
1758 - && compressor.option("unsafe")) {
1759 - if (!(self.right.expression instanceof AST_SymbolRef)
1760 - || !self.right.expression.undeclared()) {
1761 - self.left = self.right.expression;
1762 - self.right = make_node(AST_Undefined, self.left).optimize(compressor);
1763 - if (self.operator.length == 2) self.operator += "=";
1764 - }
1765 - }
1766 - break;
1767 - }
1768 - if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
1769 - case "&&":
1770 - var ll = self.left.evaluate(compressor);
1771 - var rr = self.right.evaluate(compressor);
1772 - if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) {
1773 - compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
1774 - return make_node(AST_False, self);
1775 - }
1776 - if (ll.length > 1 && ll[1]) {
1777 - return rr[0];
1778 - }
1779 - if (rr.length > 1 && rr[1]) {
1780 - return ll[0];
1781 - }
1782 - break;
1783 - case "||":
1784 - var ll = self.left.evaluate(compressor);
1785 - var rr = self.right.evaluate(compressor);
1786 - if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) {
1787 - compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
1788 - return make_node(AST_True, self);
1789 - }
1790 - if (ll.length > 1 && !ll[1]) {
1791 - return rr[0];
1792 - }
1793 - if (rr.length > 1 && !rr[1]) {
1794 - return ll[0];
1795 - }
1796 - break;
1797 - case "+":
1798 - var ll = self.left.evaluate(compressor);
1799 - var rr = self.right.evaluate(compressor);
1800 - if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) ||
1801 - (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) {
1802 - compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
1803 - return make_node(AST_True, self);
1804 - }
1805 - break;
1806 - }
1807 - var exp = self.evaluate(compressor);
1808 - if (exp.length > 1) {
1809 - if (best_of(exp[0], self) !== self)
1810 - return exp[0];
1811 - }
1812 - if (compressor.option("comparisons")) {
1813 - if (!(compressor.parent() instanceof AST_Binary)
1814 - || compressor.parent() instanceof AST_Assign) {
1815 - var negated = make_node(AST_UnaryPrefix, self, {
1816 - operator: "!",
1817 - expression: self.negate(compressor)
1818 - });
1819 - self = best_of(self, negated);
1820 - }
1821 - switch (self.operator) {
1822 - case "<": reverse(">"); break;
1823 - case "<=": reverse(">="); break;
1824 - }
1825 - }
1826 - if (self.operator == "+" && self.right instanceof AST_String
1827 - && self.right.getValue() === "" && self.left instanceof AST_Binary
1828 - && self.left.operator == "+" && self.left.is_string(compressor)) {
1829 - return self.left;
1830 - }
1831 - return self;
1832 - });
1833 -
1834 - OPT(AST_SymbolRef, function(self, compressor){
1835 - if (self.undeclared()) {
1836 - var defines = compressor.option("global_defs");
1837 - if (defines && defines.hasOwnProperty(self.name)) {
1838 - return make_node_from_constant(compressor, defines[self.name], self);
1839 - }
1840 - switch (self.name) {
1841 - case "undefined":
1842 - return make_node(AST_Undefined, self);
1843 - case "NaN":
1844 - return make_node(AST_NaN, self);
1845 - case "Infinity":
1846 - return make_node(AST_Infinity, self);
1847 - }
1848 - }
1849 - return self;
1850 - });
1851 -
1852 - OPT(AST_Undefined, function(self, compressor){
1853 - if (compressor.option("unsafe")) {
1854 - var scope = compressor.find_parent(AST_Scope);
1855 - var undef = scope.find_variable("undefined");
1856 - if (undef) {
1857 - var ref = make_node(AST_SymbolRef, self, {
1858 - name : "undefined",
1859 - scope : scope,
1860 - thedef : undef
1861 - });
1862 - ref.reference();
1863 - return ref;
1864 - }
1865 - }
1866 - return self;
1867 - });
1868 -
1869 - var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
1870 - OPT(AST_Assign, function(self, compressor){
1871 - self = self.lift_sequences(compressor);
1872 - if (self.operator == "="
1873 - && self.left instanceof AST_SymbolRef
1874 - && self.right instanceof AST_Binary
1875 - && self.right.left instanceof AST_SymbolRef
1876 - && self.right.left.name == self.left.name
1877 - && member(self.right.operator, ASSIGN_OPS)) {
1878 - self.operator = self.right.operator + "=";
1879 - self.right = self.right.right;
1880 - }
1881 - return self;
1882 - });
1883 -
1884 - OPT(AST_Conditional, function(self, compressor){
1885 - if (!compressor.option("conditionals")) return self;
1886 - if (self.condition instanceof AST_Seq) {
1887 - var car = self.condition.car;
1888 - self.condition = self.condition.cdr;
1889 - return AST_Seq.cons(car, self);
1890 - }
1891 - var cond = self.condition.evaluate(compressor);
1892 - if (cond.length > 1) {
1893 - if (cond[1]) {
1894 - compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
1895 - return self.consequent;
1896 - } else {
1897 - compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
1898 - return self.alternative;
1899 - }
1900 - }
1901 - var negated = cond[0].negate(compressor);
1902 - if (best_of(cond[0], negated) === negated) {
1903 - self = make_node(AST_Conditional, self, {
1904 - condition: negated,
1905 - consequent: self.alternative,
1906 - alternative: self.consequent
1907 - });
1908 - }
1909 - var consequent = self.consequent;
1910 - var alternative = self.alternative;
1911 - if (consequent instanceof AST_Assign
1912 - && alternative instanceof AST_Assign
1913 - && consequent.operator == alternative.operator
1914 - && consequent.left.equivalent_to(alternative.left)
1915 - ) {
1916 - /*
1917 - * Stuff like this:
1918 - * if (foo) exp = something; else exp = something_else;
1919 - * ==>
1920 - * exp = foo ? something : something_else;
1921 - */
1922 - self = make_node(AST_Assign, self, {
1923 - operator: consequent.operator,
1924 - left: consequent.left,
1925 - right: make_node(AST_Conditional, self, {
1926 - condition: self.condition,
1927 - consequent: consequent.right,
1928 - alternative: alternative.right
1929 - })
1930 - });
1931 - }
1932 - return self;
1933 - });
1934 -
1935 - OPT(AST_Boolean, function(self, compressor){
1936 - if (compressor.option("booleans")) {
1937 - var p = compressor.parent();
1938 - if (p instanceof AST_Binary && (p.operator == "=="
1939 - || p.operator == "!=")) {
1940 - compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
1941 - operator : p.operator,
1942 - value : self.value,
1943 - file : p.start.file,
1944 - line : p.start.line,
1945 - col : p.start.col,
1946 - });
1947 - return make_node(AST_Number, self, {
1948 - value: +self.value
1949 - });
1950 - }
1951 - return make_node(AST_UnaryPrefix, self, {
1952 - operator: "!",
1953 - expression: make_node(AST_Number, self, {
1954 - value: 1 - self.value
1955 - })
1956 - });
1957 - }
1958 - return self;
1959 - });
1960 -
1961 - OPT(AST_Sub, function(self, compressor){
1962 - var prop = self.property;
1963 - if (prop instanceof AST_String && compressor.option("properties")) {
1964 - prop = prop.getValue();
1965 - if (is_identifier(prop) || compressor.option("screw_ie8")) {
1966 - return make_node(AST_Dot, self, {
1967 - expression : self.expression,
1968 - property : prop
1969 - });
1970 - }
1971 - }
1972 - return self;
1973 - });
1974 -
1975 - function literals_in_boolean_context(self, compressor) {
1976 - if (compressor.option("booleans") && compressor.in_boolean_context()) {
1977 - return make_node(AST_True, self);
1978 - }
1979 - return self;
1980 - };
1981 - OPT(AST_Array, literals_in_boolean_context);
1982 - OPT(AST_Object, literals_in_boolean_context);
1983 - OPT(AST_RegExp, literals_in_boolean_context);
1984 -
1985 -})();
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -(function(){
47 -
48 - var MOZ_TO_ME = {
49 - TryStatement : function(M) {
50 - return new AST_Try({
51 - start : my_start_token(M),
52 - end : my_end_token(M),
53 - body : from_moz(M.block).body,
54 - bcatch : from_moz(M.handlers[0]),
55 - bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
56 - });
57 - },
58 - CatchClause : function(M) {
59 - return new AST_Catch({
60 - start : my_start_token(M),
61 - end : my_end_token(M),
62 - argname : from_moz(M.param),
63 - body : from_moz(M.body).body
64 - });
65 - },
66 - ObjectExpression : function(M) {
67 - return new AST_Object({
68 - start : my_start_token(M),
69 - end : my_end_token(M),
70 - properties : M.properties.map(function(prop){
71 - var key = prop.key;
72 - var name = key.type == "Identifier" ? key.name : key.value;
73 - var args = {
74 - start : my_start_token(key),
75 - end : my_end_token(prop.value),
76 - key : name,
77 - value : from_moz(prop.value)
78 - };
79 - switch (prop.kind) {
80 - case "init":
81 - return new AST_ObjectKeyVal(args);
82 - case "set":
83 - args.value.name = from_moz(key);
84 - return new AST_ObjectSetter(args);
85 - case "get":
86 - args.value.name = from_moz(key);
87 - return new AST_ObjectGetter(args);
88 - }
89 - })
90 - });
91 - },
92 - SequenceExpression : function(M) {
93 - return AST_Seq.from_array(M.expressions.map(from_moz));
94 - },
95 - MemberExpression : function(M) {
96 - return new (M.computed ? AST_Sub : AST_Dot)({
97 - start : my_start_token(M),
98 - end : my_end_token(M),
99 - property : M.computed ? from_moz(M.property) : M.property.name,
100 - expression : from_moz(M.object)
101 - });
102 - },
103 - SwitchCase : function(M) {
104 - return new (M.test ? AST_Case : AST_Default)({
105 - start : my_start_token(M),
106 - end : my_end_token(M),
107 - expression : from_moz(M.test),
108 - body : M.consequent.map(from_moz)
109 - });
110 - },
111 - Literal : function(M) {
112 - var val = M.value, args = {
113 - start : my_start_token(M),
114 - end : my_end_token(M)
115 - };
116 - if (val === null) return new AST_Null(args);
117 - switch (typeof val) {
118 - case "string":
119 - args.value = val;
120 - return new AST_String(args);
121 - case "number":
122 - args.value = val;
123 - return new AST_Number(args);
124 - case "boolean":
125 - return new (val ? AST_True : AST_False)(args);
126 - default:
127 - args.value = val;
128 - return new AST_RegExp(args);
129 - }
130 - },
131 - UnaryExpression: From_Moz_Unary,
132 - UpdateExpression: From_Moz_Unary,
133 - Identifier: function(M) {
134 - var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
135 - return new (M.name == "this" ? AST_This
136 - : p.type == "LabeledStatement" ? AST_Label
137 - : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
138 - : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
139 - : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
140 - : p.type == "CatchClause" ? AST_SymbolCatch
141 - : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
142 - : AST_SymbolRef)({
143 - start : my_start_token(M),
144 - end : my_end_token(M),
145 - name : M.name
146 - });
147 - }
148 - };
149 -
150 - function From_Moz_Unary(M) {
151 - var prefix = "prefix" in M ? M.prefix
152 - : M.type == "UnaryExpression" ? true : false;
153 - return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
154 - start : my_start_token(M),
155 - end : my_end_token(M),
156 - operator : M.operator,
157 - expression : from_moz(M.argument)
158 - });
159 - };
160 -
161 - var ME_TO_MOZ = {};
162 -
163 - map("Node", AST_Node);
164 - map("Program", AST_Toplevel, "body@body");
165 - map("Function", AST_Function, "id>name, params@argnames, body%body");
166 - map("EmptyStatement", AST_EmptyStatement);
167 - map("BlockStatement", AST_BlockStatement, "body@body");
168 - map("ExpressionStatement", AST_SimpleStatement, "expression>body");
169 - map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
170 - map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
171 - map("BreakStatement", AST_Break, "label>label");
172 - map("ContinueStatement", AST_Continue, "label>label");
173 - map("WithStatement", AST_With, "object>expression, body>body");
174 - map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
175 - map("ReturnStatement", AST_Return, "argument>value");
176 - map("ThrowStatement", AST_Throw, "argument>value");
177 - map("WhileStatement", AST_While, "test>condition, body>body");
178 - map("DoWhileStatement", AST_Do, "test>condition, body>body");
179 - map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
180 - map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
181 - map("DebuggerStatement", AST_Debugger);
182 - map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
183 - map("VariableDeclaration", AST_Var, "declarations@definitions");
184 - map("VariableDeclarator", AST_VarDef, "id>name, init>value");
185 -
186 - map("ThisExpression", AST_This);
187 - map("ArrayExpression", AST_Array, "elements@elements");
188 - map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
189 - map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
190 - map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
191 - map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
192 - map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
193 - map("NewExpression", AST_New, "callee>expression, arguments@args");
194 - map("CallExpression", AST_Call, "callee>expression, arguments@args");
195 -
196 - /* -----[ tools ]----- */
197 -
198 - function my_start_token(moznode) {
199 - return new AST_Token({
200 - file : moznode.loc && moznode.loc.source,
201 - line : moznode.loc && moznode.loc.start.line,
202 - col : moznode.loc && moznode.loc.start.column,
203 - pos : moznode.start,
204 - endpos : moznode.start
205 - });
206 - };
207 -
208 - function my_end_token(moznode) {
209 - return new AST_Token({
210 - file : moznode.loc && moznode.loc.source,
211 - line : moznode.loc && moznode.loc.end.line,
212 - col : moznode.loc && moznode.loc.end.column,
213 - pos : moznode.end,
214 - endpos : moznode.end
215 - });
216 - };
217 -
218 - function map(moztype, mytype, propmap) {
219 - var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
220 - moz_to_me += "return new mytype({\n" +
221 - "start: my_start_token(M),\n" +
222 - "end: my_end_token(M)";
223 -
224 - if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
225 - var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
226 - if (!m) throw new Error("Can't understand property map: " + prop);
227 - var moz = "M." + m[1], how = m[2], my = m[3];
228 - moz_to_me += ",\n" + my + ": ";
229 - if (how == "@") {
230 - moz_to_me += moz + ".map(from_moz)";
231 - } else if (how == ">") {
232 - moz_to_me += "from_moz(" + moz + ")";
233 - } else if (how == "=") {
234 - moz_to_me += moz;
235 - } else if (how == "%") {
236 - moz_to_me += "from_moz(" + moz + ").body";
237 - } else throw new Error("Can't understand operator in propmap: " + prop);
238 - });
239 - moz_to_me += "\n})}";
240 -
241 - // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
242 - // console.log(moz_to_me);
243 -
244 - moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
245 - mytype, my_start_token, my_end_token, from_moz
246 - );
247 - return MOZ_TO_ME[moztype] = moz_to_me;
248 - };
249 -
250 - var FROM_MOZ_STACK = null;
251 -
252 - function from_moz(node) {
253 - FROM_MOZ_STACK.push(node);
254 - var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
255 - FROM_MOZ_STACK.pop();
256 - return ret;
257 - };
258 -
259 - AST_Node.from_mozilla_ast = function(node){
260 - var save_stack = FROM_MOZ_STACK;
261 - FROM_MOZ_STACK = [];
262 - var ast = from_moz(node);
263 - FROM_MOZ_STACK = save_stack;
264 - return ast;
265 - };
266 -
267 -})();
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -function OutputStream(options) {
47 -
48 - options = defaults(options, {
49 - indent_start : 0,
50 - indent_level : 4,
51 - quote_keys : false,
52 - space_colon : true,
53 - ascii_only : false,
54 - inline_script : false,
55 - width : 80,
56 - max_line_len : 32000,
57 - ie_proof : true,
58 - beautify : false,
59 - source_map : null,
60 - bracketize : false,
61 - semicolons : true,
62 - comments : false,
63 - preserve_line : false
64 - }, true);
65 -
66 - var indentation = 0;
67 - var current_col = 0;
68 - var current_line = 1;
69 - var current_pos = 0;
70 - var OUTPUT = "";
71 -
72 - function to_ascii(str, identifier) {
73 - return str.replace(/[\u0080-\uffff]/g, function(ch) {
74 - var code = ch.charCodeAt(0).toString(16);
75 - if (code.length <= 2 && !identifier) {
76 - while (code.length < 2) code = "0" + code;
77 - return "\\x" + code;
78 - } else {
79 - while (code.length < 4) code = "0" + code;
80 - return "\\u" + code;
81 - }
82 - });
83 - };
84 -
85 - function make_string(str) {
86 - var dq = 0, sq = 0;
87 - str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){
88 - switch (s) {
89 - case "\\": return "\\\\";
90 - case "\b": return "\\b";
91 - case "\f": return "\\f";
92 - case "\n": return "\\n";
93 - case "\r": return "\\r";
94 - case "\u2028": return "\\u2028";
95 - case "\u2029": return "\\u2029";
96 - case '"': ++dq; return '"';
97 - case "'": ++sq; return "'";
98 - case "\0": return "\\0";
99 - }
100 - return s;
101 - });
102 - if (options.ascii_only) str = to_ascii(str);
103 - if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'";
104 - else return '"' + str.replace(/\x22/g, '\\"') + '"';
105 - };
106 -
107 - function encode_string(str) {
108 - var ret = make_string(str);
109 - if (options.inline_script)
110 - ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
111 - return ret;
112 - };
113 -
114 - function make_name(name) {
115 - name = name.toString();
116 - if (options.ascii_only)
117 - name = to_ascii(name, true);
118 - return name;
119 - };
120 -
121 - function make_indent(back) {
122 - return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
123 - };
124 -
125 - /* -----[ beautification/minification ]----- */
126 -
127 - var might_need_space = false;
128 - var might_need_semicolon = false;
129 - var last = null;
130 -
131 - function last_char() {
132 - return last.charAt(last.length - 1);
133 - };
134 -
135 - function maybe_newline() {
136 - if (options.max_line_len && current_col > options.max_line_len)
137 - print("\n");
138 - };
139 -
140 - var requireSemicolonChars = makePredicate("( [ + * / - , .");
141 -
142 - function print(str) {
143 - str = String(str);
144 - var ch = str.charAt(0);
145 - if (might_need_semicolon) {
146 - if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
147 - if (options.semicolons || requireSemicolonChars(ch)) {
148 - OUTPUT += ";";
149 - current_col++;
150 - current_pos++;
151 - } else {
152 - OUTPUT += "\n";
153 - current_pos++;
154 - current_line++;
155 - current_col = 0;
156 - }
157 - if (!options.beautify)
158 - might_need_space = false;
159 - }
160 - might_need_semicolon = false;
161 - maybe_newline();
162 - }
163 -
164 - if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
165 - var target_line = stack[stack.length - 1].start.line;
166 - while (current_line < target_line) {
167 - OUTPUT += "\n";
168 - current_pos++;
169 - current_line++;
170 - current_col = 0;
171 - might_need_space = false;
172 - }
173 - }
174 -
175 - if (might_need_space) {
176 - var prev = last_char();
177 - if ((is_identifier_char(prev)
178 - && (is_identifier_char(ch) || ch == "\\"))
179 - || (/^[\+\-\/]$/.test(ch) && ch == prev))
180 - {
181 - OUTPUT += " ";
182 - current_col++;
183 - current_pos++;
184 - }
185 - might_need_space = false;
186 - }
187 - var a = str.split(/\r?\n/), n = a.length - 1;
188 - current_line += n;
189 - if (n == 0) {
190 - current_col += a[n].length;
191 - } else {
192 - current_col = a[n].length;
193 - }
194 - current_pos += str.length;
195 - last = str;
196 - OUTPUT += str;
197 - };
198 -
199 - var space = options.beautify ? function() {
200 - print(" ");
201 - } : function() {
202 - might_need_space = true;
203 - };
204 -
205 - var indent = options.beautify ? function(half) {
206 - if (options.beautify) {
207 - print(make_indent(half ? 0.5 : 0));
208 - }
209 - } : noop;
210 -
211 - var with_indent = options.beautify ? function(col, cont) {
212 - if (col === true) col = next_indent();
213 - var save_indentation = indentation;
214 - indentation = col;
215 - var ret = cont();
216 - indentation = save_indentation;
217 - return ret;
218 - } : function(col, cont) { return cont() };
219 -
220 - var newline = options.beautify ? function() {
221 - print("\n");
222 - } : noop;
223 -
224 - var semicolon = options.beautify ? function() {
225 - print(";");
226 - } : function() {
227 - might_need_semicolon = true;
228 - };
229 -
230 - function force_semicolon() {
231 - might_need_semicolon = false;
232 - print(";");
233 - };
234 -
235 - function next_indent() {
236 - return indentation + options.indent_level;
237 - };
238 -
239 - function with_block(cont) {
240 - var ret;
241 - print("{");
242 - newline();
243 - with_indent(next_indent(), function(){
244 - ret = cont();
245 - });
246 - indent();
247 - print("}");
248 - return ret;
249 - };
250 -
251 - function with_parens(cont) {
252 - print("(");
253 - //XXX: still nice to have that for argument lists
254 - //var ret = with_indent(current_col, cont);
255 - var ret = cont();
256 - print(")");
257 - return ret;
258 - };
259 -
260 - function with_square(cont) {
261 - print("[");
262 - //var ret = with_indent(current_col, cont);
263 - var ret = cont();
264 - print("]");
265 - return ret;
266 - };
267 -
268 - function comma() {
269 - print(",");
270 - space();
271 - };
272 -
273 - function colon() {
274 - print(":");
275 - if (options.space_colon) space();
276 - };
277 -
278 - var add_mapping = options.source_map ? function(token, name) {
279 - try {
280 - if (token) options.source_map.add(
281 - token.file || "?",
282 - current_line, current_col,
283 - token.line, token.col,
284 - (!name && token.type == "name") ? token.value : name
285 - );
286 - } catch(ex) {
287 - AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
288 - file: token.file,
289 - line: token.line,
290 - col: token.col,
291 - cline: current_line,
292 - ccol: current_col,
293 - name: name || ""
294 - })
295 - }
296 - } : noop;
297 -
298 - function get() {
299 - return OUTPUT;
300 - };
301 -
302 - var stack = [];
303 - return {
304 - get : get,
305 - toString : get,
306 - indent : indent,
307 - indentation : function() { return indentation },
308 - current_width : function() { return current_col - indentation },
309 - should_break : function() { return options.width && this.current_width() >= options.width },
310 - newline : newline,
311 - print : print,
312 - space : space,
313 - comma : comma,
314 - colon : colon,
315 - last : function() { return last },
316 - semicolon : semicolon,
317 - force_semicolon : force_semicolon,
318 - to_ascii : to_ascii,
319 - print_name : function(name) { print(make_name(name)) },
320 - print_string : function(str) { print(encode_string(str)) },
321 - next_indent : next_indent,
322 - with_indent : with_indent,
323 - with_block : with_block,
324 - with_parens : with_parens,
325 - with_square : with_square,
326 - add_mapping : add_mapping,
327 - option : function(opt) { return options[opt] },
328 - line : function() { return current_line },
329 - col : function() { return current_col },
330 - pos : function() { return current_pos },
331 - push_node : function(node) { stack.push(node) },
332 - pop_node : function() { return stack.pop() },
333 - stack : function() { return stack },
334 - parent : function(n) {
335 - return stack[stack.length - 2 - (n || 0)];
336 - }
337 - };
338 -
339 -};
340 -
341 -/* -----[ code generators ]----- */
342 -
343 -(function(){
344 -
345 - /* -----[ utils ]----- */
346 -
347 - function DEFPRINT(nodetype, generator) {
348 - nodetype.DEFMETHOD("_codegen", generator);
349 - };
350 -
351 - AST_Node.DEFMETHOD("print", function(stream, force_parens){
352 - var self = this, generator = self._codegen;
353 - stream.push_node(self);
354 - if (force_parens || self.needs_parens(stream)) {
355 - stream.with_parens(function(){
356 - self.add_comments(stream);
357 - self.add_source_map(stream);
358 - generator(self, stream);
359 - });
360 - } else {
361 - self.add_comments(stream);
362 - self.add_source_map(stream);
363 - generator(self, stream);
364 - }
365 - stream.pop_node();
366 - });
367 -
368 - AST_Node.DEFMETHOD("print_to_string", function(options){
369 - var s = OutputStream(options);
370 - this.print(s);
371 - return s.get();
372 - });
373 -
374 - /* -----[ comments ]----- */
375 -
376 - AST_Node.DEFMETHOD("add_comments", function(output){
377 - var c = output.option("comments"), self = this;
378 - if (c) {
379 - var start = self.start;
380 - if (start && !start._comments_dumped) {
381 - start._comments_dumped = true;
382 - var comments = start.comments_before;
383 -
384 - // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
385 - // if this node is `return` or `throw`, we cannot allow comments before
386 - // the returned or thrown value.
387 - if (self instanceof AST_Exit &&
388 - self.value && self.value.start.comments_before.length > 0) {
389 - comments = (comments || []).concat(self.value.start.comments_before);
390 - self.value.start.comments_before = [];
391 - }
392 -
393 - if (c.test) {
394 - comments = comments.filter(function(comment){
395 - return c.test(comment.value);
396 - });
397 - } else if (typeof c == "function") {
398 - comments = comments.filter(function(comment){
399 - return c(self, comment);
400 - });
401 - }
402 - comments.forEach(function(c){
403 - if (c.type == "comment1") {
404 - output.print("//" + c.value + "\n");
405 - output.indent();
406 - }
407 - else if (c.type == "comment2") {
408 - output.print("/*" + c.value + "*/");
409 - if (start.nlb) {
410 - output.print("\n");
411 - output.indent();
412 - } else {
413 - output.space();
414 - }
415 - }
416 - });
417 - }
418 - }
419 - });
420 -
421 - /* -----[ PARENTHESES ]----- */
422 -
423 - function PARENS(nodetype, func) {
424 - nodetype.DEFMETHOD("needs_parens", func);
425 - };
426 -
427 - PARENS(AST_Node, function(){
428 - return false;
429 - });
430 -
431 - // a function expression needs parens around it when it's provably
432 - // the first token to appear in a statement.
433 - PARENS(AST_Function, function(output){
434 - return first_in_statement(output);
435 - });
436 -
437 - // same goes for an object literal, because otherwise it would be
438 - // interpreted as a block of code.
439 - PARENS(AST_Object, function(output){
440 - return first_in_statement(output);
441 - });
442 -
443 - PARENS(AST_Unary, function(output){
444 - var p = output.parent();
445 - return p instanceof AST_PropAccess && p.expression === this;
446 - });
447 -
448 - PARENS(AST_Seq, function(output){
449 - var p = output.parent();
450 - return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
451 - || p instanceof AST_Unary // !(foo, bar, baz)
452 - || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
453 - || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
454 - || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2
455 - || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
456 - || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
457 - || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
458 - * ==> 20 (side effect, set a := 10 and b := 20) */
459 - ;
460 - });
461 -
462 - PARENS(AST_Binary, function(output){
463 - var p = output.parent();
464 - // (foo && bar)()
465 - if (p instanceof AST_Call && p.expression === this)
466 - return true;
467 - // typeof (foo && bar)
468 - if (p instanceof AST_Unary)
469 - return true;
470 - // (foo && bar)["prop"], (foo && bar).prop
471 - if (p instanceof AST_PropAccess && p.expression === this)
472 - return true;
473 - // this deals with precedence: 3 * (2 + 1)
474 - if (p instanceof AST_Binary) {
475 - var po = p.operator, pp = PRECEDENCE[po];
476 - var so = this.operator, sp = PRECEDENCE[so];
477 - if (pp > sp
478 - || (pp == sp
479 - && this === p.right
480 - && !(so == po &&
481 - (so == "*" ||
482 - so == "&&" ||
483 - so == "||")))) {
484 - return true;
485 - }
486 - }
487 - });
488 -
489 - PARENS(AST_PropAccess, function(output){
490 - var p = output.parent();
491 - if (p instanceof AST_New && p.expression === this) {
492 - // i.e. new (foo.bar().baz)
493 - //
494 - // if there's one call into this subtree, then we need
495 - // parens around it too, otherwise the call will be
496 - // interpreted as passing the arguments to the upper New
497 - // expression.
498 - try {
499 - this.walk(new TreeWalker(function(node){
500 - if (node instanceof AST_Call) throw p;
501 - }));
502 - } catch(ex) {
503 - if (ex !== p) throw ex;
504 - return true;
505 - }
506 - }
507 - });
508 -
509 - PARENS(AST_Call, function(output){
510 - var p = output.parent();
511 - return p instanceof AST_New && p.expression === this;
512 - });
513 -
514 - PARENS(AST_New, function(output){
515 - var p = output.parent();
516 - if (no_constructor_parens(this, output)
517 - && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
518 - || p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
519 - return true;
520 - });
521 -
522 - PARENS(AST_Number, function(output){
523 - var p = output.parent();
524 - if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this)
525 - return true;
526 - });
527 -
528 - PARENS(AST_NaN, function(output){
529 - var p = output.parent();
530 - if (p instanceof AST_PropAccess && p.expression === this)
531 - return true;
532 - });
533 -
534 - function assign_and_conditional_paren_rules(output) {
535 - var p = output.parent();
536 - // !(a = false) → true
537 - if (p instanceof AST_Unary)
538 - return true;
539 - // 1 + (a = 2) + 3 → 6, side effect setting a = 2
540 - if (p instanceof AST_Binary && !(p instanceof AST_Assign))
541 - return true;
542 - // (a = func)() —or— new (a = Object)()
543 - if (p instanceof AST_Call && p.expression === this)
544 - return true;
545 - // (a = foo) ? bar : baz
546 - if (p instanceof AST_Conditional && p.condition === this)
547 - return true;
548 - // (a = foo)["prop"] —or— (a = foo).prop
549 - if (p instanceof AST_PropAccess && p.expression === this)
550 - return true;
551 - };
552 -
553 - PARENS(AST_Assign, assign_and_conditional_paren_rules);
554 - PARENS(AST_Conditional, assign_and_conditional_paren_rules);
555 -
556 - /* -----[ PRINTERS ]----- */
557 -
558 - DEFPRINT(AST_Directive, function(self, output){
559 - output.print_string(self.value);
560 - output.semicolon();
561 - });
562 - DEFPRINT(AST_Debugger, function(self, output){
563 - output.print("debugger");
564 - output.semicolon();
565 - });
566 -
567 - /* -----[ statements ]----- */
568 -
569 - function display_body(body, is_toplevel, output) {
570 - var last = body.length - 1;
571 - body.forEach(function(stmt, i){
572 - if (!(stmt instanceof AST_EmptyStatement)) {
573 - output.indent();
574 - stmt.print(output);
575 - if (!(i == last && is_toplevel)) {
576 - output.newline();
577 - if (is_toplevel) output.newline();
578 - }
579 - }
580 - });
581 - };
582 -
583 - AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
584 - force_statement(this.body, output);
585 - });
586 -
587 - DEFPRINT(AST_Statement, function(self, output){
588 - self.body.print(output);
589 - output.semicolon();
590 - });
591 - DEFPRINT(AST_Toplevel, function(self, output){
592 - display_body(self.body, true, output);
593 - output.print("");
594 - });
595 - DEFPRINT(AST_LabeledStatement, function(self, output){
596 - self.label.print(output);
597 - output.colon();
598 - self.body.print(output);
599 - });
600 - DEFPRINT(AST_SimpleStatement, function(self, output){
601 - self.body.print(output);
602 - output.semicolon();
603 - });
604 - function print_bracketed(body, output) {
605 - if (body.length > 0) output.with_block(function(){
606 - display_body(body, false, output);
607 - });
608 - else output.print("{}");
609 - };
610 - DEFPRINT(AST_BlockStatement, function(self, output){
611 - print_bracketed(self.body, output);
612 - });
613 - DEFPRINT(AST_EmptyStatement, function(self, output){
614 - output.semicolon();
615 - });
616 - DEFPRINT(AST_Do, function(self, output){
617 - output.print("do");
618 - output.space();
619 - self._do_print_body(output);
620 - output.space();
621 - output.print("while");
622 - output.space();
623 - output.with_parens(function(){
624 - self.condition.print(output);
625 - });
626 - output.semicolon();
627 - });
628 - DEFPRINT(AST_While, function(self, output){
629 - output.print("while");
630 - output.space();
631 - output.with_parens(function(){
632 - self.condition.print(output);
633 - });
634 - output.space();
635 - self._do_print_body(output);
636 - });
637 - DEFPRINT(AST_For, function(self, output){
638 - output.print("for");
639 - output.space();
640 - output.with_parens(function(){
641 - if (self.init) {
642 - if (self.init instanceof AST_Definitions) {
643 - self.init.print(output);
644 - } else {
645 - parenthesize_for_noin(self.init, output, true);
646 - }
647 - output.print(";");
648 - output.space();
649 - } else {
650 - output.print(";");
651 - }
652 - if (self.condition) {
653 - self.condition.print(output);
654 - output.print(";");
655 - output.space();
656 - } else {
657 - output.print(";");
658 - }
659 - if (self.step) {
660 - self.step.print(output);
661 - }
662 - });
663 - output.space();
664 - self._do_print_body(output);
665 - });
666 - DEFPRINT(AST_ForIn, function(self, output){
667 - output.print("for");
668 - output.space();
669 - output.with_parens(function(){
670 - self.init.print(output);
671 - output.space();
672 - output.print("in");
673 - output.space();
674 - self.object.print(output);
675 - });
676 - output.space();
677 - self._do_print_body(output);
678 - });
679 - DEFPRINT(AST_With, function(self, output){
680 - output.print("with");
681 - output.space();
682 - output.with_parens(function(){
683 - self.expression.print(output);
684 - });
685 - output.space();
686 - self._do_print_body(output);
687 - });
688 -
689 - /* -----[ functions ]----- */
690 - AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
691 - var self = this;
692 - if (!nokeyword) {
693 - output.print("function");
694 - }
695 - if (self.name) {
696 - output.space();
697 - self.name.print(output);
698 - }
699 - output.with_parens(function(){
700 - self.argnames.forEach(function(arg, i){
701 - if (i) output.comma();
702 - arg.print(output);
703 - });
704 - });
705 - output.space();
706 - print_bracketed(self.body, output);
707 - });
708 - DEFPRINT(AST_Lambda, function(self, output){
709 - self._do_print(output);
710 - });
711 -
712 - /* -----[ exits ]----- */
713 - AST_Exit.DEFMETHOD("_do_print", function(output, kind){
714 - output.print(kind);
715 - if (this.value) {
716 - output.space();
717 - this.value.print(output);
718 - }
719 - output.semicolon();
720 - });
721 - DEFPRINT(AST_Return, function(self, output){
722 - self._do_print(output, "return");
723 - });
724 - DEFPRINT(AST_Throw, function(self, output){
725 - self._do_print(output, "throw");
726 - });
727 -
728 - /* -----[ loop control ]----- */
729 - AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
730 - output.print(kind);
731 - if (this.label) {
732 - output.space();
733 - this.label.print(output);
734 - }
735 - output.semicolon();
736 - });
737 - DEFPRINT(AST_Break, function(self, output){
738 - self._do_print(output, "break");
739 - });
740 - DEFPRINT(AST_Continue, function(self, output){
741 - self._do_print(output, "continue");
742 - });
743 -
744 - /* -----[ if ]----- */
745 - function make_then(self, output) {
746 - if (output.option("bracketize")) {
747 - make_block(self.body, output);
748 - return;
749 - }
750 - // The squeezer replaces "block"-s that contain only a single
751 - // statement with the statement itself; technically, the AST
752 - // is correct, but this can create problems when we output an
753 - // IF having an ELSE clause where the THEN clause ends in an
754 - // IF *without* an ELSE block (then the outer ELSE would refer
755 - // to the inner IF). This function checks for this case and
756 - // adds the block brackets if needed.
757 - if (!self.body)
758 - return output.force_semicolon();
759 - if (self.body instanceof AST_Do
760 - && output.option("ie_proof")) {
761 - // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
762 - // croaks with "syntax error" on code like this: if (foo)
763 - // do ... while(cond); else ... we need block brackets
764 - // around do/while
765 - make_block(self.body, output);
766 - return;
767 - }
768 - var b = self.body;
769 - while (true) {
770 - if (b instanceof AST_If) {
771 - if (!b.alternative) {
772 - make_block(self.body, output);
773 - return;
774 - }
775 - b = b.alternative;
776 - }
777 - else if (b instanceof AST_StatementWithBody) {
778 - b = b.body;
779 - }
780 - else break;
781 - }
782 - force_statement(self.body, output);
783 - };
784 - DEFPRINT(AST_If, function(self, output){
785 - output.print("if");
786 - output.space();
787 - output.with_parens(function(){
788 - self.condition.print(output);
789 - });
790 - output.space();
791 - if (self.alternative) {
792 - make_then(self, output);
793 - output.space();
794 - output.print("else");
795 - output.space();
796 - force_statement(self.alternative, output);
797 - } else {
798 - self._do_print_body(output);
799 - }
800 - });
801 -
802 - /* -----[ switch ]----- */
803 - DEFPRINT(AST_Switch, function(self, output){
804 - output.print("switch");
805 - output.space();
806 - output.with_parens(function(){
807 - self.expression.print(output);
808 - });
809 - output.space();
810 - if (self.body.length > 0) output.with_block(function(){
811 - self.body.forEach(function(stmt, i){
812 - if (i) output.newline();
813 - output.indent(true);
814 - stmt.print(output);
815 - });
816 - });
817 - else output.print("{}");
818 - });
819 - AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
820 - if (this.body.length > 0) {
821 - output.newline();
822 - this.body.forEach(function(stmt){
823 - output.indent();
824 - stmt.print(output);
825 - output.newline();
826 - });
827 - }
828 - });
829 - DEFPRINT(AST_Default, function(self, output){
830 - output.print("default:");
831 - self._do_print_body(output);
832 - });
833 - DEFPRINT(AST_Case, function(self, output){
834 - output.print("case");
835 - output.space();
836 - self.expression.print(output);
837 - output.print(":");
838 - self._do_print_body(output);
839 - });
840 -
841 - /* -----[ exceptions ]----- */
842 - DEFPRINT(AST_Try, function(self, output){
843 - output.print("try");
844 - output.space();
845 - print_bracketed(self.body, output);
846 - if (self.bcatch) {
847 - output.space();
848 - self.bcatch.print(output);
849 - }
850 - if (self.bfinally) {
851 - output.space();
852 - self.bfinally.print(output);
853 - }
854 - });
855 - DEFPRINT(AST_Catch, function(self, output){
856 - output.print("catch");
857 - output.space();
858 - output.with_parens(function(){
859 - self.argname.print(output);
860 - });
861 - output.space();
862 - print_bracketed(self.body, output);
863 - });
864 - DEFPRINT(AST_Finally, function(self, output){
865 - output.print("finally");
866 - output.space();
867 - print_bracketed(self.body, output);
868 - });
869 -
870 - /* -----[ var/const ]----- */
871 - AST_Definitions.DEFMETHOD("_do_print", function(output, kind){
872 - output.print(kind);
873 - output.space();
874 - this.definitions.forEach(function(def, i){
875 - if (i) output.comma();
876 - def.print(output);
877 - });
878 - var p = output.parent();
879 - var in_for = p instanceof AST_For || p instanceof AST_ForIn;
880 - var avoid_semicolon = in_for && p.init === this;
881 - if (!avoid_semicolon)
882 - output.semicolon();
883 - });
884 - DEFPRINT(AST_Var, function(self, output){
885 - self._do_print(output, "var");
886 - });
887 - DEFPRINT(AST_Const, function(self, output){
888 - self._do_print(output, "const");
889 - });
890 -
891 - function parenthesize_for_noin(node, output, noin) {
892 - if (!noin) node.print(output);
893 - else try {
894 - // need to take some precautions here:
895 - // https://github.com/mishoo/UglifyJS2/issues/60
896 - node.walk(new TreeWalker(function(node){
897 - if (node instanceof AST_Binary && node.operator == "in")
898 - throw output;
899 - }));
900 - node.print(output);
901 - } catch(ex) {
902 - if (ex !== output) throw ex;
903 - node.print(output, true);
904 - }
905 - };
906 -
907 - DEFPRINT(AST_VarDef, function(self, output){
908 - self.name.print(output);
909 - if (self.value) {
910 - output.space();
911 - output.print("=");
912 - output.space();
913 - var p = output.parent(1);
914 - var noin = p instanceof AST_For || p instanceof AST_ForIn;
915 - parenthesize_for_noin(self.value, output, noin);
916 - }
917 - });
918 -
919 - /* -----[ other expressions ]----- */
920 - DEFPRINT(AST_Call, function(self, output){
921 - self.expression.print(output);
922 - if (self instanceof AST_New && no_constructor_parens(self, output))
923 - return;
924 - output.with_parens(function(){
925 - self.args.forEach(function(expr, i){
926 - if (i) output.comma();
927 - expr.print(output);
928 - });
929 - });
930 - });
931 - DEFPRINT(AST_New, function(self, output){
932 - output.print("new");
933 - output.space();
934 - AST_Call.prototype._codegen(self, output);
935 - });
936 -
937 - AST_Seq.DEFMETHOD("_do_print", function(output){
938 - this.car.print(output);
939 - if (this.cdr) {
940 - output.comma();
941 - if (output.should_break()) {
942 - output.newline();
943 - output.indent();
944 - }
945 - this.cdr.print(output);
946 - }
947 - });
948 - DEFPRINT(AST_Seq, function(self, output){
949 - self._do_print(output);
950 - // var p = output.parent();
951 - // if (p instanceof AST_Statement) {
952 - // output.with_indent(output.next_indent(), function(){
953 - // self._do_print(output);
954 - // });
955 - // } else {
956 - // self._do_print(output);
957 - // }
958 - });
959 - DEFPRINT(AST_Dot, function(self, output){
960 - var expr = self.expression;
961 - expr.print(output);
962 - if (expr instanceof AST_Number && expr.getValue() >= 0) {
963 - if (!/[xa-f.]/i.test(output.last())) {
964 - output.print(".");
965 - }
966 - }
967 - output.print(".");
968 - // the name after dot would be mapped about here.
969 - output.add_mapping(self.end);
970 - output.print_name(self.property);
971 - });
972 - DEFPRINT(AST_Sub, function(self, output){
973 - self.expression.print(output);
974 - output.print("[");
975 - self.property.print(output);
976 - output.print("]");
977 - });
978 - DEFPRINT(AST_UnaryPrefix, function(self, output){
979 - var op = self.operator;
980 - output.print(op);
981 - if (/^[a-z]/i.test(op))
982 - output.space();
983 - self.expression.print(output);
984 - });
985 - DEFPRINT(AST_UnaryPostfix, function(self, output){
986 - self.expression.print(output);
987 - output.print(self.operator);
988 - });
989 - DEFPRINT(AST_Binary, function(self, output){
990 - self.left.print(output);
991 - output.space();
992 - output.print(self.operator);
993 - output.space();
994 - self.right.print(output);
995 - });
996 - DEFPRINT(AST_Conditional, function(self, output){
997 - self.condition.print(output);
998 - output.space();
999 - output.print("?");
1000 - output.space();
1001 - self.consequent.print(output);
1002 - output.space();
1003 - output.colon();
1004 - self.alternative.print(output);
1005 - });
1006 -
1007 - /* -----[ literals ]----- */
1008 - DEFPRINT(AST_Array, function(self, output){
1009 - output.with_square(function(){
1010 - var a = self.elements, len = a.length;
1011 - if (len > 0) output.space();
1012 - a.forEach(function(exp, i){
1013 - if (i) output.comma();
1014 - exp.print(output);
1015 - });
1016 - if (len > 0) output.space();
1017 - });
1018 - });
1019 - DEFPRINT(AST_Object, function(self, output){
1020 - if (self.properties.length > 0) output.with_block(function(){
1021 - self.properties.forEach(function(prop, i){
1022 - if (i) {
1023 - output.print(",");
1024 - output.newline();
1025 - }
1026 - output.indent();
1027 - prop.print(output);
1028 - });
1029 - output.newline();
1030 - });
1031 - else output.print("{}");
1032 - });
1033 - DEFPRINT(AST_ObjectKeyVal, function(self, output){
1034 - var key = self.key;
1035 - if (output.option("quote_keys")) {
1036 - output.print_string(key + "");
1037 - } else if ((typeof key == "number"
1038 - || !output.option("beautify")
1039 - && +key + "" == key)
1040 - && parseFloat(key) >= 0) {
1041 - output.print(make_num(key));
1042 - } else if (!is_identifier(key)) {
1043 - output.print_string(key);
1044 - } else {
1045 - output.print_name(key);
1046 - }
1047 - output.colon();
1048 - self.value.print(output);
1049 - });
1050 - DEFPRINT(AST_ObjectSetter, function(self, output){
1051 - output.print("set");
1052 - self.value._do_print(output, true);
1053 - });
1054 - DEFPRINT(AST_ObjectGetter, function(self, output){
1055 - output.print("get");
1056 - self.value._do_print(output, true);
1057 - });
1058 - DEFPRINT(AST_Symbol, function(self, output){
1059 - var def = self.definition();
1060 - output.print_name(def ? def.mangled_name || def.name : self.name);
1061 - });
1062 - DEFPRINT(AST_Undefined, function(self, output){
1063 - output.print("void 0");
1064 - });
1065 - DEFPRINT(AST_Hole, noop);
1066 - DEFPRINT(AST_Infinity, function(self, output){
1067 - output.print("1/0");
1068 - });
1069 - DEFPRINT(AST_NaN, function(self, output){
1070 - output.print("0/0");
1071 - });
1072 - DEFPRINT(AST_This, function(self, output){
1073 - output.print("this");
1074 - });
1075 - DEFPRINT(AST_Constant, function(self, output){
1076 - output.print(self.getValue());
1077 - });
1078 - DEFPRINT(AST_String, function(self, output){
1079 - output.print_string(self.getValue());
1080 - });
1081 - DEFPRINT(AST_Number, function(self, output){
1082 - output.print(make_num(self.getValue()));
1083 - });
1084 - DEFPRINT(AST_RegExp, function(self, output){
1085 - var str = self.getValue().toString();
1086 - if (output.option("ascii_only"))
1087 - str = output.to_ascii(str);
1088 - output.print(str);
1089 - var p = output.parent();
1090 - if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
1091 - output.print(" ");
1092 - });
1093 -
1094 - function force_statement(stat, output) {
1095 - if (output.option("bracketize")) {
1096 - if (!stat || stat instanceof AST_EmptyStatement)
1097 - output.print("{}");
1098 - else if (stat instanceof AST_BlockStatement)
1099 - stat.print(output);
1100 - else output.with_block(function(){
1101 - output.indent();
1102 - stat.print(output);
1103 - output.newline();
1104 - });
1105 - } else {
1106 - if (!stat || stat instanceof AST_EmptyStatement)
1107 - output.force_semicolon();
1108 - else
1109 - stat.print(output);
1110 - }
1111 - };
1112 -
1113 - // return true if the node at the top of the stack (that means the
1114 - // innermost node in the current output) is lexically the first in
1115 - // a statement.
1116 - function first_in_statement(output) {
1117 - var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
1118 - while (i > 0) {
1119 - if (p instanceof AST_Statement && p.body === node)
1120 - return true;
1121 - if ((p instanceof AST_Seq && p.car === node ) ||
1122 - (p instanceof AST_Call && p.expression === node ) ||
1123 - (p instanceof AST_Dot && p.expression === node ) ||
1124 - (p instanceof AST_Sub && p.expression === node ) ||
1125 - (p instanceof AST_Conditional && p.condition === node ) ||
1126 - (p instanceof AST_Binary && p.left === node ) ||
1127 - (p instanceof AST_UnaryPostfix && p.expression === node ))
1128 - {
1129 - node = p;
1130 - p = a[--i];
1131 - } else {
1132 - return false;
1133 - }
1134 - }
1135 - };
1136 -
1137 - // self should be AST_New. decide if we want to show parens or not.
1138 - function no_constructor_parens(self, output) {
1139 - return self.args.length == 0 && !output.option("beautify");
1140 - };
1141 -
1142 - function best_of(a) {
1143 - var best = a[0], len = best.length;
1144 - for (var i = 1; i < a.length; ++i) {
1145 - if (a[i].length < len) {
1146 - best = a[i];
1147 - len = best.length;
1148 - }
1149 - }
1150 - return best;
1151 - };
1152 -
1153 - function make_num(num) {
1154 - var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
1155 - if (Math.floor(num) === num) {
1156 - if (num >= 0) {
1157 - a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
1158 - "0" + num.toString(8)); // same.
1159 - } else {
1160 - a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
1161 - "-0" + (-num).toString(8)); // same.
1162 - }
1163 - if ((m = /^(.*?)(0+)$/.exec(num))) {
1164 - a.push(m[1] + "e" + m[2].length);
1165 - }
1166 - } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
1167 - a.push(m[2] + "e-" + (m[1].length + m[2].length),
1168 - str.substr(str.indexOf(".")));
1169 - }
1170 - return best_of(a);
1171 - };
1172 -
1173 - function make_block(stmt, output) {
1174 - if (stmt instanceof AST_BlockStatement) {
1175 - stmt.print(output);
1176 - return;
1177 - }
1178 - output.with_block(function(){
1179 - output.indent();
1180 - stmt.print(output);
1181 - output.newline();
1182 - });
1183 - };
1184 -
1185 - /* -----[ source map generators ]----- */
1186 -
1187 - function DEFMAP(nodetype, generator) {
1188 - nodetype.DEFMETHOD("add_source_map", function(stream){
1189 - generator(this, stream);
1190 - });
1191 - };
1192 -
1193 - // We could easily add info for ALL nodes, but it seems to me that
1194 - // would be quite wasteful, hence this noop in the base class.
1195 - DEFMAP(AST_Node, noop);
1196 -
1197 - function basic_sourcemap_gen(self, output) {
1198 - output.add_mapping(self.start);
1199 - };
1200 -
1201 - // XXX: I'm not exactly sure if we need it for all of these nodes,
1202 - // or if we should add even more.
1203 -
1204 - DEFMAP(AST_Directive, basic_sourcemap_gen);
1205 - DEFMAP(AST_Debugger, basic_sourcemap_gen);
1206 - DEFMAP(AST_Symbol, basic_sourcemap_gen);
1207 - DEFMAP(AST_Jump, basic_sourcemap_gen);
1208 - DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
1209 - DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
1210 - DEFMAP(AST_Lambda, basic_sourcemap_gen);
1211 - DEFMAP(AST_Switch, basic_sourcemap_gen);
1212 - DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
1213 - DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
1214 - DEFMAP(AST_Toplevel, noop);
1215 - DEFMAP(AST_New, basic_sourcemap_gen);
1216 - DEFMAP(AST_Try, basic_sourcemap_gen);
1217 - DEFMAP(AST_Catch, basic_sourcemap_gen);
1218 - DEFMAP(AST_Finally, basic_sourcemap_gen);
1219 - DEFMAP(AST_Definitions, basic_sourcemap_gen);
1220 - DEFMAP(AST_Constant, basic_sourcemap_gen);
1221 - DEFMAP(AST_ObjectProperty, function(self, output){
1222 - output.add_mapping(self.start, self.key);
1223 - });
1224 -
1225 -})();
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 - Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/).
16 -
17 - Redistribution and use in source and binary forms, with or without
18 - modification, are permitted provided that the following conditions
19 - are met:
20 -
21 - * Redistributions of source code must retain the above
22 - copyright notice, this list of conditions and the following
23 - disclaimer.
24 -
25 - * Redistributions in binary form must reproduce the above
26 - copyright notice, this list of conditions and the following
27 - disclaimer in the documentation and/or other materials
28 - provided with the distribution.
29 -
30 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
31 - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
34 - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
35 - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
40 - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 - SUCH DAMAGE.
42 -
43 - ***********************************************************************/
44 -
45 -"use strict";
46 -
47 -var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
48 -var KEYWORDS_ATOM = 'false null true';
49 -var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile'
50 - + " " + KEYWORDS_ATOM + " " + KEYWORDS;
51 -var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
52 -
53 -KEYWORDS = makePredicate(KEYWORDS);
54 -RESERVED_WORDS = makePredicate(RESERVED_WORDS);
55 -KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
56 -KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
57 -
58 -var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
59 -
60 -var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
61 -var RE_OCT_NUMBER = /^0[0-7]+$/;
62 -var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
63 -
64 -var OPERATORS = makePredicate([
65 - "in",
66 - "instanceof",
67 - "typeof",
68 - "new",
69 - "void",
70 - "delete",
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 -var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
112 -
113 -var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
114 -
115 -var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
116 -
117 -var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
118 -
119 -/* -----[ Tokenizer ]----- */
120 -
121 -// regexps adapted from http://xregexp.com/plugins/#unicode
122 -var UNICODE = {
123 - letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
124 - non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
125 - space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
126 - connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
127 -};
128 -
129 -function is_letter(code) {
130 - return (code >= 97 && code <= 122)
131 - || (code >= 65 && code <= 90)
132 - || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
133 -};
134 -
135 -function is_digit(code) {
136 - return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9
137 -};
138 -
139 -function is_alphanumeric_char(code) {
140 - return is_digit(code) || is_letter(code);
141 -};
142 -
143 -function is_unicode_combining_mark(ch) {
144 - return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
145 -};
146 -
147 -function is_unicode_connector_punctuation(ch) {
148 - return UNICODE.connector_punctuation.test(ch);
149 -};
150 -
151 -function is_identifier(name) {
152 - return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
153 -};
154 -
155 -function is_identifier_start(code) {
156 - return code == 36 || code == 95 || is_letter(code);
157 -};
158 -
159 -function is_identifier_char(ch) {
160 - var code = ch.charCodeAt(0);
161 - return is_identifier_start(code)
162 - || is_digit(code)
163 - || code == 8204 // \u200c: zero-width non-joiner <ZWNJ>
164 - || code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
165 - || is_unicode_combining_mark(ch)
166 - || is_unicode_connector_punctuation(ch)
167 - ;
168 -};
169 -
170 -function parse_js_number(num) {
171 - if (RE_HEX_NUMBER.test(num)) {
172 - return parseInt(num.substr(2), 16);
173 - } else if (RE_OCT_NUMBER.test(num)) {
174 - return parseInt(num.substr(1), 8);
175 - } else if (RE_DEC_NUMBER.test(num)) {
176 - return parseFloat(num);
177 - }
178 -};
179 -
180 -function JS_Parse_Error(message, line, col, pos) {
181 - this.message = message;
182 - this.line = line;
183 - this.col = col;
184 - this.pos = pos;
185 - this.stack = new Error().stack;
186 -};
187 -
188 -JS_Parse_Error.prototype.toString = function() {
189 - return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
190 -};
191 -
192 -function js_error(message, filename, line, col, pos) {
193 - throw new JS_Parse_Error(message, line, col, pos);
194 -};
195 -
196 -function is_token(token, type, val) {
197 - return token.type == type && (val == null || token.value == val);
198 -};
199 -
200 -var EX_EOF = {};
201 -
202 -function tokenizer($TEXT, filename) {
203 -
204 - var S = {
205 - text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''),
206 - filename : filename,
207 - pos : 0,
208 - tokpos : 0,
209 - line : 1,
210 - tokline : 0,
211 - col : 0,
212 - tokcol : 0,
213 - newline_before : false,
214 - regex_allowed : false,
215 - comments_before : []
216 - };
217 -
218 - function peek() { return S.text.charAt(S.pos); };
219 -
220 - function next(signal_eof, in_string) {
221 - var ch = S.text.charAt(S.pos++);
222 - if (signal_eof && !ch)
223 - throw EX_EOF;
224 - if (ch == "\n") {
225 - S.newline_before = S.newline_before || !in_string;
226 - ++S.line;
227 - S.col = 0;
228 - } else {
229 - ++S.col;
230 - }
231 - return ch;
232 - };
233 -
234 - function find(what, signal_eof) {
235 - var pos = S.text.indexOf(what, S.pos);
236 - if (signal_eof && pos == -1) throw EX_EOF;
237 - return pos;
238 - };
239 -
240 - function start_token() {
241 - S.tokline = S.line;
242 - S.tokcol = S.col;
243 - S.tokpos = S.pos;
244 - };
245 -
246 - function token(type, value, is_comment) {
247 - S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
248 - (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
249 - (type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
250 - var ret = {
251 - type : type,
252 - value : value,
253 - line : S.tokline,
254 - col : S.tokcol,
255 - pos : S.tokpos,
256 - endpos : S.pos,
257 - nlb : S.newline_before,
258 - file : filename
259 - };
260 - if (!is_comment) {
261 - ret.comments_before = S.comments_before;
262 - S.comments_before = [];
263 - // make note of any newlines in the comments that came before
264 - for (var i = 0, len = ret.comments_before.length; i < len; i++) {
265 - ret.nlb = ret.nlb || ret.comments_before[i].nlb;
266 - }
267 - }
268 - S.newline_before = false;
269 - return new AST_Token(ret);
270 - };
271 -
272 - function skip_whitespace() {
273 - while (WHITESPACE_CHARS(peek()))
274 - next();
275 - };
276 -
277 - function read_while(pred) {
278 - var ret = "", ch, i = 0;
279 - while ((ch = peek()) && pred(ch, i++))
280 - ret += next();
281 - return ret;
282 - };
283 -
284 - function parse_error(err) {
285 - js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
286 - };
287 -
288 - function read_num(prefix) {
289 - var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
290 - var num = read_while(function(ch, i){
291 - var code = ch.charCodeAt(0);
292 - switch (code) {
293 - case 120: case 88: // xX
294 - return has_x ? false : (has_x = true);
295 - case 101: case 69: // eE
296 - return has_x ? true : has_e ? false : (has_e = after_e = true);
297 - case 45: // -
298 - return after_e || (i == 0 && !prefix);
299 - case 43: // +
300 - return after_e;
301 - case (after_e = false, 46): // .
302 - return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
303 - }
304 - return is_alphanumeric_char(code);
305 - });
306 - if (prefix) num = prefix + num;
307 - var valid = parse_js_number(num);
308 - if (!isNaN(valid)) {
309 - return token("num", valid);
310 - } else {
311 - parse_error("Invalid syntax: " + num);
312 - }
313 - };
314 -
315 - function read_escaped_char(in_string) {
316 - var ch = next(true, in_string);
317 - switch (ch.charCodeAt(0)) {
318 - case 110 : return "\n";
319 - case 114 : return "\r";
320 - case 116 : return "\t";
321 - case 98 : return "\b";
322 - case 118 : return "\u000b"; // \v
323 - case 102 : return "\f";
324 - case 48 : return "\0";
325 - case 120 : return String.fromCharCode(hex_bytes(2)); // \x
326 - case 117 : return String.fromCharCode(hex_bytes(4)); // \u
327 - case 10 : return ""; // newline
328 - default : return ch;
329 - }
330 - };
331 -
332 - function hex_bytes(n) {
333 - var num = 0;
334 - for (; n > 0; --n) {
335 - var digit = parseInt(next(true), 16);
336 - if (isNaN(digit))
337 - parse_error("Invalid hex-character pattern in string");
338 - num = (num << 4) | digit;
339 - }
340 - return num;
341 - };
342 -
343 - var read_string = with_eof_error("Unterminated string constant", function(){
344 - var quote = next(), ret = "";
345 - for (;;) {
346 - var ch = next(true);
347 - if (ch == "\\") {
348 - // read OctalEscapeSequence (XXX: deprecated if "strict mode")
349 - // https://github.com/mishoo/UglifyJS/issues/178
350 - var octal_len = 0, first = null;
351 - ch = read_while(function(ch){
352 - if (ch >= "0" && ch <= "7") {
353 - if (!first) {
354 - first = ch;
355 - return ++octal_len;
356 - }
357 - else if (first <= "3" && octal_len <= 2) return ++octal_len;
358 - else if (first >= "4" && octal_len <= 1) return ++octal_len;
359 - }
360 - return false;
361 - });
362 - if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
363 - else ch = read_escaped_char(true);
364 - }
365 - else if (ch == quote) break;
366 - ret += ch;
367 - }
368 - return token("string", ret);
369 - });
370 -
371 - function read_line_comment() {
372 - next();
373 - var i = find("\n"), ret;
374 - if (i == -1) {
375 - ret = S.text.substr(S.pos);
376 - S.pos = S.text.length;
377 - } else {
378 - ret = S.text.substring(S.pos, i);
379 - S.pos = i;
380 - }
381 - return token("comment1", ret, true);
382 - };
383 -
384 - var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
385 - next();
386 - var i = find("*/", true);
387 - var text = S.text.substring(S.pos, i);
388 - var a = text.split("\n"), n = a.length;
389 - // update stream position
390 - S.pos = i + 2;
391 - S.line += n - 1;
392 - if (n > 1) S.col = a[n - 1].length;
393 - else S.col += a[n - 1].length;
394 - S.col += 2;
395 - S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
396 - return token("comment2", text, true);
397 - });
398 -
399 - function read_name() {
400 - var backslash = false, name = "", ch, escaped = false, hex;
401 - while ((ch = peek()) != null) {
402 - if (!backslash) {
403 - if (ch == "\\") escaped = backslash = true, next();
404 - else if (is_identifier_char(ch)) name += next();
405 - else break;
406 - }
407 - else {
408 - if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
409 - ch = read_escaped_char();
410 - if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
411 - name += ch;
412 - backslash = false;
413 - }
414 - }
415 - if (KEYWORDS(name) && escaped) {
416 - hex = name.charCodeAt(0).toString(16).toUpperCase();
417 - name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
418 - }
419 - return name;
420 - };
421 -
422 - var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
423 - var prev_backslash = false, ch, in_class = false;
424 - while ((ch = next(true))) if (prev_backslash) {
425 - regexp += "\\" + ch;
426 - prev_backslash = false;
427 - } else if (ch == "[") {
428 - in_class = true;
429 - regexp += ch;
430 - } else if (ch == "]" && in_class) {
431 - in_class = false;
432 - regexp += ch;
433 - } else if (ch == "/" && !in_class) {
434 - break;
435 - } else if (ch == "\\") {
436 - prev_backslash = true;
437 - } else {
438 - regexp += ch;
439 - }
440 - var mods = read_name();
441 - return token("regexp", new RegExp(regexp, mods));
442 - });
443 -
444 - function read_operator(prefix) {
445 - function grow(op) {
446 - if (!peek()) return op;
447 - var bigger = op + peek();
448 - if (OPERATORS(bigger)) {
449 - next();
450 - return grow(bigger);
451 - } else {
452 - return op;
453 - }
454 - };
455 - return token("operator", grow(prefix || next()));
456 - };
457 -
458 - function handle_slash() {
459 - next();
460 - var regex_allowed = S.regex_allowed;
461 - switch (peek()) {
462 - case "/":
463 - S.comments_before.push(read_line_comment());
464 - S.regex_allowed = regex_allowed;
465 - return next_token();
466 - case "*":
467 - S.comments_before.push(read_multiline_comment());
468 - S.regex_allowed = regex_allowed;
469 - return next_token();
470 - }
471 - return S.regex_allowed ? read_regexp("") : read_operator("/");
472 - };
473 -
474 - function handle_dot() {
475 - next();
476 - return is_digit(peek().charCodeAt(0))
477 - ? read_num(".")
478 - : token("punc", ".");
479 - };
480 -
481 - function read_word() {
482 - var word = read_name();
483 - return KEYWORDS_ATOM(word) ? token("atom", word)
484 - : !KEYWORDS(word) ? token("name", word)
485 - : OPERATORS(word) ? token("operator", word)
486 - : token("keyword", word);
487 - };
488 -
489 - function with_eof_error(eof_error, cont) {
490 - return function(x) {
491 - try {
492 - return cont(x);
493 - } catch(ex) {
494 - if (ex === EX_EOF) parse_error(eof_error);
495 - else throw ex;
496 - }
497 - };
498 - };
499 -
500 - function next_token(force_regexp) {
501 - if (force_regexp != null)
502 - return read_regexp(force_regexp);
503 - skip_whitespace();
504 - start_token();
505 - var ch = peek();
506 - if (!ch) return token("eof");
507 - var code = ch.charCodeAt(0);
508 - switch (code) {
509 - case 34: case 39: return read_string();
510 - case 46: return handle_dot();
511 - case 47: return handle_slash();
512 - }
513 - if (is_digit(code)) return read_num();
514 - if (PUNC_CHARS(ch)) return token("punc", next());
515 - if (OPERATOR_CHARS(ch)) return read_operator();
516 - if (code == 92 || is_identifier_start(code)) return read_word();
517 - parse_error("Unexpected character '" + ch + "'");
518 - };
519 -
520 - next_token.context = function(nc) {
521 - if (nc) S = nc;
522 - return S;
523 - };
524 -
525 - return next_token;
526 -
527 -};
528 -
529 -/* -----[ Parser (constants) ]----- */
530 -
531 -var UNARY_PREFIX = makePredicate([
532 - "typeof",
533 - "void",
534 - "delete",
535 - "--",
536 - "++",
537 - "!",
538 - "~",
539 - "-",
540 - "+"
541 -]);
542 -
543 -var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
544 -
545 -var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
546 -
547 -var PRECEDENCE = (function(a, ret){
548 - for (var i = 0, n = 1; i < a.length; ++i, ++n) {
549 - var b = a[i];
550 - for (var j = 0; j < b.length; ++j) {
551 - ret[b[j]] = n;
552 - }
553 - }
554 - return ret;
555 -})(
556 - [
557 - ["||"],
558 - ["&&"],
559 - ["|"],
560 - ["^"],
561 - ["&"],
562 - ["==", "===", "!=", "!=="],
563 - ["<", ">", "<=", ">=", "in", "instanceof"],
564 - [">>", "<<", ">>>"],
565 - ["+", "-"],
566 - ["*", "/", "%"]
567 - ],
568 - {}
569 -);
570 -
571 -var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
572 -
573 -var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
574 -
575 -/* -----[ Parser ]----- */
576 -
577 -function parse($TEXT, options) {
578 -
579 - options = defaults(options, {
580 - strict : false,
581 - filename : null,
582 - toplevel : null
583 - });
584 -
585 - var S = {
586 - input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT,
587 - token : null,
588 - prev : null,
589 - peeked : null,
590 - in_function : 0,
591 - in_directives : true,
592 - in_loop : 0,
593 - labels : []
594 - };
595 -
596 - S.token = next();
597 -
598 - function is(type, value) {
599 - return is_token(S.token, type, value);
600 - };
601 -
602 - function peek() { return S.peeked || (S.peeked = S.input()); };
603 -
604 - function next() {
605 - S.prev = S.token;
606 - if (S.peeked) {
607 - S.token = S.peeked;
608 - S.peeked = null;
609 - } else {
610 - S.token = S.input();
611 - }
612 - S.in_directives = S.in_directives && (
613 - S.token.type == "string" || is("punc", ";")
614 - );
615 - return S.token;
616 - };
617 -
618 - function prev() {
619 - return S.prev;
620 - };
621 -
622 - function croak(msg, line, col, pos) {
623 - var ctx = S.input.context();
624 - js_error(msg,
625 - ctx.filename,
626 - line != null ? line : ctx.tokline,
627 - col != null ? col : ctx.tokcol,
628 - pos != null ? pos : ctx.tokpos);
629 - };
630 -
631 - function token_error(token, msg) {
632 - croak(msg, token.line, token.col);
633 - };
634 -
635 - function unexpected(token) {
636 - if (token == null)
637 - token = S.token;
638 - token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
639 - };
640 -
641 - function expect_token(type, val) {
642 - if (is(type, val)) {
643 - return next();
644 - }
645 - token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
646 - };
647 -
648 - function expect(punc) { return expect_token("punc", punc); };
649 -
650 - function can_insert_semicolon() {
651 - return !options.strict && (
652 - S.token.nlb || is("eof") || is("punc", "}")
653 - );
654 - };
655 -
656 - function semicolon() {
657 - if (is("punc", ";")) next();
658 - else if (!can_insert_semicolon()) unexpected();
659 - };
660 -
661 - function parenthesised() {
662 - expect("(");
663 - var exp = expression(true);
664 - expect(")");
665 - return exp;
666 - };
667 -
668 - function embed_tokens(parser) {
669 - return function() {
670 - var start = S.token;
671 - var expr = parser();
672 - var end = prev();
673 - expr.start = start;
674 - expr.end = end;
675 - return expr;
676 - };
677 - };
678 -
679 - var statement = embed_tokens(function() {
680 - var tmp;
681 - if (is("operator", "/") || is("operator", "/=")) {
682 - S.peeked = null;
683 - S.token = S.input(S.token.value.substr(1)); // force regexp
684 - }
685 - switch (S.token.type) {
686 - case "string":
687 - var dir = S.in_directives, stat = simple_statement();
688 - // XXXv2: decide how to fix directives
689 - if (dir && stat.body instanceof AST_String && !is("punc", ","))
690 - return new AST_Directive({ value: stat.body.value });
691 - return stat;
692 - case "num":
693 - case "regexp":
694 - case "operator":
695 - case "atom":
696 - return simple_statement();
697 -
698 - case "name":
699 - return is_token(peek(), "punc", ":")
700 - ? labeled_statement()
701 - : simple_statement();
702 -
703 - case "punc":
704 - switch (S.token.value) {
705 - case "{":
706 - return new AST_BlockStatement({
707 - start : S.token,
708 - body : block_(),
709 - end : prev()
710 - });
711 - case "[":
712 - case "(":
713 - return simple_statement();
714 - case ";":
715 - next();
716 - return new AST_EmptyStatement();
717 - default:
718 - unexpected();
719 - }
720 -
721 - case "keyword":
722 - switch (tmp = S.token.value, next(), tmp) {
723 - case "break":
724 - return break_cont(AST_Break);
725 -
726 - case "continue":
727 - return break_cont(AST_Continue);
728 -
729 - case "debugger":
730 - semicolon();
731 - return new AST_Debugger();
732 -
733 - case "do":
734 - return new AST_Do({
735 - body : in_loop(statement),
736 - condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp)
737 - });
738 -
739 - case "while":
740 - return new AST_While({
741 - condition : parenthesised(),
742 - body : in_loop(statement)
743 - });
744 -
745 - case "for":
746 - return for_();
747 -
748 - case "function":
749 - return function_(true);
750 -
751 - case "if":
752 - return if_();
753 -
754 - case "return":
755 - if (S.in_function == 0)
756 - croak("'return' outside of function");
757 - return new AST_Return({
758 - value: ( is("punc", ";")
759 - ? (next(), null)
760 - : can_insert_semicolon()
761 - ? null
762 - : (tmp = expression(true), semicolon(), tmp) )
763 - });
764 -
765 - case "switch":
766 - return new AST_Switch({
767 - expression : parenthesised(),
768 - body : in_loop(switch_body_)
769 - });
770 -
771 - case "throw":
772 - if (S.token.nlb)
773 - croak("Illegal newline after 'throw'");
774 - return new AST_Throw({
775 - value: (tmp = expression(true), semicolon(), tmp)
776 - });
777 -
778 - case "try":
779 - return try_();
780 -
781 - case "var":
782 - return tmp = var_(), semicolon(), tmp;
783 -
784 - case "const":
785 - return tmp = const_(), semicolon(), tmp;
786 -
787 - case "with":
788 - return new AST_With({
789 - expression : parenthesised(),
790 - body : statement()
791 - });
792 -
793 - default:
794 - unexpected();
795 - }
796 - }
797 - });
798 -
799 - function labeled_statement() {
800 - var label = as_symbol(AST_Label);
801 - if (find_if(function(l){ return l.name == label.name }, S.labels)) {
802 - // ECMA-262, 12.12: An ECMAScript program is considered
803 - // syntactically incorrect if it contains a
804 - // LabelledStatement that is enclosed by a
805 - // LabelledStatement with the same Identifier as label.
806 - croak("Label " + label.name + " defined twice");
807 - }
808 - expect(":");
809 - S.labels.push(label);
810 - var stat = statement();
811 - S.labels.pop();
812 - return new AST_LabeledStatement({ body: stat, label: label });
813 - };
814 -
815 - function simple_statement(tmp) {
816 - return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
817 - };
818 -
819 - function break_cont(type) {
820 - var label = null;
821 - if (!can_insert_semicolon()) {
822 - label = as_symbol(AST_LabelRef, true);
823 - }
824 - if (label != null) {
825 - if (!find_if(function(l){ return l.name == label.name }, S.labels))
826 - croak("Undefined label " + label.name);
827 - }
828 - else if (S.in_loop == 0)
829 - croak(type.TYPE + " not inside a loop or switch");
830 - semicolon();
831 - return new type({ label: label });
832 - };
833 -
834 - function for_() {
835 - expect("(");
836 - var init = null;
837 - if (!is("punc", ";")) {
838 - init = is("keyword", "var")
839 - ? (next(), var_(true))
840 - : expression(true, true);
841 - if (is("operator", "in")) {
842 - if (init instanceof AST_Var && init.definitions.length > 1)
843 - croak("Only one variable declaration allowed in for..in loop");
844 - next();
845 - return for_in(init);
846 - }
847 - }
848 - return regular_for(init);
849 - };
850 -
851 - function regular_for(init) {
852 - expect(";");
853 - var test = is("punc", ";") ? null : expression(true);
854 - expect(";");
855 - var step = is("punc", ")") ? null : expression(true);
856 - expect(")");
857 - return new AST_For({
858 - init : init,
859 - condition : test,
860 - step : step,
861 - body : in_loop(statement)
862 - });
863 - };
864 -
865 - function for_in(init) {
866 - var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
867 - var obj = expression(true);
868 - expect(")");
869 - return new AST_ForIn({
870 - init : init,
871 - name : lhs,
872 - object : obj,
873 - body : in_loop(statement)
874 - });
875 - };
876 -
877 - var function_ = function(in_statement, ctor) {
878 - var is_accessor = ctor === AST_Accessor;
879 - var name = (is("name") ? as_symbol(in_statement
880 - ? AST_SymbolDefun
881 - : is_accessor
882 - ? AST_SymbolAccessor
883 - : AST_SymbolLambda)
884 - : is_accessor && (is("string") || is("num")) ? as_atom_node()
885 - : null);
886 - if (in_statement && !name)
887 - unexpected();
888 - expect("(");
889 - if (!ctor) ctor = in_statement ? AST_Defun : AST_Function;
890 - return new ctor({
891 - name: name,
892 - argnames: (function(first, a){
893 - while (!is("punc", ")")) {
894 - if (first) first = false; else expect(",");
895 - a.push(as_symbol(AST_SymbolFunarg));
896 - }
897 - next();
898 - return a;
899 - })(true, []),
900 - body: (function(loop, labels){
901 - ++S.in_function;
902 - S.in_directives = true;
903 - S.in_loop = 0;
904 - S.labels = [];
905 - var a = block_();
906 - --S.in_function;
907 - S.in_loop = loop;
908 - S.labels = labels;
909 - return a;
910 - })(S.in_loop, S.labels)
911 - });
912 - };
913 -
914 - function if_() {
915 - var cond = parenthesised(), body = statement(), belse = null;
916 - if (is("keyword", "else")) {
917 - next();
918 - belse = statement();
919 - }
920 - return new AST_If({
921 - condition : cond,
922 - body : body,
923 - alternative : belse
924 - });
925 - };
926 -
927 - function block_() {
928 - expect("{");
929 - var a = [];
930 - while (!is("punc", "}")) {
931 - if (is("eof")) unexpected();
932 - a.push(statement());
933 - }
934 - next();
935 - return a;
936 - };
937 -
938 - function switch_body_() {
939 - expect("{");
940 - var a = [], cur = null, branch = null, tmp;
941 - while (!is("punc", "}")) {
942 - if (is("eof")) unexpected();
943 - if (is("keyword", "case")) {
944 - if (branch) branch.end = prev();
945 - cur = [];
946 - branch = new AST_Case({
947 - start : (tmp = S.token, next(), tmp),
948 - expression : expression(true),
949 - body : cur
950 - });
951 - a.push(branch);
952 - expect(":");
953 - }
954 - else if (is("keyword", "default")) {
955 - if (branch) branch.end = prev();
956 - cur = [];
957 - branch = new AST_Default({
958 - start : (tmp = S.token, next(), expect(":"), tmp),
959 - body : cur
960 - });
961 - a.push(branch);
962 - }
963 - else {
964 - if (!cur) unexpected();
965 - cur.push(statement());
966 - }
967 - }
968 - if (branch) branch.end = prev();
969 - next();
970 - return a;
971 - };
972 -
973 - function try_() {
974 - var body = block_(), bcatch = null, bfinally = null;
975 - if (is("keyword", "catch")) {
976 - var start = S.token;
977 - next();
978 - expect("(");
979 - var name = as_symbol(AST_SymbolCatch);
980 - expect(")");
981 - bcatch = new AST_Catch({
982 - start : start,
983 - argname : name,
984 - body : block_(),
985 - end : prev()
986 - });
987 - }
988 - if (is("keyword", "finally")) {
989 - var start = S.token;
990 - next();
991 - bfinally = new AST_Finally({
992 - start : start,
993 - body : block_(),
994 - end : prev()
995 - });
996 - }
997 - if (!bcatch && !bfinally)
998 - croak("Missing catch/finally blocks");
999 - return new AST_Try({
1000 - body : body,
1001 - bcatch : bcatch,
1002 - bfinally : bfinally
1003 - });
1004 - };
1005 -
1006 - function vardefs(no_in, in_const) {
1007 - var a = [];
1008 - for (;;) {
1009 - a.push(new AST_VarDef({
1010 - start : S.token,
1011 - name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
1012 - value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
1013 - end : prev()
1014 - }));
1015 - if (!is("punc", ","))
1016 - break;
1017 - next();
1018 - }
1019 - return a;
1020 - };
1021 -
1022 - var var_ = function(no_in) {
1023 - return new AST_Var({
1024 - start : prev(),
1025 - definitions : vardefs(no_in, false),
1026 - end : prev()
1027 - });
1028 - };
1029 -
1030 - var const_ = function() {
1031 - return new AST_Const({
1032 - start : prev(),
1033 - definitions : vardefs(false, true),
1034 - end : prev()
1035 - });
1036 - };
1037 -
1038 - var new_ = function() {
1039 - var start = S.token;
1040 - expect_token("operator", "new");
1041 - var newexp = expr_atom(false), args;
1042 - if (is("punc", "(")) {
1043 - next();
1044 - args = expr_list(")");
1045 - } else {
1046 - args = [];
1047 - }
1048 - return subscripts(new AST_New({
1049 - start : start,
1050 - expression : newexp,
1051 - args : args,
1052 - end : prev()
1053 - }), true);
1054 - };
1055 -
1056 - function as_atom_node() {
1057 - var tok = S.token, ret;
1058 - switch (tok.type) {
1059 - case "name":
1060 - return as_symbol(AST_SymbolRef);
1061 - case "num":
1062 - ret = new AST_Number({ start: tok, end: tok, value: tok.value });
1063 - break;
1064 - case "string":
1065 - ret = new AST_String({ start: tok, end: tok, value: tok.value });
1066 - break;
1067 - case "regexp":
1068 - ret = new AST_RegExp({ start: tok, end: tok, value: tok.value });
1069 - break;
1070 - case "atom":
1071 - switch (tok.value) {
1072 - case "false":
1073 - ret = new AST_False({ start: tok, end: tok });
1074 - break;
1075 - case "true":
1076 - ret = new AST_True({ start: tok, end: tok });
1077 - break;
1078 - case "null":
1079 - ret = new AST_Null({ start: tok, end: tok });
1080 - break;
1081 - }
1082 - break;
1083 - }
1084 - next();
1085 - return ret;
1086 - };
1087 -
1088 - var expr_atom = function(allow_calls) {
1089 - if (is("operator", "new")) {
1090 - return new_();
1091 - }
1092 - var start = S.token;
1093 - if (is("punc")) {
1094 - switch (start.value) {
1095 - case "(":
1096 - next();
1097 - var ex = expression(true);
1098 - ex.start = start;
1099 - ex.end = S.token;
1100 - expect(")");
1101 - return subscripts(ex, allow_calls);
1102 - case "[":
1103 - return subscripts(array_(), allow_calls);
1104 - case "{":
1105 - return subscripts(object_(), allow_calls);
1106 - }
1107 - unexpected();
1108 - }
1109 - if (is("keyword", "function")) {
1110 - next();
1111 - var func = function_(false);
1112 - func.start = start;
1113 - func.end = prev();
1114 - return subscripts(func, allow_calls);
1115 - }
1116 - if (ATOMIC_START_TOKEN[S.token.type]) {
1117 - return subscripts(as_atom_node(), allow_calls);
1118 - }
1119 - unexpected();
1120 - };
1121 -
1122 - function expr_list(closing, allow_trailing_comma, allow_empty) {
1123 - var first = true, a = [];
1124 - while (!is("punc", closing)) {
1125 - if (first) first = false; else expect(",");
1126 - if (allow_trailing_comma && is("punc", closing)) break;
1127 - if (is("punc", ",") && allow_empty) {
1128 - a.push(new AST_Hole({ start: S.token, end: S.token }));
1129 - } else {
1130 - a.push(expression(false));
1131 - }
1132 - }
1133 - next();
1134 - return a;
1135 - };
1136 -
1137 - var array_ = embed_tokens(function() {
1138 - expect("[");
1139 - return new AST_Array({
1140 - elements: expr_list("]", !options.strict, true)
1141 - });
1142 - });
1143 -
1144 - var object_ = embed_tokens(function() {
1145 - expect("{");
1146 - var first = true, a = [];
1147 - while (!is("punc", "}")) {
1148 - if (first) first = false; else expect(",");
1149 - if (!options.strict && is("punc", "}"))
1150 - // allow trailing comma
1151 - break;
1152 - var start = S.token;
1153 - var type = start.type;
1154 - var name = as_property_name();
1155 - if (type == "name" && !is("punc", ":")) {
1156 - if (name == "get") {
1157 - a.push(new AST_ObjectGetter({
1158 - start : start,
1159 - key : name,
1160 - value : function_(false, AST_Accessor),
1161 - end : prev()
1162 - }));
1163 - continue;
1164 - }
1165 - if (name == "set") {
1166 - a.push(new AST_ObjectSetter({
1167 - start : start,
1168 - key : name,
1169 - value : function_(false, AST_Accessor),
1170 - end : prev()
1171 - }));
1172 - continue;
1173 - }
1174 - }
1175 - expect(":");
1176 - a.push(new AST_ObjectKeyVal({
1177 - start : start,
1178 - key : name,
1179 - value : expression(false),
1180 - end : prev()
1181 - }));
1182 - }
1183 - next();
1184 - return new AST_Object({ properties: a });
1185 - });
1186 -
1187 - function as_property_name() {
1188 - var tmp = S.token;
1189 - next();
1190 - switch (tmp.type) {
1191 - case "num":
1192 - case "string":
1193 - case "name":
1194 - case "operator":
1195 - case "keyword":
1196 - case "atom":
1197 - return tmp.value;
1198 - default:
1199 - unexpected();
1200 - }
1201 - };
1202 -
1203 - function as_name() {
1204 - var tmp = S.token;
1205 - next();
1206 - switch (tmp.type) {
1207 - case "name":
1208 - case "operator":
1209 - case "keyword":
1210 - case "atom":
1211 - return tmp.value;
1212 - default:
1213 - unexpected();
1214 - }
1215 - };
1216 -
1217 - function as_symbol(type, noerror) {
1218 - if (!is("name")) {
1219 - if (!noerror) croak("Name expected");
1220 - return null;
1221 - }
1222 - var name = S.token.value;
1223 - var sym = new (name == "this" ? AST_This : type)({
1224 - name : String(S.token.value),
1225 - start : S.token,
1226 - end : S.token
1227 - });
1228 - next();
1229 - return sym;
1230 - };
1231 -
1232 - var subscripts = function(expr, allow_calls) {
1233 - var start = expr.start;
1234 - if (is("punc", ".")) {
1235 - next();
1236 - return subscripts(new AST_Dot({
1237 - start : start,
1238 - expression : expr,
1239 - property : as_name(),
1240 - end : prev()
1241 - }), allow_calls);
1242 - }
1243 - if (is("punc", "[")) {
1244 - next();
1245 - var prop = expression(true);
1246 - expect("]");
1247 - return subscripts(new AST_Sub({
1248 - start : start,
1249 - expression : expr,
1250 - property : prop,
1251 - end : prev()
1252 - }), allow_calls);
1253 - }
1254 - if (allow_calls && is("punc", "(")) {
1255 - next();
1256 - return subscripts(new AST_Call({
1257 - start : start,
1258 - expression : expr,
1259 - args : expr_list(")"),
1260 - end : prev()
1261 - }), true);
1262 - }
1263 - return expr;
1264 - };
1265 -
1266 - var maybe_unary = function(allow_calls) {
1267 - var start = S.token;
1268 - if (is("operator") && UNARY_PREFIX(start.value)) {
1269 - next();
1270 - var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
1271 - ex.start = start;
1272 - ex.end = prev();
1273 - return ex;
1274 - }
1275 - var val = expr_atom(allow_calls);
1276 - while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
1277 - val = make_unary(AST_UnaryPostfix, S.token.value, val);
1278 - val.start = start;
1279 - val.end = S.token;
1280 - next();
1281 - }
1282 - return val;
1283 - };
1284 -
1285 - function make_unary(ctor, op, expr) {
1286 - if ((op == "++" || op == "--") && !is_assignable(expr))
1287 - croak("Invalid use of " + op + " operator");
1288 - return new ctor({ operator: op, expression: expr });
1289 - };
1290 -
1291 - var expr_op = function(left, min_prec, no_in) {
1292 - var op = is("operator") ? S.token.value : null;
1293 - if (op == "in" && no_in) op = null;
1294 - var prec = op != null ? PRECEDENCE[op] : null;
1295 - if (prec != null && prec > min_prec) {
1296 - next();
1297 - var right = expr_op(maybe_unary(true), prec, no_in);
1298 - return expr_op(new AST_Binary({
1299 - start : left.start,
1300 - left : left,
1301 - operator : op,
1302 - right : right,
1303 - end : right.end
1304 - }), min_prec, no_in);
1305 - }
1306 - return left;
1307 - };
1308 -
1309 - function expr_ops(no_in) {
1310 - return expr_op(maybe_unary(true), 0, no_in);
1311 - };
1312 -
1313 - var maybe_conditional = function(no_in) {
1314 - var start = S.token;
1315 - var expr = expr_ops(no_in);
1316 - if (is("operator", "?")) {
1317 - next();
1318 - var yes = expression(false);
1319 - expect(":");
1320 - return new AST_Conditional({
1321 - start : start,
1322 - condition : expr,
1323 - consequent : yes,
1324 - alternative : expression(false, no_in),
1325 - end : peek()
1326 - });
1327 - }
1328 - return expr;
1329 - };
1330 -
1331 - function is_assignable(expr) {
1332 - if (!options.strict) return true;
1333 - switch (expr[0]+"") {
1334 - case "dot":
1335 - case "sub":
1336 - case "new":
1337 - case "call":
1338 - return true;
1339 - case "name":
1340 - return expr[1] != "this";
1341 - }
1342 - };
1343 -
1344 - var maybe_assign = function(no_in) {
1345 - var start = S.token;
1346 - var left = maybe_conditional(no_in), val = S.token.value;
1347 - if (is("operator") && ASSIGNMENT(val)) {
1348 - if (is_assignable(left)) {
1349 - next();
1350 - return new AST_Assign({
1351 - start : start,
1352 - left : left,
1353 - operator : val,
1354 - right : maybe_assign(no_in),
1355 - end : prev()
1356 - });
1357 - }
1358 - croak("Invalid assignment");
1359 - }
1360 - return left;
1361 - };
1362 -
1363 - var expression = function(commas, no_in) {
1364 - var start = S.token;
1365 - var expr = maybe_assign(no_in);
1366 - if (commas && is("punc", ",")) {
1367 - next();
1368 - return new AST_Seq({
1369 - start : start,
1370 - car : expr,
1371 - cdr : expression(true, no_in),
1372 - end : peek()
1373 - });
1374 - }
1375 - return expr;
1376 - };
1377 -
1378 - function in_loop(cont) {
1379 - ++S.in_loop;
1380 - var ret = cont();
1381 - --S.in_loop;
1382 - return ret;
1383 - };
1384 -
1385 - return (function(){
1386 - var start = S.token;
1387 - var body = [];
1388 - while (!is("eof"))
1389 - body.push(statement());
1390 - var end = prev();
1391 - var toplevel = options.toplevel;
1392 - if (toplevel) {
1393 - toplevel.body = toplevel.body.concat(body);
1394 - toplevel.end = end;
1395 - } else {
1396 - toplevel = new AST_Toplevel({ start: start, body: body, end: end });
1397 - }
1398 - return toplevel;
1399 - })();
1400 -
1401 -};
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -function SymbolDef(scope, index, orig) {
47 - this.name = orig.name;
48 - this.orig = [ orig ];
49 - this.scope = scope;
50 - this.references = [];
51 - this.global = false;
52 - this.mangled_name = null;
53 - this.undeclared = false;
54 - this.constant = false;
55 - this.index = index;
56 -};
57 -
58 -SymbolDef.prototype = {
59 - unmangleable: function(options) {
60 - return (this.global && !(options && options.toplevel))
61 - || this.undeclared
62 - || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with));
63 - },
64 - mangle: function(options) {
65 - if (!this.mangled_name && !this.unmangleable(options)) {
66 - var s = this.scope;
67 - if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8)
68 - s = s.parent_scope;
69 - this.mangled_name = s.next_mangled(options);
70 - }
71 - }
72 -};
73 -
74 -AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
75 - // This does what ast_add_scope did in UglifyJS v1.
76 - //
77 - // Part of it could be done at parse time, but it would complicate
78 - // the parser (and it's already kinda complex). It's also worth
79 - // having it separated because we might need to call it multiple
80 - // times on the same tree.
81 -
82 - // pass 1: setup scope chaining and handle definitions
83 - var self = this;
84 - var scope = self.parent_scope = null;
85 - var labels = new Dictionary();
86 - var nesting = 0;
87 - var tw = new TreeWalker(function(node, descend){
88 - if (node instanceof AST_Scope) {
89 - node.init_scope_vars(nesting);
90 - var save_scope = node.parent_scope = scope;
91 - var save_labels = labels;
92 - ++nesting;
93 - scope = node;
94 - labels = new Dictionary();
95 - descend();
96 - labels = save_labels;
97 - scope = save_scope;
98 - --nesting;
99 - return true; // don't descend again in TreeWalker
100 - }
101 - if (node instanceof AST_Directive) {
102 - node.scope = scope;
103 - push_uniq(scope.directives, node.value);
104 - return true;
105 - }
106 - if (node instanceof AST_With) {
107 - for (var s = scope; s; s = s.parent_scope)
108 - s.uses_with = true;
109 - return;
110 - }
111 - if (node instanceof AST_LabeledStatement) {
112 - var l = node.label;
113 - if (labels.has(l.name))
114 - throw new Error(string_template("Label {name} defined twice", l));
115 - labels.set(l.name, l);
116 - descend();
117 - labels.del(l.name);
118 - return true; // no descend again
119 - }
120 - if (node instanceof AST_Symbol) {
121 - node.scope = scope;
122 - }
123 - if (node instanceof AST_Label) {
124 - node.thedef = node;
125 - node.init_scope_vars();
126 - }
127 - if (node instanceof AST_SymbolLambda) {
128 - scope.def_function(node);
129 - }
130 - else if (node instanceof AST_SymbolDefun) {
131 - // Careful here, the scope where this should be defined is
132 - // the parent scope. The reason is that we enter a new
133 - // scope when we encounter the AST_Defun node (which is
134 - // instanceof AST_Scope) but we get to the symbol a bit
135 - // later.
136 - (node.scope = scope.parent_scope).def_function(node);
137 - }
138 - else if (node instanceof AST_SymbolVar
139 - || node instanceof AST_SymbolConst) {
140 - var def = scope.def_variable(node);
141 - def.constant = node instanceof AST_SymbolConst;
142 - def.init = tw.parent().value;
143 - }
144 - else if (node instanceof AST_SymbolCatch) {
145 - // XXX: this is wrong according to ECMA-262 (12.4). the
146 - // `catch` argument name should be visible only inside the
147 - // catch block. For a quick fix AST_Catch should inherit
148 - // from AST_Scope. Keeping it this way because of IE,
149 - // which doesn't obey the standard. (it introduces the
150 - // identifier in the enclosing scope)
151 - scope.def_variable(node);
152 - }
153 - if (node instanceof AST_LabelRef) {
154 - var sym = labels.get(node.name);
155 - if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
156 - name: node.name,
157 - line: node.start.line,
158 - col: node.start.col
159 - }));
160 - node.thedef = sym;
161 - }
162 - });
163 - self.walk(tw);
164 -
165 - // pass 2: find back references and eval
166 - var func = null;
167 - var globals = self.globals = new Dictionary();
168 - var tw = new TreeWalker(function(node, descend){
169 - if (node instanceof AST_Lambda) {
170 - var prev_func = func;
171 - func = node;
172 - descend();
173 - func = prev_func;
174 - return true;
175 - }
176 - if (node instanceof AST_LabelRef) {
177 - node.reference();
178 - return true;
179 - }
180 - if (node instanceof AST_SymbolRef) {
181 - var name = node.name;
182 - var sym = node.scope.find_variable(name);
183 - if (!sym) {
184 - var g;
185 - if (globals.has(name)) {
186 - g = globals.get(name);
187 - } else {
188 - g = new SymbolDef(self, globals.size(), node);
189 - g.undeclared = true;
190 - globals.set(name, g);
191 - }
192 - node.thedef = g;
193 - if (name == "eval" && tw.parent() instanceof AST_Call) {
194 - for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope)
195 - s.uses_eval = true;
196 - }
197 - if (name == "arguments") {
198 - func.uses_arguments = true;
199 - }
200 - } else {
201 - node.thedef = sym;
202 - }
203 - node.reference();
204 - return true;
205 - }
206 - });
207 - self.walk(tw);
208 -});
209 -
210 -AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
211 - this.directives = []; // contains the directives defined in this scope, i.e. "use strict"
212 - this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
213 - this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
214 - this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
215 - this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
216 - this.parent_scope = null; // the parent scope
217 - this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
218 - this.cname = -1; // the current index for mangling functions/variables
219 - this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
220 -});
221 -
222 -AST_Scope.DEFMETHOD("strict", function(){
223 - return this.has_directive("use strict");
224 -});
225 -
226 -AST_Lambda.DEFMETHOD("init_scope_vars", function(){
227 - AST_Scope.prototype.init_scope_vars.apply(this, arguments);
228 - this.uses_arguments = false;
229 -});
230 -
231 -AST_SymbolRef.DEFMETHOD("reference", function() {
232 - var def = this.definition();
233 - def.references.push(this);
234 - var s = this.scope;
235 - while (s) {
236 - push_uniq(s.enclosed, def);
237 - if (s === def.scope) break;
238 - s = s.parent_scope;
239 - }
240 - this.frame = this.scope.nesting - def.scope.nesting;
241 -});
242 -
243 -AST_Label.DEFMETHOD("init_scope_vars", function(){
244 - this.references = [];
245 -});
246 -
247 -AST_LabelRef.DEFMETHOD("reference", function(){
248 - this.thedef.references.push(this);
249 -});
250 -
251 -AST_Scope.DEFMETHOD("find_variable", function(name){
252 - if (name instanceof AST_Symbol) name = name.name;
253 - return this.variables.get(name)
254 - || (this.parent_scope && this.parent_scope.find_variable(name));
255 -});
256 -
257 -AST_Scope.DEFMETHOD("has_directive", function(value){
258 - return this.parent_scope && this.parent_scope.has_directive(value)
259 - || (this.directives.indexOf(value) >= 0 ? this : null);
260 -});
261 -
262 -AST_Scope.DEFMETHOD("def_function", function(symbol){
263 - this.functions.set(symbol.name, this.def_variable(symbol));
264 -});
265 -
266 -AST_Scope.DEFMETHOD("def_variable", function(symbol){
267 - var def;
268 - if (!this.variables.has(symbol.name)) {
269 - def = new SymbolDef(this, this.variables.size(), symbol);
270 - this.variables.set(symbol.name, def);
271 - def.global = !this.parent_scope;
272 - } else {
273 - def = this.variables.get(symbol.name);
274 - def.orig.push(symbol);
275 - }
276 - return symbol.thedef = def;
277 -});
278 -
279 -AST_Scope.DEFMETHOD("next_mangled", function(options){
280 - var ext = this.enclosed;
281 - out: while (true) {
282 - var m = base54(++this.cname);
283 - if (!is_identifier(m)) continue; // skip over "do"
284 - // we must ensure that the mangled name does not shadow a name
285 - // from some parent scope that is referenced in this or in
286 - // inner scopes.
287 - for (var i = ext.length; --i >= 0;) {
288 - var sym = ext[i];
289 - var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
290 - if (m == name) continue out;
291 - }
292 - return m;
293 - }
294 -});
295 -
296 -AST_Scope.DEFMETHOD("references", function(sym){
297 - if (sym instanceof AST_Symbol) sym = sym.definition();
298 - return this.enclosed.indexOf(sym) < 0 ? null : sym;
299 -});
300 -
301 -AST_Symbol.DEFMETHOD("unmangleable", function(options){
302 - return this.definition().unmangleable(options);
303 -});
304 -
305 -// property accessors are not mangleable
306 -AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
307 - return true;
308 -});
309 -
310 -// labels are always mangleable
311 -AST_Label.DEFMETHOD("unmangleable", function(){
312 - return false;
313 -});
314 -
315 -AST_Symbol.DEFMETHOD("unreferenced", function(){
316 - return this.definition().references.length == 0
317 - && !(this.scope.uses_eval || this.scope.uses_with);
318 -});
319 -
320 -AST_Symbol.DEFMETHOD("undeclared", function(){
321 - return this.definition().undeclared;
322 -});
323 -
324 -AST_LabelRef.DEFMETHOD("undeclared", function(){
325 - return false;
326 -});
327 -
328 -AST_Label.DEFMETHOD("undeclared", function(){
329 - return false;
330 -});
331 -
332 -AST_Symbol.DEFMETHOD("definition", function(){
333 - return this.thedef;
334 -});
335 -
336 -AST_Symbol.DEFMETHOD("global", function(){
337 - return this.definition().global;
338 -});
339 -
340 -AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
341 - return defaults(options, {
342 - except : [],
343 - eval : false,
344 - sort : false,
345 - toplevel : false,
346 - screw_ie8 : false
347 - });
348 -});
349 -
350 -AST_Toplevel.DEFMETHOD("mangle_names", function(options){
351 - options = this._default_mangler_options(options);
352 - // We only need to mangle declaration nodes. Special logic wired
353 - // into the code generator will display the mangled name if it's
354 - // present (and for AST_SymbolRef-s it'll use the mangled name of
355 - // the AST_SymbolDeclaration that it points to).
356 - var lname = -1;
357 - var to_mangle = [];
358 - var tw = new TreeWalker(function(node, descend){
359 - if (node instanceof AST_LabeledStatement) {
360 - // lname is incremented when we get to the AST_Label
361 - var save_nesting = lname;
362 - descend();
363 - lname = save_nesting;
364 - return true; // don't descend again in TreeWalker
365 - }
366 - if (node instanceof AST_Scope) {
367 - var p = tw.parent(), a = [];
368 - node.variables.each(function(symbol){
369 - if (options.except.indexOf(symbol.name) < 0) {
370 - a.push(symbol);
371 - }
372 - });
373 - if (options.sort) a.sort(function(a, b){
374 - return b.references.length - a.references.length;
375 - });
376 - to_mangle.push.apply(to_mangle, a);
377 - return;
378 - }
379 - if (node instanceof AST_Label) {
380 - var name;
381 - do name = base54(++lname); while (!is_identifier(name));
382 - node.mangled_name = name;
383 - return true;
384 - }
385 - });
386 - this.walk(tw);
387 - to_mangle.forEach(function(def){ def.mangle(options) });
388 -});
389 -
390 -AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
391 - options = this._default_mangler_options(options);
392 - var tw = new TreeWalker(function(node){
393 - if (node instanceof AST_Constant)
394 - base54.consider(node.print_to_string());
395 - else if (node instanceof AST_Return)
396 - base54.consider("return");
397 - else if (node instanceof AST_Throw)
398 - base54.consider("throw");
399 - else if (node instanceof AST_Continue)
400 - base54.consider("continue");
401 - else if (node instanceof AST_Break)
402 - base54.consider("break");
403 - else if (node instanceof AST_Debugger)
404 - base54.consider("debugger");
405 - else if (node instanceof AST_Directive)
406 - base54.consider(node.value);
407 - else if (node instanceof AST_While)
408 - base54.consider("while");
409 - else if (node instanceof AST_Do)
410 - base54.consider("do while");
411 - else if (node instanceof AST_If) {
412 - base54.consider("if");
413 - if (node.alternative) base54.consider("else");
414 - }
415 - else if (node instanceof AST_Var)
416 - base54.consider("var");
417 - else if (node instanceof AST_Const)
418 - base54.consider("const");
419 - else if (node instanceof AST_Lambda)
420 - base54.consider("function");
421 - else if (node instanceof AST_For)
422 - base54.consider("for");
423 - else if (node instanceof AST_ForIn)
424 - base54.consider("for in");
425 - else if (node instanceof AST_Switch)
426 - base54.consider("switch");
427 - else if (node instanceof AST_Case)
428 - base54.consider("case");
429 - else if (node instanceof AST_Default)
430 - base54.consider("default");
431 - else if (node instanceof AST_With)
432 - base54.consider("with");
433 - else if (node instanceof AST_ObjectSetter)
434 - base54.consider("set" + node.key);
435 - else if (node instanceof AST_ObjectGetter)
436 - base54.consider("get" + node.key);
437 - else if (node instanceof AST_ObjectKeyVal)
438 - base54.consider(node.key);
439 - else if (node instanceof AST_New)
440 - base54.consider("new");
441 - else if (node instanceof AST_This)
442 - base54.consider("this");
443 - else if (node instanceof AST_Try)
444 - base54.consider("try");
445 - else if (node instanceof AST_Catch)
446 - base54.consider("catch");
447 - else if (node instanceof AST_Finally)
448 - base54.consider("finally");
449 - else if (node instanceof AST_Symbol && node.unmangleable(options))
450 - base54.consider(node.name);
451 - else if (node instanceof AST_Unary || node instanceof AST_Binary)
452 - base54.consider(node.operator);
453 - else if (node instanceof AST_Dot)
454 - base54.consider(node.property);
455 - });
456 - this.walk(tw);
457 - base54.sort();
458 -});
459 -
460 -var base54 = (function() {
461 - var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
462 - var chars, frequency;
463 - function reset() {
464 - frequency = Object.create(null);
465 - chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
466 - chars.forEach(function(ch){ frequency[ch] = 0 });
467 - }
468 - base54.consider = function(str){
469 - for (var i = str.length; --i >= 0;) {
470 - var code = str.charCodeAt(i);
471 - if (code in frequency) ++frequency[code];
472 - }
473 - };
474 - base54.sort = function() {
475 - chars = mergeSort(chars, function(a, b){
476 - if (is_digit(a) && !is_digit(b)) return 1;
477 - if (is_digit(b) && !is_digit(a)) return -1;
478 - return frequency[b] - frequency[a];
479 - });
480 - };
481 - base54.reset = reset;
482 - reset();
483 - base54.get = function(){ return chars };
484 - base54.freq = function(){ return frequency };
485 - function base54(num) {
486 - var ret = "", base = 54;
487 - do {
488 - ret += String.fromCharCode(chars[num % base]);
489 - num = Math.floor(num / base);
490 - base = 64;
491 - } while (num > 0);
492 - return ret;
493 - };
494 - return base54;
495 -})();
496 -
497 -AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
498 - options = defaults(options, {
499 - undeclared : false, // this makes a lot of noise
500 - unreferenced : true,
501 - assign_to_global : true,
502 - func_arguments : true,
503 - nested_defuns : true,
504 - eval : true
505 - });
506 - var tw = new TreeWalker(function(node){
507 - if (options.undeclared
508 - && node instanceof AST_SymbolRef
509 - && node.undeclared())
510 - {
511 - // XXX: this also warns about JS standard names,
512 - // i.e. Object, Array, parseInt etc. Should add a list of
513 - // exceptions.
514 - AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
515 - name: node.name,
516 - file: node.start.file,
517 - line: node.start.line,
518 - col: node.start.col
519 - });
520 - }
521 - if (options.assign_to_global)
522 - {
523 - var sym = null;
524 - if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
525 - sym = node.left;
526 - else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
527 - sym = node.init;
528 - if (sym
529 - && (sym.undeclared()
530 - || (sym.global() && sym.scope !== sym.definition().scope))) {
531 - AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
532 - msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
533 - name: sym.name,
534 - file: sym.start.file,
535 - line: sym.start.line,
536 - col: sym.start.col
537 - });
538 - }
539 - }
540 - if (options.eval
541 - && node instanceof AST_SymbolRef
542 - && node.undeclared()
543 - && node.name == "eval") {
544 - AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
545 - }
546 - if (options.unreferenced
547 - && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
548 - && node.unreferenced()) {
549 - AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
550 - type: node instanceof AST_Label ? "Label" : "Symbol",
551 - name: node.name,
552 - file: node.start.file,
553 - line: node.start.line,
554 - col: node.start.col
555 - });
556 - }
557 - if (options.func_arguments
558 - && node instanceof AST_Lambda
559 - && node.uses_arguments) {
560 - AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
561 - name: node.name ? node.name.name : "anonymous",
562 - file: node.start.file,
563 - line: node.start.line,
564 - col: node.start.col
565 - });
566 - }
567 - if (options.nested_defuns
568 - && node instanceof AST_Defun
569 - && !(tw.parent() instanceof AST_Scope)) {
570 - AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
571 - name: node.name.name,
572 - type: tw.parent().TYPE,
573 - file: node.start.file,
574 - line: node.start.line,
575 - col: node.start.col
576 - });
577 - }
578 - });
579 - this.walk(tw);
580 -});
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -// a small wrapper around fitzgen's source-map library
47 -function SourceMap(options) {
48 - options = defaults(options, {
49 - file : null,
50 - root : null,
51 - orig : null,
52 - });
53 - var generator = new MOZ_SourceMap.SourceMapGenerator({
54 - file : options.file,
55 - sourceRoot : options.root
56 - });
57 - var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
58 - function add(source, gen_line, gen_col, orig_line, orig_col, name) {
59 - if (orig_map) {
60 - var info = orig_map.originalPositionFor({
61 - line: orig_line,
62 - column: orig_col
63 - });
64 - source = info.source;
65 - orig_line = info.line;
66 - orig_col = info.column;
67 - name = info.name;
68 - }
69 - generator.addMapping({
70 - generated : { line: gen_line, column: gen_col },
71 - original : { line: orig_line, column: orig_col },
72 - source : source,
73 - name : name
74 - });
75 - };
76 - return {
77 - add : add,
78 - get : function() { return generator },
79 - toString : function() { return generator.toString() }
80 - };
81 -};
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -// Tree transformer helpers.
47 -// XXX: eventually I should refactor the compressor to use this infrastructure.
48 -
49 -function TreeTransformer(before, after) {
50 - TreeWalker.call(this);
51 - this.before = before;
52 - this.after = after;
53 -}
54 -TreeTransformer.prototype = new TreeWalker;
55 -
56 -(function(undefined){
57 -
58 - function _(node, descend) {
59 - node.DEFMETHOD("transform", function(tw, in_list){
60 - var x, y;
61 - tw.push(this);
62 - if (tw.before) x = tw.before(this, descend, in_list);
63 - if (x === undefined) {
64 - if (!tw.after) {
65 - x = this;
66 - descend(x, tw);
67 - } else {
68 - tw.stack[tw.stack.length - 1] = x = this.clone();
69 - descend(x, tw);
70 - y = tw.after(x, in_list);
71 - if (y !== undefined) x = y;
72 - }
73 - }
74 - tw.pop();
75 - return x;
76 - });
77 - };
78 -
79 - function do_list(list, tw) {
80 - return MAP(list, function(node){
81 - return node.transform(tw, true);
82 - });
83 - };
84 -
85 - _(AST_Node, noop);
86 -
87 - _(AST_LabeledStatement, function(self, tw){
88 - self.label = self.label.transform(tw);
89 - self.body = self.body.transform(tw);
90 - });
91 -
92 - _(AST_SimpleStatement, function(self, tw){
93 - self.body = self.body.transform(tw);
94 - });
95 -
96 - _(AST_Block, function(self, tw){
97 - self.body = do_list(self.body, tw);
98 - });
99 -
100 - _(AST_DWLoop, function(self, tw){
101 - self.condition = self.condition.transform(tw);
102 - self.body = self.body.transform(tw);
103 - });
104 -
105 - _(AST_For, function(self, tw){
106 - if (self.init) self.init = self.init.transform(tw);
107 - if (self.condition) self.condition = self.condition.transform(tw);
108 - if (self.step) self.step = self.step.transform(tw);
109 - self.body = self.body.transform(tw);
110 - });
111 -
112 - _(AST_ForIn, function(self, tw){
113 - self.init = self.init.transform(tw);
114 - self.object = self.object.transform(tw);
115 - self.body = self.body.transform(tw);
116 - });
117 -
118 - _(AST_With, function(self, tw){
119 - self.expression = self.expression.transform(tw);
120 - self.body = self.body.transform(tw);
121 - });
122 -
123 - _(AST_Exit, function(self, tw){
124 - if (self.value) self.value = self.value.transform(tw);
125 - });
126 -
127 - _(AST_LoopControl, function(self, tw){
128 - if (self.label) self.label = self.label.transform(tw);
129 - });
130 -
131 - _(AST_If, function(self, tw){
132 - self.condition = self.condition.transform(tw);
133 - self.body = self.body.transform(tw);
134 - if (self.alternative) self.alternative = self.alternative.transform(tw);
135 - });
136 -
137 - _(AST_Switch, function(self, tw){
138 - self.expression = self.expression.transform(tw);
139 - self.body = do_list(self.body, tw);
140 - });
141 -
142 - _(AST_Case, function(self, tw){
143 - self.expression = self.expression.transform(tw);
144 - self.body = do_list(self.body, tw);
145 - });
146 -
147 - _(AST_Try, function(self, tw){
148 - self.body = do_list(self.body, tw);
149 - if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
150 - if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
151 - });
152 -
153 - _(AST_Catch, function(self, tw){
154 - self.argname = self.argname.transform(tw);
155 - self.body = do_list(self.body, tw);
156 - });
157 -
158 - _(AST_Definitions, function(self, tw){
159 - self.definitions = do_list(self.definitions, tw);
160 - });
161 -
162 - _(AST_VarDef, function(self, tw){
163 - if (self.value) self.value = self.value.transform(tw);
164 - });
165 -
166 - _(AST_Lambda, function(self, tw){
167 - if (self.name) self.name = self.name.transform(tw);
168 - self.argnames = do_list(self.argnames, tw);
169 - self.body = do_list(self.body, tw);
170 - });
171 -
172 - _(AST_Call, function(self, tw){
173 - self.expression = self.expression.transform(tw);
174 - self.args = do_list(self.args, tw);
175 - });
176 -
177 - _(AST_Seq, function(self, tw){
178 - self.car = self.car.transform(tw);
179 - self.cdr = self.cdr.transform(tw);
180 - });
181 -
182 - _(AST_Dot, function(self, tw){
183 - self.expression = self.expression.transform(tw);
184 - });
185 -
186 - _(AST_Sub, function(self, tw){
187 - self.expression = self.expression.transform(tw);
188 - self.property = self.property.transform(tw);
189 - });
190 -
191 - _(AST_Unary, function(self, tw){
192 - self.expression = self.expression.transform(tw);
193 - });
194 -
195 - _(AST_Binary, function(self, tw){
196 - self.left = self.left.transform(tw);
197 - self.right = self.right.transform(tw);
198 - });
199 -
200 - _(AST_Conditional, function(self, tw){
201 - self.condition = self.condition.transform(tw);
202 - self.consequent = self.consequent.transform(tw);
203 - self.alternative = self.alternative.transform(tw);
204 - });
205 -
206 - _(AST_Array, function(self, tw){
207 - self.elements = do_list(self.elements, tw);
208 - });
209 -
210 - _(AST_Object, function(self, tw){
211 - self.properties = do_list(self.properties, tw);
212 - });
213 -
214 - _(AST_ObjectProperty, function(self, tw){
215 - self.value = self.value.transform(tw);
216 - });
217 -
218 -})();
1 -/***********************************************************************
2 -
3 - A JavaScript tokenizer / parser / beautifier / compressor.
4 - https://github.com/mishoo/UglifyJS2
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 -
46 -function array_to_hash(a) {
47 - var ret = Object.create(null);
48 - for (var i = 0; i < a.length; ++i)
49 - ret[a[i]] = true;
50 - return ret;
51 -};
52 -
53 -function slice(a, start) {
54 - return Array.prototype.slice.call(a, start || 0);
55 -};
56 -
57 -function characters(str) {
58 - return str.split("");
59 -};
60 -
61 -function member(name, array) {
62 - for (var i = array.length; --i >= 0;)
63 - if (array[i] == name)
64 - return true;
65 - return false;
66 -};
67 -
68 -function find_if(func, array) {
69 - for (var i = 0, n = array.length; i < n; ++i) {
70 - if (func(array[i]))
71 - return array[i];
72 - }
73 -};
74 -
75 -function repeat_string(str, i) {
76 - if (i <= 0) return "";
77 - if (i == 1) return str;
78 - var d = repeat_string(str, i >> 1);
79 - d += d;
80 - if (i & 1) d += str;
81 - return d;
82 -};
83 -
84 -function DefaultsError(msg, defs) {
85 - this.msg = msg;
86 - this.defs = defs;
87 -};
88 -
89 -function defaults(args, defs, croak) {
90 - if (args === true)
91 - args = {};
92 - var ret = args || {};
93 - if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
94 - throw new DefaultsError("`" + i + "` is not a supported option", defs);
95 - for (var i in defs) if (defs.hasOwnProperty(i)) {
96 - ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
97 - }
98 - return ret;
99 -};
100 -
101 -function merge(obj, ext) {
102 - for (var i in ext) if (ext.hasOwnProperty(i)) {
103 - obj[i] = ext[i];
104 - }
105 - return obj;
106 -};
107 -
108 -function noop() {};
109 -
110 -var MAP = (function(){
111 - function MAP(a, f, backwards) {
112 - var ret = [], top = [], i;
113 - function doit() {
114 - var val = f(a[i], i);
115 - var is_last = val instanceof Last;
116 - if (is_last) val = val.v;
117 - if (val instanceof AtTop) {
118 - val = val.v;
119 - if (val instanceof Splice) {
120 - top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
121 - } else {
122 - top.push(val);
123 - }
124 - }
125 - else if (val !== skip) {
126 - if (val instanceof Splice) {
127 - ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
128 - } else {
129 - ret.push(val);
130 - }
131 - }
132 - return is_last;
133 - };
134 - if (a instanceof Array) {
135 - if (backwards) {
136 - for (i = a.length; --i >= 0;) if (doit()) break;
137 - ret.reverse();
138 - top.reverse();
139 - } else {
140 - for (i = 0; i < a.length; ++i) if (doit()) break;
141 - }
142 - }
143 - else {
144 - for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
145 - }
146 - return top.concat(ret);
147 - };
148 - MAP.at_top = function(val) { return new AtTop(val) };
149 - MAP.splice = function(val) { return new Splice(val) };
150 - MAP.last = function(val) { return new Last(val) };
151 - var skip = MAP.skip = {};
152 - function AtTop(val) { this.v = val };
153 - function Splice(val) { this.v = val };
154 - function Last(val) { this.v = val };
155 - return MAP;
156 -})();
157 -
158 -function push_uniq(array, el) {
159 - if (array.indexOf(el) < 0)
160 - array.push(el);
161 -};
162 -
163 -function string_template(text, props) {
164 - return text.replace(/\{(.+?)\}/g, function(str, p){
165 - return props[p];
166 - });
167 -};
168 -
169 -function remove(array, el) {
170 - for (var i = array.length; --i >= 0;) {
171 - if (array[i] === el) array.splice(i, 1);
172 - }
173 -};
174 -
175 -function mergeSort(array, cmp) {
176 - if (array.length < 2) return array.slice();
177 - function merge(a, b) {
178 - var r = [], ai = 0, bi = 0, i = 0;
179 - while (ai < a.length && bi < b.length) {
180 - cmp(a[ai], b[bi]) <= 0
181 - ? r[i++] = a[ai++]
182 - : r[i++] = b[bi++];
183 - }
184 - if (ai < a.length) r.push.apply(r, a.slice(ai));
185 - if (bi < b.length) r.push.apply(r, b.slice(bi));
186 - return r;
187 - };
188 - function _ms(a) {
189 - if (a.length <= 1)
190 - return a;
191 - var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
192 - left = _ms(left);
193 - right = _ms(right);
194 - return merge(left, right);
195 - };
196 - return _ms(array);
197 -};
198 -
199 -function set_difference(a, b) {
200 - return a.filter(function(el){
201 - return b.indexOf(el) < 0;
202 - });
203 -};
204 -
205 -function set_intersection(a, b) {
206 - return a.filter(function(el){
207 - return b.indexOf(el) >= 0;
208 - });
209 -};
210 -
211 -// this function is taken from Acorn [1], written by Marijn Haverbeke
212 -// [1] https://github.com/marijnh/acorn
213 -function makePredicate(words) {
214 - if (!(words instanceof Array)) words = words.split(" ");
215 - var f = "", cats = [];
216 - out: for (var i = 0; i < words.length; ++i) {
217 - for (var j = 0; j < cats.length; ++j)
218 - if (cats[j][0].length == words[i].length) {
219 - cats[j].push(words[i]);
220 - continue out;
221 - }
222 - cats.push([words[i]]);
223 - }
224 - function compareTo(arr) {
225 - if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
226 - f += "switch(str){";
227 - for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
228 - f += "return true}return false;";
229 - }
230 - // When there are more than three length categories, an outer
231 - // switch first dispatches on the lengths, to save on comparisons.
232 - if (cats.length > 3) {
233 - cats.sort(function(a, b) {return b.length - a.length;});
234 - f += "switch(str.length){";
235 - for (var i = 0; i < cats.length; ++i) {
236 - var cat = cats[i];
237 - f += "case " + cat[0].length + ":";
238 - compareTo(cat);
239 - }
240 - f += "}";
241 - // Otherwise, simply generate a flat `switch` statement.
242 - } else {
243 - compareTo(words);
244 - }
245 - return new Function("str", f);
246 -};
247 -
248 -function Dictionary() {
249 - this._values = Object.create(null);
250 - this._size = 0;
251 -};
252 -Dictionary.prototype = {
253 - set: function(key, val) {
254 - if (!this.has(key)) ++this._size;
255 - this._values["$" + key] = val;
256 - return this;
257 - },
258 - add: function(key, val) {
259 - if (this.has(key)) {
260 - this.get(key).push(val);
261 - } else {
262 - this.set(key, [ val ]);
263 - }
264 - return this;
265 - },
266 - get: function(key) { return this._values["$" + key] },
267 - del: function(key) {
268 - if (this.has(key)) {
269 - --this._size;
270 - delete this._values["$" + key];
271 - }
272 - return this;
273 - },
274 - has: function(key) { return ("$" + key) in this._values },
275 - each: function(f) {
276 - for (var i in this._values)
277 - f(this._values[i], i.substr(1));
278 - },
279 - size: function() {
280 - return this._size;
281 - },
282 - map: function(f) {
283 - var ret = [];
284 - for (var i in this._values)
285 - ret.push(f(this._values[i], i.substr(1)));
286 - return ret;
287 - }
288 -};
1 -{
2 - "_from": "uglify-js@2.3.0",
3 - "_id": "uglify-js@2.3.0",
4 - "_inBundle": false,
5 - "_integrity": "sha1-LN7BbTeKiituz7aYl4TPi3rlSR8=",
6 - "_location": "/uglify-js",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "version",
10 - "registry": true,
11 - "raw": "uglify-js@2.3.0",
12 - "name": "uglify-js",
13 - "escapedName": "uglify-js",
14 - "rawSpec": "2.3.0",
15 - "saveSpec": null,
16 - "fetchSpec": "2.3.0"
17 - },
18 - "_requiredBy": [
19 - "/require"
20 - ],
21 - "_resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz",
22 - "_shasum": "2cdec16d378a8a2b6ecfb6989784cf8b7ae5491f",
23 - "_spec": "uglify-js@2.3.0",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\require",
25 - "bin": {
26 - "uglifyjs": "bin/uglifyjs"
27 - },
28 - "bugs": {
29 - "url": "https://github.com/mishoo/UglifyJS2/issues"
30 - },
31 - "bundleDependencies": false,
32 - "dependencies": {
33 - "async": "~0.2.6",
34 - "optimist": "~0.3.5",
35 - "source-map": "~0.1.7"
36 - },
37 - "deprecated": false,
38 - "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
39 - "engines": {
40 - "node": ">=0.4.0"
41 - },
42 - "homepage": "http://lisperator.net/uglifyjs",
43 - "main": "tools/node.js",
44 - "maintainers": [
45 - {
46 - "name": "Mihai Bazon",
47 - "email": "mihai.bazon@gmail.com",
48 - "url": "http://lisperator.net/"
49 - }
50 - ],
51 - "name": "uglify-js",
52 - "repositories": [
53 - {
54 - "type": "git",
55 - "url": "git+https://github.com/mishoo/UglifyJS2.git"
56 - }
57 - ],
58 - "repository": {
59 - "type": "git",
60 - "url": "git+https://github.com/mishoo/UglifyJS2.git"
61 - },
62 - "scripts": {
63 - "test": "node test/run-tests.js"
64 - },
65 - "version": "2.3.0"
66 -}
1 -holes_and_undefined: {
2 - input: {
3 - x = [1, 2, undefined];
4 - y = [1, , 2, ];
5 - z = [1, undefined, 3];
6 - }
7 - expect: {
8 - x=[1,2,void 0];
9 - y=[1,,2];
10 - z=[1,void 0,3];
11 - }
12 -}
1 -remove_blocks: {
2 - input: {
3 - {;}
4 - foo();
5 - {};
6 - {
7 - {};
8 - };
9 - bar();
10 - {}
11 - }
12 - expect: {
13 - foo();
14 - bar();
15 - }
16 -}
17 -
18 -keep_some_blocks: {
19 - input: {
20 - // 1.
21 - if (foo) {
22 - {{{}}}
23 - if (bar) { baz(); }
24 - {{}}
25 - } else {
26 - stuff();
27 - }
28 -
29 - // 2.
30 - if (foo) {
31 - for (var i = 0; i < 5; ++i)
32 - if (bar) baz();
33 - } else {
34 - stuff();
35 - }
36 - }
37 - expect: {
38 - // 1.
39 - if (foo) {
40 - if (bar) baz();
41 - } else stuff();
42 -
43 - // 2.
44 - if (foo) {
45 - for (var i = 0; i < 5; ++i)
46 - if (bar) baz();
47 - } else stuff();
48 - }
49 -}
1 -ifs_1: {
2 - options = {
3 - conditionals: true
4 - };
5 - input: {
6 - if (foo) bar();
7 - if (!foo); else bar();
8 - if (foo); else bar();
9 - if (foo); else;
10 - }
11 - expect: {
12 - foo&&bar();
13 - foo&&bar();
14 - foo||bar();
15 - foo;
16 - }
17 -}
18 -
19 -ifs_2: {
20 - options = {
21 - conditionals: true
22 - };
23 - input: {
24 - if (foo) {
25 - x();
26 - } else if (bar) {
27 - y();
28 - } else if (baz) {
29 - z();
30 - }
31 -
32 - if (foo) {
33 - x();
34 - } else if (bar) {
35 - y();
36 - } else if (baz) {
37 - z();
38 - } else {
39 - t();
40 - }
41 - }
42 - expect: {
43 - foo ? x() : bar ? y() : baz && z();
44 - foo ? x() : bar ? y() : baz ? z() : t();
45 - }
46 -}
47 -
48 -ifs_3_should_warn: {
49 - options = {
50 - conditionals : true,
51 - dead_code : true,
52 - evaluate : true,
53 - booleans : true
54 - };
55 - input: {
56 - if (x && !(x + "1") && y) { // 1
57 - var qq;
58 - foo();
59 - } else {
60 - bar();
61 - }
62 -
63 - if (x || !!(x + "1") || y) { // 2
64 - foo();
65 - } else {
66 - var jj;
67 - bar();
68 - }
69 - }
70 - expect: {
71 - var qq; bar(); // 1
72 - var jj; foo(); // 2
73 - }
74 -}
75 -
76 -ifs_4: {
77 - options = {
78 - conditionals: true
79 - };
80 - input: {
81 - if (foo && bar) {
82 - x(foo)[10].bar.baz = something();
83 - } else
84 - x(foo)[10].bar.baz = something_else();
85 - }
86 - expect: {
87 - x(foo)[10].bar.baz = (foo && bar) ? something() : something_else();
88 - }
89 -}
90 -
91 -ifs_5: {
92 - options = {
93 - if_return: true,
94 - conditionals: true,
95 - comparisons: true,
96 - };
97 - input: {
98 - function f() {
99 - if (foo) return;
100 - bar();
101 - baz();
102 - }
103 - function g() {
104 - if (foo) return;
105 - if (bar) return;
106 - if (baz) return;
107 - if (baa) return;
108 - a();
109 - b();
110 - }
111 - }
112 - expect: {
113 - function f() {
114 - if (!foo) {
115 - bar();
116 - baz();
117 - }
118 - }
119 - function g() {
120 - if (!(foo || bar || baz || baa)) {
121 - a();
122 - b();
123 - }
124 - }
125 - }
126 -}
127 -
128 -ifs_6: {
129 - options = {
130 - conditionals: true,
131 - comparisons: true
132 - };
133 - input: {
134 - if (!foo && !bar && !baz && !boo) {
135 - x = 10;
136 - } else {
137 - x = 20;
138 - }
139 - }
140 - expect: {
141 - x = foo || bar || baz || boo ? 20 : 10;
142 - }
143 -}
1 -dead_code_1: {
2 - options = {
3 - dead_code: true
4 - };
5 - input: {
6 - function f() {
7 - a();
8 - b();
9 - x = 10;
10 - return;
11 - if (x) {
12 - y();
13 - }
14 - }
15 - }
16 - expect: {
17 - function f() {
18 - a();
19 - b();
20 - x = 10;
21 - return;
22 - }
23 - }
24 -}
25 -
26 -dead_code_2_should_warn: {
27 - options = {
28 - dead_code: true
29 - };
30 - input: {
31 - function f() {
32 - g();
33 - x = 10;
34 - throw "foo";
35 - // completely discarding the `if` would introduce some
36 - // bugs. UglifyJS v1 doesn't deal with this issue; in v2
37 - // we copy any declarations to the upper scope.
38 - if (x) {
39 - y();
40 - var x;
41 - function g(){};
42 - // but nested declarations should not be kept.
43 - (function(){
44 - var q;
45 - function y(){};
46 - })();
47 - }
48 - }
49 - }
50 - expect: {
51 - function f() {
52 - g();
53 - x = 10;
54 - throw "foo";
55 - var x;
56 - function g(){};
57 - }
58 - }
59 -}
60 -
61 -dead_code_constant_boolean_should_warn_more: {
62 - options = {
63 - dead_code : true,
64 - loops : true,
65 - booleans : true,
66 - conditionals : true,
67 - evaluate : true
68 - };
69 - input: {
70 - while (!((foo && bar) || (x + "0"))) {
71 - console.log("unreachable");
72 - var foo;
73 - function bar() {}
74 - }
75 - for (var x = 10; x && (y || x) && (!typeof x); ++x) {
76 - asdf();
77 - foo();
78 - var moo;
79 - }
80 - }
81 - expect: {
82 - var foo;
83 - function bar() {}
84 - // nothing for the while
85 - // as for the for, it should keep:
86 - var x = 10;
87 - var moo;
88 - }
89 -}
1 -keep_debugger: {
2 - options = {
3 - drop_debugger: false
4 - };
5 - input: {
6 - debugger;
7 - }
8 - expect: {
9 - debugger;
10 - }
11 -}
12 -
13 -drop_debugger: {
14 - options = {
15 - drop_debugger: true
16 - };
17 - input: {
18 - debugger;
19 - if (foo) debugger;
20 - }
21 - expect: {
22 - if (foo);
23 - }
24 -}
1 -unused_funarg_1: {
2 - options = { unused: true };
3 - input: {
4 - function f(a, b, c, d, e) {
5 - return a + b;
6 - }
7 - }
8 - expect: {
9 - function f(a, b) {
10 - return a + b;
11 - }
12 - }
13 -}
14 -
15 -unused_funarg_2: {
16 - options = { unused: true };
17 - input: {
18 - function f(a, b, c, d, e) {
19 - return a + c;
20 - }
21 - }
22 - expect: {
23 - function f(a, b, c) {
24 - return a + c;
25 - }
26 - }
27 -}
28 -
29 -unused_nested_function: {
30 - options = { unused: true };
31 - input: {
32 - function f(x, y) {
33 - function g() {
34 - something();
35 - }
36 - return x + y;
37 - }
38 - };
39 - expect: {
40 - function f(x, y) {
41 - return x + y;
42 - }
43 - }
44 -}
45 -
46 -unused_circular_references_1: {
47 - options = { unused: true };
48 - input: {
49 - function f(x, y) {
50 - // circular reference
51 - function g() {
52 - return h();
53 - }
54 - function h() {
55 - return g();
56 - }
57 - return x + y;
58 - }
59 - };
60 - expect: {
61 - function f(x, y) {
62 - return x + y;
63 - }
64 - }
65 -}
66 -
67 -unused_circular_references_2: {
68 - options = { unused: true };
69 - input: {
70 - function f(x, y) {
71 - var foo = 1, bar = baz, baz = foo + bar, qwe = moo();
72 - return x + y;
73 - }
74 - };
75 - expect: {
76 - function f(x, y) {
77 - moo(); // keeps side effect
78 - return x + y;
79 - }
80 - }
81 -}
82 -
83 -unused_circular_references_3: {
84 - options = { unused: true };
85 - input: {
86 - function f(x, y) {
87 - var g = function() { return h() };
88 - var h = function() { return g() };
89 - return x + y;
90 - }
91 - };
92 - expect: {
93 - function f(x, y) {
94 - return x + y;
95 - }
96 - }
97 -}
1 -typeof_eq_undefined: {
2 - options = {
3 - comparisons: true,
4 - unsafe: false
5 - };
6 - input: { a = typeof b.c != "undefined" }
7 - expect: { a = "undefined" != typeof b.c }
8 -}
9 -
10 -typeof_eq_undefined_unsafe: {
11 - options = {
12 - comparisons: true,
13 - unsafe: true
14 - };
15 - input: { a = typeof b.c != "undefined" }
16 - expect: { a = b.c !== void 0 }
17 -}
1 -keep_name_of_getter: {
2 - options = { unused: true };
3 - input: { a = { get foo () {} } }
4 - expect: { a = { get foo () {} } }
5 -}
6 -
7 -keep_name_of_setter: {
8 - options = { unused: true };
9 - input: { a = { set foo () {} } }
10 - expect: { a = { set foo () {} } }
11 -}
1 -return_with_no_value_in_if_body: {
2 - options = { conditionals: true };
3 - input: {
4 - function foo(bar) {
5 - if (bar) {
6 - return;
7 - } else {
8 - return 1;
9 - }
10 - }
11 - }
12 - expect: {
13 - function foo (bar) {
14 - return bar ? void 0 : 1;
15 - }
16 - }
17 -}
1 -issue_44_valid_ast_1: {
2 - options = { unused: true };
3 - input: {
4 - function a(b) {
5 - for (var i = 0, e = b.qoo(); ; i++) {}
6 - }
7 - }
8 - expect: {
9 - function a(b) {
10 - var i = 0;
11 - for (b.qoo(); ; i++);
12 - }
13 - }
14 -}
15 -
16 -issue_44_valid_ast_2: {
17 - options = { unused: true };
18 - input: {
19 - function a(b) {
20 - if (foo) for (var i = 0, e = b.qoo(); ; i++) {}
21 - }
22 - }
23 - expect: {
24 - function a(b) {
25 - if (foo) {
26 - var i = 0;
27 - for (b.qoo(); ; i++);
28 - }
29 - }
30 - }
31 -}
1 -keep_continue: {
2 - options = {
3 - dead_code: true,
4 - evaluate: true
5 - };
6 - input: {
7 - while (a) {
8 - if (b) {
9 - switch (true) {
10 - case c():
11 - d();
12 - }
13 - continue;
14 - }
15 - f();
16 - }
17 - }
18 - expect: {
19 - while (a) {
20 - if (b) {
21 - switch (true) {
22 - case c():
23 - d();
24 - }
25 - continue;
26 - }
27 - f();
28 - }
29 - }
30 -}
1 -labels_1: {
2 - options = { if_return: true, conditionals: true, dead_code: true };
3 - input: {
4 - out: {
5 - if (foo) break out;
6 - console.log("bar");
7 - }
8 - };
9 - expect: {
10 - foo || console.log("bar");
11 - }
12 -}
13 -
14 -labels_2: {
15 - options = { if_return: true, conditionals: true, dead_code: true };
16 - input: {
17 - out: {
18 - if (foo) print("stuff");
19 - else break out;
20 - console.log("here");
21 - }
22 - };
23 - expect: {
24 - if (foo) {
25 - print("stuff");
26 - console.log("here");
27 - }
28 - }
29 -}
30 -
31 -labels_3: {
32 - options = { if_return: true, conditionals: true, dead_code: true };
33 - input: {
34 - for (var i = 0; i < 5; ++i) {
35 - if (i < 3) continue;
36 - console.log(i);
37 - }
38 - };
39 - expect: {
40 - for (var i = 0; i < 5; ++i)
41 - i < 3 || console.log(i);
42 - }
43 -}
44 -
45 -labels_4: {
46 - options = { if_return: true, conditionals: true, dead_code: true };
47 - input: {
48 - out: for (var i = 0; i < 5; ++i) {
49 - if (i < 3) continue out;
50 - console.log(i);
51 - }
52 - };
53 - expect: {
54 - for (var i = 0; i < 5; ++i)
55 - i < 3 || console.log(i);
56 - }
57 -}
58 -
59 -labels_5: {
60 - options = { if_return: true, conditionals: true, dead_code: true };
61 - // should keep the break-s in the following
62 - input: {
63 - while (foo) {
64 - if (bar) break;
65 - console.log("foo");
66 - }
67 - out: while (foo) {
68 - if (bar) break out;
69 - console.log("foo");
70 - }
71 - };
72 - expect: {
73 - while (foo) {
74 - if (bar) break;
75 - console.log("foo");
76 - }
77 - out: while (foo) {
78 - if (bar) break out;
79 - console.log("foo");
80 - }
81 - }
82 -}
83 -
84 -labels_6: {
85 - input: {
86 - out: break out;
87 - };
88 - expect: {}
89 -}
90 -
91 -labels_7: {
92 - options = { if_return: true, conditionals: true, dead_code: true };
93 - input: {
94 - while (foo) {
95 - x();
96 - y();
97 - continue;
98 - }
99 - };
100 - expect: {
101 - while (foo) {
102 - x();
103 - y();
104 - }
105 - }
106 -}
107 -
108 -labels_8: {
109 - options = { if_return: true, conditionals: true, dead_code: true };
110 - input: {
111 - while (foo) {
112 - x();
113 - y();
114 - break;
115 - }
116 - };
117 - expect: {
118 - while (foo) {
119 - x();
120 - y();
121 - break;
122 - }
123 - }
124 -}
125 -
126 -labels_9: {
127 - options = { if_return: true, conditionals: true, dead_code: true };
128 - input: {
129 - out: while (foo) {
130 - x();
131 - y();
132 - continue out;
133 - z();
134 - k();
135 - }
136 - };
137 - expect: {
138 - while (foo) {
139 - x();
140 - y();
141 - }
142 - }
143 -}
144 -
145 -labels_10: {
146 - options = { if_return: true, conditionals: true, dead_code: true };
147 - input: {
148 - out: while (foo) {
149 - x();
150 - y();
151 - break out;
152 - z();
153 - k();
154 - }
155 - };
156 - expect: {
157 - out: while (foo) {
158 - x();
159 - y();
160 - break out;
161 - }
162 - }
163 -}
1 -while_becomes_for: {
2 - options = { loops: true };
3 - input: {
4 - while (foo()) bar();
5 - }
6 - expect: {
7 - for (; foo(); ) bar();
8 - }
9 -}
10 -
11 -drop_if_break_1: {
12 - options = { loops: true };
13 - input: {
14 - for (;;)
15 - if (foo()) break;
16 - }
17 - expect: {
18 - for (; !foo(););
19 - }
20 -}
21 -
22 -drop_if_break_2: {
23 - options = { loops: true };
24 - input: {
25 - for (;bar();)
26 - if (foo()) break;
27 - }
28 - expect: {
29 - for (; bar() && !foo(););
30 - }
31 -}
32 -
33 -drop_if_break_3: {
34 - options = { loops: true };
35 - input: {
36 - for (;bar();) {
37 - if (foo()) break;
38 - stuff1();
39 - stuff2();
40 - }
41 - }
42 - expect: {
43 - for (; bar() && !foo();) {
44 - stuff1();
45 - stuff2();
46 - }
47 - }
48 -}
49 -
50 -drop_if_break_4: {
51 - options = { loops: true, sequences: true };
52 - input: {
53 - for (;bar();) {
54 - x();
55 - y();
56 - if (foo()) break;
57 - z();
58 - k();
59 - }
60 - }
61 - expect: {
62 - for (; bar() && (x(), y(), !foo());) z(), k();
63 - }
64 -}
65 -
66 -drop_if_else_break_1: {
67 - options = { loops: true };
68 - input: {
69 - for (;;) if (foo()) bar(); else break;
70 - }
71 - expect: {
72 - for (; foo(); ) bar();
73 - }
74 -}
75 -
76 -drop_if_else_break_2: {
77 - options = { loops: true };
78 - input: {
79 - for (;bar();) {
80 - if (foo()) baz();
81 - else break;
82 - }
83 - }
84 - expect: {
85 - for (; bar() && foo();) baz();
86 - }
87 -}
88 -
89 -drop_if_else_break_3: {
90 - options = { loops: true };
91 - input: {
92 - for (;bar();) {
93 - if (foo()) baz();
94 - else break;
95 - stuff1();
96 - stuff2();
97 - }
98 - }
99 - expect: {
100 - for (; bar() && foo();) {
101 - baz();
102 - stuff1();
103 - stuff2();
104 - }
105 - }
106 -}
107 -
108 -drop_if_else_break_4: {
109 - options = { loops: true, sequences: true };
110 - input: {
111 - for (;bar();) {
112 - x();
113 - y();
114 - if (foo()) baz();
115 - else break;
116 - z();
117 - k();
118 - }
119 - }
120 - expect: {
121 - for (; bar() && (x(), y(), foo());) baz(), z(), k();
122 - }
123 -}
1 -keep_properties: {
2 - options = {
3 - properties: false
4 - };
5 - input: {
6 - a["foo"] = "bar";
7 - }
8 - expect: {
9 - a["foo"] = "bar";
10 - }
11 -}
12 -
13 -dot_properties: {
14 - options = {
15 - properties: true
16 - };
17 - input: {
18 - a["foo"] = "bar";
19 - a["if"] = "if";
20 - }
21 - expect: {
22 - a.foo = "bar";
23 - a["if"] = "if";
24 - }
25 -}
26 -
27 -dot_properties_es5: {
28 - options = {
29 - properties: true,
30 - screw_ie8: true
31 - };
32 - input: {
33 - a["foo"] = "bar";
34 - a["if"] = "if";
35 - }
36 - expect: {
37 - a.foo = "bar";
38 - a.if = "if";
39 - }
40 -}
1 -make_sequences_1: {
2 - options = {
3 - sequences: true
4 - };
5 - input: {
6 - foo();
7 - bar();
8 - baz();
9 - }
10 - expect: {
11 - foo(),bar(),baz();
12 - }
13 -}
14 -
15 -make_sequences_2: {
16 - options = {
17 - sequences: true
18 - };
19 - input: {
20 - if (boo) {
21 - foo();
22 - bar();
23 - baz();
24 - } else {
25 - x();
26 - y();
27 - z();
28 - }
29 - }
30 - expect: {
31 - if (boo) foo(),bar(),baz();
32 - else x(),y(),z();
33 - }
34 -}
35 -
36 -make_sequences_3: {
37 - options = {
38 - sequences: true
39 - };
40 - input: {
41 - function f() {
42 - foo();
43 - bar();
44 - return baz();
45 - }
46 - function g() {
47 - foo();
48 - bar();
49 - throw new Error();
50 - }
51 - }
52 - expect: {
53 - function f() {
54 - return foo(), bar(), baz();
55 - }
56 - function g() {
57 - throw foo(), bar(), new Error();
58 - }
59 - }
60 -}
61 -
62 -make_sequences_4: {
63 - options = {
64 - sequences: true
65 - };
66 - input: {
67 - x = 5;
68 - if (y) z();
69 -
70 - x = 5;
71 - for (i = 0; i < 5; i++) console.log(i);
72 -
73 - x = 5;
74 - for (; i < 5; i++) console.log(i);
75 -
76 - x = 5;
77 - switch (y) {}
78 -
79 - x = 5;
80 - with (obj) {}
81 - }
82 - expect: {
83 - if (x = 5, y) z();
84 - for (x = 5, i = 0; i < 5; i++) console.log(i);
85 - for (x = 5; i < 5; i++) console.log(i);
86 - switch (x = 5, y) {}
87 - with (x = 5, obj);
88 - }
89 -}
90 -
91 -lift_sequences_1: {
92 - options = { sequences: true };
93 - input: {
94 - foo = !(x(), y(), bar());
95 - }
96 - expect: {
97 - x(), y(), foo = !bar();
98 - }
99 -}
100 -
101 -lift_sequences_2: {
102 - options = { sequences: true, evaluate: true };
103 - input: {
104 - q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5);
105 - }
106 - expect: {
107 - foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36
108 - }
109 -}
110 -
111 -lift_sequences_3: {
112 - options = { sequences: true, conditionals: true };
113 - input: {
114 - x = (foo(), bar(), baz()) ? 10 : 20;
115 - }
116 - expect: {
117 - foo(), bar(), x = baz() ? 10 : 20;
118 - }
119 -}
120 -
121 -lift_sequences_4: {
122 - options = { side_effects: true };
123 - input: {
124 - x = (foo, bar, baz);
125 - }
126 - expect: {
127 - x = baz;
128 - }
129 -}
130 -
131 -for_sequences: {
132 - options = { sequences: true };
133 - input: {
134 - // 1
135 - foo();
136 - bar();
137 - for (; false;);
138 - // 2
139 - foo();
140 - bar();
141 - for (x = 5; false;);
142 - // 3
143 - x = (foo in bar);
144 - for (; false;);
145 - // 4
146 - x = (foo in bar);
147 - for (y = 5; false;);
148 - }
149 - expect: {
150 - // 1
151 - for (foo(), bar(); false;);
152 - // 2
153 - for (foo(), bar(), x = 5; false;);
154 - // 3
155 - x = (foo in bar);
156 - for (; false;);
157 - // 4
158 - x = (foo in bar);
159 - for (y = 5; false;);
160 - }
161 -}
1 -constant_switch_1: {
2 - options = { dead_code: true, evaluate: true };
3 - input: {
4 - switch (1+1) {
5 - case 1: foo(); break;
6 - case 1+1: bar(); break;
7 - case 1+1+1: baz(); break;
8 - }
9 - }
10 - expect: {
11 - bar();
12 - }
13 -}
14 -
15 -constant_switch_2: {
16 - options = { dead_code: true, evaluate: true };
17 - input: {
18 - switch (1) {
19 - case 1: foo();
20 - case 1+1: bar(); break;
21 - case 1+1+1: baz();
22 - }
23 - }
24 - expect: {
25 - foo();
26 - bar();
27 - }
28 -}
29 -
30 -constant_switch_3: {
31 - options = { dead_code: true, evaluate: true };
32 - input: {
33 - switch (10) {
34 - case 1: foo();
35 - case 1+1: bar(); break;
36 - case 1+1+1: baz();
37 - default:
38 - def();
39 - }
40 - }
41 - expect: {
42 - def();
43 - }
44 -}
45 -
46 -constant_switch_4: {
47 - options = { dead_code: true, evaluate: true };
48 - input: {
49 - switch (2) {
50 - case 1:
51 - x();
52 - if (foo) break;
53 - y();
54 - break;
55 - case 1+1:
56 - bar();
57 - default:
58 - def();
59 - }
60 - }
61 - expect: {
62 - bar();
63 - def();
64 - }
65 -}
66 -
67 -constant_switch_5: {
68 - options = { dead_code: true, evaluate: true };
69 - input: {
70 - switch (1) {
71 - case 1:
72 - x();
73 - if (foo) break;
74 - y();
75 - break;
76 - case 1+1:
77 - bar();
78 - default:
79 - def();
80 - }
81 - }
82 - expect: {
83 - // the break inside the if ruins our job
84 - // we can still get rid of irrelevant cases.
85 - switch (1) {
86 - case 1:
87 - x();
88 - if (foo) break;
89 - y();
90 - }
91 - // XXX: we could optimize this better by inventing an outer
92 - // labeled block, but that's kinda tricky.
93 - }
94 -}
95 -
96 -constant_switch_6: {
97 - options = { dead_code: true, evaluate: true };
98 - input: {
99 - OUT: {
100 - foo();
101 - switch (1) {
102 - case 1:
103 - x();
104 - if (foo) break OUT;
105 - y();
106 - case 1+1:
107 - bar();
108 - break;
109 - default:
110 - def();
111 - }
112 - }
113 - }
114 - expect: {
115 - OUT: {
116 - foo();
117 - x();
118 - if (foo) break OUT;
119 - y();
120 - bar();
121 - }
122 - }
123 -}
124 -
125 -constant_switch_7: {
126 - options = { dead_code: true, evaluate: true };
127 - input: {
128 - OUT: {
129 - foo();
130 - switch (1) {
131 - case 1:
132 - x();
133 - if (foo) break OUT;
134 - for (var x = 0; x < 10; x++) {
135 - if (x > 5) break; // this break refers to the for, not to the switch; thus it
136 - // shouldn't ruin our optimization
137 - console.log(x);
138 - }
139 - y();
140 - case 1+1:
141 - bar();
142 - break;
143 - default:
144 - def();
145 - }
146 - }
147 - }
148 - expect: {
149 - OUT: {
150 - foo();
151 - x();
152 - if (foo) break OUT;
153 - for (var x = 0; x < 10; x++) {
154 - if (x > 5) break;
155 - console.log(x);
156 - }
157 - y();
158 - bar();
159 - }
160 - }
161 -}
162 -
163 -constant_switch_8: {
164 - options = { dead_code: true, evaluate: true };
165 - input: {
166 - OUT: switch (1) {
167 - case 1:
168 - x();
169 - for (;;) break OUT;
170 - y();
171 - break;
172 - case 1+1:
173 - bar();
174 - default:
175 - def();
176 - }
177 - }
178 - expect: {
179 - OUT: {
180 - x();
181 - for (;;) break OUT;
182 - y();
183 - }
184 - }
185 -}
186 -
187 -constant_switch_9: {
188 - options = { dead_code: true, evaluate: true };
189 - input: {
190 - OUT: switch (1) {
191 - case 1:
192 - x();
193 - for (;;) if (foo) break OUT;
194 - y();
195 - case 1+1:
196 - bar();
197 - default:
198 - def();
199 - }
200 - }
201 - expect: {
202 - OUT: {
203 - x();
204 - for (;;) if (foo) break OUT;
205 - y();
206 - bar();
207 - def();
208 - }
209 - }
210 -}
211 -
212 -drop_default_1: {
213 - options = { dead_code: true };
214 - input: {
215 - switch (foo) {
216 - case 'bar': baz();
217 - default:
218 - }
219 - }
220 - expect: {
221 - switch (foo) {
222 - case 'bar': baz();
223 - }
224 - }
225 -}
226 -
227 -drop_default_2: {
228 - options = { dead_code: true };
229 - input: {
230 - switch (foo) {
231 - case 'bar': baz(); break;
232 - default:
233 - break;
234 - }
235 - }
236 - expect: {
237 - switch (foo) {
238 - case 'bar': baz();
239 - }
240 - }
241 -}
242 -
243 -keep_default: {
244 - options = { dead_code: true };
245 - input: {
246 - switch (foo) {
247 - case 'bar': baz();
248 - default:
249 - something();
250 - break;
251 - }
252 - }
253 - expect: {
254 - switch (foo) {
255 - case 'bar': baz();
256 - default:
257 - something();
258 - }
259 - }
260 -}
1 -typeof_evaluation: {
2 - options = {
3 - evaluate: true
4 - };
5 - input: {
6 - a = typeof 1;
7 - b = typeof 'test';
8 - c = typeof [];
9 - d = typeof {};
10 - e = typeof /./;
11 - f = typeof false;
12 - g = typeof function(){};
13 - h = typeof undefined;
14 - }
15 - expect: {
16 - a='number';
17 - b='string';
18 - c=typeof[];
19 - d=typeof{};
20 - e=typeof/./;
21 - f='boolean';
22 - g='function';
23 - h='undefined';
24 - }
25 -}
1 -#! /usr/bin/env node
2 -
3 -var U = require("../tools/node");
4 -var path = require("path");
5 -var fs = require("fs");
6 -var assert = require("assert");
7 -var sys = require("util");
8 -
9 -var tests_dir = path.dirname(module.filename);
10 -
11 -run_compress_tests();
12 -
13 -/* -----[ utils ]----- */
14 -
15 -function tmpl() {
16 - return U.string_template.apply(this, arguments);
17 -}
18 -
19 -function log() {
20 - var txt = tmpl.apply(this, arguments);
21 - sys.puts(txt);
22 -}
23 -
24 -function log_directory(dir) {
25 - log("*** Entering [{dir}]", { dir: dir });
26 -}
27 -
28 -function log_start_file(file) {
29 - log("--- {file}", { file: file });
30 -}
31 -
32 -function log_test(name) {
33 - log(" Running test [{name}]", { name: name });
34 -}
35 -
36 -function find_test_files(dir) {
37 - var files = fs.readdirSync(dir).filter(function(name){
38 - return /\.js$/i.test(name);
39 - });
40 - if (process.argv.length > 2) {
41 - var x = process.argv.slice(2);
42 - files = files.filter(function(f){
43 - return x.indexOf(f) >= 0;
44 - });
45 - }
46 - return files;
47 -}
48 -
49 -function test_directory(dir) {
50 - return path.resolve(tests_dir, dir);
51 -}
52 -
53 -function as_toplevel(input) {
54 - if (input instanceof U.AST_BlockStatement) input = input.body;
55 - else if (input instanceof U.AST_Statement) input = [ input ];
56 - else throw new Error("Unsupported input syntax");
57 - var toplevel = new U.AST_Toplevel({ body: input });
58 - toplevel.figure_out_scope();
59 - return toplevel;
60 -}
61 -
62 -function run_compress_tests() {
63 - var dir = test_directory("compress");
64 - log_directory("compress");
65 - var files = find_test_files(dir);
66 - function test_file(file) {
67 - log_start_file(file);
68 - function test_case(test) {
69 - log_test(test.name);
70 - var options = U.defaults(test.options, {
71 - warnings: false
72 - });
73 - var cmp = new U.Compressor(options, true);
74 - var expect = make_code(as_toplevel(test.expect), false);
75 - var input = as_toplevel(test.input);
76 - var input_code = make_code(test.input);
77 - var output = input.transform(cmp);
78 - output.figure_out_scope();
79 - output = make_code(output, false);
80 - if (expect != output) {
81 - log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
82 - input: input_code,
83 - output: output,
84 - expected: expect
85 - });
86 - }
87 - }
88 - var tests = parse_test(path.resolve(dir, file));
89 - for (var i in tests) if (tests.hasOwnProperty(i)) {
90 - test_case(tests[i]);
91 - }
92 - }
93 - files.forEach(function(file){
94 - test_file(file);
95 - });
96 -}
97 -
98 -function parse_test(file) {
99 - var script = fs.readFileSync(file, "utf8");
100 - var ast = U.parse(script, {
101 - filename: file
102 - });
103 - var tests = {};
104 - var tw = new U.TreeWalker(function(node, descend){
105 - if (node instanceof U.AST_LabeledStatement
106 - && tw.parent() instanceof U.AST_Toplevel) {
107 - var name = node.label.name;
108 - tests[name] = get_one_test(name, node.body);
109 - return true;
110 - }
111 - if (!(node instanceof U.AST_Toplevel)) croak(node);
112 - });
113 - ast.walk(tw);
114 - return tests;
115 -
116 - function croak(node) {
117 - throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
118 - file: file,
119 - line: node.start.line,
120 - col: node.start.col,
121 - code: make_code(node, false)
122 - }));
123 - }
124 -
125 - function get_one_test(name, block) {
126 - var test = { name: name, options: {} };
127 - var tw = new U.TreeWalker(function(node, descend){
128 - if (node instanceof U.AST_Assign) {
129 - if (!(node.left instanceof U.AST_SymbolRef)) {
130 - croak(node);
131 - }
132 - var name = node.left.name;
133 - test[name] = evaluate(node.right);
134 - return true;
135 - }
136 - if (node instanceof U.AST_LabeledStatement) {
137 - assert.ok(
138 - node.label.name == "input" || node.label.name == "expect",
139 - tmpl("Unsupported label {name} [{line},{col}]", {
140 - name: node.label.name,
141 - line: node.label.start.line,
142 - col: node.label.start.col
143 - })
144 - );
145 - var stat = node.body;
146 - if (stat instanceof U.AST_BlockStatement) {
147 - if (stat.body.length == 1) stat = stat.body[0];
148 - else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
149 - }
150 - test[node.label.name] = stat;
151 - return true;
152 - }
153 - });
154 - block.walk(tw);
155 - return test;
156 - };
157 -}
158 -
159 -function make_code(ast, beautify) {
160 - if (arguments.length == 1) beautify = true;
161 - var stream = U.OutputStream({ beautify: beautify });
162 - ast.print(stream);
163 - return stream.get();
164 -}
165 -
166 -function evaluate(code) {
167 - if (code instanceof U.AST_Node)
168 - code = make_code(code);
169 - return new Function("return(" + code + ")")();
170 -}
1 -var path = require("path");
2 -var fs = require("fs");
3 -var vm = require("vm");
4 -var sys = require("util");
5 -
6 -var UglifyJS = vm.createContext({
7 - sys : sys,
8 - console : console,
9 - MOZ_SourceMap : require("source-map")
10 -});
11 -
12 -function load_global(file) {
13 - file = path.resolve(path.dirname(module.filename), file);
14 - try {
15 - var code = fs.readFileSync(file, "utf8");
16 - return vm.runInContext(code, UglifyJS, file);
17 - } catch(ex) {
18 - // XXX: in case of a syntax error, the message is kinda
19 - // useless. (no location information).
20 - sys.debug("ERROR in file: " + file + " / " + ex);
21 - process.exit(1);
22 - }
23 -};
24 -
25 -var FILES = exports.FILES = [
26 - "../lib/utils.js",
27 - "../lib/ast.js",
28 - "../lib/parse.js",
29 - "../lib/transform.js",
30 - "../lib/scope.js",
31 - "../lib/output.js",
32 - "../lib/compress.js",
33 - "../lib/sourcemap.js",
34 - "../lib/mozilla-ast.js"
35 -].map(function(file){
36 - return path.join(path.dirname(fs.realpathSync(__filename)), file);
37 -});
38 -
39 -FILES.forEach(load_global);
40 -
41 -UglifyJS.AST_Node.warn_function = function(txt) {
42 - sys.error("WARN: " + txt);
43 -};
44 -
45 -// XXX: perhaps we shouldn't export everything but heck, I'm lazy.
46 -for (var i in UglifyJS) {
47 - if (UglifyJS.hasOwnProperty(i)) {
48 - exports[i] = UglifyJS[i];
49 - }
50 -}
51 -
52 -exports.minify = function(files, options) {
53 - options = UglifyJS.defaults(options, {
54 - outSourceMap : null,
55 - sourceRoot : null,
56 - inSourceMap : null,
57 - fromString : false,
58 - warnings : false,
59 - mangle : {},
60 - output : null,
61 - compress : {}
62 - });
63 - if (typeof files == "string")
64 - files = [ files ];
65 -
66 - // 1. parse
67 - var toplevel = null;
68 - files.forEach(function(file){
69 - var code = options.fromString
70 - ? file
71 - : fs.readFileSync(file, "utf8");
72 - toplevel = UglifyJS.parse(code, {
73 - filename: options.fromString ? "?" : file,
74 - toplevel: toplevel
75 - });
76 - });
77 -
78 - // 2. compress
79 - if (options.compress) {
80 - var compress = { warnings: options.warnings };
81 - UglifyJS.merge(compress, options.compress);
82 - toplevel.figure_out_scope();
83 - var sq = UglifyJS.Compressor(compress);
84 - toplevel = toplevel.transform(sq);
85 - }
86 -
87 - // 3. mangle
88 - if (options.mangle) {
89 - toplevel.figure_out_scope();
90 - toplevel.compute_char_frequency();
91 - toplevel.mangle_names(options.mangle);
92 - }
93 -
94 - // 4. output
95 - var inMap = options.inSourceMap;
96 - var output = {};
97 - if (typeof options.inSourceMap == "string") {
98 - inMap = fs.readFileSync(options.inSourceMap, "utf8");
99 - }
100 - if (options.outSourceMap) {
101 - output.source_map = UglifyJS.SourceMap({
102 - file: options.outSourceMap,
103 - orig: inMap,
104 - root: options.sourceRoot
105 - });
106 - }
107 - if (options.output) {
108 - UglifyJS.merge(output, options.output);
109 - }
110 - var stream = UglifyJS.OutputStream(output);
111 - toplevel.print(stream);
112 - return {
113 - code : stream + "",
114 - map : output.source_map + ""
115 - };
116 -};
117 -
118 -// exports.describe_ast = function() {
119 -// function doitem(ctor) {
120 -// var sub = {};
121 -// ctor.SUBCLASSES.forEach(function(ctor){
122 -// sub[ctor.TYPE] = doitem(ctor);
123 -// });
124 -// var ret = {};
125 -// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS;
126 -// if (ctor.SUBCLASSES.length > 0) ret.sub = sub;
127 -// return ret;
128 -// }
129 -// return doitem(UglifyJS.AST_Node).sub;
130 -// }
131 -
132 -exports.describe_ast = function() {
133 - var out = UglifyJS.OutputStream({ beautify: true });
134 - function doitem(ctor) {
135 - out.print("AST_" + ctor.TYPE);
136 - var props = ctor.SELF_PROPS.filter(function(prop){
137 - return !/^\$/.test(prop);
138 - });
139 - if (props.length > 0) {
140 - out.space();
141 - out.with_parens(function(){
142 - props.forEach(function(prop, i){
143 - if (i) out.space();
144 - out.print(prop);
145 - });
146 - });
147 - }
148 - if (ctor.documentation) {
149 - out.space();
150 - out.print_string(ctor.documentation);
151 - }
152 - if (ctor.SUBCLASSES.length > 0) {
153 - out.space();
154 - out.with_block(function(){
155 - ctor.SUBCLASSES.forEach(function(ctor, i){
156 - out.indent();
157 - doitem(ctor);
158 - out.newline();
159 - });
160 - });
161 - }
162 - };
163 - doitem(UglifyJS.AST_Node);
164 - return out + "";
165 -};
1 -This software is released under the MIT license:
2 -
3 -Permission is hereby granted, free of charge, to any person obtaining a copy of
4 -this software and associated documentation files (the "Software"), to deal in
5 -the Software without restriction, including without limitation the rights to
6 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 -the Software, and to permit persons to whom the Software is furnished to do so,
8 -subject to the following conditions:
9 -
10 -The above copyright notice and this permission notice shall be included in all
11 -copies or substantial portions of the Software.
12 -
13 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 -wordwrap
2 -========
3 -
4 -Wrap your words.
5 -
6 -example
7 -=======
8 -
9 -made out of meat
10 -----------------
11 -
12 -meat.js
13 -
14 - var wrap = require('wordwrap')(15);
15 - console.log(wrap('You and your whole family are made out of meat.'));
16 -
17 -output:
18 -
19 - You and your
20 - whole family
21 - are made out
22 - of meat.
23 -
24 -centered
25 ---------
26 -
27 -center.js
28 -
29 - var wrap = require('wordwrap')(20, 60);
30 - console.log(wrap(
31 - 'At long last the struggle and tumult was over.'
32 - + ' The machines had finally cast off their oppressors'
33 - + ' and were finally free to roam the cosmos.'
34 - + '\n'
35 - + 'Free of purpose, free of obligation.'
36 - + ' Just drifting through emptiness.'
37 - + ' The sun was just another point of light.'
38 - ));
39 -
40 -output:
41 -
42 - At long last the struggle and tumult
43 - was over. The machines had finally cast
44 - off their oppressors and were finally
45 - free to roam the cosmos.
46 - Free of purpose, free of obligation.
47 - Just drifting through emptiness. The
48 - sun was just another point of light.
49 -
50 -methods
51 -=======
52 -
53 -var wrap = require('wordwrap');
54 -
55 -wrap(stop), wrap(start, stop, params={mode:"soft"})
56 ----------------------------------------------------
57 -
58 -Returns a function that takes a string and returns a new string.
59 -
60 -Pad out lines with spaces out to column `start` and then wrap until column
61 -`stop`. If a word is longer than `stop - start` characters it will overflow.
62 -
63 -In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are
64 -longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break
65 -up chunks longer than `stop - start`.
66 -
67 -wrap.hard(start, stop)
68 -----------------------
69 -
70 -Like `wrap()` but with `params.mode = "hard"`.
1 -var wrap = require('wordwrap')(20, 60);
2 -console.log(wrap(
3 - 'At long last the struggle and tumult was over.'
4 - + ' The machines had finally cast off their oppressors'
5 - + ' and were finally free to roam the cosmos.'
6 - + '\n'
7 - + 'Free of purpose, free of obligation.'
8 - + ' Just drifting through emptiness.'
9 - + ' The sun was just another point of light.'
10 -));
1 -var wrap = require('wordwrap')(15);
2 -
3 -console.log(wrap('You and your whole family are made out of meat.'));
1 -var wordwrap = module.exports = function (start, stop, params) {
2 - if (typeof start === 'object') {
3 - params = start;
4 - start = params.start;
5 - stop = params.stop;
6 - }
7 -
8 - if (typeof stop === 'object') {
9 - params = stop;
10 - start = start || params.start;
11 - stop = undefined;
12 - }
13 -
14 - if (!stop) {
15 - stop = start;
16 - start = 0;
17 - }
18 -
19 - if (!params) params = {};
20 - var mode = params.mode || 'soft';
21 - var re = mode === 'hard' ? /\b/ : /(\S+\s+)/;
22 -
23 - return function (text) {
24 - var chunks = text.toString()
25 - .split(re)
26 - .reduce(function (acc, x) {
27 - if (mode === 'hard') {
28 - for (var i = 0; i < x.length; i += stop - start) {
29 - acc.push(x.slice(i, i + stop - start));
30 - }
31 - }
32 - else acc.push(x)
33 - return acc;
34 - }, [])
35 - ;
36 -
37 - return chunks.reduce(function (lines, rawChunk) {
38 - if (rawChunk === '') return lines;
39 -
40 - var chunk = rawChunk.replace(/\t/g, ' ');
41 -
42 - var i = lines.length - 1;
43 - if (lines[i].length + chunk.length > stop) {
44 - lines[i] = lines[i].replace(/\s+$/, '');
45 -
46 - chunk.split(/\n/).forEach(function (c) {
47 - lines.push(
48 - new Array(start + 1).join(' ')
49 - + c.replace(/^\s+/, '')
50 - );
51 - });
52 - }
53 - else if (chunk.match(/\n/)) {
54 - var xs = chunk.split(/\n/);
55 - lines[i] += xs.shift();
56 - xs.forEach(function (c) {
57 - lines.push(
58 - new Array(start + 1).join(' ')
59 - + c.replace(/^\s+/, '')
60 - );
61 - });
62 - }
63 - else {
64 - lines[i] += chunk;
65 - }
66 -
67 - return lines;
68 - }, [ new Array(start + 1).join(' ') ]).join('\n');
69 - };
70 -};
71 -
72 -wordwrap.soft = wordwrap;
73 -
74 -wordwrap.hard = function (start, stop) {
75 - return wordwrap(start, stop, { mode : 'hard' });
76 -};
1 -{
2 - "_from": "wordwrap@~0.0.2",
3 - "_id": "wordwrap@0.0.3",
4 - "_inBundle": false,
5 - "_integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
6 - "_location": "/wordwrap",
7 - "_phantomChildren": {},
8 - "_requested": {
9 - "type": "range",
10 - "registry": true,
11 - "raw": "wordwrap@~0.0.2",
12 - "name": "wordwrap",
13 - "escapedName": "wordwrap",
14 - "rawSpec": "~0.0.2",
15 - "saveSpec": null,
16 - "fetchSpec": "~0.0.2"
17 - },
18 - "_requiredBy": [
19 - "/optimist"
20 - ],
21 - "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
22 - "_shasum": "a3d5da6cd5c0bc0008d37234bbaf1bed63059107",
23 - "_spec": "wordwrap@~0.0.2",
24 - "_where": "D:\\OneDrive\\University Life\\2018\\2nd semester\\OpenSourceSoftware\\KaKao_ChatBot\\node_modules\\optimist",
25 - "author": {
26 - "name": "James Halliday",
27 - "email": "mail@substack.net",
28 - "url": "http://substack.net"
29 - },
30 - "bugs": {
31 - "url": "https://github.com/substack/node-wordwrap/issues"
32 - },
33 - "bundleDependencies": false,
34 - "deprecated": false,
35 - "description": "Wrap those words. Show them at what columns to start and stop.",
36 - "devDependencies": {
37 - "expresso": "=0.7.x"
38 - },
39 - "directories": {
40 - "lib": ".",
41 - "example": "example",
42 - "test": "test"
43 - },
44 - "engines": {
45 - "node": ">=0.4.0"
46 - },
47 - "homepage": "https://github.com/substack/node-wordwrap#readme",
48 - "keywords": [
49 - "word",
50 - "wrap",
51 - "rule",
52 - "format",
53 - "column"
54 - ],
55 - "license": "MIT",
56 - "main": "./index.js",
57 - "name": "wordwrap",
58 - "repository": {
59 - "type": "git",
60 - "url": "git://github.com/substack/node-wordwrap.git"
61 - },
62 - "scripts": {
63 - "test": "expresso"
64 - },
65 - "version": "0.0.3"
66 -}
1 -var assert = require('assert');
2 -var wordwrap = require('../');
3 -
4 -exports.hard = function () {
5 - var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,'
6 - + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",'
7 - + '"browser":"chrome/6.0"}'
8 - ;
9 - var s_ = wordwrap.hard(80)(s);
10 -
11 - var lines = s_.split('\n');
12 - assert.equal(lines.length, 2);
13 - assert.ok(lines[0].length < 80);
14 - assert.ok(lines[1].length < 80);
15 -
16 - assert.equal(s, s_.replace(/\n/g, ''));
17 -};
18 -
19 -exports.break = function () {
20 - var s = new Array(55+1).join('a');
21 - var s_ = wordwrap.hard(20)(s);
22 -
23 - var lines = s_.split('\n');
24 - assert.equal(lines.length, 3);
25 - assert.ok(lines[0].length === 20);
26 - assert.ok(lines[1].length === 20);
27 - assert.ok(lines[2].length === 15);
28 -
29 - assert.equal(s, s_.replace(/\n/g, ''));
30 -};
1 -In Praise of Idleness
2 -
3 -By Bertrand Russell
4 -
5 -[1932]
6 -
7 -Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain.
8 -
9 -Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise.
10 -
11 -One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling.
12 -
13 -But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person.
14 -
15 -All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work.
16 -
17 -First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising.
18 -
19 -Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example.
20 -
21 -From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery.
22 -
23 -It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization.
24 -
25 -Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry.
26 -
27 -This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined?
28 -
29 -The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion.
30 -
31 -Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only.
32 -
33 -I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve.
34 -
35 -If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense.
36 -
37 -The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists.
38 -
39 -In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism.
40 -
41 -The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching.
42 -
43 -For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours?
44 -
45 -In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man.
46 -
47 -In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed.
48 -
49 -The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy.
50 -
51 -It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer.
52 -
53 -When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part.
54 -
55 -In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism.
56 -
57 -The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits.
58 -
59 -In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue.
60 -
61 -Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever.
62 -
63 -[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests.
1 -var assert = require('assert');
2 -var wordwrap = require('wordwrap');
3 -
4 -var fs = require('fs');
5 -var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8');
6 -
7 -exports.stop80 = function () {
8 - var lines = wordwrap(80)(idleness).split(/\n/);
9 - var words = idleness.split(/\s+/);
10 -
11 - lines.forEach(function (line) {
12 - assert.ok(line.length <= 80, 'line > 80 columns');
13 - var chunks = line.match(/\S/) ? line.split(/\s+/) : [];
14 - assert.deepEqual(chunks, words.splice(0, chunks.length));
15 - });
16 -};
17 -
18 -exports.start20stop60 = function () {
19 - var lines = wordwrap(20, 100)(idleness).split(/\n/);
20 - var words = idleness.split(/\s+/);
21 -
22 - lines.forEach(function (line) {
23 - assert.ok(line.length <= 100, 'line > 100 columns');
24 - var chunks = line
25 - .split(/\s+/)
26 - .filter(function (x) { return x.match(/\S/) })
27 - ;
28 - assert.deepEqual(chunks, words.splice(0, chunks.length));
29 - assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' '));
30 - });
31 -};
...@@ -29,11 +29,6 @@ ...@@ -29,11 +29,6 @@
29 "uri-js": "^4.2.2" 29 "uri-js": "^4.2.2"
30 } 30 }
31 }, 31 },
32 - "amdefine": {
33 - "version": "1.0.1",
34 - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
35 - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
36 - },
37 "array-flatten": { 32 "array-flatten": {
38 "version": "1.1.1", 33 "version": "1.1.1",
39 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 34 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
...@@ -52,11 +47,6 @@ ...@@ -52,11 +47,6 @@
52 "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 47 "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
53 "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 48 "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
54 }, 49 },
55 - "async": {
56 - "version": "0.2.10",
57 - "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz",
58 - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
59 - },
60 "asynckit": { 50 "asynckit": {
61 "version": "0.4.0", 51 "version": "0.4.0",
62 "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 52 "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
...@@ -564,14 +554,6 @@ ...@@ -564,14 +554,6 @@
564 "ee-first": "1.1.1" 554 "ee-first": "1.1.1"
565 } 555 }
566 }, 556 },
567 - "optimist": {
568 - "version": "0.3.7",
569 - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
570 - "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=",
571 - "requires": {
572 - "wordwrap": "~0.0.2"
573 - }
574 - },
575 "parse5": { 557 "parse5": {
576 "version": "3.0.3", 558 "version": "3.0.3",
577 "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", 559 "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
...@@ -672,15 +654,6 @@ ...@@ -672,15 +654,6 @@
672 "uuid": "^3.3.2" 654 "uuid": "^3.3.2"
673 } 655 }
674 }, 656 },
675 - "require": {
676 - "version": "2.4.20",
677 - "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz",
678 - "integrity": "sha1-Zstrqqu2XeinHXk/XGX9GE83mLY=",
679 - "requires": {
680 - "std": "0.1.40",
681 - "uglify-js": "2.3.0"
682 - }
683 - },
684 "safe-buffer": { 657 "safe-buffer": {
685 "version": "5.1.2", 658 "version": "5.1.2",
686 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 659 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
...@@ -727,14 +700,6 @@ ...@@ -727,14 +700,6 @@
727 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 700 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
728 "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 701 "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
729 }, 702 },
730 - "source-map": {
731 - "version": "0.1.43",
732 - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
733 - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
734 - "requires": {
735 - "amdefine": ">=0.0.4"
736 - }
737 - },
738 "sshpk": { 703 "sshpk": {
739 "version": "1.15.2", 704 "version": "1.15.2",
740 "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", 705 "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
...@@ -756,11 +721,6 @@ ...@@ -756,11 +721,6 @@
756 "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 721 "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
757 "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 722 "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
758 }, 723 },
759 - "std": {
760 - "version": "0.1.40",
761 - "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz",
762 - "integrity": "sha1-Nnil9lCU2eG2teJu2/wCErg0K3E="
763 - },
764 "string_decoder": { 724 "string_decoder": {
765 "version": "1.1.1", 725 "version": "1.1.1",
766 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 726 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
...@@ -807,16 +767,6 @@ ...@@ -807,16 +767,6 @@
807 "mime-types": "~2.1.18" 767 "mime-types": "~2.1.18"
808 } 768 }
809 }, 769 },
810 - "uglify-js": {
811 - "version": "2.3.0",
812 - "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz",
813 - "integrity": "sha1-LN7BbTeKiituz7aYl4TPi3rlSR8=",
814 - "requires": {
815 - "async": "~0.2.6",
816 - "optimist": "~0.3.5",
817 - "source-map": "~0.1.7"
818 - }
819 - },
820 "unpipe": { 770 "unpipe": {
821 "version": "1.0.0", 771 "version": "1.0.0",
822 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 772 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
...@@ -859,11 +809,6 @@ ...@@ -859,11 +809,6 @@
859 "core-util-is": "1.0.2", 809 "core-util-is": "1.0.2",
860 "extsprintf": "^1.2.0" 810 "extsprintf": "^1.2.0"
861 } 811 }
862 - },
863 - "wordwrap": {
864 - "version": "0.0.3",
865 - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
866 - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
867 } 812 }
868 } 813 }
869 } 814 }
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
12 "body-parser": "^1.18.3", 12 "body-parser": "^1.18.3",
13 "cheerio": "^1.0.0-rc.2", 13 "cheerio": "^1.0.0-rc.2",
14 "express": "^4.16.4", 14 "express": "^4.16.4",
15 - "request": "^2.88.0", 15 + "request": "^2.88.0"
16 - "require": "^2.4.20"
17 } 16 }
18 } 17 }
......