<commit_before>const assert = require('assert')
const helper = require('../modules/helper')
const Board = require('../modules/board')

describe('Board', () => {
    describe('constructor', () => {
        it('should create an empty board', () => {
            let board = new Board()

            for (let x = 0; x < board.width; x++) {
                for (let y = 0; y < board.height; y++) {
                    assert.equal(board.get([x, y]), 0)
                }
            }
        })
        it('should have no capture information', () => {
            let board = new Board()
            assert.deepEqual(board.captures, {'-1': 0, '1': 0})
        })
        it('should have no markups and lines', () => {
            let board = new Board()
            assert.deepEqual(board.lines, [])
            assert.deepEqual(board.markups, {})
        })
    })

    describe('clone', () => {
        it('should clone board arrangement', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))
            let clone = board.clone()

            assert.deepEqual(board.arrangement, clone.arrangement)

            board.set([5, 5], 1)
            assert.notDeepEqual(board.arrangement, clone.arrangement)
        })
    })

    describe('hasVertex', () => {
        it('should return true when vertex is on board', () => {
            let board = new Board()
            assert(board.hasVertex([0, 0]))
            assert(board.hasVertex([13, 18]))
            assert(board.hasVertex([5, 4]))
        })
        it('should return false when vertex is not on board', () => {
            let board = new Board()
            assert(!board.hasVertex([-1, -1]))
            assert(!board.hasVertex([5, -1]))
            assert(!board.hasVertex([board.width, 0]))
            assert(!board.hasVertex([board.width, board.height]))
        })
    })

    describe('clear', () => {
        it('should clear the stones on the board', () => {
            let board = new Board(9, 9)
            board.set([0, 0], 1).set([1, 1], -1).set([3, 5], 1)
            board.clear()
            assert.deepEqual(board.arrangement, new Board(9, 9).arrangement)
        })
        it('should not clear markups or lines', () => {
            let board = new Board(9, 9)
            let lines = [
                [[0, 0], [8, 8], false],
                [[8, 8], [0, 0], true]
            ]
            board.lines = lines
            board.markups[[5, 5]] = ['label', 'A']

            board.clear()
            assert.deepEqual(board.lines, lines)
            assert.notDeepEqual(board.markups, new Board(9, 9).markups)
        })
    })

    describe('getDistance', () => {
        it('should return the Manhattan distance between two vertices', () => {
            let board = new Board()
            assert.equal(board.getDistance([1, 2], [8, 4]), 9)
            assert.equal(board.getDistance([-1, -2], [8, 4]), 15)
        })
    })

    describe('getCanonicalVertex', () => {
        it('should work', () => {
            let board = new Board()
            assert.deepEqual(board.getCanonicalVertex([3, 4]), [3, 4])
            assert.deepEqual(board.getCanonicalVertex([4, 3]), [3, 4])
            assert.deepEqual(board.getCanonicalVertex([18, 3]), [0, 3])
            assert.deepEqual(board.getCanonicalVertex([15, 5]), [3, 5])
        })
    })

    describe('getSymmetries', () => {
        it('should work', () => {
            let board = new Board()

            assert.deepEqual(
                board.getSymmetries([3, 4]).sort(helper.lexicalCompare),
                [[3, 4], [3, 14], [4, 3], [4, 15], [14, 3], [14, 15], [15, 4], [15, 14]]
            )
            assert.deepEqual(
                board.getSymmetries([4, 3]).sort(helper.lexicalCompare),
                [[3, 4], [3, 14], [4, 3], [4, 15], [14, 3], [14, 15], [15, 4], [15, 14]]
            )
            assert.deepEqual(
                board.getSymmetries([18, 3]).sort(helper.lexicalCompare),
                [[0, 3], [0, 3], [0, 15], [0, 15], [3, 0], [3, 0], [15, 0], [15, 0]]
            )
            assert.deepEqual(
                board.getSymmetries([15, 5]).sort(helper.lexicalCompare),
                [[3, 5], [3, 13], [5, 3], [5, 15], [13, 3], [13, 15], [15, 5], [15, 13]]
            )
        })
    })

    describe('getNeighbors', () => {
        it('should return neighbors for vertices in the middle', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([1, 1]), [[0, 1], [2, 1], [1, 0], [1, 2]])
        })
        it('should return neighbors for vertices on the side', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([1, 0]), [[0, 0], [2, 0], [1, 1]])
        })
        it('should return neighbors for vertices in the corner', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([0, 0]), [[1, 0], [0, 1]])
        })
        it('should return empty list for vertices not on board', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([-1, -1]), [])
        })
    })

    describe('getConnectedComponent', () => {
        it('should be able to return the chain of a vertex', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))

            assert.deepEqual(
                board.getConnectedComponent([1, 1], [-1]).sort(helper.lexicalCompare),
                [[1, 1], [2, 1]]
            )
        })
        it('should be able to return the stone connected component of a vertex', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))

            assert.deepEqual(
                board.getConnectedComponent([1, 1], [-1, 1]).sort(helper.lexicalCompare),
                [[0, 1], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
            )
        })
    })

    describe('getLiberties', () => {
        it('should return the liberties of the chain of the given vertex', () => {
            let board = new Board()
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))

            assert.deepEqual(
                board.getLiberties([1, 1]).sort(helper.lexicalCompare),
                [[0, 1], [1, 0], [1, 2], [2, 0], [2, 2], [3, 1]]
            )
            assert.deepEqual(board.getLiberties([1, 2]), [])
        })
        it('should return empty list for a vertex not on the board', () => {
            let board = new Board()
            assert.deepEqual(board.getLiberties([-1, -1]), [])
        })
    })

    describe('isValid', () => {
        it('should return true for valid board arrangements', () => {
            let board = new Board()
            assert(board.isValid())

            board.set([1, 1], 1).set([1, 2], -1)
            assert(board.isValid())
        })
        it('should return false for non-valid board arrangements', () => {
            let board = new Board()
            ;[[1, 0], [0, 1]].forEach(x => board.set(x, 1))
            ;[[0, 0]].forEach(x => board.set(x, -1))
            assert(!board.isValid())

            board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2], [3, 1]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))
            assert(!board.isValid())
        })
    })

    describe('makeMove', () => {
        it('should not mutate board', () => {
            let board = new Board()
            board.makeMove(1, [5, 5])
            assert.deepEqual(board.arrangement, new Board().arrangement)
        })
        it('should make a move', () => {
            let board = new Board()
            let move = board.makeMove(1, [5, 5])
            board.set([5, 5], 1)
            assert.deepEqual(board.arrangement, move.arrangement)
        })
        it('should remove captured stones', () => {
            let board = new Board()
            let black = [[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]]
            let white = [[1, 1], [2, 1]]

            black.forEach(x => board.set(x, 1))
            white.forEach(x => board.set(x, -1))

            let move = board.makeMove(1, [3, 1])

            assert.equal(move.get([3, 1]), 1)
            black.forEach(x => assert.equal(move.get(x), 1))
            white.forEach(x => assert.equal(move.get(x), 0))

            // Edge capture

            board = new Board()

            board.set([0, 1], 1).set([0, 0], -1)

            move = board.makeMove(1, [1, 0])

            assert.equal(move.get([0, 0]), 0)
            assert.equal(move.get([1, 0]), 1)
            assert.equal(move.get([0, 1]), 1)
        })
        it('should count captures correctly', () => {
            let board = new Board()
            let black = [[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]]
            let white = [[1, 1], [2, 1]]

            black.forEach(x => board.set(x, 1))
            white.forEach(x => board.set(x, -1))

            let move = board.makeMove(1, [3, 1])
            assert.equal(move.captures[-1], 0)
            assert.equal(move.captures[1], white.length)

            board = new Board()

            board.set([0, 1], 1).set([0, 0], -1)

            move = board.makeMove(1, [1, 0])

            assert.equal(move.captures[-1], 0)
            assert.equal(move.captures[1], 1)
        })
        it('should handle suicide correctly', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2], [3, 1]].forEach(x => board.set(x, 1))
            ;[[1, 1]].forEach(x => board.set(x, -1))
            let move = board.makeMove(-1, [2, 1])
            assert.equal(move.get([1, 1]), 0)
            assert.equal(move.get([2, 1]), 0)
            assert.equal(move.get([3, 1]), 1)
            assert.equal(move.get([1, 2]), 1)
        })
        it('should handle stone overwrites correctly' () => {
            let board = new Board()
            ;[[10, 9], [10, 10], [10, 11]].forEach(x => board.set(x, 1))
            ;[[10, 8], [9, 9], [11, 9]].forEach(x => board.set(x, -1))
            let move = board.makeMove(-1, [10, 10])
            assert.equal(move.get([10, 10]), -1)
            assert.equal(move.get([10, 9]), 0)
            assert.equal(move.get([10, 11]), 1)
        })
        it('should make a pass', () => {
            let board = new Board()
            assert.deepEqual(board.makeMove(1, [-1, -1]).arrangement, board.arrangement)
            board.set([1, 1], -1)
            assert.deepEqual(board.makeMove(1, [-1, -1]).arrangement, board.arrangement)
        })
    })
})
<commit_msg>comma<commit_after>const assert = require('assert')
const helper = require('../modules/helper')
const Board = require('../modules/board')

