<commit_before>var async = require('async');
var cheerio = require('cheerio');
var chalk = require('chalk');
var crypto = require('crypto');
var http = require('http');
var process = require('process');
var request = require('request');
var util = require('util');
var telegram = require('telegram-bot-api');

var uriencoder = require('./encoder');
var fixedURIencode = function(uri){
	return uriencoder(encodeURIComponent(uri));
};

var remover = require('./remover');
var config = require('./config/');

var api = new telegram({
	token: config.token,
	updates: {
		enabled: false
	}
});

global.api = api;
global.config = config;
var app = require('./app');

var namuwikiReqIds = [];
var inlineSession = {};
var inlineResults = {};
var lastRequest = 0;
var inlineId = 0;
var searchSelector = 'article.wiki-article section a:not(.page-link)';
var handleMessage = function(from, chatId, message){
	if(message.text.startsWith('/nw')){
		if(attempt(from, chatId)){
			api.sendMessage({
				chat_id: chatId,
				text: "조금 있다가 해보세요!\n(현재 60초에 명령어 " + config.commandAmount + "개로 제한하고 있습니다.)\n나무위키 본관측에 많은 트래픽이 가는 것을 방지하기 위한 조치이니 협조해주시면 감사하겠습니다!"
			}).catch(() => {});
		}

		var url = message.text.replace(/^\/nw(?:@[a-zA-Z0-9]*)?[ ]*/, '');
		if(url === ''){
			api.sendMessage({
				chat_id: chatId,
				text: '사용법: /nw [검색할 무언가]\n혹은 @namuwikiBot [검색할 무언가] 입력 후 기다리기\n\n개발자: @Khinenw\n사용한 이미지: 무냐 by eb\n세피로트 by SMINORFF_KAMCHATKA\n사용된 이미지는 모두 CC-BY-NC-SA 2.0 조건 하에 배포되고 있습니다.'
			}).catch(() => {});
			return;
		}

		getNamuwiki(url, function(err, url, overview){
			if(err){
				if(err === 404){
					request({
						method: 'get',
						headers: {
							'User-Agent': config.userAgent
						},
						url: config.searchUrl + fixedURIencode(url)
					}, (err, response, body) => {
						if(!err && response.statusCode === 200){
							var $ = cheerio.load(body);
							var hrefs = $(searchSelector);
							var results = [];

							Array.apply(null, Array(config.inlineAmount)).map((v, k) => {return k;}).forEach((i) => {
								if(hrefs.length > i){
									var url = decodeURIComponent($(hrefs.get(i)).attr('href').replace('/w/', ''));
									var hash = crypto.createHash('md5').update(url).digest('hex');
									inlineResults[hash] = {
										url: '/nw' + url,
										to: chatId,
										expires: Date.now() + 120 * 1000
									};

									results.push([{
										text: url,
										callback_data: hash
									}]);
								}
							});

							api.sendSticker({
								chat_id: chatId,
								sticker: config.failSticker[Math.floor(Math.random() * config.failSticker.length)],
								reply_markup: JSON.stringify({
									inline_keyboard: results
								})
							}).catch(() => {});
						}
					});
					return;
				}

				if(err === 503){
					api.sendMessage({
						chat_id: chatId,
						text: "현재 Cloudflare DDoS 프로텍션 때문에 문서에 접근이 불가합니다."
					}).catch(() => {});
					//TODO add bypassing sucuri ddos protection
					return;
				}
				return;
			}

			var text = "";
			if(config.useMarkdown){
				text = '**' + url + '**\n' + overview + '\n[자세히보기](' + config.url + fixedURIencode(url) + ')';
			}else{
				text = url + '\n' + overview + '\n' + config.url + fixedURIencode(url);
			}

			if(config.split && text.length > 4000){
				async.eachSeries(text.match(/[^]{1,4000}/g), function(v, cb){
					sendMarkdown(chatId, v, cb);
				});

				return;
			}

			sendMarkdown(chatId, text);
		});
	}
};

api.on('message', function(message){
	var chatId = message.chat.id;
	var from = message.from.id;
	if(typeof message.text !== 'string') return;

	handleMessage(from, chatId, message);
});

api.on('inline.callback.query', (query) => {
	var queryData = inlineResults[queryData]

	if(queryData === undefined){
		api.sendMessage({
			chat_id: from,
			text: '쿼리가 만료되었습니다! /nw@namuwikiBot 명령어를 다시 입력해주세요!'
		}).catch(() => {});
		return;
	}

	handleMessage(query.from, queryData.to, queryData.url);
});

api.on('inline.query', (query) => {
	if(inlineSession[query.from.id] === undefined){
		inlineSession[query.from.id] = [];
	}

	inlineSession[query.from.id] = {
		query: query,
		time: Date.now() + config.querySpeed
	};
});

setInterval(() => {
	async.forEachOfSeries(inlineSession, (v, k, asyncCallback) => {
		if(v.done) return;
		if(Date.now() < v.time) return;

		inlineSession[k].done = true;

		var query = v.query;
		if(attempt(query.from.id)) return;

		request({
			method: 'get',
			headers: {
				'User-Agent': config.userAgent
			},
			url: config.searchUrl + fixedURIencode(query.query)
		}, (err, response, body) => {
			if(!err && response.statusCode === 200){
				var $ = cheerio.load(body);
				var hrefs = $(searchSelector);
				var results = [];

				async.eachSeries(Array.apply(null, Array(config.inlineAmount)).map((v, k) => {return k;}), (i, cb) => {
					if(hrefs.length > i){
						getNamuwiki(decodeURIComponent($(hrefs.get(i)).attr('href').replace('/w/', '')), (err, url, overview) => {
							if(err){
								return;
							}

							results.push({
								type: 'article',
								id: (++inlineId) + '',
								title: url,
								message_text: '**' + url + '**\n' + overview + '\n[자세히보기](' + config.url + fixedURIencode(url) + ')',
								//parse_mode: 'Markdown',
								url: config.url + fixedURIencode(url)
							});
							cb();
						}, 0, true);
					}
				}, () => {
					api.answerInlineQuery({
						inline_query_id: query.id,
						results: results
					}, (err, res) => {
						if(err){
							console.log(chalk.bgRed(util.inspect(err)));
							return;
						}
						asyncCallback();
					});
				});
			}
		});
	});

}, config.queryInterval);

setInterval(() => {
	Object.keys(inlineResults).forEach((k) => {
		if(inlineResults[k].expires < Date.now()){
			inlineResults[k] = undefined;
			delete inlineResults[k];
		}
	});
}, 60000);

function log(logContents, chatId){
	api.sendMessage({
		chat_id: chatId,
		text: "요청을 처리하는 도중 서버측에서 오류가 발생했습니다! :(\n@Khinenw 에게 제보하여주시면 감사하겠습니다!"
	}).catch(() => {});

	console.log(chalk.bgRed("=======Starting error report======="));
	async.forEachOfSeries(logContents, function(v, k, cb){
		console.log(chalk.yellow(k + " : " + v));
		cb();
	}, function(){
		console.log(chalk.bgRed("========End of error report========"));
	});
}

function attempt(from){
	if(namuwikiReqIds[from] !== undefined){
		if(namuwikiReqIds[from].date < Date.now()){
			namuwikiReqIds[from].count = 0;
			namuwikiReqIds[from].date = Date.now() + 60000;
		}

		if(namuwikiReqIds[from].count >= config.commandAmount){
			return true;
		}

		namuwikiReqIds[from].count++;
	}else{
		namuwikiReqIds[from] = {
			count: 0,
			date: Date.now() + 60000
		};
	}

	return false;
}

function sendMarkdown(chatId, v, cb){
	cb = cb || () => {};

	api.sendMessage({
		chat_id: chatId,
		text: v,
		parse_mode: 'Markdown'
	}, function(err, data){
		if(err){
			api.sendMessage({
				chat_id: chatId,
				text: v
			}, (err, data) => {
				if(err){
					log({
						'Time': (new Date()).toUTCString(),
						'Error 1': util.inspect(err)/*,
						'URL': url*/
					}, chatId);
				}

				cb();
			});
			return;
		}

		cb();
	});
}