describe('Board', () => {
    describe('constructor', () => {
        it('should create an empty board', () => {
            let board = new Board()

            for (let x = 0; x < board.width; x++) {
                for (let y = 0; y < board.height; y++) {
                    assert.equal(board.get([x, y]), 0)
                }
            }
        })
        it('should have no capture information', () => {
            let board = new Board()
            assert.deepEqual(board.captures, {'-1': 0, '1': 0})
        })
        it('should have no markups and lines', () => {
            let board = new Board()
            assert.deepEqual(board.lines, [])
            assert.deepEqual(board.markups, {})
        })
    })

    describe('clone', () => {
        it('should clone board arrangement', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))
            let clone = board.clone()

            assert.deepEqual(board.arrangement, clone.arrangement)

            board.set([5, 5], 1)
            assert.notDeepEqual(board.arrangement, clone.arrangement)
        })
    })

    describe('hasVertex', () => {
        it('should return true when vertex is on board', () => {
            let board = new Board()
            assert(board.hasVertex([0, 0]))
            assert(board.hasVertex([13, 18]))
            assert(board.hasVertex([5, 4]))
        })
        it('should return false when vertex is not on board', () => {
            let board = new Board()
            assert(!board.hasVertex([-1, -1]))
            assert(!board.hasVertex([5, -1]))
            assert(!board.hasVertex([board.width, 0]))
            assert(!board.hasVertex([board.width, board.height]))
        })
    })

    describe('clear', () => {
        it('should clear the stones on the board', () => {
            let board = new Board(9, 9)
            board.set([0, 0], 1).set([1, 1], -1).set([3, 5], 1)
            board.clear()
            assert.deepEqual(board.arrangement, new Board(9, 9).arrangement)
        })
        it('should not clear markups or lines', () => {
            let board = new Board(9, 9)
            let lines = [
                [[0, 0], [8, 8], false],
                [[8, 8], [0, 0], true]
            ]
            board.lines = lines
            board.markups[[5, 5]] = ['label', 'A']

            board.clear()
            assert.deepEqual(board.lines, lines)
            assert.notDeepEqual(board.markups, new Board(9, 9).markups)
        })
    })

    describe('getDistance', () => {
        it('should return the Manhattan distance between two vertices', () => {
            let board = new Board()
            assert.equal(board.getDistance([1, 2], [8, 4]), 9)
            assert.equal(board.getDistance([-1, -2], [8, 4]), 15)
        })
    })

    describe('getCanonicalVertex', () => {
        it('should work', () => {
            let board = new Board()
            assert.deepEqual(board.getCanonicalVertex([3, 4]), [3, 4])
            assert.deepEqual(board.getCanonicalVertex([4, 3]), [3, 4])
            assert.deepEqual(board.getCanonicalVertex([18, 3]), [0, 3])
            assert.deepEqual(board.getCanonicalVertex([15, 5]), [3, 5])
        })
    })

    describe('getSymmetries', () => {
        it('should work', () => {
            let board = new Board()

            assert.deepEqual(
                board.getSymmetries([3, 4]).sort(helper.lexicalCompare),
                [[3, 4], [3, 14], [4, 3], [4, 15], [14, 3], [14, 15], [15, 4], [15, 14]]
            )
            assert.deepEqual(
                board.getSymmetries([4, 3]).sort(helper.lexicalCompare),
                [[3, 4], [3, 14], [4, 3], [4, 15], [14, 3], [14, 15], [15, 4], [15, 14]]
            )
            assert.deepEqual(
                board.getSymmetries([18, 3]).sort(helper.lexicalCompare),
                [[0, 3], [0, 3], [0, 15], [0, 15], [3, 0], [3, 0], [15, 0], [15, 0]]
            )
            assert.deepEqual(
                board.getSymmetries([15, 5]).sort(helper.lexicalCompare),
                [[3, 5], [3, 13], [5, 3], [5, 15], [13, 3], [13, 15], [15, 5], [15, 13]]
            )
        })
    })

    describe('getNeighbors', () => {
        it('should return neighbors for vertices in the middle', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([1, 1]), [[0, 1], [2, 1], [1, 0], [1, 2]])
        })
        it('should return neighbors for vertices on the side', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([1, 0]), [[0, 0], [2, 0], [1, 1]])
        })
        it('should return neighbors for vertices in the corner', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([0, 0]), [[1, 0], [0, 1]])
        })
        it('should return empty list for vertices not on board', () => {
            let board = new Board()
            assert.deepEqual(board.getNeighbors([-1, -1]), [])
        })
    })

    describe('getConnectedComponent', () => {
        it('should be able to return the chain of a vertex', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))

            assert.deepEqual(
                board.getConnectedComponent([1, 1], [-1]).sort(helper.lexicalCompare),
                [[1, 1], [2, 1]]
            )
        })
        it('should be able to return the stone connected component of a vertex', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))

            assert.deepEqual(
                board.getConnectedComponent([1, 1], [-1, 1]).sort(helper.lexicalCompare),
                [[0, 1], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
            )
        })
    })

    describe('getLiberties', () => {
        it('should return the liberties of the chain of the given vertex', () => {
            let board = new Board()
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))

            assert.deepEqual(
                board.getLiberties([1, 1]).sort(helper.lexicalCompare),
                [[0, 1], [1, 0], [1, 2], [2, 0], [2, 2], [3, 1]]
            )
            assert.deepEqual(board.getLiberties([1, 2]), [])
        })
        it('should return empty list for a vertex not on the board', () => {
            let board = new Board()
            assert.deepEqual(board.getLiberties([-1, -1]), [])
        })
    })

    describe('isValid', () => {
        it('should return true for valid board arrangements', () => {
            let board = new Board()
            assert(board.isValid())

            board.set([1, 1], 1).set([1, 2], -1)
            assert(board.isValid())
        })
        it('should return false for non-valid board arrangements', () => {
            let board = new Board()
            ;[[1, 0], [0, 1]].forEach(x => board.set(x, 1))
            ;[[0, 0]].forEach(x => board.set(x, -1))
            assert(!board.isValid())

            board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2], [3, 1]].forEach(x => board.set(x, 1))
            ;[[1, 1], [2, 1]].forEach(x => board.set(x, -1))
            assert(!board.isValid())
        })
    })

    describe('makeMove', () => {
        it('should not mutate board', () => {
            let board = new Board()
            board.makeMove(1, [5, 5])
            assert.deepEqual(board.arrangement, new Board().arrangement)
        })
        it('should make a move', () => {
            let board = new Board()
            let move = board.makeMove(1, [5, 5])
            board.set([5, 5], 1)
            assert.deepEqual(board.arrangement, move.arrangement)
        })
        it('should remove captured stones', () => {
            let board = new Board()
            let black = [[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]]
            let white = [[1, 1], [2, 1]]

            black.forEach(x => board.set(x, 1))
            white.forEach(x => board.set(x, -1))

            let move = board.makeMove(1, [3, 1])

            assert.equal(move.get([3, 1]), 1)
            black.forEach(x => assert.equal(move.get(x), 1))
            white.forEach(x => assert.equal(move.get(x), 0))

            // Edge capture

            board = new Board()

            board.set([0, 1], 1).set([0, 0], -1)

            move = board.makeMove(1, [1, 0])

            assert.equal(move.get([0, 0]), 0)
            assert.equal(move.get([1, 0]), 1)
            assert.equal(move.get([0, 1]), 1)
        })
        it('should count captures correctly', () => {
            let board = new Board()
            let black = [[0, 1], [1, 0], [1, 2], [2, 0], [2, 2]]
            let white = [[1, 1], [2, 1]]

            black.forEach(x => board.set(x, 1))
            white.forEach(x => board.set(x, -1))

            let move = board.makeMove(1, [3, 1])
            assert.equal(move.captures[-1], 0)
            assert.equal(move.captures[1], white.length)

            board = new Board()

            board.set([0, 1], 1).set([0, 0], -1)

            move = board.makeMove(1, [1, 0])

            assert.equal(move.captures[-1], 0)
            assert.equal(move.captures[1], 1)
        })
        it('should handle suicide correctly', () => {
            let board = new Board()
            ;[[0, 1], [1, 0], [1, 2], [2, 0], [2, 2], [3, 1]].forEach(x => board.set(x, 1))
            ;[[1, 1]].forEach(x => board.set(x, -1))
            let move = board.makeMove(-1, [2, 1])
            assert.equal(move.get([1, 1]), 0)
            assert.equal(move.get([2, 1]), 0)
            assert.equal(move.get([3, 1]), 1)
            assert.equal(move.get([1, 2]), 1)
        })
        it('should handle stone overwrites correctly', () => {
            let board = new Board()
            ;[[10, 9], [10, 10], [10, 11]].forEach(x => board.set(x, 1))
            ;[[10, 8], [9, 9], [11, 9]].forEach(x => board.set(x, -1))
            let move = board.makeMove(-1, [10, 10])
            assert.equal(move.get([10, 10]), -1)
            assert.equal(move.get([10, 9]), 0)
            assert.equal(move.get([10, 11]), 1)
        })
        it('should make a pass', () => {
            let board = new Board()
            assert.deepEqual(board.makeMove(1, [-1, -1]).arrangement, board.arrangement)
            board.set([1, 1], -1)
            assert.deepEqual(board.makeMove(1, [-1, -1]).arrangement, board.arrangement)
        })
    })
})
<|endoftext|>


<commit_before>;(function( factory ){
	if ( typeof module !== "undefined" && module.exports ) {
		module.exports = factory();

	} else if ( typeof define !== "undefined" ) {
		define( factory );

	} else {
		P = factory();
	}
})(function() {
	"use strict";

	var
		// linked list with head node - used as a queue of tasks
		// f: task, w: ticks required, n: next node
		head = { f: null, w: 0, n: null }, tail = head,

		// vars for tick re-usage
		lastIsSafe = false, pendingTicks = 0, neededTicks = 0,
		requestTick, // requestTick( onTick, 0 ) is the only valid usage!

		// window or worker
		wow = ot(typeof window) && window || ot(typeof worker) && worker;

	function onTick() {
		--pendingTicks;
		while ( head.n ) {
			head = head.n;
			neededTicks -= head.w;
			var f = head.f;
			head.f = null;
			f();
		}
		lastIsSafe = false;
	}

	function runLater( f, couldThrow ) {
		var w = 0;
		if ( !lastIsSafe && ++neededTicks > pendingTicks ) {
			++pendingTicks;
			requestTick( onTick, 0 );
			w = 1;
		};
		tail = tail.n = { f: f, w: w, n: null };
		lastIsSafe = couldThrow !== true;
	}

	function ot( type ) {
		return type === "object" || type === "function";
	}

	function ft( type ) {
		return type === "function";
	}

	if ( ot(typeof process) && process && ft(typeof process.nextTick) ) {
		requestTick = process.nextTick;

	} else if ( wow && ft(typeof wow.setImmediate) ) {
		requestTick = function( cb ) {
			wow.setImmediate( cb );
		};

	} else if ( ft(typeof MessageChannel) ) {
		var channel = new MessageChannel();
		channel.port1.onmessage = onTick;
		requestTick = function() {
			channel.port2.postMessage(0);
		};

	} else {
		requestTick = setTimeout;

		if ( wow && ot(typeof Image) && Image ) {
			(function(){
				var c = 0;

				var requestTickViaImage = function( cb ) {
					var img = new Image();
					img.onerror = cb;
					img.src = 'data:image/png,';
				};

				try {
					requestTickViaImage(function() {
						if ( --c === 0 ) {
							requestTick = requestTickViaImage;
						}
					});
					++c;
				} catch (e) {}

				c && setTimeout(function() {
					c = 0;
				}, 0);
			})();
		}
	}

	//__________________________________________________________________________

	function each( arr, cb ) {
		for ( var i = 0, l = arr.length; i < l; ++i ) {
			cb( arr[i], i );
		}
	}

	var P = resolve;
	P.prototype = Promise.prototype;

	P.defer = defer;
	function defer() {
		var pending = [],
			rejected = false,
			value;

		function then( onFulfilled, onRejected ) {
			var def = defer();

			function onReslved() {
				var func = rejected ? onRejected : onFulfilled;

				if ( typeof func !== "function" ) {
					if ( rejected ) {
						def.reject( value );
					} else {
						def.fulfill( value );
					}

				} else {
					var val;

					try {
						val = func( value );
						if ( val && typeof val.then === "function" ) {
							val.then( def.fulfill, def.reject );
							return;
						}
					} catch ( ex ) {
						def.reject( ex );
					}

					def.fulfill( val );
				}
			}

			if ( pending ) {
				pending.push( onReslved );

			} else {
				runLater( onReslved );
			}

			return def.promise;
		}

		function fulfill( val ) {
			if ( pending ) {
				value = val;
				each( pending, runLater );
				pending = null;
			}
		}

		function reject( error ) {
			if ( pending ) {
				rejected = true;
				fulfill( error );
			}
		}

		return {
			promise: new Promise( then ),
			fulfill: fulfill,
			reject: reject
		};
	}

	function Promise( then ) {
		this.then = then;
	}

	Promise.prototype.done = function( cb, eb ) {
		var p = this;
		if ( cb || eb ) {
			p = p.then( cb, eb );
		}
		p.then(null, function( error ) {
			runLater(function() {
				if ( P.onerror ) {
					P.onerror( error );
				} else {
					throw error;
				}
			}, true);
		});
	};

	Promise.prototype.spread = function( cb, eb ) {
		return this.then(cb && function( values ) {
			return cb.apply( void 0, values );
		}, eb);
	};

	P.resolve = resolve;
	function resolve( val ) {
		if ( val instanceof Promise ) {
			return val;
		}

		var def = defer();

		if ( val && typeof val.then === "function" ) {
			val.then( def.fulfill, def.reject );

		} else {
			def.fulfill( val );
		}

		return def.promise;
	}

	P.reject = reject;
	function reject( value ) {
		var def = defer();
		def.reject( value );
		return def.promise;
	}

	P.all = all;
	function all( promises ) {
		var countDown = promises.length;
		if ( countDown === 0 ) {
			return resolve( promises );
		}
		var def = defer();
		each(promises, function( promise, index ) {
			resolve( promise ).then(function( value ) {
				promises[ index ] = value;
				if ( --countDown === 0 ) {
					def.fulfill( promises );
				}
			}, def.reject );
		});
		return def.promise;
	}

	P.promise = function( makeOrPromise ) {
		var def = defer();
		resolve( makeOrPromise )
		.then(function( make ) {
			try {
				make( def.resolve, def.reject );
			} catch ( ex ) {
				def.reject( ex );
			}
		}, def.reject);
		return def.promise;
	};

	P.onerror = null;

	P.nextTick = function( f ) {
		runLater( f, true );
	};

	//P.runLater = runLater;

	return P;
});
<commit_msg>Minor refactor.<commit_after>;(function( factory ){
	if ( typeof module !== "undefined" && module && module.exports ) {
		module.exports = factory();

	} else if ( typeof define !== "function" ) {
		define( factory );

	} else {
		P = factory();
	}
})(function() {
	"use strict";

	var
		// linked list with head node - used as a queue of tasks
		// f: task, w: ticks required, n: next node
		head = { f: null, w: 0, n: null }, tail = head,

		// vars for tick re-usage
		lastIsSafe = false, pendingTicks = 0, neededTicks = 0,

		channel, // MessageChannel
		requestTick, // requestTick( onTick, 0 ) is the only valid usage!

		// window or worker
		wow = ot(typeof window) && window || ot(typeof worker) && worker;

	function onTick() {
		--pendingTicks;
		while ( head.n ) {
			head = head.n;
			neededTicks -= head.w;
			var f = head.f;
			head.f = null;
			f();
		}
		lastIsSafe = false;
	}

	function runLater( f, couldThrow ) {
		var w = 0;
		if ( !lastIsSafe && ++neededTicks > pendingTicks ) {
			++pendingTicks;
			requestTick( onTick, 0 );
			w = 1;
		};
		tail = tail.n = { f: f, w: w, n: null };
		lastIsSafe = couldThrow !== true;
	}

	function ot( type ) {
		return type === "object" || type === "function";
	}

	function ft( type ) {
		return type === "function";
	}

	if ( ot(typeof process) && process && ft(typeof process.nextTick) ) {
		requestTick = process.nextTick;

	} else if ( wow && ft(typeof wow.setImmediate) ) {
		requestTick = function( cb ) {
			wow.setImmediate( cb );
		};

	} else if ( ft(typeof MessageChannel) ) {
		channel = new MessageChannel();
		channel.port1.onmessage = onTick;
		requestTick = function() {
			channel.port2.postMessage(0);
		};

	} else {
		requestTick = setTimeout;

		if ( wow && ot(typeof Image) && Image ) {
			(function(){
				var c = 0;

				var requestTickViaImage = function( cb ) {
					var img = new Image();
					img.onerror = cb;
					img.src = 'data:image/png,';
				};

				try {
					requestTickViaImage(function() {
						if ( --c === 0 ) {
							requestTick = requestTickViaImage;
						}
					});
					++c;
				} catch (e) {}

				c && setTimeout(function() {
					c = 0;
				}, 0);
			})();
		}
	}

	//__________________________________________________________________________

	function each( arr, cb ) {
		for ( var i = 0, l = arr.length; i < l; ++i ) {
			cb( arr[i], i );
		}
	}

	var P = resolve;
	P.prototype = Promise.prototype;

	P.defer = defer;
	function defer() {
		var pending = [],
			rejected = false,
			value;

		function then( onFulfilled, onRejected ) {
			var def = defer();

			function onReslved() {
				var func = rejected ? onRejected : onFulfilled;

				if ( typeof func !== "function" ) {
					if ( rejected ) {
						def.reject( value );
					} else {
						def.fulfill( value );
					}

				} else {
					var val;

					try {
						val = func( value );
						if ( val && typeof val.then === "function" ) {
							val.then( def.fulfill, def.reject );
							return;
						}
					} catch ( ex ) {
						def.reject( ex );
					}

					def.fulfill( val );
				}
			}

			if ( pending ) {
				pending.push( onReslved );

			} else {
				runLater( onReslved );
			}

			return def.promise;
		}

		function fulfill( val ) {
			if ( pending ) {
				value = val;
				each( pending, runLater );
				pending = null;
			}
		}

		function reject( error ) {
			if ( pending ) {
				rejected = true;
				fulfill( error );
			}
		}

		return {
			promise: new Promise( then ),
			fulfill: fulfill,
			reject: reject
		};
	}

	function Promise( then ) {
		this.then = then;
	}

	Promise.prototype.done = function( cb, eb ) {
		var p = this;
		if ( cb || eb ) {
			p = p.then( cb, eb );
		}
		p.then(null, function( error ) {
			runLater(function() {
				if ( P.onerror ) {
					P.onerror( error );
				} else {
					throw error;
				}
			}, true);
		});
	};

	Promise.prototype.spread = function( cb, eb ) {
		return this.then(cb && function( values ) {
			return cb.apply( void 0, values );
		}, eb);
	};

	P.resolve = resolve;
	function resolve( val ) {
		if ( val instanceof Promise ) {
			return val;
		}

		var def = defer();

		if ( val && typeof val.then === "function" ) {
			val.then( def.fulfill, def.reject );

		} else {
			def.fulfill( val );
		}

		return def.promise;
	}

	P.reject = reject;
	function reject( value ) {
		var def = defer();
		def.reject( value );
		return def.promise;
	}

	P.all = all;
	function all( promises ) {
		var countDown = promises.length;
		if ( countDown === 0 ) {
			return resolve( promises );
		}
		var def = defer();
		each(promises, function( promise, index ) {
			resolve( promise ).then(function( value ) {
				promises[ index ] = value;
				if ( --countDown === 0 ) {
					def.fulfill( promises );
				}
			}, def.reject );
		});
		return def.promise;
	}

	P.promise = function( makeOrPromise ) {
		var def = defer();
		resolve( makeOrPromise ).then(function( make ) {
			try {
				make( def.fulfill, def.reject );
			} catch ( ex ) {
				def.reject( ex );
			}
		}, def.reject);
		return def.promise;
	};

	P.onerror = null;

	P.nextTick = function( f ) {
		runLater( f, true );
	};

	//P.runLater = runLater;

	return P;
});
<|endoftext|>


<commit_before>
var connect = require('../');

var app = connect();

app.use(connect.bodyParser());

app.use(function(req, res){
  res.end(JSON.stringify(req.body));
});