function getNamuwiki(url, callback, redirectionCount, waited){
	if(!waited && lastRequest + config.requestInterval > Date.now()){
		setTimeout(() => {
			getNamuwiki(url, callback, redirectionCount, true);
		}, config.requestInterval);
		return;
	}

	lastRequest = Date.now();

	if(redirectionCount > config.maxRedirection){
		callback(new Error("Too many redirections!"));
	}

	request({
		method: 'get',
		headers: {
			'User-Agent': config.userAgent
		},
		url: config.rawUrl + fixedURIencode(url)
	}, function(err, response, body){
		if(!err && response.statusCode === 200){
			console.log(chalk.cyan(response.statusCode + ': ' + url));

			if(body.includes('#redirect ')){
				var redirectionTarget = body.match(/^\s*#redirect\s+(.*)\s*$/m);
				if(redirectionTarget && redirectionTarget[1]){
					getNamuwiki(redirectionTarget[1], callback, redirectionCount + 1, true);
					return;
				}
			}

			var split = body.split(/^\s*[=]+ .* [=]+\s*$/gm);
			var overview = "";

			if(split.length <= 1){
				overview = split[0];
			}else{
				overview = split[1];
			}

			async.forEachOfSeries(config.remove, function(v, k, cb){
				remover[k].remove(v, overview, function(returnVal){
					overview = returnVal;
					cb();
				});
			}, function(){
				callback(undefined, url, overview);
			});
		}else{
			if(err){
				console.error(chalk.bgRed(err.toString()));
				callback(500);
				return;
			}
			console.log(chalk.yellow(response.statusCode + ': ' + url));
			callback(response.statusCode);
			return;
		}
	});
}

var port = ((val) => {
	var portNumber = parseInt(val, 10);

	if(isNaN(portNumber)){
		return val;
	}

	if(portNumber >= 0){
		return portNumber;
	}

	return false;
})(process.env.PORT || '443');

var useCert = (process.env.CERT === 'true');

app.set('port', port);

var options;

if(useCert){
	options = {
		key: fs.readFileSync('/cert/key.pem'),
		crt: fs.readFileSync('/cert/crt.pem')
	};
}

if(useCert) var httpServer = http.createServer(options, app);
else var httpServer = http.createServer(app);

httpServer.listen(port);
httpServer.on('error', (err) => {
	if(err.syscall !== 'listen') throw err;
	var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;

	switch(err.code){
		case 'EACCES':
			console.error('Permission Denied!');
			process.exit(1);
			return;

		case 'EADDRINUSE':
			console.error('Address in use!');
			process.exit(1);
			return;
	}

	throw error;
});

httpServer.on('listening', () => {
	var addr = httpServer.address();
	console.log((typeof addr === 'string') ? 'Pipe ' + addr : 'Listening on port ' + addr.port);
});

if(!useCert){
	var _baseurl = 'https://api.telegram.org/bot' + config.token + '/';

	request({
		method: 'POST',
		json: true,
		formData: {
			url: config.hookUrl + config.token
		},
		url: _baseurl + 'setWebhook'
	});
}else api.setWebhook(config.hookUrl + config.token, options.crt);
<commit_msg>Fixed undefined bug<commit_after>var async = require('async');
var cheerio = require('cheerio');
var chalk = require('chalk');
var crypto = require('crypto');
var http = require('http');
var process = require('process');
var request = require('request');
var util = require('util');
var telegram = require('telegram-bot-api');

var uriencoder = require('./encoder');
var fixedURIencode = function(uri){
	return uriencoder(encodeURIComponent(uri));
};

var remover = require('./remover');
var config = require('./config/');

var api = new telegram({
	token: config.token,
	updates: {
		enabled: false
	}
});

global.api = api;
global.config = config;
var app = require('./app');

var namuwikiReqIds = [];
var inlineSession = {};
var inlineResults = [];
var lastRequest = 0;
var inlineId = 0;
var searchSelector = 'article.wiki-article section a:not(.page-link)';
var handleMessage = function(from, chatId, message){
	if(message.text.startsWith('/nw')){
		if(attempt(from, chatId)){
			api.sendMessage({
				chat_id: chatId,
				text: "조금 있다가 해보세요!\n(현재 60초에 명령어 " + config.commandAmount + "개로 제한하고 있습니다.)\n나무위키 본관측에 많은 트래픽이 가는 것을 방지하기 위한 조치이니 협조해주시면 감사하겠습니다!"
			}).catch(() => {});
		}

		var url = message.text.replace(/^\/nw(?:@[a-zA-Z0-9]*)?[ ]*/, '');
		if(url === ''){
			api.sendMessage({
				chat_id: chatId,
				text: '사용법: /nw [검색할 무언가]\n혹은 @namuwikiBot [검색할 무언가] 입력 후 기다리기\n\n개발자: @Khinenw\n사용한 이미지: 무냐 by eb\n세피로트 by SMINORFF_KAMCHATKA\n사용된 이미지는 모두 CC-BY-NC-SA 2.0 조건 하에 배포되고 있습니다.'
			}).catch(() => {});
			return;
		}

		var _url = url;
		getNamuwiki(url, function(err, url, overview){
			if(err){
				if(err === 404){
					request({
						method: 'get',
						headers: {
							'User-Agent': config.userAgent
						},
						url: config.searchUrl + fixedURIencode(_url)
					}, (err, response, body) => {
						if(!err && response.statusCode === 200){
							var $ = cheerio.load(body);
							var hrefs = $(searchSelector);
							var results = [];

							Array.apply(null, Array(config.inlineAmount)).map((v, k) => {return k;}).forEach((i) => {
								if(hrefs.length > i){
									var url = decodeURIComponent($(hrefs.get(i)).attr('href').replace('/w/', ''));
									var hash = crypto.createHash('md5').update(chatId + ':' + url).digest('hex');
									inlineResults[hash] = {
										url: '/nw ' + url,
										to: chatId,
										expires: Date.now() + 120 * 1000
									};

									results.push([{
										text: url,
										callback_data: hash
									}]);
								}
							});

							api.sendSticker({
								chat_id: chatId,
								sticker: config.failSticker[Math.floor(Math.random() * config.failSticker.length)],
								reply_markup: JSON.stringify({
									inline_keyboard: results
								})
							}).catch(() => {});
						}
					});
					return;
				}

				if(err === 503){
					api.sendMessage({
						chat_id: chatId,
						text: "현재 Cloudflare DDoS 프로텍션 때문에 문서에 접근이 불가합니다."
					}).catch(() => {});
					//TODO add bypassing sucuri ddos protection
					return;
				}
				return;
			}

			var text = "";
			if(config.useMarkdown){
				text = '**' + url + '**\n' + overview + '\n[자세히보기](' + config.url + fixedURIencode(url) + ')';
			}else{
				text = url + '\n' + overview + '\n' + config.url + fixedURIencode(url);
			}

			if(config.split && text.length > 4000){
				async.eachSeries(text.match(/[^]{1,4000}/g), function(v, cb){
					sendMarkdown(chatId, v, cb);
				});

				return;
			}

			sendMarkdown(chatId, text);
		});
	}
};

api.on('message', function(message){
	var chatId = message.chat.id;
	var from = message.from.id;
	if(typeof message.text !== 'string') return;

	handleMessage(from, chatId, message);
});

api.on('inline.callback.query', (query) => {
	var queryData = inlineResults[queryData]

	if(queryData === undefined){
		api.sendMessage({
			chat_id: from,
			text: '쿼리가 만료되었습니다! /nw@namuwikiBot 명령어를 다시 입력해주세요!'
		}).catch(() => {});
		return;
	}

	handleMessage(query.from, queryData.to, queryData.url);
});

api.on('inline.query', (query) => {
	if(inlineSession[query.from.id] === undefined){
		inlineSession[query.from.id] = [];
	}

	inlineSession[query.from.id] = {
		query: query,
		time: Date.now() + config.querySpeed
	};
});

setInterval(() => {
	async.forEachOfSeries(inlineSession, (v, k, asyncCallback) => {
		if(v.done) return;
		if(Date.now() < v.time) return;

		inlineSession[k].done = true;

		var query = v.query;
		if(attempt(query.from.id)) return;

		request({
			method: 'get',
			headers: {
				'User-Agent': config.userAgent
			},
			url: config.searchUrl + fixedURIencode(query.query)
		}, (err, response, body) => {
			if(!err && response.statusCode === 200){
				var $ = cheerio.load(body);
				var hrefs = $(searchSelector);
				var results = [];

				async.eachSeries(Array.apply(null, Array(config.inlineAmount)).map((v, k) => {return k;}), (i, cb) => {
					if(hrefs.length > i){
						getNamuwiki(decodeURIComponent($(hrefs.get(i)).attr('href').replace('/w/', '')), (err, url, overview) => {
							if(err){
								return;
							}

							results.push({
								type: 'article',
								id: (++inlineId) + '',
								title: url,
								message_text: '**' + url + '**\n' + overview + '\n[자세히보기](' + config.url + fixedURIencode(url) + ')',
								//parse_mode: 'Markdown',
								url: config.url + fixedURIencode(url)
							});
							cb();
						}, 0, true);
					}
				}, () => {
					api.answerInlineQuery({
						inline_query_id: query.id,
						results: results
					}, (err, res) => {
						if(err){
							console.log(chalk.bgRed(util.inspect(err)));
							return;
						}
						asyncCallback();
					});
				});
			}
		});
	});

}, config.queryInterval);

setInterval(() => {
	Object.keys(inlineResults).forEach((k) => {
		if(inlineResults[k].expires < Date.now()){
			inlineResults[k] = undefined;
			delete inlineResults[k];
		}
	});
}, 60000);

function log(logContents, chatId){
	api.sendMessage({
		chat_id: chatId,
		text: "요청을 처리하는 도중 서버측에서 오류가 발생했습니다! :(\n@Khinenw 에게 제보하여주시면 감사하겠습니다!"
	}).catch(() => {});

	console.log(chalk.bgRed("=======Starting error report======="));
	async.forEachOfSeries(logContents, function(v, k, cb){
		console.log(chalk.yellow(k + " : " + v));
		cb();
	}, function(){
		console.log(chalk.bgRed("========End of error report========"));
	});
}

function attempt(from){
	if(namuwikiReqIds[from] !== undefined){
		if(namuwikiReqIds[from].date < Date.now()){
			namuwikiReqIds[from].count = 0;
			namuwikiReqIds[from].date = Date.now() + 60000;
		}

		if(namuwikiReqIds[from].count >= config.commandAmount){
			return true;
		}

		namuwikiReqIds[from].count++;
	}else{
		namuwikiReqIds[from] = {
			count: 0,
			date: Date.now() + 60000
		};
	}

	return false;
}

function sendMarkdown(chatId, v, cb){
	cb = cb || () => {};

	api.sendMessage({
		chat_id: chatId,
		text: v,
		parse_mode: 'Markdown'
	}, function(err, data){
		if(err){
			api.sendMessage({
				chat_id: chatId,
				text: v
			}, (err, data) => {
				if(err){
					log({
						'Time': (new Date()).toUTCString(),
						'Error 1': util.inspect(err)/*,
						'URL': url*/
					}, chatId);
				}

				cb();
			});
			return;
		}

		cb();
	});
}

function getNamuwiki(url, callback, redirectionCount, waited){
	if(!waited && lastRequest + config.requestInterval > Date.now()){
		setTimeout(() => {
			getNamuwiki(url, callback, redirectionCount, true);
		}, config.requestInterval);
		return;
	}

	lastRequest = Date.now();

	if(redirectionCount > config.maxRedirection){
		callback(new Error("Too many redirections!"));
	}

	request({
		method: 'get',
		headers: {
			'User-Agent': config.userAgent
		},
		url: config.rawUrl + fixedURIencode(url)
	}, function(err, response, body){
		if(!err && response.statusCode === 200){
			console.log(chalk.cyan(response.statusCode + ': ' + url));

			if(body.includes('#redirect ')){
				var redirectionTarget = body.match(/^\s*#redirect\s+(.*)\s*$/m);
				if(redirectionTarget && redirectionTarget[1]){
					getNamuwiki(redirectionTarget[1], callback, redirectionCount + 1, true);
					return;
				}
			}

			var split = body.split(/^\s*[=]+ .* [=]+\s*$/gm);
			var overview = "";

			if(split.length <= 1){
				overview = split[0];
			}else{
				overview = split[1];
			}

			async.forEachOfSeries(config.remove, function(v, k, cb){
				remover[k].remove(v, overview, function(returnVal){
					overview = returnVal;
					cb();
				});
			}, function(){
				callback(undefined, url, overview);
			});
		}else{
			if(err){
				console.error(chalk.bgRed(err.toString()));
				callback(500);
				return;
			}
			console.log(chalk.yellow(response.statusCode + ': ' + url));
			callback(response.statusCode);
			return;
		}
	});
}

var port = ((val) => {
	var portNumber = parseInt(val, 10);

	if(isNaN(portNumber)){
		return val;
	}

	if(portNumber >= 0){
		return portNumber;
	}

	return false;
})(process.env.PORT || '443');

var useCert = (process.env.CERT === 'true');

app.set('port', port);

var options;

if(useCert){
	options = {
		key: fs.readFileSync('/cert/key.pem'),
		crt: fs.readFileSync('/cert/crt.pem')
	};
}

if(useCert) var httpServer = http.createServer(options, app);
else var httpServer = http.createServer(app);

httpServer.listen(port);
httpServer.on('error', (err) => {
	if(err.syscall !== 'listen') throw err;
	var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;

	switch(err.code){
		case 'EACCES':
			console.error('Permission Denied!');
			process.exit(1);
			return;

		case 'EADDRINUSE':
			console.error('Address in use!');
			process.exit(1);
			return;
	}

	throw error;
});

httpServer.on('listening', () => {
	var addr = httpServer.address();
	console.log((typeof addr === 'string') ? 'Pipe ' + addr : 'Listening on port ' + addr.port);
});

if(!useCert){
	var _baseurl = 'https://api.telegram.org/bot' + config.token + '/';

	request({
		method: 'POST',
		json: true,
		formData: {
			url: config.hookUrl + config.token
		},
		url: _baseurl + 'setWebhook'
	});
}else api.setWebhook(config.hookUrl + config.token, options.crt);
<|endoftext|>


<commit_before>var chai = require('chai')
  , expect = require('chai').expect
  , sinon = require('sinon')
  , loadState = require('../../lib/middleware/load')
  , Dispatcher = require('../../lib/manager');

describe('load', function() {

  it('should be named loadState', function() {
    var store = new Object();
    expect(loadState(store).name).to.equal('loadState');
  });

  describe('loading state without state query parameter', function() {
    var store = {
      load: function(){}
    };

    before(function() {
      sinon.stub(store, 'load').yields(null, { name: 'test', x: 1 });
    });

    after(function() {
      store.load.restore();
    });

    var request, err;
    before(function(done) {
      chai.connect.use(loadState(store))
        .req(function(req) {
          request = req;
          req.query = { state: '12345678' };
        })
        .next(function(e) {
          err = e;
          done();
        })
        .dispatch();
    });

    it('should not error', function() {
      expect(err).to.be.undefined;
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        name: 'test',
        x: 1
      });
    });

    it('should not call store#load', function() {
      expect(store.load).to.have.been.calledOnce;
      var call = store.load.getCall(0);
      expect(call.args[0]).to.equal(request);
      expect(call.args[1]).to.equal('12345678');
    });
  });

  describe('loading state without handle', function() {
    var store = {
      load: function(){}
    };

    before(function() {
      sinon.stub(store, 'load').yields(null, undefined);
    });

    after(function() {
      store.load.restore();
    });

    var request, err;
    before(function(done) {
      chai.connect.use(loadState(store))
        .req(function(req) {
          request = req;
        })
        .next(function(e) {
          err = e;
          done();
        })
        .dispatch();
    });

    it('should not error', function() {
      expect(err).to.be.undefined;
    });

    it('should not set state', function() {
      expect(request.state).to.be.undefined;
    });

    it('should not call store#load', function() {
      expect(store.load).to.not.have.been.called;
    });
  });

});
<commit_msg>More tests.<commit_after>var chai = require('chai')
  , expect = require('chai').expect
  , sinon = require('sinon')
  , loadState = require('../../lib/middleware/load')
  , Dispatcher = require('../../lib/manager');