describe('connect.bodyParser()', function(){
  it('should default to {}', function(done){
    app.request()
    .post('/')
    .end(function(res){
      res.body.should.equal('{}');
      done();
    })
  })

  it('should parse JSON', function(done){
    app.request()
    .post('/')
    .set('Content-Type', 'application/json')
    .write('{"user":"tobi"}')
    .end(function(res){
      res.body.should.equal('{"user":"tobi"}');
      done();
    });
  })

  it('should parse x-www-form-urlencoded', function(done){
    app.request()
    .post('/')
    .set('Content-Type', 'application/x-www-form-urlencoded')
    .write('user=tobi')
    .end(function(res){
      res.body.should.equal('{"user":"tobi"}');
      done();
    });
  })

  describe('with multipart/form-data', function(){
    it('should populate req.body', function(done){
      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user"\r\n')
      .write('\r\n')
      .write('Tobi')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('{"user":"Tobi"}');
        done();
      });
    })

    it('should support files', function(done){
      var app = connect();

      app.use(connect.bodyParser());

      app.use(function(req, res){
        req.body.user.should.eql({ name: 'Tobi' });
        req.body.text.constructor.name.should.equal('File');
        res.end(req.body.text.name);
      });

      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user[name]"\r\n')
      .write('\r\n')
      .write('Tobi')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="text"; filename="foo.txt"\r\n')
      .write('\r\n')
      .write('some text here')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('foo.txt');
        done();
      });
    })

    it('should work with multiple fields', function(done){
      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user"\r\n')
      .write('\r\n')
      .write('Tobi')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="age"\r\n')
      .write('\r\n')
      .write('1')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('{"user":"Tobi","age":"1"}');
        done();
      });
    })

    it('should support nesting', function(done){
      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user[name]"\r\n')
      .write('\r\n')
      .write('tobi')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="user[age]"\r\n')
      .write('\r\n')
      .write('1')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="species"\r\n')
      .write('\r\n')
      .write('ferret')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('{"user":{"name":"tobi","age":"1"},"species":"ferret"}');
        done();
      });
    })
  })
})<commit_msg>multiple<commit_after>
var connect = require('../');

var app = connect();

app.use(connect.bodyParser());

app.use(function(req, res){
  res.end(JSON.stringify(req.body));
});

describe('connect.bodyParser()', function(){
  it('should default to {}', function(done){
    app.request()
    .post('/')
    .end(function(res){
      res.body.should.equal('{}');
      done();
    })
  })

  it('should parse JSON', function(done){
    app.request()
    .post('/')
    .set('Content-Type', 'application/json')
    .write('{"user":"tobi"}')
    .end(function(res){
      res.body.should.equal('{"user":"tobi"}');
      done();
    });
  })

  it('should parse x-www-form-urlencoded', function(done){
    app.request()
    .post('/')
    .set('Content-Type', 'application/x-www-form-urlencoded')
    .write('user=tobi')
    .end(function(res){
      res.body.should.equal('{"user":"tobi"}');
      done();
    });
  })

  describe('with multipart/form-data', function(){
    it('should populate req.body', function(done){
      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user"\r\n')
      .write('\r\n')
      .write('Tobi')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('{"user":"Tobi"}');
        done();
      });
    })

    it('should support files', function(done){
      var app = connect();

      app.use(connect.bodyParser());

      app.use(function(req, res){
        req.body.user.should.eql({ name: 'Tobi' });
        req.body.text.constructor.name.should.equal('File');
        res.end(req.body.text.name);
      });

      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user[name]"\r\n')
      .write('\r\n')
      .write('Tobi')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="text"; filename="foo.txt"\r\n')
      .write('\r\n')
      .write('some text here')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('foo.txt');
        done();
      });
    })

    it('should work with multiple fields', function(done){
      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user"\r\n')
      .write('\r\n')
      .write('Tobi')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="age"\r\n')
      .write('\r\n')
      .write('1')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('{"user":"Tobi","age":"1"}');
        done();
      });
    })

    it('should support nesting', function(done){
      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="user[name]"\r\n')
      .write('\r\n')
      .write('tobi')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="user[age]"\r\n')
      .write('\r\n')
      .write('1')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="species"\r\n')
      .write('\r\n')
      .write('ferret')
      .write('\r\n--foo--')
      .end(function(res){
        res.body.should.equal('{"user":{"name":"tobi","age":"1"},"species":"ferret"}');
        done();
      });
    })

    it('should support multiple files of the same name', function(done){
      var app = connect();

      app.use(connect.bodyParser());

      app.use(function(req, res){
        req.body.text.should.have.length(2);
        var foo = req.body.text.shift();
        var bar = req.body.text.shift();
        foo.name.should.equal('foo.txt');
        foo.size.should.equal(14);
        bar.name.should.equal('bar.txt');
        bar.size.should.equal(20);
        res.end();
      });

      app.request()
      .post('/')
      .set('Content-Type', 'multipart/form-data; boundary=foo')
      .write('--foo\r\n')
      .write('Content-Disposition: form-data; name="text"; filename="foo.txt"\r\n')
      .write('\r\n')
      .write('some text here')
      .write('\r\n--foo\r\n')
      .write('Content-Disposition: form-data; name="text"; filename="bar.txt"\r\n')
      .write('\r\n')
      .write('some more text stuff')
      .write('\r\n--foo--')
      .end(function(res){
        res.statusCode.should.equal(200);
        done();
      });
    })

  })
})<|endoftext|>


<commit_before><commit_msg>Allow agent to be specific in options.<commit_after><|endoftext|>


<commit_before>;(function( factory ){
	// CommonJS
	if ( typeof module !== "undefined" && module && module.exports ) {
		module.exports = factory();

	// RequireJS
	} else if ( typeof define === "function" && define.amd ) {
		define( factory );

	// global
	} else {
		P = factory();
	}
})(function() {
	"use strict";

	var
		head = { f: null, n: null }, tail = head,
		running = false,

		channel, // MessageChannel
		requestTick, // --> requestTick( onTick, 0 )

		// window or worker
		wow = ot(typeof window) && window || ot(typeof worker) && worker,

		toStr = ({}).toString,
		isArray;

	function onTick() {
		while ( head.n ) {
			head = head.n;
			var f = head.f;
			head.f = null;
			f();
		}
		running = false;
	}

	var runLater = function( f ) {
		tail = tail.n = { f: f, n: null };
		if ( !running ) {
			running = true;
			requestTick( onTick, 0 );
		}
	};

	function ot( type ) {
		return type === "object" || type === "function";
	}

	function ft( type ) {
		return type === "function";
	}

	if ( ot(typeof process) && process && process.nextTick ) {
		requestTick = process.nextTick;

	} else if ( ft(typeof setImmediate) ) {
		requestTick = wow ?
			function( cb ) {
				wow.setImmediate( cb );
			} :
			function( cb ) {
				setImmediate( cb );
			};

	} else if ( ft(typeof MessageChannel) ) {
		channel = new MessageChannel();
		channel.port1.onmessage = onTick;
		requestTick = function() {
			channel.port2.postMessage(0);
		};

	} else {
		requestTick = setTimeout;

		if ( wow && ot(typeof Image) && Image ) {
			(function(){
				var c = 0;

				var requestTickViaImage = function( cb ) {
					var img = new Image();
					img.onerror = cb;
					img.src = 'data:image/png,';
				};

				// Before using it, test if it works properly, with async dispatching.
				try {
					requestTickViaImage(function() {
						if ( --c === 0 ) {
							requestTick = requestTickViaImage;
						}
					});
					++c;
				} catch (e) {}

				// Also use it only if faster then setTimeout.
				c && setTimeout(function() {
					c = 0;
				}, 0);
			})();
		}
	}

	//__________________________________________________________________________

	isArray = Array.isArray || function( val ) {
		return !!val && toStr.call( val ) === "[object Array]";
	};

	function forEach( arr, cb ) {
		for ( var i = 0, l = arr.length; i < l; ++i ) {
			if ( i in arr ) {
				cb( arr[i], i );
			}
		}
	}

	function each( obj, cb ) {
		if ( isArray(obj) ) {
			forEach( obj, cb );
			return;
		}

		for ( var prop in obj ) {
			cb( obj[prop], prop );
		}
	}

	function reportError( error ) {
		try {
			if ( P.onerror ) {
				P.onerror( error );
			} else {
				throw error;
			}

		} catch ( e ) {
			setTimeout(function() {
				throw e;
			}, 0);
		}
	}

	var PENDING = 0;
	var FULFILLED = 1;
	var REJECTED = 2;

	function P( x ) {
		return x instanceof Promise ?
			x :
			Resolve( new Promise(), x );
	}

	function Settle( p, state, value ) {
		if ( p._state ) {
			return p;
		}

		p._state = state;
		p._value = value;

		if ( p._pending.length > 0 ) {
			forEach( p._pending, runLater );
		}
		p._pending = null;

		return p;
	}

	function Append( p, f ) {
		p._pending.push( f );
		//p._tail = p._tail.n = { f: f, n: null };
	}

	function Resolve( p, x ) {
		if ( p._state ) {
			return p;
		}

		if ( x instanceof Promise ) {
			if ( x._state ) {
				Settle( p, x._state, x._value );

			} else {
				Append(x, function() {
					Settle( p, x._state, x._value );
				});
			}

		} else if ( x !== Object(x) ) {
			Settle( p, FULFILLED, x );

		} else {
			runLater(function() {
				try {
					var then = x.then;

					if ( typeof then === "function" ) {
						var r = resolverFor( p, x );
						then.call( x, r.resolve, r.reject );

					} else {
						Settle( p, FULFILLED, x );
					}

				} catch ( e ) {
					Settle( p, REJECTED, e );
				}
			});
		}

		return p;
	}

	function resolverFor( promise, x ) {
		var done = false;

		return {
			promise: promise,

			resolve: function( y ) {
				if ( !done ) {
					done = true;

					if ( x && x === y ) {
						Settle( promise, FULFILLED, y );

					} else {
						Resolve( promise, y );
					}
				}
			},

			reject: function( reason ) {
				if ( !done ) {
					done = true;
					Settle( promise, REJECTED, reason );
				}
			}
		};
	}

	P.defer = defer;
	function defer() {
		return resolverFor( new Promise() );
	}

	function Promise() {
		this._state = 0;
		this._value = void 0;
		this._pending = [];
	}

	Promise.prototype.then = function( onFulfilled, onRejected ) {
		var cb = typeof onFulfilled === "function" ? onFulfilled : null;
		var eb = typeof onRejected === "function" ? onRejected : null;

		var p = this;
		var p2 = new Promise();

		function onSettled() {
			var x, func = p._state === FULFILLED ? cb : eb;

			if ( func !== null ) {
				try {
					x = func( p._value );

				} catch ( e ) {
					Settle( p2, REJECTED, e );
					return;
				}

				Resolve( p2, x );

			} else {
				Settle( p2, p._state, p._value );
			}
		}

		if ( p._state === PENDING ) {
			Append( p, onSettled );

		} else {
			runLater( onSettled );
		}

		return p2;
	};

	Promise.prototype.done = function( cb, eb ) {
		var p = this;

		if ( cb || eb ) {
			p = p.then( cb, eb );
		}

		p.then( null, reportError );
	};

	Promise.prototype.fail = function( eb ) {
		return this.then( null, eb );
	};

	Promise.prototype.spread = function( cb, eb ) {
		return this.then(cb && function( array ) {
			return all( array ).then(function( values ) {
				return cb.apply( void 0, values );
			});
		}, eb);
	};

	Promise.prototype.timeout = function( ms, msg ) {
		var p = this;
		var p2 = new Promise();

		if ( p._state !== PENDING ) {
			Settle( p2, p._state, p._value );

		} else {
			var timeoutId = setTimeout(function() {
				Settle( p2, REJECTED,
					new Error(msg || "Timed out after " + ms + " ms") );
			}, ms);

			Append(p, function() {
				clearTimeout( timeoutId );
				Settle( p2, p._state, p._value );
			});
		}

		return p2;
	};

	Promise.prototype.delay = function( ms ) {
		var p = this;
		var p2 = new Promise();
		setTimeout(function() {
			Resolve( p2, p );
		}, ms);
		return p2;
	};

	Promise.prototype.inspect = function() {
		switch ( this._state ) {
			case PENDING:   return { state: "pending" };
			case FULFILLED: return { state: "fulfilled", value: this._value };
			case REJECTED:  return { state: "rejected", reason: this._value };
			default: throw new TypeError("invalid state");
		}
	};

	P.allSettled = allSettled;
	function allSettled( promises ) {
		var waiting = 0;
		var finalPromise = new Promise();
		var results = [];
		each( promises, function( promise, index ) {
			var p = P( promise );
			if ( p._state === PENDING ) {
				++waiting;
				Append(p, function() {
					results[ index ] = p.inspect();
					if ( --waiting === 0 ) {
						Settle( finalPromise, FULFILLED, results );
					}
				});
			} else {
				results[ index ] = p.inspect();
			}
		});
		if ( waiting === 0 ) {
			Settle( finalPromise, FULFILLED, results );
		}
		return finalPromise;
	}

	P.all = all;
	function all( promises ) {
		var waiting = 0;
		var d = defer();
		each( promises, function( promise, index ) {
			var p = P( promise );
			if ( p._state === PENDING ) {
				++waiting;
				p.then(function( value ) {
					promises[ index ] = value;
					if ( --waiting === 0 ) {
						d.resolve( promises );
					}
				}, d.reject);

			} else {
				promises[ index ] = p._value;
			}
		});
		if ( waiting === 0 ) {
			d.resolve( promises );
		}
		return d.promise;
	}

	P.onerror = null;

	P.nextTick = function( f ) {
		runLater(function() {
			try {
				f();

			} catch ( ex ) {
				setTimeout(function() {
					throw ex;
				}, 0);
			}
		});
	};

	P._each = each;

	return P;
});
<commit_msg>Rename operation `Append` to `OnSettled`.<commit_after>;(function( factory ){
	// CommonJS
	if ( typeof module !== "undefined" && module && module.exports ) {
		module.exports = factory();

	// RequireJS
	} else if ( typeof define === "function" && define.amd ) {
		define( factory );

	// global
	} else {
		P = factory();
	}
})(function() {
	"use strict";

	var
		head = { f: null, n: null }, tail = head,
		running = false,

		channel, // MessageChannel
		requestTick, // --> requestTick( onTick, 0 )

		// window or worker
		wow = ot(typeof window) && window || ot(typeof worker) && worker,

		toStr = ({}).toString,
		isArray;

	function onTick() {
		while ( head.n ) {
			head = head.n;
			var f = head.f;
			head.f = null;
			f();
		}
		running = false;
	}

	var runLater = function( f ) {
		tail = tail.n = { f: f, n: null };
		if ( !running ) {
			running = true;
			requestTick( onTick, 0 );
		}
	};

	function ot( type ) {
		return type === "object" || type === "function";
	}

	function ft( type ) {
		return type === "function";
	}

	if ( ot(typeof process) && process && process.nextTick ) {
		requestTick = process.nextTick;

	} else if ( ft(typeof setImmediate) ) {
		requestTick = wow ?
			function( cb ) {
				wow.setImmediate( cb );
			} :
			function( cb ) {
				setImmediate( cb );
			};

	} else if ( ft(typeof MessageChannel) ) {
		channel = new MessageChannel();
		channel.port1.onmessage = onTick;
		requestTick = function() {
			channel.port2.postMessage(0);
		};

	} else {
		requestTick = setTimeout;

		if ( wow && ot(typeof Image) && Image ) {
			(function(){
				var c = 0;

				var requestTickViaImage = function( cb ) {
					var img = new Image();
					img.onerror = cb;
					img.src = 'data:image/png,';
				};

				// Before using it, test if it works properly, with async dispatching.
				try {
					requestTickViaImage(function() {
						if ( --c === 0 ) {
							requestTick = requestTickViaImage;
						}
					});
					++c;
				} catch (e) {}

				// Also use it only if faster then setTimeout.
				c && setTimeout(function() {
					c = 0;
				}, 0);
			})();
		}
	}

	//__________________________________________________________________________

	isArray = Array.isArray || function( val ) {
		return !!val && toStr.call( val ) === "[object Array]";
	};

	function forEach( arr, cb ) {
		for ( var i = 0, l = arr.length; i < l; ++i ) {
			if ( i in arr ) {
				cb( arr[i], i );
			}
		}
	}

	function each( obj, cb ) {
		if ( isArray(obj) ) {
			forEach( obj, cb );
			return;
		}

		for ( var prop in obj ) {
			cb( obj[prop], prop );
		}
	}

	function reportError( error ) {
		try {
			if ( P.onerror ) {
				P.onerror( error );
			} else {
				throw error;
			}

		} catch ( e ) {
			setTimeout(function() {
				throw e;
			}, 0);
		}
	}

	var PENDING = 0;
	var FULFILLED = 1;
	var REJECTED = 2;

	function P( x ) {
		return x instanceof Promise ?
			x :
			Resolve( new Promise(), x );
	}

	function Settle( p, state, value ) {
		if ( p._state ) {
			return p;
		}

		p._state = state;
		p._value = value;

		if ( p._pending.length > 0 ) {
			forEach( p._pending, runLater );
		}
		p._pending = null;

		return p;
	}

	function OnSettled( p, f ) {
		p._pending.push( f );
		//p._tail = p._tail.n = { f: f, n: null };
	}

	function Resolve( p, x ) {
		if ( p._state ) {
			return p;
		}

		if ( x instanceof Promise ) {
			if ( x._state ) {
				Settle( p, x._state, x._value );

			} else {
				OnSettled(x, function() {
					Settle( p, x._state, x._value );
				});
			}

		} else if ( x !== Object(x) ) {
			Settle( p, FULFILLED, x );

		} else {
			runLater(function() {
				try {
					var then = x.then;

					if ( typeof then === "function" ) {
						var r = resolverFor( p, x );
						then.call( x, r.resolve, r.reject );

					} else {
						Settle( p, FULFILLED, x );
					}

				} catch ( e ) {
					Settle( p, REJECTED, e );
				}
			});
		}

		return p;
	}

	function resolverFor( promise, x ) {
		var done = false;

		return {
			promise: promise,

			resolve: function( y ) {
				if ( !done ) {
					done = true;

					if ( x && x === y ) {
						Settle( promise, FULFILLED, y );

					} else {
						Resolve( promise, y );
					}
				}
			},

			reject: function( reason ) {
				if ( !done ) {
					done = true;
					Settle( promise, REJECTED, reason );
				}
			}
		};
	}

	P.defer = defer;
	function defer() {
		return resolverFor( new Promise() );
	}

	function Promise() {
		this._state = 0;
		this._value = void 0;
		this._pending = [];
	}

	Promise.prototype.then = function( onFulfilled, onRejected ) {
		var cb = typeof onFulfilled === "function" ? onFulfilled : null;
		var eb = typeof onRejected === "function" ? onRejected : null;

		var p = this;
		var p2 = new Promise();

		function onSettled() {
			var x, func = p._state === FULFILLED ? cb : eb;

			if ( func !== null ) {
				try {
					x = func( p._value );

				} catch ( e ) {
					Settle( p2, REJECTED, e );
					return;
				}

				Resolve( p2, x );

			} else {
				Settle( p2, p._state, p._value );
			}
		}

		if ( p._state === PENDING ) {
			OnSettled( p, onSettled );

		} else {
			runLater( onSettled );
		}

		return p2;
	};

	Promise.prototype.done = function( cb, eb ) {
		var p = this;

		if ( cb || eb ) {
			p = p.then( cb, eb );
		}

		p.then( null, reportError );
	};

	Promise.prototype.fail = function( eb ) {
		return this.then( null, eb );
	};

	Promise.prototype.spread = function( cb, eb ) {
		return this.then(cb && function( array ) {
			return all( array ).then(function( values ) {
				return cb.apply( void 0, values );
			});
		}, eb);
	};

	Promise.prototype.timeout = function( ms, msg ) {
		var p = this;
		var p2 = new Promise();

		if ( p._state !== PENDING ) {
			Settle( p2, p._state, p._value );

		} else {
			var timeoutId = setTimeout(function() {
				Settle( p2, REJECTED,
					new Error(msg || "Timed out after " + ms + " ms") );
			}, ms);

			OnSettled(p, function() {
				clearTimeout( timeoutId );
				Settle( p2, p._state, p._value );
			});
		}

		return p2;
	};

	Promise.prototype.delay = function( ms ) {
		var p = this;
		var p2 = new Promise();
		setTimeout(function() {
			Resolve( p2, p );
		}, ms);
		return p2;
	};

	Promise.prototype.inspect = function() {
		switch ( this._state ) {
			case PENDING:   return { state: "pending" };
			case FULFILLED: return { state: "fulfilled", value: this._value };
			case REJECTED:  return { state: "rejected", reason: this._value };
			default: throw new TypeError("invalid state");
		}
	};

	P.allSettled = allSettled;
	function allSettled( promises ) {
		var waiting = 0;
		var finalPromise = new Promise();
		var results = [];
		each( promises, function( promise, index ) {
			var p = P( promise );
			if ( p._state === PENDING ) {
				++waiting;
				OnSettled(p, function() {
					results[ index ] = p.inspect();
					if ( --waiting === 0 ) {
						Settle( finalPromise, FULFILLED, results );
					}
				});
			} else {
				results[ index ] = p.inspect();
			}
		});
		if ( waiting === 0 ) {
			Settle( finalPromise, FULFILLED, results );
		}
		return finalPromise;
	}

	P.all = all;
	function all( promises ) {
		var waiting = 0;
		var d = defer();
		each( promises, function( promise, index ) {
			var p = P( promise );
			if ( p._state === PENDING ) {
				++waiting;
				p.then(function( value ) {
					promises[ index ] = value;
					if ( --waiting === 0 ) {
						d.resolve( promises );
					}
				}, d.reject);

			} else {
				promises[ index ] = p._value;
			}
		});
		if ( waiting === 0 ) {
			d.resolve( promises );
		}
		return d.promise;
	}

	P.onerror = null;

	P.nextTick = function( f ) {
		runLater(function() {
			try {
				f();

			} catch ( ex ) {
				setTimeout(function() {
					throw ex;
				}, 0);
			}
		});
	};

	P._each = each;

	return P;
});
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');
const {tmpdir} = require('os');