describe('load', function() {

  it('should be named loadState', function() {
    var store = new Object();
    expect(loadState(store).name).to.equal('loadState');
  });

  describe('loading state with state query parameter', function() {
    var store = {
      load: function(){}
    };

    before(function() {
      sinon.stub(store, 'load').yields(null, { name: 'test', x: 1 });
    });

    after(function() {
      store.load.restore();
    });

    var request, err;
    before(function(done) {
      chai.connect.use(loadState(store))
        .req(function(req) {
          request = req;
          req.query = { state: '12345678' };
        })
        .next(function(e) {
          err = e;
          done();
        })
        .dispatch();
    });

    it('should not error', function() {
      expect(err).to.be.undefined;
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        name: 'test',
        x: 1
      });
    });

    it('should call store#load', function() {
      expect(store.load).to.have.been.calledOnce;
      var call = store.load.getCall(0);
      expect(call.args[0]).to.equal(request);
      expect(call.args[1]).to.equal('12345678');
    });
  });

  describe('loading state with state body parameter', function() {
    var store = {
      load: function(){}
    };

    before(function() {
      sinon.stub(store, 'load').yields(null, { name: 'test', x: 1 });
    });

    after(function() {
      store.load.restore();
    });

    var request, err;
    before(function(done) {
      chai.connect.use(loadState(store))
        .req(function(req) {
          request = req;
          req.body = { state: '12345678' };
        })
        .next(function(e) {
          err = e;
          done();
        })
        .dispatch();
    });

    it('should not error', function() {
      expect(err).to.be.undefined;
    });

    it('should set state', function() {
      expect(request.state).to.be.an('object');
      expect(request.state).to.deep.equal({
        name: 'test',
        x: 1
      });
    });

    it('should call store#load', function() {
      expect(store.load).to.have.been.calledOnce;
      var call = store.load.getCall(0);
      expect(call.args[0]).to.equal(request);
      expect(call.args[1]).to.equal('12345678');
    });
  });

  describe('loading state without handle', function() {
    var store = {
      load: function(){}
    };

    before(function() {
      sinon.stub(store, 'load').yields(null, undefined);
    });

    after(function() {
      store.load.restore();
    });

    var request, err;
    before(function(done) {
      chai.connect.use(loadState(store))
        .req(function(req) {
          request = req;
        })
        .next(function(e) {
          err = e;
          done();
        })
        .dispatch();
    });

    it('should not error', function() {
      expect(err).to.be.undefined;
    });

    it('should not set state', function() {
      expect(request.state).to.be.undefined;
    });

    it('should not call store#load', function() {
      expect(store.load).to.not.have.been.called;
    });
  });

});
<|endoftext|>


<commit_before>// /* skale machine learning library */

// 'use strict';

// module.exports = require('./lib/ml.js');

// Copyright 2016 Luca-SAS, licensed under the Apache License 2.0

'use strict';

var thenify = require('thenify');
var Source = require('skale-engine').Source;

var ml = {};
module.exports = ml;

ml.StandardScaler = require('./lib/StandardScaler.js');
ml.BinaryClassificationMetrics = require('./lib/BinaryClassificationMetrics.js');
ml.LogisticRegressionWithSGD = require('./lib/LogisticRegressionWithSGD.js');

ml.randomSVMData = function (sc, N, D, seed, nPartitions) {
	function randomSVMLine(i, a, task) {
		var seed = i * (a.D + 1);
		var data = task.lib.ml.randn2(a.D + 1, seed);
		data[0] = Math.round(Math.abs(data[0])) * 2 - 1;
		return [data.shift(), data];
	}
	return new Source(sc, N, randomSVMLine, {D, seed}, nPartitions);
};

ml.randomSVMLine = function(rng, D) {
	var data = rng.randn(D + 1);
	data[0] = Math.round(Math.abs(data[0])) * 2 - 1;
	return [data.shift(), data];
};

/*
	Linear Models:
		- classification (logistic regression, SVM)
		- regression (least square, Lasso, ridge)
	NB:
		All those models can be trained using a stochastic gradient descent
		using different loss functions (logistic, hinge and squared) and different regularizers (Zero, L1, L2, elastic net)
*/

ml.LinearSVM = function (data, D, N, w) {
	var self = this;
	this.w = w || zeros(D);

	this.train = thenify(function(nIterations, callback) {
		var i = 0;
		iterate();

		function hingeLossGradient(p, args) {
			var grad = [], dot_prod = 0, label = p[0], features = p[1];
			for (var i = 0; i < features.length; i++)
				dot_prod += features[i] * args.weights[i];

			if (label * dot_prod < 1)
				for (var i = 0; i < features.length; i++)
					grad[i] = -label * features[i];
			else
				for (var i = 0; i < features.length; i++)
					grad[i] = 0;

			return grad;
		}

		function sum(a, b) {
			for (var i = 0; i < b.length; i++)
				a[i] += b[i];
			return a;
		}

		function iterate() {
			console.time(i);
			data.map(hingeLossGradient, {weights: self.w}).reduce(sum, zeros(D), function(err, gradient) {
				console.timeEnd(i);
				for (var j = 0; j < self.w.length; j++)
					self.w[j] -= gradient[j] / (N * Math.sqrt(i + 1));
				if (++i == nIterations) callback();
				else iterate();
			});
		}
	});
};

ml.LinearRegression = function (data, D, N, w) {
	var self = this;
	this.w = w || zeros(D);

	this.train = thenify(function(nIterations, callback) {
		var i = 0;
		iterate();

		function squaredLossGradient(p, args) {
			var grad = [], dot_prod = 0, label = p[0], features = p[1];
			for (var i = 0; i < features.length; i++)
				dot_prod += features[i] * args.weights[i];
			for (var i = 0; i < features.length; i++)
				grad[i] = (dot_prod - label) * features[i];
			return grad;
		}

		function sum(a, b) {
			for (var i = 0; i < b.length; i++)
				a[i] += b[i];
			return a;
		}

		function iterate() {
			console.time(i);
			data.map(squaredLossGradient, {weights: self.w}).reduce(sum, zeros(D)).on('data', function(gradient) {
				console.timeEnd(i);
				for (var j = 0; j < self.w.length; j++)
					self.w[j] -= gradient[j] / (N * Math.sqrt(i + 1));
				if (++i == nIterations) callback();
				else iterate();
			});
		}
	});
};

// Decision tree basic unoptimized algorithm
// Begin ID3
// 	Load learning sets first, create decision tree root  node 'rootNode', add learning set S into root node as its subset.
// 	For rootNode, we compute Entropy(rootNode.subset) first
// 	If Entropy(rootNode.subset)==0, then
// 		rootNode.subset consists of records all with the same value for the  categorical attribute,
// 		return a leaf node with decision attribute:attribute value;
// 	If Entropy(rootNode.subset)!=0, then
// 		compute information gain for each attribute left(have not been used in splitting),
// 		find attribute A with Maximum(Gain(S,A)).
// 		Create child nodes of this rootNode and add to rootNode in the decision tree.
// 	For each child of the rootNode, apply
// 		ID3(S,A,V) recursively until reach node that has entropy=0 or reach leaf node.
// End ID3

ml.KMeans = function (data, nClusters, initMeans) {
	var seed = 1;
	var maxMse = 0.0000001;
	this.mse = [];
	this.means = initMeans;

	var D = initMeans ? initMeans[0].length : undefined ;
	var self = this;

	this.closestSpectralNorm = function (element, args) {
		var smallestSn = Infinity;
		var smallestSnIdx = 0;
		for (var i = 0; i < args.means.length; i++) {
			var sn = 0;
			for (var j = 0; j < element.length; j++)
				sn += Math.pow(element[1][j] - args.means[i][j], 2);
			if (sn < smallestSn) {
				smallestSnIdx = i;
				smallestSn = sn;
			}
		}
		return [smallestSnIdx, {data: element[1], sum: 1}];
	};

	this.train = thenify(function(nIterations, callback) {
		var i = 0;

		if (self.means === undefined) {
			console.time(i);
			data.takeSample(false, nClusters, seed, function(err, res) {
				console.timeEnd(i++);
				self.means = res;
				D = self.means[0].length;
				iterate();
			});
		} else iterate();

		function accumulate(a, b) {
			a.sum += b.sum;
			for (var i = 0; i < b.data.length; i++)
				a.data[i] += b.data[i];
			return a;
		}

		function iterate() {
			console.time(i);
			var newMeans = [];
			var res = data.map(self.closestSpectralNorm, {means: self.means})
				.reduceByKey(accumulate, {data: zeros(D), sum: 0})
				.map(function(a) {
					return a[1].data.map(function(e) {return e / a[1].sum;});
				}, [])
				.collect();
			res.on('data', function(data) {
				newMeans.push(data);
			});
			res.on('end',function(){
				console.timeEnd(i);
				var dist = 0;
				for (var k = 0; k < nClusters; k++)
					for (var j = 0; j < self.means[k].length; j++)
						dist += Math.pow(newMeans[k][j] - self.means[k][j], 2);
				self.means = newMeans;
				self.mse.push(dist);
				console.log('mse: ' + dist);
				if ((dist < maxMse) || (++i == nIterations)) callback();
				else iterate();
			});
		}
	});
};

function zeros(N) {
	var w = new Array(N);
	for (var i = 0; i < N; i++)
		w[i] = 0;
	return w;
}

/*
	Random(initSeed)
		Simple seeded random number generator
	Methods:
		- Random.next(): Generates a number x, so as -1 < x < 1
		- Random.reset(): Reset seed to initial seed value
*/
function Random(initSeed) {
	this.seed = initSeed || 1;

	this.next = function () {
	    var x = Math.sin(this.seed++) * 10000;
	    return (x - Math.floor(x)) * 2 - 1;
	};

	this.reset = function () {
		this.seed = initSeed;
	};

	this.randn = function (N) {
		var w = new Array(N);
		for (var i = 0; i < N; i++)
			w[i] = this.next();
		return w;
	};

	this.nextDouble = function () {
		return 0.5 * this.next() + 0.5;			// Must be uniform, not gaussian
	};
}

function rand2(seed) {
	var x = Math.sin(seed) * 10000;
	return (x - Math.floor(x)) * 2 - 1;
}

function randn2(n, seed) {
	var a = new Array(n), i;
	for (i = 0; i < n; i++) a[i] = rand2(seed++);
	return a;
}

function Poisson(lambda, initSeed) {
	this.seed = initSeed || 1;

	var rng = new Random(initSeed);

	this.sample = function () {
		var L = Math.exp(-lambda), k = 0, p = 1;
		do {
			k++;
			p *= rng.nextDouble();
		} while (p > L);
		return k - 1;
	}
}

// Compute a checksum of an arbitrary object
function cksum(o) {
	var i, h = 0, s = o.toString(), len = s.length;
	for (i = 0; i < len; i++) {
		h = ((h << 5) - h) + s.charCodeAt(i);
		h = h & h;	// convert to 32 bit integer
	}
	return Math.abs(h);
}

ml.Random = Random;
ml.Poisson = Poisson;
ml.cksum = cksum;
ml.zeros = zeros;
ml.rand2 = rand2;
ml.randn2 = randn2;
<commit_msg>ml.randomSVMData: remove dependeny on worker side ml<commit_after>// /* skale machine learning library */

// 'use strict';

// module.exports = require('./lib/ml.js');

// Copyright 2016 Luca-SAS, licensed under the Apache License 2.0

'use strict';

var thenify = require('thenify');
var Source = require('skale-engine').Source;

var ml = {};
module.exports = ml;

ml.StandardScaler = require('./lib/StandardScaler.js');
ml.BinaryClassificationMetrics = require('./lib/BinaryClassificationMetrics.js');
ml.LogisticRegressionWithSGD = require('./lib/LogisticRegressionWithSGD.js');

ml.randomSVMData = function (sc, N, D, seed, nPartitions) {
	function randomSVMLine(i, a, task) {
		var seed = i * (a.D + 1);
		var data = randn2(a.D + 1, seed);
		data[0] = Math.round(Math.abs(data[0])) * 2 - 1;
		return [data.shift(), data];

		function rand2(seed) {
			var x = Math.sin(seed) * 10000;
			return (x - Math.floor(x)) * 2 - 1;
		}

		function randn2(n, seed) {
			var a = new Array(n), i;
			for (i = 0; i < n; i++) a[i] = rand2(seed++);
			return a;
		}
	}
	return new Source(sc, N, randomSVMLine, {D, seed}, nPartitions);
};

ml.randomSVMLine = function(rng, D) {
	var data = rng.randn(D + 1);
	data[0] = Math.round(Math.abs(data[0])) * 2 - 1;
	return [data.shift(), data];
};

/*
	Linear Models:
		- classification (logistic regression, SVM)
		- regression (least square, Lasso, ridge)
	NB:
		All those models can be trained using a stochastic gradient descent
		using different loss functions (logistic, hinge and squared) and different regularizers (Zero, L1, L2, elastic net)
*/

ml.LinearSVM = function (data, D, N, w) {
	var self = this;
	this.w = w || zeros(D);

	this.train = thenify(function(nIterations, callback) {
		var i = 0;
		iterate();

		function hingeLossGradient(p, args) {
			var grad = [], dot_prod = 0, label = p[0], features = p[1];
			for (var i = 0; i < features.length; i++)
				dot_prod += features[i] * args.weights[i];

			if (label * dot_prod < 1)
				for (var i = 0; i < features.length; i++)
					grad[i] = -label * features[i];
			else
				for (var i = 0; i < features.length; i++)
					grad[i] = 0;

			return grad;
		}

		function sum(a, b) {
			for (var i = 0; i < b.length; i++)
				a[i] += b[i];
			return a;
		}

		function iterate() {
			console.time(i);
			data.map(hingeLossGradient, {weights: self.w}).reduce(sum, zeros(D), function(err, gradient) {
				console.timeEnd(i);
				for (var j = 0; j < self.w.length; j++)
					self.w[j] -= gradient[j] / (N * Math.sqrt(i + 1));
				if (++i == nIterations) callback();
				else iterate();
			});
		}
	});
};

ml.LinearRegression = function (data, D, N, w) {
	var self = this;
	this.w = w || zeros(D);

	this.train = thenify(function(nIterations, callback) {
		var i = 0;
		iterate();

		function squaredLossGradient(p, args) {
			var grad = [], dot_prod = 0, label = p[0], features = p[1];
			for (var i = 0; i < features.length; i++)
				dot_prod += features[i] * args.weights[i];
			for (var i = 0; i < features.length; i++)
				grad[i] = (dot_prod - label) * features[i];
			return grad;
		}

		function sum(a, b) {
			for (var i = 0; i < b.length; i++)
				a[i] += b[i];
			return a;
		}

		function iterate() {
			console.time(i);
			data.map(squaredLossGradient, {weights: self.w}).reduce(sum, zeros(D)).on('data', function(gradient) {
				console.timeEnd(i);
				for (var j = 0; j < self.w.length; j++)
					self.w[j] -= gradient[j] / (N * Math.sqrt(i + 1));
				if (++i == nIterations) callback();
				else iterate();
			});
		}
	});
};

// Decision tree basic unoptimized algorithm
// Begin ID3
// 	Load learning sets first, create decision tree root  node 'rootNode', add learning set S into root node as its subset.
// 	For rootNode, we compute Entropy(rootNode.subset) first
// 	If Entropy(rootNode.subset)==0, then
// 		rootNode.subset consists of records all with the same value for the  categorical attribute,
// 		return a leaf node with decision attribute:attribute value;
// 	If Entropy(rootNode.subset)!=0, then
// 		compute information gain for each attribute left(have not been used in splitting),
// 		find attribute A with Maximum(Gain(S,A)).
// 		Create child nodes of this rootNode and add to rootNode in the decision tree.
// 	For each child of the rootNode, apply
// 		ID3(S,A,V) recursively until reach node that has entropy=0 or reach leaf node.
// End ID3

ml.KMeans = function (data, nClusters, initMeans) {
	var seed = 1;
	var maxMse = 0.0000001;
	this.mse = [];
	this.means = initMeans;

	var D = initMeans ? initMeans[0].length : undefined ;
	var self = this;

	this.closestSpectralNorm = function (element, args) {
		var smallestSn = Infinity;
		var smallestSnIdx = 0;
		for (var i = 0; i < args.means.length; i++) {
			var sn = 0;
			for (var j = 0; j < element.length; j++)
				sn += Math.pow(element[1][j] - args.means[i][j], 2);
			if (sn < smallestSn) {
				smallestSnIdx = i;
				smallestSn = sn;
			}
		}
		return [smallestSnIdx, {data: element[1], sum: 1}];
	};

	this.train = thenify(function(nIterations, callback) {
		var i = 0;

		if (self.means === undefined) {
			console.time(i);
			data.takeSample(false, nClusters, seed, function(err, res) {
				console.timeEnd(i++);
				self.means = res;
				D = self.means[0].length;
				iterate();
			});
		} else iterate();

		function accumulate(a, b) {
			a.sum += b.sum;
			for (var i = 0; i < b.data.length; i++)
				a.data[i] += b.data[i];
			return a;
		}

		function iterate() {
			console.time(i);
			var newMeans = [];
			var res = data.map(self.closestSpectralNorm, {means: self.means})
				.reduceByKey(accumulate, {data: zeros(D), sum: 0})
				.map(function(a) {
					return a[1].data.map(function(e) {return e / a[1].sum;});
				}, [])
				.collect();
			res.on('data', function(data) {
				newMeans.push(data);
			});
			res.on('end',function(){
				console.timeEnd(i);
				var dist = 0;
				for (var k = 0; k < nClusters; k++)
					for (var j = 0; j < self.means[k].length; j++)
						dist += Math.pow(newMeans[k][j] - self.means[k][j], 2);
				self.means = newMeans;
				self.mse.push(dist);
				console.log('mse: ' + dist);
				if ((dist < maxMse) || (++i == nIterations)) callback();
				else iterate();
			});
		}
	});
};

function zeros(N) {
	var w = new Array(N);
	for (var i = 0; i < N; i++)
		w[i] = 0;
	return w;
}