const {join, basename} = path;

const rimraf = require('rimraf');
const mkdirp = require('mkdirp');
const test = require('supertape');
const copymitter = require('..');

const temp = () => {
    return fs.mkdtempSync(path.join(tmpdir(), `copymitter-`));
};

test('file: no args', (t) => {
    t.throws(copymitter, /from should be a string!/, 'should throw when no args');
    t.end();
});

test('file: no to', (t) => {
    const fn = () => copymitter('/hello');
    t.throws(fn, /to should be a string!/, 'should throw when no to');
    t.end();
});

test('file: no files', (t) => {
    const fn = () => copymitter('/hello', '/world');
    t.throws(fn, /files should be an array!/, 'should throw when no args');
    t.end();
});

test('file: error EACESS', (t) => {
    const cp = copymitter(__dirname, '/', [
        path.basename(__filename),
    ]);

    cp.on('error', (error) => {
        t.equal(error.code, 'EACCES', error.message);
        cp.abort();
    });

    cp.on('end', () => {
        t.end();
    });
});

test('directory: error EACESS', (t) => {
    const from = path.join(__dirname, '..');
    const name = 'package.json';

    const cp = copymitter(from, '/', [
        name,
    ]);

    cp.on('error', (error) => {
        t.equal(error.code, 'EACCES', error.message);
        cp.abort();
    });

    cp.on('end', () => {
        t.end();
    });
});