/*
	Random(initSeed)
		Simple seeded random number generator
	Methods:
		- Random.next(): Generates a number x, so as -1 < x < 1
		- Random.reset(): Reset seed to initial seed value
*/
function Random(initSeed) {
	this.seed = initSeed || 1;

	this.next = function () {
	    var x = Math.sin(this.seed++) * 10000;
	    return (x - Math.floor(x)) * 2 - 1;
	};

	this.reset = function () {
		this.seed = initSeed;
	};

	this.randn = function (N) {
		var w = new Array(N);
		for (var i = 0; i < N; i++)
			w[i] = this.next();
		return w;
	};

	this.nextDouble = function () {
		return 0.5 * this.next() + 0.5;			// Must be uniform, not gaussian
	};
}

function Poisson(lambda, initSeed) {
	this.seed = initSeed || 1;

	var rng = new Random(initSeed);

	this.sample = function () {
		var L = Math.exp(-lambda), k = 0, p = 1;
		do {
			k++;
			p *= rng.nextDouble();
		} while (p > L);
		return k - 1;
	}
}

// Compute a checksum of an arbitrary object
function cksum(o) {
	var i, h = 0, s = o.toString(), len = s.length;
	for (i = 0; i < len; i++) {
		h = ((h << 5) - h) + s.charCodeAt(i);
		h = h & h;	// convert to 32 bit integer
	}
	return Math.abs(h);
}

ml.Random = Random;
ml.Poisson = Poisson;
ml.cksum = cksum;
ml.zeros = zeros;
<|endoftext|>


<commit_before>// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --expose-debug-as debug --expose-gc
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug

Date();
RegExp();

// Count script types.
var named_native_count = 0;
var extension_count = 0;
var normal_count = 0;
var scripts = Debug.scripts();
for (i = 0; i < scripts.length; i++) {
  if (scripts[i].type == Debug.ScriptType.Native) {
    if (scripts[i].name) {
      named_native_count++;
    }
  } else if (scripts[i].type == Debug.ScriptType.Extension) {
    extension_count++;
  } else if (scripts[i].type == Debug.ScriptType.Normal) {
    normal_count++;
  } else {
    assertUnreachable('Unexpected type ' + scripts[i].type);
  }
}

// This has to be updated if the number of native scripts change.
assertEquals(14, named_native_count);
// If no snapshot is used, only the 'gc' extension is loaded.
// If snapshot is used, all extensions are cached in the snapshot.
assertTrue(extension_count == 1 || extension_count == 5);
// This script and mjsunit.js has been loaded.  If using d8, d8 loads
// a normal script during startup too.
assertTrue(normal_count == 2 || normal_count == 3);

// Test a builtins script.
var math_script = Debug.findScript('native math.js');
assertEquals('native math.js', math_script.name);
assertEquals(Debug.ScriptType.Native, math_script.type);

// Test a builtins delay loaded script.
var date_delay_script = Debug.findScript('native date.js');
assertEquals('native date.js', date_delay_script.name);
assertEquals(Debug.ScriptType.Native, date_delay_script.type);

// Test a debugger script.
var debug_delay_script = Debug.findScript('native debug.js');
assertEquals('native debug.js', debug_delay_script.name);
assertEquals(Debug.ScriptType.Native, debug_delay_script.type);

// Test an extension script.
var extension_gc_script = Debug.findScript('v8/gc');
if (extension_gc_script) {
  assertEquals('v8/gc', extension_gc_script.name);
  assertEquals(Debug.ScriptType.Extension, extension_gc_script.type);
}

// Test a normal script.
var mjsunit_js_script = Debug.findScript(/mjsunit.js/);
assertTrue(/mjsunit.js/.test(mjsunit_js_script.name));
assertEquals(Debug.ScriptType.Normal, mjsunit_js_script.type);

// Check a nonexistent script.
var dummy_script = Debug.findScript('dummy.js');
assertTrue(typeof dummy_script == 'undefined');
<commit_msg>Only count uniquely named native scripts for debug.<commit_after>// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --expose-debug-as debug --expose-gc
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug

Date();
RegExp();

// Count script types.
var named_native_count = 0;
var named_native_names = {};
var extension_count = 0;
var normal_count = 0;
var scripts = Debug.scripts();
for (i = 0; i < scripts.length; i++) {
  if (scripts[i].type == Debug.ScriptType.Native) {
    if (scripts[i].name) {
      // TODO(1641): Remove check for equally named native scripts once the
      // underlying issue is fixed.
      if (!named_native_names[scripts[i].name]) {
        named_native_names[scripts[i].name] = true;
        named_native_count++;
      }
    }
  } else if (scripts[i].type == Debug.ScriptType.Extension) {
    extension_count++;
  } else if (scripts[i].type == Debug.ScriptType.Normal) {
    normal_count++;
  } else {
    assertUnreachable('Unexpected type ' + scripts[i].type);
  }
}

// This has to be updated if the number of native scripts change.
assertEquals(14, named_native_count);
// If no snapshot is used, only the 'gc' extension is loaded.
// If snapshot is used, all extensions are cached in the snapshot.
assertTrue(extension_count == 1 || extension_count == 5);
// This script and mjsunit.js has been loaded.  If using d8, d8 loads
// a normal script during startup too.
assertTrue(normal_count == 2 || normal_count == 3);

// Test a builtins script.
var math_script = Debug.findScript('native math.js');
assertEquals('native math.js', math_script.name);
assertEquals(Debug.ScriptType.Native, math_script.type);

// Test a builtins delay loaded script.
var date_delay_script = Debug.findScript('native date.js');
assertEquals('native date.js', date_delay_script.name);
assertEquals(Debug.ScriptType.Native, date_delay_script.type);

// Test a debugger script.
var debug_delay_script = Debug.findScript('native debug.js');
assertEquals('native debug.js', debug_delay_script.name);
assertEquals(Debug.ScriptType.Native, debug_delay_script.type);

// Test an extension script.
var extension_gc_script = Debug.findScript('v8/gc');
if (extension_gc_script) {
  assertEquals('v8/gc', extension_gc_script.name);
  assertEquals(Debug.ScriptType.Extension, extension_gc_script.type);
}

// Test a normal script.
var mjsunit_js_script = Debug.findScript(/mjsunit.js/);
assertTrue(/mjsunit.js/.test(mjsunit_js_script.name));
assertEquals(Debug.ScriptType.Normal, mjsunit_js_script.type);

// Check a nonexistent script.
var dummy_script = Debug.findScript('dummy.js');
assertTrue(typeof dummy_script == 'undefined');
<|endoftext|>


<commit_before>var fs       = require('fs');
var path     = require('path');
var chalk    = require('chalk');
var findup   = require('findup-sync');
var mkdirp   = require('mkdirp');
var JSHINT   = require('jshint').JSHINT;
var Filter   = require('broccoli-persistent-filter');
var crypto   = require('crypto');

var stringify = require('json-stable-stringify');

JSHinter.prototype = Object.create(Filter.prototype);
JSHinter.prototype.constructor = JSHinter;
function JSHinter (inputNode, options) {
  if (!(this instanceof JSHinter)) return new JSHinter(inputNode, options);

  this.options = options = options || {};

  Filter.call(this, inputNode, {
    annotation: options.annotation,
    persist: true
  });
  this.log       = true;
  this.console = console;

  for (var key in options) {
    if (options.hasOwnProperty(key)) {
      this[key] = options[key]
    }
  }
};

JSHinter.prototype.extensions = ['js'];
JSHinter.prototype.targetExtension = 'jshint.js';

JSHinter.prototype.baseDir = function() {
  return __dirname;
};

JSHinter.prototype.build = function () {
  var self = this
  self._errors = [];

  if (!self.jshintrc) {
    var jshintPath = self.jshintrcPath || path.join(this.inputPaths[0], self.jshintrcRoot || '');
    self.jshintrc = self.getConfig(jshintPath);
  }

  return Filter.prototype.build.call(this)
  .finally(function() {
    if (self._errors.length > 0) {
      var label = ' JSHint Error' + (self._errors.length > 1 ? 's' : '')
      self.console.log('\n' + self._errors.join('\n'));
      self.console.log(chalk.yellow('===== ' + self._errors.length + label + '\n'));
    }
  })
}

JSHinter.prototype.processString = function (content, relativePath) {
  var passed = JSHINT(content, this.jshintrc);
  var errors = this.processErrors(relativePath, JSHINT.errors),
      generalError;

  if (this.failOnAnyError && errors.length > 0){
    generalError = new Error('JSHint failed');
    generalError.jshintErrors = errors;
    throw generalError;
  }
  if (!passed && this.log) {
    this.logError(errors);
  }

  if (!this.disableTestGenerator) {
    return this.testGenerator(relativePath, passed, errors);
  }
};

JSHinter.prototype.processErrors = function (file, errors) {
  if (!errors) { return ''; }

  var len = errors.length,
  str = '',
  error, idx;

  if (len === 0) { return ''; }

  for (idx=0; idx<len; idx++) {
    error = errors[idx];
    if (error !== null) {
      str += file  + ': line ' + error.line + ', col ' +
        error.character + ', ' + error.reason + '\n';
    }
  }

  return str + "\n" + len + ' error' + ((len === 1) ? '' : 's');
}

JSHinter.prototype.testGenerator = function(relativePath, passed, errors) {
  if (errors) {
    errors = "\\n" + this.escapeErrorString(errors);
  } else {
    errors = ""
  }

  return "QUnit.module('JSHint - " + path.dirname(relativePath) + "');\n" +
         "QUnit.test('" + relativePath + " should pass jshint', function(assert) { \n" +
         "  assert.ok(" + !!passed + ", '" + relativePath + " should pass jshint." + errors + "'); \n" +
         "});\n"
};

JSHinter.prototype.logError = function(message, color) {
  color = color || 'red';

  this._errors.push(chalk[color](message) + "\n");
};

JSHinter.prototype.getConfig = function(rootPath) {
  if (!rootPath) { rootPath = process.cwd(); }

  var jshintrcPath = findup('.jshintrc', {cwd: rootPath, nocase: true});

  if (jshintrcPath) {
    var config = fs.readFileSync(jshintrcPath, {encoding: 'utf8'});

    try {
      return JSON.parse(this.stripComments(config));
    } catch (e) {
      this.console.error(chalk.red('Error occured parsing .jshintrc.'));
      this.console.error(e.stack);

      return null;
    }
  }
};

JSHinter.prototype.stripComments = function(string) {
  string = string || "";

  string = string.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, "");
  string = string.replace(/\/\/[^\n\r]*/g, ""); // Everything after '//'

  return string;
};

JSHinter.prototype.escapeErrorString = function(string) {
  string = string.replace(/\n/gi, "\\n");
  string = string.replace(/'/gi, "\\'");

  return string;
};

JSHinter.prototype.optionsHash  = function() {
  if (!this._optionsHash) {
    this._optionsHash = crypto.createHash('md5')
      .update(stringify(this.options), 'utf8')
      .update(stringify(this.jshintrc) || '', 'utf8')
      .digest('hex');
  }

  return this._optionsHash;
};

JSHinter.prototype.cacheKeyProcessString = function(string, relativePath) {
  return this.optionsHash() + Filter.prototype.cacheKeyProcessString.call(this, string, relativePath);
};

module.exports = JSHinter;
<commit_msg>Add `testGenerator` and `logError` to optionsHash calculations.<commit_after>var fs       = require('fs');
var path     = require('path');
var chalk    = require('chalk');
var findup   = require('findup-sync');
var mkdirp   = require('mkdirp');
var JSHINT   = require('jshint').JSHINT;
var Filter   = require('broccoli-persistent-filter');
var crypto   = require('crypto');

var stringify = require('json-stable-stringify');

JSHinter.prototype = Object.create(Filter.prototype);
JSHinter.prototype.constructor = JSHinter;
function JSHinter (inputNode, options) {
  if (!(this instanceof JSHinter)) return new JSHinter(inputNode, options);

  options = options || {};

  Filter.call(this, inputNode, {
    annotation: options.annotation,
    persist: true
  });
  this.log     = true;
  this.options = options;
  this.console = console;

  for (var key in options) {
    if (options.hasOwnProperty(key)) {
      this[key] = options[key]
    }
  }
};

JSHinter.prototype.extensions = ['js'];
JSHinter.prototype.targetExtension = 'jshint.js';

JSHinter.prototype.baseDir = function() {
  return __dirname;
};

JSHinter.prototype.build = function () {
  var self = this
  self._errors = [];

  if (!self.jshintrc) {
    var jshintPath = self.jshintrcPath || path.join(this.inputPaths[0], self.jshintrcRoot || '');
    self.jshintrc = self.getConfig(jshintPath);
  }

  return Filter.prototype.build.call(this)
  .finally(function() {
    if (self._errors.length > 0) {
      var label = ' JSHint Error' + (self._errors.length > 1 ? 's' : '')
      self.console.log('\n' + self._errors.join('\n'));
      self.console.log(chalk.yellow('===== ' + self._errors.length + label + '\n'));
    }
  })
}

JSHinter.prototype.processString = function (content, relativePath) {
  var passed = JSHINT(content, this.jshintrc);
  var errors = this.processErrors(relativePath, JSHINT.errors),
      generalError;

  if (this.failOnAnyError && errors.length > 0){
    generalError = new Error('JSHint failed');
    generalError.jshintErrors = errors;
    throw generalError;
  }
  if (!passed && this.log) {
    this.logError(errors);
  }

  if (!this.disableTestGenerator) {
    return this.testGenerator(relativePath, passed, errors);
  }
};

JSHinter.prototype.processErrors = function (file, errors) {
  if (!errors) { return ''; }

  var len = errors.length,
  str = '',
  error, idx;

  if (len === 0) { return ''; }

  for (idx=0; idx<len; idx++) {
    error = errors[idx];
    if (error !== null) {
      str += file  + ': line ' + error.line + ', col ' +
        error.character + ', ' + error.reason + '\n';
    }
  }

  return str + "\n" + len + ' error' + ((len === 1) ? '' : 's');
}

JSHinter.prototype.testGenerator = function(relativePath, passed, errors) {
  if (errors) {
    errors = "\\n" + this.escapeErrorString(errors);
  } else {
    errors = ""
  }

  return "QUnit.module('JSHint - " + path.dirname(relativePath) + "');\n" +
         "QUnit.test('" + relativePath + " should pass jshint', function(assert) { \n" +
         "  assert.ok(" + !!passed + ", '" + relativePath + " should pass jshint." + errors + "'); \n" +
         "});\n"
};

JSHinter.prototype.logError = function(message, color) {
  color = color || 'red';

  this._errors.push(chalk[color](message) + "\n");
};

JSHinter.prototype.getConfig = function(rootPath) {
  if (!rootPath) { rootPath = process.cwd(); }

  var jshintrcPath = findup('.jshintrc', {cwd: rootPath, nocase: true});

  if (jshintrcPath) {
    var config = fs.readFileSync(jshintrcPath, {encoding: 'utf8'});

    try {
      return JSON.parse(this.stripComments(config));
    } catch (e) {
      this.console.error(chalk.red('Error occured parsing .jshintrc.'));
      this.console.error(e.stack);

      return null;
    }
  }
};

JSHinter.prototype.stripComments = function(string) {
  string = string || "";

  string = string.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, "");
  string = string.replace(/\/\/[^\n\r]*/g, ""); // Everything after '//'

  return string;
};