test('copy 1 file: to: src', (t) => {
    const from = path.join(__dirname, '/../lib/');
    const to = temp();
    const name = path.basename(__filename);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (src) => {
        const fromFull = path.join(from, name);
        const toFull = path.join(to, name);

        t.equal(src, fromFull, 'file paths should be equal');
        fs.unlinkSync(toFull);
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to: dest', (t) => {
    const from = path.join(__dirname, '/../lib/');
    const to = temp();
    const name = path.basename(__filename);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (src, dest) => {
        const full = path.join(to, name);

        t.equal(dest, full, 'file paths should be equal');
        fs.unlinkSync(full);
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to (error: ENOENT, create dir error)', (t) => {
    const {mkdir} = fs;
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    let was;
    fs.mkdir = (name, mode, cb) => {
        if (was)
            return cb(Error('NOT EEXIST'));

        was = true;

        cb();
    };

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('error', (error) => {
        t.ok(error, 'should be error: ' + error.message);
        cp.abort();
    });

    cp.on('end', () => {
        fs.mkdir = mkdir;
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to (directory exist)', (t) => {
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    mkdirp.sync(path.join(to, 'lib', 'copymitter.js'));

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('progress', (n) => {
        if (n === 100)
            t.pass('should equal');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to (directory exist, error mkdir)', (t) => {
    const {mkdir} = fs;
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    let was;

    stub('mkdirp', async () => {
        if (was)
            throw Error('NOT EEXIST');

        was = true;
    });

    const copymitter = rerequire('..');

    mkdirp.sync(path.join(to, 'lib', 'copymitter.js'));

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('error', (error) => {
        t.ok(error, 'should be error: ' + error.message);
        cp.abort();
    });

    cp.on('end', () => {
        fs.mkdir = mkdir;
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: from', (t) => {
    const from = path.join(__dirname, '/../lib/');
    const to = temp();
    const name = path.basename(__filename);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (file) => {
        const full = path.join(from, name);

        const dataFile = fs.readFileSync(file, 'utf8');
        const dataFull = fs.readFileSync(full, 'utf8');
        const statFile = fs.statSync(file);
        const statFull = fs.statSync(full);

        t.equal(dataFile, dataFull, 'files data should be equal');
        t.equal(statFile.mode, statFull.mode, 'fils mode should be equal');
        fs.unlinkSync(path.join(to, name));
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: from: symlink', (t) => {
    const from = path.join(__dirname, 'fixture');
    const to = temp();

    const name = 'symlink';

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (file) => {
        const full = path.join(from, name);

        const dataFile = fs.readFileSync(file, 'utf8');
        const dataFull = fs.readFileSync(full, 'utf8');
        const statFile = fs.statSync(file);
        const statFull = fs.statSync(full);

        t.equal(dataFile, dataFull, 'files data should be equal');
        t.equal(statFile.mode, statFull.mode, 'fils mode should be equal');
        fs.unlinkSync(path.join(to, name));
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy directories: exist', (t) => {
    const to = temp();
    const from = join(__dirname);
    const name = basename(__filename);
    const names = [
        name,
    ];

    const cp = copymitter(from, to, names);

    cp.on('end', () => {
        const dir = join(to, name);
        const stat = fs.statSync(dir);

        rimraf.sync(to);

        t.ok(stat, 'should copy dir');
        t.end();
    });
});

test('copy directories: emit: src', (t) => {
    const from = __dirname;
    const to = temp();
    const name = path.basename(__filename);
    const names = [
        name,
    ];

    const cp = copymitter(from, to, names);

    cp.once('directory', (src) => {
        t.ok(src, 'should emit directory name');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });

});

test('copy directories: emit: dest', (t) => {
    const from = __dirname;
    const to = temp();
    const name = path.basename(__filename);
    const names = [
        name,
    ];

    const cp = copymitter(from, to, names);

    cp.once('directory', (src, dest) => {
        t.ok(dest, 'should emit "dest"');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });

});

test('file: error ENOENT', (t) => {
    const from = '/';
    const to = temp();

    const cp = copymitter(from, to, [
        Math.random()
            .toString(),
    ]);

    cp.on('error', (error) => {
        t.equal(error.code, 'ENOENT', error.message);
        cp.abort();
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('pause/continue', (t) => {
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    mkdirp.sync(to);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('pause', () => {
        t.pass('should emit pause');
        cp.continue();
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });

    cp.pause();
});

function stub(name, fn) {
    require.cache[require.resolve(name)].exports = fn;
}

function rerequire(name) {
    delete require.cache[require.resolve(name)];
    return require(name);
}

<commit_msg>chore(copymitter) lint<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const {tmpdir} = require('os');

const {join, basename} = path;

const rimraf = require('rimraf');
const mkdirp = require('mkdirp');
const test = require('supertape');
const copymitter = require('..');

const temp = () => {
    return fs.mkdtempSync(path.join(tmpdir(), `copymitter-`));
};

test('file: no args', (t) => {
    t.throws(copymitter, /from should be a string!/, 'should throw when no args');
    t.end();
});

test('file: no to', (t) => {
    const fn = () => copymitter('/hello');
    t.throws(fn, /to should be a string!/, 'should throw when no to');
    t.end();
});

test('file: no files', (t) => {
    const fn = () => copymitter('/hello', '/world');
    t.throws(fn, /files should be an array!/, 'should throw when no args');
    t.end();
});

test('file: error EACESS', (t) => {
    const cp = copymitter(__dirname, '/', [
        path.basename(__filename),
    ]);

    cp.on('error', (error) => {
        t.equal(error.code, 'EACCES', error.message);
        cp.abort();
    });

    cp.on('end', () => {
        t.end();
    });
});

test('directory: error EACESS', (t) => {
    const from = path.join(__dirname, '..');
    const name = 'package.json';

    const cp = copymitter(from, '/', [
        name,
    ]);

    cp.on('error', (error) => {
        t.equal(error.code, 'EACCES', error.message);
        cp.abort();
    });

    cp.on('end', () => {
        t.end();
    });
});

test('copy 1 file: to: src', (t) => {
    const from = path.join(__dirname, '/../lib/');
    const to = temp();
    const name = path.basename(__filename);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (src) => {
        const fromFull = path.join(from, name);
        const toFull = path.join(to, name);

        t.equal(src, fromFull, 'file paths should be equal');
        fs.unlinkSync(toFull);
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to: dest', (t) => {
    const from = path.join(__dirname, '/../lib/');
    const to = temp();
    const name = path.basename(__filename);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (src, dest) => {
        const full = path.join(to, name);

        t.equal(dest, full, 'file paths should be equal');
        fs.unlinkSync(full);
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to (error: ENOENT, create dir error)', (t) => {
    const {mkdir} = fs;
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    let was;
    fs.mkdir = (name, mode, cb) => {
        if (was)
            return cb(Error('NOT EEXIST'));

        was = true;

        cb();
    };

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('error', (error) => {
        t.ok(error, 'should be error: ' + error.message);
        cp.abort();
    });

    cp.on('end', () => {
        fs.mkdir = mkdir;
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to (directory exist)', (t) => {
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    mkdirp.sync(path.join(to, 'lib', 'copymitter.js'));

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('progress', (n) => {
        if (n === 100)
            t.pass('should equal');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: to (directory exist, error mkdir)', (t) => {
    const {mkdir} = fs;
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    let was;

    stub('mkdirp', async () => {
        if (was)
            throw Error('NOT EEXIST');

        was = true;
    });

    const copymitter = rerequire('..');

    mkdirp.sync(path.join(to, 'lib', 'copymitter.js'));

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('error', (error) => {
        t.ok(error, 'should be error: ' + error.message);
        cp.abort();
    });

    cp.on('end', () => {
        fs.mkdir = mkdir;
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: from', (t) => {
    const from = path.join(__dirname, '/../lib/');
    const to = temp();
    const name = path.basename(__filename);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (file) => {
        const full = path.join(from, name);

        const dataFile = fs.readFileSync(file, 'utf8');
        const dataFull = fs.readFileSync(full, 'utf8');
        const statFile = fs.statSync(file);
        const statFull = fs.statSync(full);

        t.equal(dataFile, dataFull, 'files data should be equal');
        t.equal(statFile.mode, statFull.mode, 'fils mode should be equal');
        fs.unlinkSync(path.join(to, name));
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy 1 file: from: symlink', (t) => {
    const from = path.join(__dirname, 'fixture');
    const to = temp();

    const name = 'symlink';

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('file', (file) => {
        const full = path.join(from, name);

        const dataFile = fs.readFileSync(file, 'utf8');
        const dataFull = fs.readFileSync(full, 'utf8');
        const statFile = fs.statSync(file);
        const statFull = fs.statSync(full);

        t.equal(dataFile, dataFull, 'files data should be equal');
        t.equal(statFile.mode, statFull.mode, 'fils mode should be equal');
        fs.unlinkSync(path.join(to, name));
    });

    cp.on('progress', (progress) => {
        t.equal(progress, 100, 'progress');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy directories: exist', (t) => {
    const to = temp();
    const from = join(__dirname);
    const name = basename(__filename);
    const names = [
        name,
    ];

    const cp = copymitter(from, to, names);

    cp.on('end', () => {
        const dir = join(to, name);
        const stat = fs.statSync(dir);

        rimraf.sync(to);

        t.ok(stat, 'should copy dir');
        t.end();
    });
});

test('copy directories: emit: src', (t) => {
    const from = __dirname;
    const to = temp();
    const name = path.basename(__filename);
    const names = [
        name,
    ];

    const cp = copymitter(from, to, names);

    cp.once('directory', (src) => {
        t.ok(src, 'should emit directory name');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('copy directories: emit: dest', (t) => {
    const from = __dirname;
    const to = temp();
    const name = path.basename(__filename);
    const names = [
        name,
    ];

    const cp = copymitter(from, to, names);

    cp.once('directory', (src, dest) => {
        t.ok(dest, 'should emit "dest"');
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('file: error ENOENT', (t) => {
    const from = '/';
    const to = temp();

    const cp = copymitter(from, to, [
        Math.random()
            .toString(),
    ]);

    cp.on('error', (error) => {
        t.equal(error.code, 'ENOENT', error.message);
        cp.abort();
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });
});

test('pause/continue', (t) => {
    const from = path.join(__dirname, '..');
    const to = temp();
    const name = 'lib';

    mkdirp.sync(to);

    const cp = copymitter(from, to, [
        name,
    ]);

    cp.on('pause', () => {
        t.pass('should emit pause');
        cp.continue();
    });

    cp.on('end', () => {
        rimraf.sync(to);
        t.end();
    });

    cp.pause();
});

function stub(name, fn) {
    require.cache[require.resolve(name)].exports = fn;
}

function rerequire(name) {
    delete require.cache[require.resolve(name)];
    return require(name);
}

<|endoftext|>


<commit_before>var readline = require('readline');
var P = require('./lib/nml/parser');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
var util = require('util');

var buffer = '';

function p(obj) {
  console.log(util.inspect(obj, {depth: 16, colors: true}));
}

function runCode(code) {
  console.log('----');
  try {
    p(P.codeToAst(code));
  } catch(err) {
    console.log('Syntax error\n'+err);
  }
}

function doPrompt() {
  rl.question('>', function(input) {
    if(input.trim() == '.run') {
      runCode(buffer);
      buffer = '';
    } else {
      buffer += input + "\n";
    }
    doPrompt();
  });
}

doPrompt();
<commit_msg>crash debug repl when there is a bug<commit_after>var readline = require('readline');
var P = require('./lib/nml/parser');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
var util = require('util');

var buffer = '';

function p(obj) {
  console.log(util.inspect(obj, {depth: 16, colors: true}));
}

function runCode(code) {
  console.log('----');
  //try {
    p(P.codeToAst(code));
  //} catch(err) {
    //console.log('Syntax error\n'+err);
  //}
}

function doPrompt() {
  rl.question('>', function(input) {
    if(input.trim() == '.run') {
      runCode(buffer);
      buffer = '';
    } else {
      buffer += input + "\n";
    }
    doPrompt();
  });
}

doPrompt();
<|endoftext|>


<commit_before>const Client = require('node-rest-client').Client;
const moment = require('moment');
const util = require('util');
const Series = require('time-series-data-generator');
const csv = require('csv');
const fs = require('fs');

const rootUrl = "https://ml.nexosis.com/v1/";

const key = process.env.NEXOSIS_API_KEY;

if(!key) {
    throw new Error("NEXOSIS_API_KEY environment variable must be set");
}

const devNull = err=> {};

const client = new Client();

const action = process.argv[2] || "lastsession";

if(action === "forecast") {
    let interval = 'day';
    if(process.argv.length >= 4) {
        interval = process.argv[3];
    }
    postPredictionJob(interval, dumpResponse);
}

if(action === "sessions") {
    getSessions(dumpResponse);
}

if(action === "getsession") {
    getSession(process.argv[3], dumpResponse);
}

if(action === "lastsession") {
    getSessions(data=> getLastSession(data));
}

if(action === "results") {
    let csvPath = undefined;

    if(process.argv.length >= 4) {
        csvPath = process.argv[3];
    }

    getSessions(data=> getResultsForLastSession(data, csvPath));
}

if(action === "getforecast") {
    getForecast(process.argv[3], dumpResponse);
}

if(action === "model") {
    getModel(process.argv[3], dumpResponse);
}

if(action == "put") {
    let name = "foo";
    if(process.argv.length >= 4) {
        name = process.argv[3];
    }

    putData(name, dumpResponse);
}

if(action === "data") {
    if(process.argv.length < 4) {
        listDataSets(dumpResponse);
    }
    else {
        let csvPath = undefined;
        if(process.argv.length >= 5) {
            csvPath = process.argv[4];
        }
        console.log(process.argv, csvPath, process.argv.length);
        getData(process.argv[3], dumpResponse, csvPath);
    }

}

function dumpResponse(data, response) {
    console.log(response.headers);
    if(response.statusCode !== 200) {
        console.log(response);
    }
    console.log(util.inspect(data, false, null));
}

function putData(name, callback) {
    let args = defaultArgs();
    args.data = fakeData();

    client.put(`${rootUrl}data/${name}`, args, function(data, response) {
        callback(data, response);
    });

}

function getSession(id, callback) {
    let args = defaultArgs();
    client.get(`${rootUrl}sessions/${id}`, args, function(data, response) {
        callback(data, response);
    });
}

function getLastSession(sessions) {
    const session = sessions.items[sessions.items.length-1];
    getSession(session.sessionId, dumpResponse);

}

function getResultsForLastSession(sessions, csvPath) {
    const session = sessions.items[sessions.items.length-1].sessionId;
    getSessionResults(session, dumpResponse, csvPath);
}

function defaultArgs() {
    var args = {
        headers: { "api-key": key, "Content-Type": "application/json" },
    };
    return args;
}

function fakeData(interval) {
    let data = {data: []};
    let until = moment.utc().startOf(interval).subtract(1, `${interval}s`);
    let from = moment.utc().startOf(interval).subtract(1, `${interval}s`).subtract(100, `${interval}s`);

    var duration = moment.duration(1, `${interval}s`).asSeconds();

    var series = new Series({ from: from.toISOString(), until: until.toISOString(), interval: duration, keyName: "foo"});
    var seriesBar = series.clone({keyName: "bar"});

    var opts = {coefficient: 40, constant: 50,  decimalDigits: 0, period: duration*10};

    var barData = seriesBar.cos(opts)
    data.data = series.sin(opts);

    for(let i = 0; i < data.data.length; i++) {
        data.data[i].bar = barData[i].bar;
    }

    return data;
}

function postPredictionJob(interval, callback) {
    var args = defaultArgs();
    args.data = fakeData(interval);

    let start = moment.utc().startOf(interval);
    let end = moment.utc().startOf(interval).add(30, `${interval}s`);

    client.post(`${rootUrl}sessions/forecast?startDate=${start.toISOString()}&endDate=${end.toISOString()}&targetColumn=foo&resultInterval=${interval}`, args, function (data, response) {
    callback(data, response);
    });
}

function getSessions(callback) {
    var args = defaultArgs();
    client.get(`${rootUrl}sessions`, args, function(data, response) {
        callback(data, response);
    });
}

function getSessionResults(id, callback, csvPath) {
    var args = defaultArgs();
    client.get(`${rootUrl}sessions/${id}/results`, args, function(data, response) {
        callback(data, response);
        if(csvPath) {
            csv.stringify(data.data, {header: true}, (err,csvData)=>fs.writeFile(csvPath,csvData, devNull));
        }
    });
}

function getModel(dataSetName, callback) {
    var args = defaultArgs();
    let url = `${rootUrl}data/${dataSetName}/forecast/model`;
    client.get(url, args, function(data, response) {
        callback(data, response);
    });
}

function getForecast(dataSetName, callback) {
    var args = defaultArgs();
    let url = `${rootUrl}data/${dataSetName}/forecast`;
    client.get(url, args, function(data, response) {
        callback(data, response);
    });
}

function getData(dataSetName, callback, csvPath) {
    var args = defaultArgs();
    let url = `${rootUrl}data/${dataSetName}`;
    client.get(url, args, function(data, response) {
        callback(data, response);
        if(csvPath) {
            csv.stringify(data.data, {header: true},  (err,csvData)=>fs.writeFile(csvPath,csvData, devNull));
        }
    });
}

function listDataSets(callback) {
    var args = defaultArgs();
    client.get(`${rootUrl}data`, args, function(data, response) {
        callback(data, response);
    });
}<commit_msg>Update sample<commit_after>const Client = require('node-rest-client').Client;
const moment = require('moment');
const util = require('util');
const Series = require('time-series-data-generator');
const csv = require('csv');
const fs = require('fs');

const rootUrl = "https://ml.nexosis.com/v1/";

const key = process.env.NEXOSIS_API_KEY;

if(!key) {
    throw new Error("NEXOSIS_API_KEY environment variable must be set");
}

const devNull = err=> {};

const client = new Client();

const action = process.argv[2] || "lastsession";

if(action === "forecast") {
    let interval = 'day';
    let dataSet = 'foo';
    if(process.argv.length >= 4) {
        dataSet = process.argv[3];
    }

    if(process.argv.length >= 5) {
        interval = process.argv[4];
    }

    deleteData(dataSet);
    putData(dataSet, interval)
    postPredictionJob(dataSet, interval, dumpResponse);
}

if(action === "sessions") {
    getSessions(dumpResponse);
}

if(action === "getsession") {
    getSession(process.argv[3], dumpResponse);
}

if(action === "lastsession") {
    getSessions(data=> getLastSession(data));
}

if(action === "results") {
    let csvPath = undefined;

    if(process.argv.length >= 4) {
        csvPath = process.argv[3];
    }

    getSessions(data=> getResultsForLastSession(data, csvPath));
}

if(action === "getforecast") {
    getForecast(process.argv[3], dumpResponse);
}

if(action === "model") {
    getModel(process.argv[3], dumpResponse);
}

if(action == "put") {
    let name = "foo";
    if(process.argv.length >= 4) {
        name = process.argv[3];
    }
    deleteData(dataSet);
    putData(name, 'day', dumpResponse);
}

if(action === "data") {
    if(process.argv.length < 4) {
        listDataSets(dumpResponse);
    }
    else {
        let csvPath = undefined;
        if(process.argv.length >= 5) {
            csvPath = process.argv[4];
        }
        console.log(process.argv, csvPath, process.argv.length);
        getData(process.argv[3], dumpResponse, csvPath);
    }

}

function dumpResponse(data, response) {
    console.log(response.headers);
    if(response.statusCode !== 200) {
        console.log(response);
    }
    console.log(util.inspect(data, false, null));
}

function deleteData(name) {
    let args = defaultArgs();

    client.delete(`${rootUrl}data/${name}`, args, function(data, response) {
    });

}

function putData(name, interval, callback) {
    let args = defaultArgs();
    args.data = fakeData(interval);

    client.put(`${rootUrl}data/${name}`, args, function(data, response) {
        if(callback) {
            callback(data, response);
        }
    });

}

function getSession(id, callback) {
    let args = defaultArgs();
    client.get(`${rootUrl}sessions/${id}`, args, function(data, response) {
        callback(data, response);
    });
}

function getLastSession(sessions) {
    const session = sessions.items[sessions.items.length-1];
    getSession(session.sessionId, dumpResponse);

}

function getResultsForLastSession(sessions, csvPath) {
    const session = sessions.items[sessions.items.length-1].sessionId;
    getSessionResults(session, dumpResponse, csvPath);
}

function defaultArgs() {
    var args = {
        headers: { "api-key": key, "Content-Type": "application/json" },
    };
    return args;
}

function fakeData(interval) {
    let data = {data: []};
    let until = moment.utc().startOf(interval).subtract(1, `${interval}s`);
    let from = moment.utc().startOf(interval).subtract(1, `${interval}s`).subtract(100, `${interval}s`);

    var duration = moment.duration(1, `${interval}s`).asSeconds();

    var series = new Series({ from: from.toISOString(), until: until.toISOString(), interval: duration, keyName: "foo"});
    var seriesBar = series.clone({keyName: "bar"});

    var opts = {coefficient: 40, constant: 50,  decimalDigits: 0, period: duration*10};

    var barData = seriesBar.cos(opts)
    data.data = series.sin(opts);

    for(let i = 0; i < data.data.length; i++) {
        data.data[i].bar = barData[i].bar;
    }

    return data;
}

function postPredictionJob(dataSet, interval, callback) {
    var args = defaultArgs();

    let start = moment.utc().startOf(interval);
    let end = moment.utc().startOf(interval).add(30, `${interval}s`);

    client.post(`${rootUrl}sessions/forecast?dataSetName=${dataSet}&startDate=${start.toISOString()}&endDate=${end.toISOString()}&targetColumn=foo&resultInterval=${interval}`, args, function (data, response) {
    callback(data, response);
    });
}

function getSessions(callback) {
    var args = defaultArgs();
    client.get(`${rootUrl}sessions`, args, function(data, response) {
        callback(data, response);
    });
}

function getSessionResults(id, callback, csvPath) {
    var args = defaultArgs();
    client.get(`${rootUrl}sessions/${id}/results`, args, function(data, response) {
        callback(data, response);
        if(csvPath) {
            csv.stringify(data.data, {header: true}, (err,csvData)=>fs.writeFile(csvPath,csvData, devNull));
        }
    });
}

function getModel(dataSetName, callback) {
    var args = defaultArgs();
    let url = `${rootUrl}data/${dataSetName}/forecast/model`;
    client.get(url, args, function(data, response) {
        callback(data, response);
    });
}

function getForecast(dataSetName, callback) {
    var args = defaultArgs();
    let url = `${rootUrl}data/${dataSetName}/forecast`;
    client.get(url, args, function(data, response) {
        callback(data, response);
    });
}

function getData(dataSetName, callback, csvPath) {
    var args = defaultArgs();
    let url = `${rootUrl}data/${dataSetName}`;
    client.get(url, args, function(data, response) {
        callback(data, response);
        if(csvPath) {
            csv.stringify(data.data, {header: true},  (err,csvData)=>fs.writeFile(csvPath,csvData, devNull));
        }
    });
}

function listDataSets(callback) {
    var args = defaultArgs();
    client.get(`${rootUrl}data`, args, function(data, response) {
        callback(data, response);
    });
}<|endoftext|>


<commit_before>'use strict';

var Node = require('../node');
var dot = require('dot');

var TYPE = 'weighted_centroid';

var PARAMS = {
    source : Node.PARAM.NODE(Node.GEOMETRY.POINT),
    weight_column : Node.PARAM.STRING,
    category_column : Node.PARAM.STRING
};

var WeightedCentroid  = Node.create(TYPE, PARAMS, {cache: false});

module.exports = WeightedCentroid;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

var weightedCentroidTemplate = dot.template([
    'SELECT the_geom , class',
    'FROM cdb_crankshaft.CDB_WeightedMean(\'{{=it.query}}\',\'{{=it.weight_col}}\',\'{{=it.category_col}}\')'
].join('\n'));

function query(it) {
    return weightedCentroidTemplate(it);
}

WeightedCentroid.prototype.sql = function(){
    return query({
        query : this.source.getQuery(),
        weight_column : this.weight_column,
        category_column : this.category_column
    });
};

<commit_msg>missed col -> columns<commit_after>'use strict';

var Node = require('../node');
var dot = require('dot');

var TYPE = 'weighted_centroid';

var PARAMS = {
    source : Node.PARAM.NODE(Node.GEOMETRY.POINT),
    weight_column : Node.PARAM.STRING,
    category_column : Node.PARAM.STRING
};

var WeightedCentroid  = Node.create(TYPE, PARAMS, {cache: false});

module.exports = WeightedCentroid;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

var weightedCentroidTemplate = dot.template([
    'SELECT the_geom , class',
    'FROM cdb_crankshaft.CDB_WeightedMean(\'{{=it.query}}\',\'{{=it.weight_column}}\',\'{{=it.category_column}}\')'
].join('\n'));

function query(it) {
    return weightedCentroidTemplate(it);
}

WeightedCentroid.prototype.sql = function(){
    return query({
        query : this.source.getQuery(),
        weight_column : this.weight_column,
        category_column : this.category_column
    });
};

<|endoftext|>


<commit_before>"use babel";

import store from "./../store";
import { grammarToLanguage } from "./../utils";
/**
 * @version 1.0.0
 *
 *
 * The Plugin API allows you to make Hydrogen awesome.
 * You will be able to interact with this class in your Hydrogen Plugin using
 * Atom's [Service API](http://blog.atom.io/2015/03/25/new-services-API.html).
 *
 * Take a look at our [Example Plugin](https://github.com/lgeiger/hydrogen-example-plugin)
 * and the [Atom Flight Manual](http://flight-manual.atom.io/hacking-atom/) for
 * learning how to interact with Hydrogen in your own plugin.
 *
 * @class HydrogenProvider
 */
export default class HydrogenProvider {
  constructor(_hydrogen) {
    this._hydrogen = _hydrogen;
    this._happy = true;
  }

  /*
   * Calls your callback when the kernel has changed.
   * @param {Function} Callback
   */
  onDidChangeKernel(callback) {
    this._hydrogen.emitter.on("did-change-kernel", kernel => {
      if (kernel) {
        return callback(kernel.getPluginWrapper());
      }
      return callback(null);
    });
  }

  /*
   * Get the `HydrogenKernel` of the currently active text editor.
   * @return {Class} `HydrogenKernel`
   */
  getActiveKernel() {
    if (!store.kernel) {
      const grammar = store.editor.getGrammar();
      const language = grammarToLanguage(grammar);
      throw new Error(`No running kernel for language \`${language}\` found`);
    }

    return store.kernel.getPluginWrapper();
  }
}
<commit_msg>HydrogenProvider: Remove use of grammarToLanguage<commit_after>"use babel";

import store from "./../store";
/**
 * @version 1.0.0
 *
 *
 * The Plugin API allows you to make Hydrogen awesome.
 * You will be able to interact with this class in your Hydrogen Plugin using
 * Atom's [Service API](http://blog.atom.io/2015/03/25/new-services-API.html).
 *
 * Take a look at our [Example Plugin](https://github.com/lgeiger/hydrogen-example-plugin)
 * and the [Atom Flight Manual](http://flight-manual.atom.io/hacking-atom/) for
 * learning how to interact with Hydrogen in your own plugin.
 *
 * @class HydrogenProvider
 */
export default class HydrogenProvider {
  constructor(_hydrogen) {
    this._hydrogen = _hydrogen;
    this._happy = true;
  }

  /*
   * Calls your callback when the kernel has changed.
   * @param {Function} Callback
   */
  onDidChangeKernel(callback) {
    this._hydrogen.emitter.on("did-change-kernel", kernel => {
      if (kernel) {
        return callback(kernel.getPluginWrapper());
      }
      return callback(null);
    });
  }

  /*
   * Get the `HydrogenKernel` of the currently active text editor.
   * @return {Class} `HydrogenKernel`
   */
  getActiveKernel() {
    if (!store.kernel) {
      const grammar = store.editor.getGrammar();
      throw new Error(
        `No running kernel for grammar \`${grammar.name}\` found`
      );
    }

    return store.kernel.getPluginWrapper();
  }
}
<|endoftext|>