JSHinter.prototype.escapeErrorString = function(string) {
  string = string.replace(/\n/gi, "\\n");
  string = string.replace(/'/gi, "\\'");

  return string;
};

JSHinter.prototype.optionsHash  = function() {
  if (!this._optionsHash) {
    this._optionsHash = crypto.createHash('md5')
      .update(stringify(this.options), 'utf8')
      .update(stringify(this.jshintrc) || '', 'utf8')
      .update(this.testGenerator.toString(), 'utf8')
      .update(this.logError.toString(), 'utf8')
      .digest('hex');
  }

  return this._optionsHash;
};

JSHinter.prototype.cacheKeyProcessString = function(string, relativePath) {
  return this.optionsHash() + Filter.prototype.cacheKeyProcessString.call(this, string, relativePath);
};

module.exports = JSHinter;
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import formatDistance from 'date-fns/formatDistance';
import format from 'date-fns/format';
import findPost from '../lib/findPost';
import Button from './Button';
import webp from '../lib/webp';

const PostDate = ({ date }) => {
  const relative =
    formatDistance(Date.now(), date) === 'about 1 month'
      ? 'last month'
      : `${formatDistance(Date.now(), date)} ago`;
  return (
    <h2 title={`Posted ${format(date, 'MMMM D, YYYY')}`}>
      Posted {relative}

  );
};

PostDate.propTypes = {
  date: PropTypes.number.isRequired,
};

const Header = props => {
  const post = findPost(props.id);
  const { title, date, image: { imageUrl } } = post;
  return (

{props.title || title}

        {!props.link && date && <PostDate date={date} />}
        {props.link && <Button text="Read More" link={props.id} />}

  );
};

Header.defaultProps = {
  link: null,
  id: null,
  title: null,
};

Header.propTypes = {
  title: PropTypes.string,
  link: PropTypes.string,
  id: PropTypes.string,
};

export default Header;
<commit_msg>make bg a little more easier to read<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import formatDistance from 'date-fns/formatDistance';
import format from 'date-fns/format';
import findPost from '../lib/findPost';
import Button from './Button';
import webp from '../lib/webp';

const PostDate = ({ date }) => {
  const relative =
    formatDistance(Date.now(), date) === 'about 1 month'
      ? 'last month'
      : `${formatDistance(Date.now(), date)} ago`;
  return (
    <h2 title={`Posted ${format(date, 'MMMM D, YYYY')}`}>
      Posted {relative}

  );
};

PostDate.propTypes = {
  date: PropTypes.number.isRequired,
};

const Header = props => {
  const post = findPost(props.id);
  const { title, date, image: { imageUrl } } = post;
  const fallbackbg = imageUrl
    ? `url(/static/images/posts/${imageUrl})`
    : 'url(/static/images/posts/brevite-434280.jpg)';

  const webpbg = imageUrl
    ? `url(/static/images/posts/${webp(imageUrl).url})`
    : 'url(/static/images/posts/brevite-434280.webp)';

  const background = `${webpbg}, ${fallbackbg}`;
  return (

{props.title || title}

        {!props.link && date && <PostDate date={date} />}
        {props.link && <Button text="Read More" link={props.id} />}

  );
};

Header.defaultProps = {
  link: null,
  id: null,
  title: null,
};

Header.propTypes = {
  title: PropTypes.string,
  link: PropTypes.string,
  id: PropTypes.string,
};

export default Header;
<|endoftext|>


<commit_before>var path = require('path');
var dust = require('dustjs-linkedin');
var assign = require('object-assign');
var loaderUtils = require('loader-utils');
var fs = require('fs');

// Create a default function for naming the template based on the path
function defaultNamingFunction( template_path, options, content ) {
	return template_path
			.replace( '.dust', '' )					 // remove .dust file extension
			.split( path.sep ).join( '/' );	 // split at path separator and replace with a forward slash
}

// Create a wrapper function for calling dust.render
function defaultWrapperGenerator( name ) {
  return "function( context, callback ) { dust.render( '" + name + "', context, callback ); }"
}

// Export actual loader method
module.exports = function( content ) {
  if (this.cacheable) { this.cacheable(); }

  // Set up default options & override them with other options
  var default_options = {
	 root: '',
   dustAlias: 'dustjs',
	 namingFn: defaultNamingFunction,
   wrapperGenerator: defaultWrapperGenerator
  };
  var global_options = this.options['dust-loader-complete'];
  var loader_options = loaderUtils.parseQuery(this.query);
  var options = assign({}, default_options, global_options, loader_options);

  // Fix slashes & resolve root
  options.root = path.resolve( options.root.replace( '/', path.sep ) );

  // Get the path
  var template_path = this.resourcePath.replace( options.root + path.sep, '' );

  // Create the template name
  var name = options.namingFn( template_path, options, content );

  // Compile the template
  var template = dust.compile( content, name );

  // Find any referenced templates & add them to a list of dependencies
  var reg = /{>\s?"?([\w\.\/\-_]+)"?.*\/}/g,
  	result = null,
	  deps = [];

  while ( (result = reg.exec( content ) ) !== null ) {
	  deps.push( "var partial" + deps.length + " = require('" + result[1] + "');" );
  }

  //a regex to see if there are any {! require("DUST_FILE") !} comments to also require
  var require_reg = /{! require\("([\w\.\/\-_\|[\]]+)\"\) !}/g;

  //a regex to check if there are any brackets in the require statment like patterns/atoms/[button|button_link]
  var bracket_reg = /\[([^\]]*)\]/g;

  //variables to hold the results from the require regex and the bracket regex
  var require_result, bracket_result;

  //if there is a require comment, parse it out even further
  while ( (require_result = require_reg.exec( content ) ) !== null ) {
    //this will check if there are any comments that have a | delimited list of files, such as {! require("patterns/atoms/[button|button_link]") !}
    bracket_result = bracket_reg.exec(require_result[1]);

    //if there is a require_result, split the files by | and include them all
    if(bracket_result) {
      var parts = bracket_result[1].split("|");
      for(var i = 0; i < parts.length; i++) {
        var output = require_result[1].replace(bracket_reg, parts[i]);
        deps.push( "var partial" + deps.length + " = require('" + output + "');" );
      }
    }
    //if there isn't a require_result, assume it was just a normal require like {! require("patterns/atoms/button") !}
    else {
      deps.push( "var partial" + deps.length + " = require('" + require_result[1] + "');" );
    }
  }

  // Return the code needed to run this template
  return "var dust = require('" + options.dustAlias + "/lib/dust'); "
  		 + deps.join( ' ' )
         + template
         + "module.exports = " + options.wrapperGenerator( name );
};
<commit_msg>Changing the first regex so that it doesn't include things like {>"patterns/atoms/{variable}"/}<commit_after>var path = require('path');
var dust = require('dustjs-linkedin');
var assign = require('object-assign');
var loaderUtils = require('loader-utils');
var fs = require('fs');

// Create a default function for naming the template based on the path
function defaultNamingFunction( template_path, options, content ) {
	return template_path
			.replace( '.dust', '' )					 // remove .dust file extension
			.split( path.sep ).join( '/' );	 // split at path separator and replace with a forward slash
}

// Create a wrapper function for calling dust.render
function defaultWrapperGenerator( name ) {
  return "function( context, callback ) { dust.render( '" + name + "', context, callback ); }"
}

// Export actual loader method
module.exports = function( content ) {
  if (this.cacheable) { this.cacheable(); }

  // Set up default options & override them with other options
  var default_options = {
	 root: '',
   dustAlias: 'dustjs',
	 namingFn: defaultNamingFunction,
   wrapperGenerator: defaultWrapperGenerator
  };
  var global_options = this.options['dust-loader-complete'];
  var loader_options = loaderUtils.parseQuery(this.query);
  var options = assign({}, default_options, global_options, loader_options);

  // Fix slashes & resolve root
  options.root = path.resolve( options.root.replace( '/', path.sep ) );

  // Get the path
  var template_path = this.resourcePath.replace( options.root + path.sep, '' );

  // Create the template name
  var name = options.namingFn( template_path, options, content );

  // Compile the template
  var template = dust.compile( content, name );

  // Find any referenced templates & add them to a list of dependencies
  var reg = /{>\s?"?([\w\.\/\-_]+)"?( .*\/}|\/})/g,
  	result = null,
	  deps = [];

  while ( (result = reg.exec( content ) ) !== null ) {
	  deps.push( "var partial" + deps.length + " = require('" + result[1] + "');" );
  }

  //a regex to see if there are any {! require("DUST_FILE") !} comments to also require
  var require_reg = /{! require\("([\w\.\/\-_\|[\]]+)\"\) !}/g;

  //a regex to check if there are any brackets in the require statment like patterns/atoms/[button|button_link]
  var bracket_reg = /\[([^\]]*)\]/g;

  //variables to hold the results from the require regex and the bracket regex
  var require_result, bracket_result;

  //if there is a require comment, parse it out even further
  while ( (require_result = require_reg.exec( content ) ) !== null ) {
    //this will check if there are any comments that have a | delimited list of files, such as {! require("patterns/atoms/[button|button_link]") !}
    bracket_result = bracket_reg.exec(require_result[1]);

    //if there is a require_result, split the files by | and include them all
    if(bracket_result) {
      var parts = bracket_result[1].split("|");
      for(var i = 0; i < parts.length; i++) {
        var output = require_result[1].replace(bracket_reg, parts[i]);
        deps.push( "var partial" + deps.length + " = require('" + output + "');" );
      }
    }
    //if there isn't a require_result, assume it was just a normal require like {! require("patterns/atoms/button") !}
    else {
      deps.push( "var partial" + deps.length + " = require('" + require_result[1] + "');" );
    }
  }

  // Return the code needed to run this template
  return "var dust = require('" + options.dustAlias + "/lib/dust'); "
  		 + deps.join( ' ' )
         + template
         + "module.exports = " + options.wrapperGenerator( name );
};
<|endoftext|>


<commit_before>import Head from 'next/head'
import Link from 'next/link'
import ActiveLink from './ActiveLink'

const Layout = (props) => (

      <title key="title">{process.env.NEXT_PUBLIC_NAME}</title>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="theme-color" content="#000000" />
      <link rel="icon" href="/favicon.ico" />
      <link rel="apple-touch-icon" href="/logo192.png" />
      <link rel="manifest" href="/manifest.json" />
      <meta name="twitter:site" content="@sonu27" />
      <meta name="twitter:creator" content="@sonu27" />

{props.children}

)

const Header = () => (

      <Link href="/">
        Sonu Rai
      </Link>

        <ActiveLink href="/">
          Home
        </ActiveLink>
        <ActiveLink href="/about">
          About
        </ActiveLink>
        <ActiveLink href="/contact">
          Contact
        </ActiveLink>

)

const Footer = () => (

© 2013-{new Date().getFullYear()} Amarjeet Rai

)

export default Layout
<commit_msg>Change import<commit_after>import Head from 'next/head'
import Link from 'next/link'
import ActiveLink from 'components/ActiveLink'

const Layout = (props) => (

      <title key="title">{process.env.NEXT_PUBLIC_NAME}</title>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="theme-color" content="#000000" />
      <link rel="icon" href="/favicon.ico" />
      <link rel="apple-touch-icon" href="/logo192.png" />
      <link rel="manifest" href="/manifest.json" />
      <meta name="twitter:site" content="@sonu27" />
      <meta name="twitter:creator" content="@sonu27" />

{props.children}

)

const Header = () => (

      <Link href="/">
        Sonu Rai
      </Link>

        <ActiveLink href="/">
          Home
        </ActiveLink>
        <ActiveLink href="/about">
          About
        </ActiveLink>
        <ActiveLink href="/contact">
          Contact
        </ActiveLink>

)

const Footer = () => (

© 2013-{new Date().getFullYear()} Amarjeet Rai

)

export default Layout
<|endoftext|>


<commit_before>var indexOf = function (xs, item) {
    if (xs.indexOf) return xs.indexOf(item);
    else for (var i = 0; i < xs.length; i++) {
        if (xs[i] === item) return i;
    }
    return -1;
};
var Object_keys = function (obj) {
    if (Object.keys) return Object.keys(obj)
    else {
        var res = [];
        for (var key in obj) res.push(key)
        return res;
    }
};

var forEach = function (xs, fn) {
    if (xs.forEach) return xs.forEach(fn)
    else for (var i = 0; i < xs.length; i++) {
        fn(xs[i], i, xs);
    }
};

var defineProp = (function() {
    try {
        Object.defineProperty({}, '_', {});
        return function(obj, name, value) {
            Object.defineProperty(obj, name, {
                writable: true,
                enumerable: false,
                configurable: true,
                value: value
            })
        };
    } catch(e) {
        return function(obj, name, value) {
            obj[name] = value;
        };
    }
}());

var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'];

function Context() {}
Context.prototype = {};

var Script = exports.Script = function NodeScript (code) {
    if (!(this instanceof Script)) return new Script(code);
    this.code = code;
};

Script.prototype.runInContext = function (context) {
    if (!(context instanceof Context)) {
        throw new TypeError("needs a 'context' argument.");
    }

    var iframe = document.createElement('iframe');
    if (!iframe.style) iframe.style = {};
    iframe.style.display = 'none';

    document.body.appendChild(iframe);

    var win = iframe.contentWindow;
    var wEval = win.eval, wExecScript = win.execScript;

    if (!wEval && wExecScript) {
        // win.eval() magically appears when this is called in IE:
        wExecScript.call(win, 'null');
        wEval = win.eval;
    }

    forEach(Object_keys(context), function (key) {
        win[key] = context[key];
    });
    forEach(globals, function (key) {
        if (context[key]) {
            win[key] = context[key];
        }
    });

    var winKeys = Object_keys(win);

    var res = wEval.call(win, this.code);

    forEach(Object_keys(win), function (key) {
        // Avoid copying circular objects like `top` and `window` by only
        // updating existing context properties or new properties in the `win`
        // that was only introduced after the eval.
        if (key in context || indexOf(winKeys, key) === -1) {
            context[key] = win[key];
        }
    });

    forEach(globals, function (key) {
        if (!(key in context)) {
            defineProp(context, key, win[key]);
        }
    });

    document.body.removeChild(iframe);

    return res;
};

Script.prototype.runInThisContext = function () {
    return eval(this.code); // maybe...
};

Script.prototype.runInNewContext = function (context) {
    var ctx = Script.createContext(context);
    var res = this.runInContext(ctx);

    if (context) {
        forEach(Object_keys(ctx), function (key) {
            context[key] = ctx[key];
        });
    }

    return res;
};

forEach(Object_keys(Script.prototype), function (name) {
    exports[name] = Script[name] = function (code) {
        var s = Script(code);
        return s[name].apply(s, [].slice.call(arguments, 1));
    };
});

exports.createScript = function (code) {
    return exports.Script(code);
};

exports.createContext = Script.createContext = function (context) {
    var copy = new Context();
    if(typeof context === 'object') {
        forEach(Object_keys(context), function (key) {
            copy[key] = context[key];
        });
    }
    return copy;
};
<commit_msg>Add `.isContext()`.<commit_after>var indexOf = function (xs, item) {
    if (xs.indexOf) return xs.indexOf(item);
    else for (var i = 0; i < xs.length; i++) {
        if (xs[i] === item) return i;
    }
    return -1;
};
var Object_keys = function (obj) {
    if (Object.keys) return Object.keys(obj)
    else {
        var res = [];
        for (var key in obj) res.push(key)
        return res;
    }
};

var forEach = function (xs, fn) {
    if (xs.forEach) return xs.forEach(fn)
    else for (var i = 0; i < xs.length; i++) {
        fn(xs[i], i, xs);
    }
};

var defineProp = (function() {
    try {
        Object.defineProperty({}, '_', {});
        return function(obj, name, value) {
            Object.defineProperty(obj, name, {
                writable: true,
                enumerable: false,
                configurable: true,
                value: value
            })
        };
    } catch(e) {
        return function(obj, name, value) {
            obj[name] = value;
        };
    }
}());

var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'];

function Context() {}
Context.prototype = {};

var Script = exports.Script = function NodeScript (code) {
    if (!(this instanceof Script)) return new Script(code);
    this.code = code;
};

Script.prototype.runInContext = function (context) {
    if (!(context instanceof Context)) {
        throw new TypeError("needs a 'context' argument.");
    }

    var iframe = document.createElement('iframe');
    if (!iframe.style) iframe.style = {};
    iframe.style.display = 'none';

    document.body.appendChild(iframe);

    var win = iframe.contentWindow;
    var wEval = win.eval, wExecScript = win.execScript;

    if (!wEval && wExecScript) {
        // win.eval() magically appears when this is called in IE:
        wExecScript.call(win, 'null');
        wEval = win.eval;
    }

    forEach(Object_keys(context), function (key) {
        win[key] = context[key];
    });
    forEach(globals, function (key) {
        if (context[key]) {
            win[key] = context[key];
        }
    });

    var winKeys = Object_keys(win);

    var res = wEval.call(win, this.code);

    forEach(Object_keys(win), function (key) {
        // Avoid copying circular objects like `top` and `window` by only
        // updating existing context properties or new properties in the `win`
        // that was only introduced after the eval.
        if (key in context || indexOf(winKeys, key) === -1) {
            context[key] = win[key];
        }
    });

    forEach(globals, function (key) {
        if (!(key in context)) {
            defineProp(context, key, win[key]);
        }
    });

    document.body.removeChild(iframe);

    return res;
};

Script.prototype.runInThisContext = function () {
    return eval(this.code); // maybe...
};

Script.prototype.runInNewContext = function (context) {
    var ctx = Script.createContext(context);
    var res = this.runInContext(ctx);

    if (context) {
        forEach(Object_keys(ctx), function (key) {
            context[key] = ctx[key];
        });
    }

    return res;
};

forEach(Object_keys(Script.prototype), function (name) {
    exports[name] = Script[name] = function (code) {
        var s = Script(code);
        return s[name].apply(s, [].slice.call(arguments, 1));
    };
});

exports.isContext = function (context) {
    return context instanceof Context;
};

exports.createScript = function (code) {
    return exports.Script(code);
};

exports.createContext = Script.createContext = function (context) {
    var copy = new Context();
    if(typeof context === 'object') {
        forEach(Object_keys(context), function (key) {
            copy[key] = context[key];
        });
    }
    return copy;
};
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert'),
    util = require('util'),
    Q = require('q'),
    promiseIt = require('../testHelpers').promiseIt,
    behaviors = require('../../src/models/behaviors'),
    Logger = require('../fakes/fakeLogger'),
    fs = require('fs');

describe('behaviors', function () {
    describe('#shellTransform', function () {
        promiseIt('should not execute during dry run', function () {
            var request = { isDryRun: true },
                responsePromise = Q({ data: 'ORIGINAL' }),
                command = 'echo Should not reach here',
                logger = Logger.create();

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function (response) {
                assert.deepEqual(response, { data: 'ORIGINAL' });
            });
        });

        promiseIt('should return output of command', function () {
            var request = {},
                responsePromise = Q({ data: 'ORIGINAL' }),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    console.log('%s', JSON.stringify({ data: 'CHANGED' }));
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function (response) {
                assert.deepEqual(response, { data: 'CHANGED' });
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });

        promiseIt('should pass request and response to shell command', function () {
            var request = { data: 'FROM REQUEST' },
                responsePromise = Q({ data: 'UNCHANGED', requestData: '' }),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    // The replace of quotes only matters on Windows due to shell differences
                    var shellRequest = JSON.parse(process.argv[2].replace("'", '')),
                        shellResponse = JSON.parse(process.argv[3].replace("'", ''));

                    shellResponse.requestData = shellRequest.data;
                    console.log(JSON.stringify(shellResponse));
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function (response) {
                assert.deepEqual(response, { data: 'UNCHANGED', requestData: 'FROM REQUEST' });
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });

        promiseIt('should reject promise if file does not exist', function () {
            var request = {},
                responsePromise = Q({}),
                command = 'fileDoesNotExist',
                logger = Logger.create();

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function () {
                assert.fail('Promise resolved, should have been rejected');
            }, function (error) {
                assert.ok(error.indexOf('not found') >= 0, error);
            });
        });

        promiseIt('should reject if command returned non-zero status code', function () {
            var request = {},
                responsePromise = Q({}),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    console.error('BOOM!!!');
                    process.exit(1);
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function () {
                assert.fail('Promise resolved, should have been rejected');
            }, function (error) {
                assert.ok(error.indexOf('Command failed') >= 0, error);
                assert.ok(error.indexOf('BOOM!!!') >= 0, error);
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });

        promiseIt('should reject if command does not return valid JSON', function () {
            var request = {},
                responsePromise = Q({}),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    console.log('This is not JSON');
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function () {
                assert.fail('Promise resolved, should have been rejected');
            }, function (error) {
                assert.ok(error.indexOf('Shell command returned invalid JSON') >= 0, error);
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });
    });
});
<commit_msg>Fixing assertion due to different Windows error message https://github.com/bbyars/mountebank/issues/171<commit_after>'use strict';

var assert = require('assert'),
    util = require('util'),
    Q = require('q'),
    promiseIt = require('../testHelpers').promiseIt,
    behaviors = require('../../src/models/behaviors'),
    Logger = require('../fakes/fakeLogger'),
    fs = require('fs');

describe('behaviors', function () {
    describe('#shellTransform', function () {
        promiseIt('should not execute during dry run', function () {
            var request = { isDryRun: true },
                responsePromise = Q({ data: 'ORIGINAL' }),
                command = 'echo Should not reach here',
                logger = Logger.create();

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function (response) {
                assert.deepEqual(response, { data: 'ORIGINAL' });
            });
        });

        promiseIt('should return output of command', function () {
            var request = {},
                responsePromise = Q({ data: 'ORIGINAL' }),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    console.log('%s', JSON.stringify({ data: 'CHANGED' }));
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function (response) {
                assert.deepEqual(response, { data: 'CHANGED' });
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });

        promiseIt('should pass request and response to shell command', function () {
            var request = { data: 'FROM REQUEST' },
                responsePromise = Q({ data: 'UNCHANGED', requestData: '' }),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    // The replace of quotes only matters on Windows due to shell differences
                    var shellRequest = JSON.parse(process.argv[2].replace("'", '')),
                        shellResponse = JSON.parse(process.argv[3].replace("'", ''));

                    shellResponse.requestData = shellRequest.data;
                    console.log(JSON.stringify(shellResponse));
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function (response) {
                assert.deepEqual(response, { data: 'UNCHANGED', requestData: 'FROM REQUEST' });
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });

        promiseIt('should reject promise if file does not exist', function () {
            var request = {},
                responsePromise = Q({}),
                command = 'fileDoesNotExist',
                logger = Logger.create();

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function () {
                assert.fail('Promise resolved, should have been rejected');
            }, function (error) {
                // Error message is OS-dependent
                assert.ok(error.indexOf('fileDoesNotExist') >= 0, error);
            });
        });

        promiseIt('should reject if command returned non-zero status code', function () {
            var request = {},
                responsePromise = Q({}),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    console.error('BOOM!!!');
                    process.exit(1);
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function () {
                assert.fail('Promise resolved, should have been rejected');
            }, function (error) {
                assert.ok(error.indexOf('Command failed') >= 0, error);
                assert.ok(error.indexOf('BOOM!!!') >= 0, error);
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });

        promiseIt('should reject if command does not return valid JSON', function () {
            var request = {},
                responsePromise = Q({}),
                command = 'node shellTransformTest.js',
                logger = Logger.create(),
                shellFn = function exec () {
                    console.log('This is not JSON');
                };

            fs.writeFileSync('shellTransformTest.js', util.format('%s\nexec();', shellFn.toString()));

            return behaviors.shellTransform(request, responsePromise, command, logger).then(function () {
                assert.fail('Promise resolved, should have been rejected');
            }, function (error) {
                assert.ok(error.indexOf('Shell command returned invalid JSON') >= 0, error);
            }).finally(function () {
                fs.unlinkSync('shellTransformTest.js');
            });
        });
    });
});
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 Expression organization is undefined on line 4, column 61 in Templates/Licenses/license-gpl30.txt.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Slider
 * Controls the opacity of the layers. Used by the TransparencySlider component.
 * @author Meine Toonen
 */

Ext.define("viewer.components.Slider",{
    extend: "viewer.components.Component",
    slider: null,
    layers : null,
    config:{
        selectedLayers: null,
        name : null,
        title: null,
        initialTransparency: 0
    },
    constructor : function (conf){
        viewer.components.Slider.superclass.constructor.call(this, conf);
        this.initConfig(conf);

        this.slider = Ext.create('Ext.slider.Single', {
            width: 200,
            value: this.initialTransparency,
            increment: 1,
            fieldLabel: this.name,
            labelAlign: "top",
            minValue: 0,
            maxValue: 100,
            renderTo: conf.sliderContainer,
            listeners:{
                change: {
                    fn: this.sliderChanged,
                    scope: this
                }
            }
        });

        return this;
    },
    sliderChanged: function (slider,value){
        if (this.layers==null){
            this.initLayers();
        }
        for(var i = 0 ; i< this.layers.length ;i++){
            var layer = this.layers[i];
            layer.setAlpha(value);
        }
    },
    getExtComponents: function() {
        return this.slider.getId();
    },
    initLayers: function(){
        var selectedLayers = this.selectedLayers;
        if(this.layers == null){
            this.layers = new Array();
        }
        for( var i = 0 ; i < selectedLayers.length;i++){
            var layer = this.viewerController.getLayerByLayerId(this.selectedLayers[i]);
            if(layer) {
                this.layers.push(layer);
            }
        }
    }
});<commit_msg>Apply initial slider transparency to layers when loaded<commit_after>/*
 * Copyright (C) 2012 Expression organization is undefined on line 4, column 61 in Templates/Licenses/license-gpl30.txt.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Slider
 * Controls the opacity of the layers. Used by the TransparencySlider component.
 * @author Meine Toonen
 */

Ext.define("viewer.components.Slider",{
    extend: "viewer.components.Component",
    slider: null,
    layers : null,
    config:{
        selectedLayers: null,
        name : null,
        title: null,
        initialTransparency: 0
    },
    constructor : function (conf){
        viewer.components.Slider.superclass.constructor.call(this, conf);
        this.initConfig(conf);

        this.slider = Ext.create('Ext.slider.Single', {
            width: 200,
            value: this.initialTransparency,
            increment: 1,
            fieldLabel: this.name,
            labelAlign: "top",
            minValue: 0,
            maxValue: 100,
            renderTo: conf.sliderContainer,
            listeners:{
                change: {
                    fn: this.sliderChanged,
                    scope: this
                }
            }
        });

        // TODO: Check EVENT, is this the right event to listen to?
        this.viewerController.mapComponent.getMap().addListener(viewer.viewercontroller.controller.Event.ON_ALL_LAYERS_LOADING_COMPLETE,this.applySlider,this);
        return this;
    },
    applySlider: function() {
        if(this.slider) this.sliderChanged(this.slider, this.slider.getValue());
    },
    sliderChanged: function (slider,value){
        if (this.layers==null){
            this.initLayers();
        }
        for(var i = 0 ; i< this.layers.length ;i++){
            var layer = this.layers[i];
            layer.setAlpha(value);
        }
    },
    getExtComponents: function() {
        return this.slider.getId();
    },
    initLayers: function(){
        var selectedLayers = this.selectedLayers;
        if(this.layers == null){
            this.layers = new Array();
        }
        for( var i = 0 ; i < selectedLayers.length;i++){
            var layer = this.viewerController.getLayerByLayerId(this.selectedLayers[i]);
            if(layer) {
                this.layers.push(layer);
            }
        }
    }
});<|endoftext|>