<commit_before>var lmap, task_layer, tiles, utf_layer;
var prefered_editor;
$('a[data-toggle="tab"]').on('shown', function (e) {
    if (e.target.id != 'map_tab' || lmap) {
        return;
    }
    lmap = L.map('leaflet');
    // create the tile layer with correct attribution
    var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
    var osmAttrib='Map data © OpenStreetMap contributors';
    var osm = new L.TileLayer(osmUrl, {attribution: osmAttrib});
    lmap.addLayer(osm);

    var layer = new L.geoJson(geometry);
    lmap.fitBounds(layer.getBounds());
    lmap.zoomOut();

    tiles = new L.TileLayer(
        '/project/' + project_id + '/{z}/{x}/{y}.png'
    );
    lmap.addLayer(tiles);

    task_layer = L.geoJson(null, {
        style: {
            weight: 1
        }
    }).addTo(lmap);

    utf_layer = new L.UtfGrid(
        '/project/' + project_id + '/{z}/{x}/{y}.json', {
        useJsonP: false
    });
    lmap.addLayer(utf_layer);
    utf_layer.on('click', function (e) {
        if (e.data && e.data.id) {
            location.hash = ["task", e.data.id].join('/');
        } else {
            clearSelection();
        }
    });
});

function clearSelection() {
    location.hash = "";
    task_layer.clearLayers();
    $('#task').fadeOut(function() {
        $('#task').empty();
        $('#task_empty').fadeIn();
    });
}

function loadTask(id, direction) {
    startLoading();
    function load() {
        $('#task').load(
            base_url + "project/" + project_id + "/task/" + id,
            null,
            function(response, status, request) {
                stopLoading();
                if (status != 'error') {
                    task_layer.clearLayers();
                    task_layer.addData(task_geometry);
                    $('#task').fadeIn();
                } else {
                    alert("an error occured");
                }
            }
        );
    }
    $(document.body).scrollTop(0);
    $('#map_tab').tab('show');
    $('#task_empty').fadeOut(
        function() {
            if (direction) {
                $('#task_actions').slide(direction)
                    .one('slid', load);
            } else {
                $('#task').fadeOut(function() {
                    load();
                });
            }
        }
    );
}

function startLoading() {
    $('#task_loading').show();
}
function stopLoading() {
    $('#task_loading').fadeOut();
}

function handleTaskResponse(data, direction) {
    tiles.redraw();

    // clear UTF Grid cache and update
    var i;
    for (i in utf_layer._cache) {
        delete utf_layer._cache[i];
    }
    utf_layer._update();

    if (data.task) {
        var task = data.task;
        loadTask(task.id, direction);
    }
    if (data.msg) {
        $('#task_msg').html(data.msg).show()
            .delay(3000)
            .fadeOut();
    }
    if (data.error_msg) {
        $('#task_error_msg').html(data.error_msg).show()
            .delay(3000)
            .fadeOut();
    }
    if (!data.task) {
        clearSelection();
    }
}

function onTaskAction(e) {

    if ($(this).hasClass('disabled')) {
        return false;
    }

    var direction = e.data && e.data.direction;
    $.getJSON(this.href || e.action, e.formData, function(data) {
        handleTaskResponse(data, direction);
    }).fail(function(error) {
        if (error.status == 401) {
            if (confirm('Please login first')) {
                window.location = login_url + '?came_from=' + encodeURIComponent(window.location.href);
            }
        }
    });
    return false;
}
$(document).on('click', '#lock', {direction: 'next'}, onTaskAction);
$(document).on('click', '#unlock', {direction: 'prev'}, onTaskAction);
$(document).on('click', '#split', {direction: 'next'}, function(e) {
    if ($(this).hasClass('disabled')) {
        return false;
    }
    if (confirm($(this).attr('data-confirm'))) {
        onTaskAction.call(this, e);
    }
    return false;
});
$(document).on('click', '.clear', clearSelection);

$(document).on('click', '#random', function(e) {
    $.getJSON($('#random').attr('href'), e.formData, function(data) {

        tiles.redraw();

        // clear UTF Grid cache and update
        var i;
        for (i in utf_layer._cache) {
            delete utf_layer._cache[i];
        }
        utf_layer._update();

        if (data.task) {
            var task = data.task;
            loadTask(task.id);
            location.hash = ["task", task.id].join('/');
            return false;
        }else{
            $('#task_msg').html("Error: random task should have returned a task ID but did not").show()
        }
        if (data.msg) {
            $('#task_msg').html(data.msg).show()
                .delay(3000)
                .fadeOut();
        }
        clearSelection();
    }).fail(function(error) {
        if (error.status == 401) {
            if (confirm('Please login first')) {
                window.location = login_url + '?came_from=' + encodeURIComponent(window.location.href);
            }
        }
    });
    return false;
});

$(document).on('submit', 'form', function(e) {
    var form = this;
    function load() {
        hideTooltips();
        var formData = $(form).serializeObject();
        var submitName = $("button[type=submit][clicked=true]").attr("name");
        formData[submitName] = true;
        //onTaskAction({
            //action: form.action,
            //formData: formData,
            //data: null
        //});
        $.post(form.action, formData, function(response) {
            handleTaskResponse(response);
        });
    }
    if ($(form).has($('#commentModal')).length > 0) {
        $('#commentModal').modal('show');
        $('#task_comment').focus()
            .on('keyup', function() {
                $('#commentModalCloseBtn').toggleClass('disabled',
                    $(this).val() === ''
                );
            });
        $('#commentModalCloseBtn').on('click', function() {
            if ($('#task_comment')[0].value !== '') {
                $('#commentModal').modal('hide');
                load();
            }
        });
    } else {
        load();
    }
    return false;
});
$(document).on("click", "form button[type=submit]", function() {
    $("button[type=submit]", $(this).parents("form")).removeAttr("clicked");
    $(this).attr("clicked", "true");
});

var exportOpen = function(evt) {
    // task_centroid and task_bounds are global variables (given for the
    // currently selected task)
    var editor;
    if (this.id == 'edit') {
        if (prefered_editor) {
            editor = prefered_editor;
        } else {
            return false;
        }
    } else {
        editor = this.id;
    }

    $.ajax({
        url: '/user/prefered_editor/' + editor,
        complete: function(t) {
            prefered_editor = editor;
            setPreferedEditor();
        }
    });

    function roundd(input, decimals) {
        var p = Math.pow(10, decimals);
        return Math.round(input*p)/p;
    }
    function getLink(options) {
        if (options.protocol === 'lbrt') {
            var bounds = options.bounds;
            return options.base + $.param({
                left: roundd(bounds[0],5),
                bottom: roundd(bounds[1],5),
                right: roundd(bounds[2],5),
                top: roundd(bounds[3],5)
            });
        } else if (options.protocol === 'llz') {
            var c = options.centroid;
            var so = new L.LatLng(task_bounds[0], task_bounds[1]),
                ne = new L.LatLng(task_bounds[2], task_bounds[3]),
                zoom = lmap.getBoundsZoom(new L.LatLngBounds(so, ne));
            return options.base + $.param({
                lon: roundd(c[0],5),
                lat: roundd(c[1],5),
                zoom: zoom
            });
        }
    }

    switch (editor) {
    case "josm":
        url = getLink({
            base: 'http://127.0.0.1:8111/load_and_zoom?',
            bounds: task_bounds,
            protocol: 'lbrt'
        });
        $.ajax({
            url: url,
            complete: function(t) {
                if (t.status != 200) {
                    alert("JOSM remote control did not respond. Do you have JOSM running and configured to be controlled remotely?");
                }
            }
        });
        break;
    case "potlatch2":
        url = getLink({
            base: 'http://www.openstreetmap.org/edit?editor=potlatch2&',
            centroid: task_centroid,
            protocol: 'llz'
        });
        window.open(url);
        break;
    case "wp":
        url = getLink({
            base: 'http://walking-papers.org/?',
            centroid: task_centroid,
            protocol: 'llz'
        });
        window.open(url);
        break;
    case "iDeditor":
        url = getLink({
            base: 'http://www.openstreetmap.org/edit?editor=id&',
            centroid: task_centroid,
            protocol: 'llz'
        });
        window.open(url);
        break;
    default:
        break;
    }
};
$(document).on('click', '#edit', exportOpen);
$(document).on('click', '#editDropdown li', exportOpen);

function setPreferedEditor() {
    if (prefered_editor !== '') {
        $('#prefered_editor').text($('#' + prefered_editor + ' a').text());
    }
}

Sammy(function() {
    this.get('#task/:id', function() {
        loadTask(this.params.id);
    });
}).run();

function hideTooltips() {
    $('[rel=tooltip]').tooltip('hide');
}
$.fn.slide = function(type) {
    // we hide tooltips since they may interact with transitions
    hideTooltips();
    var $container = $(this);
    var $active = $('<div class="item active">');
    $active.html($container.html());
    $container.html('').append($active);
    var direction = type == 'next' ? 'left' : 'right';
    var $next = $('<div>');
    if ($.support.transition) {
        $next.addClass(type);
        $next.offsetWidth; // force reflow
        $container.append($next);
        setTimeout(function() {
            $active.addClass(direction);
            $active.one($.support.transition.end, function (e) {
                $next.removeClass([type, direction].join(' ')).addClass('active');
                $active.remove();
                setTimeout(
                    function () {
                        $next.addClass('item');
                        $container.trigger('slid');
                    },
                    0
                );
            });
        }, 200); // time to hide tooltips
    } else {
        setTimeout(
            function () {
                $next.addClass('item');
                $container.trigger('slid');
            },
            0
        );
    }
    return this;
};

(function check_for_updates(){
    var interval = 20000;
    setTimeout(function(){
        $.ajax({
            url: base_url + "project/" + project_id + "/check_for_updates",
            data: {
                interval: interval
            },
            success: function(data){
                if (data.update) {
                    tiles.redraw();
                }
                check_for_updates();
            }, dataType: "json"}
        );
    }, interval);
})();
<commit_msg>Fixed id integration<commit_after>var lmap, task_layer, tiles, utf_layer;
var prefered_editor;
$('a[data-toggle="tab"]').on('shown', function (e) {
    if (e.target.id != 'map_tab' || lmap) {
        return;
    }
    lmap = L.map('leaflet');
    // create the tile layer with correct attribution
    var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
    var osmAttrib='Map data © OpenStreetMap contributors';
    var osm = new L.TileLayer(osmUrl, {attribution: osmAttrib});
    lmap.addLayer(osm);

    var layer = new L.geoJson(geometry);
    lmap.fitBounds(layer.getBounds());
    lmap.zoomOut();

    tiles = new L.TileLayer(
        '/project/' + project_id + '/{z}/{x}/{y}.png'
    );
    lmap.addLayer(tiles);

    task_layer = L.geoJson(null, {
        style: {
            weight: 1
        }
    }).addTo(lmap);

    utf_layer = new L.UtfGrid(
        '/project/' + project_id + '/{z}/{x}/{y}.json', {
        useJsonP: false
    });
    lmap.addLayer(utf_layer);
    utf_layer.on('click', function (e) {
        if (e.data && e.data.id) {
            location.hash = ["task", e.data.id].join('/');
        } else {
            clearSelection();
        }
    });
});

function clearSelection() {
    location.hash = "";
    task_layer.clearLayers();
    $('#task').fadeOut(function() {
        $('#task').empty();
        $('#task_empty').fadeIn();
    });
}

function loadTask(id, direction) {
    startLoading();
    function load() {
        $('#task').load(
            base_url + "project/" + project_id + "/task/" + id,
            null,
            function(response, status, request) {
                stopLoading();
                if (status != 'error') {
                    task_layer.clearLayers();
                    task_layer.addData(task_geometry);
                    $('#task').fadeIn();
                } else {
                    alert("an error occured");
                }
            }
        );
    }
    $(document.body).scrollTop(0);
    $('#map_tab').tab('show');
    $('#task_empty').fadeOut(
        function() {
            if (direction) {
                $('#task_actions').slide(direction)
                    .one('slid', load);
            } else {
                $('#task').fadeOut(function() {
                    load();
                });
            }
        }
    );
}

function startLoading() {
    $('#task_loading').show();
}
function stopLoading() {
    $('#task_loading').fadeOut();
}

function handleTaskResponse(data, direction) {
    tiles.redraw();

    // clear UTF Grid cache and update
    var i;
    for (i in utf_layer._cache) {
        delete utf_layer._cache[i];
    }
    utf_layer._update();

    if (data.task) {
        var task = data.task;
        loadTask(task.id, direction);
    }
    if (data.msg) {
        $('#task_msg').html(data.msg).show()
            .delay(3000)
            .fadeOut();
    }
    if (data.error_msg) {
        $('#task_error_msg').html(data.error_msg).show()
            .delay(3000)
            .fadeOut();
    }
    if (!data.task) {
        clearSelection();
    }
}

function onTaskAction(e) {

    if ($(this).hasClass('disabled')) {
        return false;
    }

    var direction = e.data && e.data.direction;
    $.getJSON(this.href || e.action, e.formData, function(data) {
        handleTaskResponse(data, direction);
    }).fail(function(error) {
        if (error.status == 401) {
            if (confirm('Please login first')) {
                window.location = login_url + '?came_from=' + encodeURIComponent(window.location.href);
            }
        }
    });
    return false;
}
$(document).on('click', '#lock', {direction: 'next'}, onTaskAction);
$(document).on('click', '#unlock', {direction: 'prev'}, onTaskAction);
$(document).on('click', '#split', {direction: 'next'}, function(e) {
    if ($(this).hasClass('disabled')) {
        return false;
    }
    if (confirm($(this).attr('data-confirm'))) {
        onTaskAction.call(this, e);
    }
    return false;
});
$(document).on('click', '.clear', clearSelection);

$(document).on('click', '#random', function(e) {
    $.getJSON($('#random').attr('href'), e.formData, function(data) {

        tiles.redraw();

        // clear UTF Grid cache and update
        var i;
        for (i in utf_layer._cache) {
            delete utf_layer._cache[i];
        }
        utf_layer._update();

        if (data.task) {
            var task = data.task;
            loadTask(task.id);
            location.hash = ["task", task.id].join('/');
            return false;
        }else{
            $('#task_msg').html("Error: random task should have returned a task ID but did not").show()
        }
        if (data.msg) {
            $('#task_msg').html(data.msg).show()
                .delay(3000)
                .fadeOut();
        }
        clearSelection();
    }).fail(function(error) {
        if (error.status == 401) {
            if (confirm('Please login first')) {
                window.location = login_url + '?came_from=' + encodeURIComponent(window.location.href);
            }
        }
    });
    return false;
});

$(document).on('submit', 'form', function(e) {
    var form = this;
    function load() {
        hideTooltips();
        var formData = $(form).serializeObject();
        var submitName = $("button[type=submit][clicked=true]").attr("name");
        formData[submitName] = true;
        //onTaskAction({
            //action: form.action,
            //formData: formData,
            //data: null
        //});
        $.post(form.action, formData, function(response) {
            handleTaskResponse(response);
        });
    }
    if ($(form).has($('#commentModal')).length > 0) {
        $('#commentModal').modal('show');
        $('#task_comment').focus()
            .on('keyup', function() {
                $('#commentModalCloseBtn').toggleClass('disabled',
                    $(this).val() === ''
                );
            });
        $('#commentModalCloseBtn').on('click', function() {
            if ($('#task_comment')[0].value !== '') {
                $('#commentModal').modal('hide');
                load();
            }
        });
    } else {
        load();
    }
    return false;
});
$(document).on("click", "form button[type=submit]", function() {
    $("button[type=submit]", $(this).parents("form")).removeAttr("clicked");
    $(this).attr("clicked", "true");
});

var exportOpen = function(evt) {
    var editor;
    if (this.id == 'edit') {
        if (prefered_editor) {
            editor = prefered_editor;
        } else {
            return false;
        }
    } else {
        editor = this.id;
    }

    $.ajax({
        url: '/user/prefered_editor/' + editor,
        complete: function(t) {
            prefered_editor = editor;
            setPreferedEditor();
        }
    });

    function roundd(input, decimals) {
        var p = Math.pow(10, decimals);
        return Math.round(input*p)/p;
    }
    function getLink(options) {
        var bounds = options.bounds;
        var so = new L.LatLng(bounds[0], bounds[1]),
            ne = new L.LatLng(bounds[2], bounds[3]),
            zoom = lmap.getBoundsZoom(new L.LatLngBounds(so, ne));
        var c = options.centroid;
        switch (options.protocol) {
            case 'lbrt':
                return options.base + $.param({
                    left: roundd(bounds[0],5),
                    bottom: roundd(bounds[1],5),
                    right: roundd(bounds[2],5),
                    top: roundd(bounds[3],5)
                });
            case 'llz':
                return options.base + $.param({
                    lon: roundd(c[0],5),
                    lat: roundd(c[1],5),
                    zoom: zoom
                });
            case 'id':
                return options.base + '#map=' +
                    [zoom, c[1], c[0]].join('/');

        }
    }

    // task_centroid and task_bounds are global variables (given for the
    // currently selected task)
    switch (editor) {
    case "josm":
        url = getLink({
            base: 'http://127.0.0.1:8111/load_and_zoom?',
            bounds: task_bounds,
            protocol: 'lbrt'
        });
        $.ajax({
            url: url,
            complete: function(t) {
                if (t.status != 200) {
                    alert("JOSM remote control did not respond. Do you have JOSM running and configured to be controlled remotely?");
                }
            }
        });
        break;
    case "potlatch2":
        url = getLink({
            base: 'http://www.openstreetmap.org/edit?editor=potlatch2&',
            centroid: task_centroid,
            protocol: 'llz'
        });
        window.open(url);
        break;
    case "wp":
        url = getLink({
            base: 'http://walking-papers.org/?',
            centroid: task_centroid,
            protocol: 'llz'
        });
        window.open(url);
        break;
    case "iDeditor":
        url = getLink({
            base: 'http://www.openstreetmap.org/edit?editor=id&',
            bounds: task_bounds,
            centroid: task_centroid,
            protocol: 'id'
        });
        window.open(url);
        break;
    default:
        break;
    }
};
$(document).on('click', '#edit', exportOpen);
$(document).on('click', '#editDropdown li', exportOpen);

function setPreferedEditor() {
    if (prefered_editor !== '') {
        $('#prefered_editor').text($('#' + prefered_editor + ' a').text());
    }
}

Sammy(function() {
    this.get('#task/:id', function() {
        loadTask(this.params.id);
    });
}).run();

function hideTooltips() {
    $('[rel=tooltip]').tooltip('hide');
}
$.fn.slide = function(type) {
    // we hide tooltips since they may interact with transitions
    hideTooltips();
    var $container = $(this);
    var $active = $('<div class="item active">');
    $active.html($container.html());
    $container.html('').append($active);
    var direction = type == 'next' ? 'left' : 'right';
    var $next = $('<div>');
    if ($.support.transition) {
        $next.addClass(type);
        $next.offsetWidth; // force reflow
        $container.append($next);
        setTimeout(function() {
            $active.addClass(direction);
            $active.one($.support.transition.end, function (e) {
                $next.removeClass([type, direction].join(' ')).addClass('active');
                $active.remove();
                setTimeout(
                    function () {
                        $next.addClass('item');
                        $container.trigger('slid');
                    },
                    0
                );
            });
        }, 200); // time to hide tooltips
    } else {
        setTimeout(
            function () {
                $next.addClass('item');
                $container.trigger('slid');
            },
            0
        );
    }
    return this;
};

(function check_for_updates(){
    var interval = 20000;
    setTimeout(function(){
        $.ajax({
            url: base_url + "project/" + project_id + "/check_for_updates",
            data: {
                interval: interval
            },
            success: function(data){
                if (data.update) {
                    tiles.redraw();
                }
                check_for_updates();
            }, dataType: "json"}
        );
    }, interval);
})();
<|endoftext|>


<commit_before>var http = require('http');
var https = require('https');
var _ = require('lodash');
var url = require('url');
var env = require('./../Configuration/configLoader').loadedConfig;
var logger = require('./../logger').logger;
var path = require('path');
var fs = require('fs');
var Cookies = require('cookies');
var NODE_ENV = (env.NODE_ENV === 'production');

//var PluginManager = require('./../Plugins');
//
//PluginManager.register(function(req, next){
//  console.log('run first');
//  next();
//
//});
//PluginManager.register(function(req, next){
//  next();
//});

var httpProxy = require('http-proxy');

var staticPages = require('./defaultFiles');

var incomingProtocol = env.sundry_redirect_ssl ? "https://" : "http://"
var proxy = httpProxy.createProxyServer();

var handleWebProxy = function(req, res, proxyTo){
  return proxy.web(req, res, {
    xfwd: true,
    target: {
      host: proxyTo.host,
      port: proxyTo.port
    }
  }, function(err){
    console.log(err);
    res.writeHead(503);
    res.write(staticPages.five);
    res.end();
  });
};

/**
 *  Handler function for default address.
 *  Returns a function to either proxy to a default
 *  application, or to write the index.html page.
 */
var handleDefaultAddress = (function(){
  if(env.sundry_default_application){
    return function(req, res){
      handleWebProxy(req, res, env.sundry_default_application)
    }
  }
  return function(req, res){
    res.writeHead(200,{'Content-Type': 'text/html'});
    res.write(staticPages.index)
    res.end()
  }
})()

module.exports = function(serverOptions, Router) {

  /**
   * Main Proxy handler
   */

  var stickyBalanceProxy = function(req, res){
    var parsedHeader = url.parse(incomingProtocol + req.headers.host).hostname;

    //Return early if this route matches the default set in the config.
    if(parsedHeader === env.sundry_default_address) {
      return handleDefaultAddress(req, res)
    }

    var cookie = new Cookies(req, res, env.sundry_sticky_cookie_secret)
    //Send our request host data to the Router to be looked up and cached if found.
    Router.findRoute(parsedHeader, cookie.get('stickyRoute'), function proxyRequest(data) {
      if(data) {

        cookie.set('stickyRoute', data.identity, {signed: true})
        return handleWebProxy(req, res, data)
      }
      else {
        res.writeHead(404, {'Content-Type': 'text/html'});
        res.write(staticPages.four)
        res.end()
      }
    })
  }

  var roundBalanceProxy = function(req, res) {
    var parsedHeader = url.parse(incomingProtocol + req.headers.host).hostname;
    //Expire this request in a reasonable amount of time if something is hanging up downstream.
    res.setTimeout(1000, function() {
      logger.log('Request for %s timed out.', req.headers.host);
      res.writeHead(408);
      res.write('Sorry We couldn\'t complete that request in time.');
      return res.end();
    });

    //Return early if this route matches the default set in the config.
    if(parsedHeader === env.sundry_default_address) {
      return handleDefaultAddress(req, res)
    }

    //Send our request host data to the Router to be looked up and cached if found.
    Router.findRoute(parsedHeader, null, function proxyRequest(data) {
      if(data) {

        return handleWebProxy(req, res, data)
      }
      else {
        res.writeHead(404, {'Content-Type': 'text/html'});
        res.write(staticPages.four)
        res.end()
      }
    })

  };

  var proxyRoute = (env.sundry_sticky) ? stickyBalanceProxy : roundBalanceProxy

  /*
   * Handle http -> https redirects differently based on the current env.
   */
  var redirect = {
    production: function(req, res) {
      res.writeHead(301, {Location: 'https://' + req.headers.host + req.url});
      res.end()
    },
    development: function(req, res){
      var host = req.headers.host.split(':');
      host[host.length - 1] = env.sundry_dev_ssl_port;
      host = host.join(':');

      res.writeHead(301, {Location: 'https://' + host + req.url});
      res.end();
    }
  };

  /*
   * Handler for dev/test response server.
   */
  var testHandler = function(req, res){
    var parsed = url.parse(req.url)
    res.setHeader('content-type', 'text/html');
    res.writeHead(200);
    res.write('<!DOCTYPE html>');
    res.write('<title>Sundry Test Server</title>');
    res.write('
Backend Server - '+ req.socket.localAddress + ':' + req.socket.localPort +'
')
    res.write('
Host - ' + req.headers.host + '
')
    res.write('
URL - ' + parsed.pathname + '
')
    res.write('
Query - ' + parsed.query + '
')
    res.write('');
    res.end();
  };

  /*
   * Return a group of servers dependant on options and env.
   * at a bare minimum this will provide a server to 301 redirect http requests
   * to https, as well as our dynamic reverse proxying server over https.
   *
   * It will optionally return a server to test and develop against locally.
   */

  var serverGroup = {};
  if(env.sundry_redirect_ssl) {
    var handleRedirect = NODE_ENV ? redirect.production : redirect.development;
    serverGroup.http = http.createServer(handleRedirect);
    serverGroup.https = https.createServer(serverOptions.tlsOptions, proxyRoute);
  } else {
    serverGroup.http = http.createServer(proxyRoute);
  }

  if(!NODE_ENV){
    _.extend(serverGroup, {test: http.createServer(testHandler), test2: http.createServer(testHandler)});
  }

  return serverGroup;
};<commit_msg>See, duplicate code does bite<commit_after>var http = require('http');
var https = require('https');
var _ = require('lodash');
var url = require('url');
var env = require('./../Configuration/configLoader').loadedConfig;
var logger = require('./../logger').logger;
var path = require('path');
var fs = require('fs');
var Cookies = require('cookies');
var NODE_ENV = (env.NODE_ENV === 'production');

//var PluginManager = require('./../Plugins');
//
//PluginManager.register(function(req, next){
//  console.log('run first');
//  next();
//
//});
//PluginManager.register(function(req, next){
//  next();
//});

var httpProxy = require('http-proxy');

var staticPages = require('./defaultFiles');

var incomingProtocol = env.sundry_redirect_ssl ? "https://" : "http://"
var proxy = httpProxy.createProxyServer();

var handleWebProxy = function(req, res, proxyTo){
  return proxy.web(req, res, {
    xfwd: true,
    target: {
      host: proxyTo.host,
      port: proxyTo.port
    }
  }, function(err){
    console.log(err);
    res.writeHead(503);
    res.write(staticPages.five);
    res.end();
  });
};

/**
 *  Handler function for default address.
 *  Returns a function to either proxy to a default
 *  application, or to write the index.html page.
 */
var handleDefaultAddress = (function(){
  if(env.sundry_default_application){
    return function(req, res){
      handleWebProxy(req, res, env.sundry_default_application)
    }
  }
  return function(req, res){
    res.writeHead(200,{'Content-Type': 'text/html'});
    res.write(staticPages.index)
    res.end()
  }
})()

module.exports = function(serverOptions, Router) {

  /**
   * Main Proxy handler
   */

  var stickyBalanceProxy = function(req, res){
    var parsedHeader = url.parse(incomingProtocol + req.headers.host).hostname;

    //Return early if this route matches the default set in the config.
    if(parsedHeader === env.sundry_default_address) {
      return handleDefaultAddress(req, res)
    }

    var cookie = new Cookies(req, res, env.sundry_sticky_cookie_secret)
    //Send our request host data to the Router to be looked up and cached if found.
    Router.findRoute(parsedHeader, cookie.get('stickyRoute'), function proxyRequest(data) {
      if(data) {

        cookie.set('stickyRoute', data.identity, {signed: true})
        return handleWebProxy(req, res, data)
      }
      else {
        res.writeHead(404, {'Content-Type': 'text/html'});
        res.write(staticPages.four)
        res.end()
      }
    })
  }

  var roundBalanceProxy = function(req, res) {
    var parsedHeader = url.parse(incomingProtocol + req.headers.host).hostname;

    //Return early if this route matches the default set in the config.
    if(parsedHeader === env.sundry_default_address) {
      return handleDefaultAddress(req, res)
    }

    //Send our request host data to the Router to be looked up and cached if found.
    Router.findRoute(parsedHeader, null, function proxyRequest(data) {
      if(data) {

        return handleWebProxy(req, res, data)
      }
      else {
        res.writeHead(404, {'Content-Type': 'text/html'});
        res.write(staticPages.four)
        res.end()
      }
    })

  };

  var proxyRoute = (env.sundry_sticky) ? stickyBalanceProxy : roundBalanceProxy

  /*
   * Handle http -> https redirects differently based on the current env.
   */
  var redirect = {
    production: function(req, res) {
      res.writeHead(301, {Location: 'https://' + req.headers.host + req.url});
      res.end()
    },
    development: function(req, res){
      var host = req.headers.host.split(':');
      host[host.length - 1] = env.sundry_dev_ssl_port;
      host = host.join(':');

      res.writeHead(301, {Location: 'https://' + host + req.url});
      res.end();
    }
  };

  /*
   * Handler for dev/test response server.
   */
  var testHandler = function(req, res){
    var parsed = url.parse(req.url)
    res.setHeader('content-type', 'text/html');
    res.writeHead(200);
    res.write('<!DOCTYPE html>');
    res.write('<title>Sundry Test Server</title>');
    res.write('
Backend Server - '+ req.socket.localAddress + ':' + req.socket.localPort +'
')
    res.write('
Host - ' + req.headers.host + '
')
    res.write('
URL - ' + parsed.pathname + '
')
    res.write('
Query - ' + parsed.query + '
')
    res.write('');
    res.end();
  };

  /*
   * Return a group of servers dependant on options and env.
   * at a bare minimum this will provide a server to 301 redirect http requests
   * to https, as well as our dynamic reverse proxying server over https.
   *
   * It will optionally return a server to test and develop against locally.
   */

  var serverGroup = {};
  if(env.sundry_redirect_ssl) {
    var handleRedirect = NODE_ENV ? redirect.production : redirect.development;
    serverGroup.http = http.createServer(handleRedirect);
    serverGroup.https = https.createServer(serverOptions.tlsOptions, proxyRoute);
  } else {
    serverGroup.http = http.createServer(proxyRoute);
  }

  if(!NODE_ENV){
    _.extend(serverGroup, {test: http.createServer(testHandler), test2: http.createServer(testHandler)});
  }

  return serverGroup;
};<|endoftext|>


<commit_before>/**
 * @workInProgress
 * @ngdoc service
 * @name angular.service.$document
 * @requires $window
 *
 * @description
 * A reference to the browser window.document, but wrapped into angular.element().
 */
angularServiceInject("$document", function(window){
  return jqLite(window.document);
}, ['$window'], true);
<commit_msg>improving the $document docs<commit_after>/**
 * @workInProgress
 * @ngdoc service
 * @name angular.service.$document
 * @requires $window
 *
 * @description
 * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`
 * element.
 */
angularServiceInject("$document", function(window){
  return jqLite(window.document);
}, ['$window'], true);
<|endoftext|>


<commit_before>var http = require('http');
var Ow = require("./api_onewire");
var CFG = require('../config');
var httpjs = require('http-json-request');
console.log(CFG.owfs);
var ow = new Ow(CFG.owfs.host, CFG.owfs.port);

var Db = require("../resources/database");
db = new Db();

httpjs.defaultHost( CFG.app.host );
httpjs.defaultHost( CFG.app.port );

function findOwid(id, cb)
{
    db.devices.findOne( {id: id, protocol: 'ow'}, function(error, data){
        if(error){
            cb(error);
        } else if( data )
        {
            cb(null, data);
        } else{
            cb(null, null, id);
        }
    });
}
function isNumber (o) {
  return ! isNaN (o-0) && o != null;
}
var instance;
function OwService(db) {
    instance=this;

    //create ping action if it not exists
    db.actions.findOne({name: 'owPing'}, function(err, found){
        if( err ){
            console.log(err);
        } if( !found ) {
            var newAct = { name: 'owPing', type: 'script', script: 'ow.ping();' }
            db.actions.create( newAct, function(err, action){
                if( err ){
                    console.log(err);
                } else {
                    console.log('Created owPing action');

                    db.schedules.findOne({name: 'owPing'}, function(err, found){
                        if( err ){
                            console.log(err);
                        } if( !found )
                        {
                            var schedule = { name: 'owPing', cron: '0 * * * * *', actions: [ action.uuid]};
                            db.schedules.create( schedule, function(err,ok){
                                if( err ){
                                    console.log(err);
                                } else {
                                    console.log('Created owPing schedule');
                                }
                            });
                        }
                    });

                }
            });
        }
    });

    //create measure action if it not exists
    db.actions.findOne({name: 'owReadAll'}, function(err, found){
        if( err ){
            console.log(err);
        } if( !found ) {
            var newAct = { name: 'owReadAll', type: 'script', script: 'ow.readAll();' }
            db.actions.create( newAct, function(err,action){
                if( err ){
                    console.log(err);
                } else {
                    console.log('Created owReadAll action');

                    db.schedules.findOne({name: 'owReadAll'}, function(err, found){
                        if( err ){
                            console.log(err);
                        } if( !found )
                        {
                            var schedule = { name: 'owReadAll', cron: '0 */5 * * * *', actions: [ action.uuid]};
                            db.schedules.create( schedule, function(err,ok){
                                if( err ){
                                    console.log(err);
                                } else {
                                    console.log('Created owReadAll schedule');
                                }
                            });
                        }
                    });
                }
            });
        }
    });

}
OwService.prototype.ping = function(archives, period){
    console.log("reload ow meters");

    if( !(archives instanceof Array))
        archives = [ [60*5, 12*24],     // meas/5min  1 days
                     [60*10, 12*24*7],  // meas/10min  7 days
                     [60*60, 24*365*50] // meas/1h    50 year
                  ];
    if( !period )
        period = 0.5;
    try {
     ow.dir("/",function(directories){
        console.log(directories);
        for(var i=0;i<directories.length;i++){
            var id = directories[i];
            if( id[0] == '/' && id[3] == '.' && id.length>14  )
            {
                id = id.replace("/","");
                //console.log("Founded device %s, check if its already in db", id);
                findOwid(id, function(error, device, id){
                    if( error ){
                    } else if( device ){
                         //console.log("id "+device.id+" is already in db");
                    } else {
                        console.log("New OW sensor detected with id "+id);
                        var device = {
                            protocol: 'ow',
                            type: 'meter',
                            id: id,
                            hoard: {
                                enable: true,
                                archives: archives,
                                period: period
                            }
                        };
                        httpjs.postJSON( '/devices.json', device, function(error, data){
                            console.log(error);
                            console.log(data);
                            db.events.create( {
                                    msg: error?'OW device creation failed':'new ow-device detected with id: '+data.id,
                                    details: error?error:null,
                                    type: error?'fatal':'general',
                                    source: {
                                        component: 'onewire-service',
                                    }
                                }, function(){});
                        });
                    }
                });
            }
        }
        //queue for next ping in the next predefined interval
     });
    } catch(e) {
        console.log("OwException");
        console.log(e);
    }
}
OwService.prototype.read = function(device, callback)
{
    var path = "/"+device.id+"/temperature";
    console.log("Reading device: "+path);
    try {
       ow.read(path, function(result){
            if( result !== false && isNumber(result) ){
                console.log("result: %d", result);
                values = []; //[[result]]
                var unixStamp = parseInt(new Date().getTime() / 1000);
                for(var i=0;i<device.hoard.archives.length;i++)
                    values.push( [unixStamp, result] ); //because all hoard-archives need to be update
                httpjs.post( '/devices/'+device.uuid+"/events.json",
                              { values: values, type: 'hoard' }, callback);
            }
            else{
                console.log("Invalid value");
                callback('fail', device);
            }
        });

    } catch(e) {
        console.log("OwException");
        console.log(e);
        callback(e, device);
    }
}
OwService.prototype.readAll = function(){
    console.log("readAll");
    console.log(instance);
    db.devices.find({protocol: 'ow', enable: true}, function(error, devs){
        if(error){
            console.log("getDevicesByProtocol::error");
            console.log(error);
        }
        else {
            for(var i=0;i<devs.length;i++){
               instance.read( devs[i], function(error, device){
                    if( error ){
                        db.devices.update( {uuid: device.uuid}, {enable: false}, function(){});
                        db.events.create( {
                            msg: 'OW read fail ('+device.id+'). Sensor Disabled. Check connection! ',
                            details: error,
                            type: 'fatal',
                            source: {
                                component: 'onewire-service',
                                uuid: device.uuid,
                            }
                        }, function(){});
                    }
               });

                //var cmd = "-t C N:"+ result;
                //console.log(cmd);
                //rrd.rrdExec( "update",  cmd, function(err){
                //    if(err){
                //        console.log(err);
                //    }
                //    else console.log("update success");
                //});
            }
        }
    });
}
// export the class
module.exports = OwService;<commit_msg>fixed onewire library.<commit_after>var http = require('http');
var Ow = require("./api_onewire");
var CFG = require('../config');
var httpjs = require('http-json-request');
console.log(CFG.owfs);
var ow = new Ow(CFG.owfs.host, CFG.owfs.port);

var Db = require("../resources/database");
db = new Db();

httpjs.defaultHost( CFG.app.host );
httpjs.defaultHost( CFG.app.port );

function findOwid(id, cb)
{
    db.devices.findOne( {id: id, protocol: 'ow'}, function(error, data){
        if(error){
            cb(error);
        } else if( data )
        {
            cb(null, data);
        } else{
            cb(null, null, id);
        }
    });
}
function isNumber (o) {
  return ! isNaN (o-0) && o != null;
}
var instance;
function OwService(db) {
    instance=this;

    //create ping action if it not exists
    db.actions.findOne({name: 'owPing'}, function(err, found){
        if( err ){
            console.log(err);
        } if( !found ) {
            var newAct = { name: 'owPing', type: 'script', script: 'ow.ping();' }
            db.actions.create( newAct, function(err, action){
                if( err ){
                    console.log(err);
                } else {
                    console.log('Created owPing action');

                    db.schedules.findOne({name: 'owPing'}, function(err, found){
                        if( err ){
                            console.log(err);
                        } if( !found )
                        {
                            var schedule = { name: 'owPing', cron: '0 * * * * *', actions: [ action.uuid]};
                            db.schedules.create( schedule, function(err,ok){
                                if( err ){
                                    console.log(err);
                                } else {
                                    console.log('Created owPing schedule');
                                }
                            });
                        }
                    });

                }
            });
        }
    });

    //create measure action if it not exists
    db.actions.findOne({name: 'owReadAll'}, function(err, found){
        if( err ){
            console.log(err);
        } if( !found ) {
            var newAct = { name: 'owReadAll', type: 'script', script: 'ow.readAll();' }
            db.actions.create( newAct, function(err,action){
                if( err ){
                    console.log(err);
                } else {
                    console.log('Created owReadAll action');

                    db.schedules.findOne({name: 'owReadAll'}, function(err, found){
                        if( err ){
                            console.log(err);
                        } if( !found )
                        {
                            var schedule = { name: 'owReadAll', cron: '0 */5 * * * *', actions: [ action.uuid]};
                            db.schedules.create( schedule, function(err,ok){
                                if( err ){
                                    console.log(err);
                                } else {
                                    console.log('Created owReadAll schedule');
                                }
                            });
                        }
                    });
                }
            });
        }
    });

}
OwService.prototype.ping = function(archives, period){
    console.log("reload ow meters");

    if( !(archives instanceof Array))
        archives = [ [60*5, 12*24],     // meas/5min  1 days
                     [60*10, 12*24*7],  // meas/10min  7 days
                     [60*60, 24*365*50] // meas/1h    50 year
                  ];
    if( !period )
        period = 0.5;
    try {
     ow.dir("/",function(directories){
        console.log(directories);
        for(var i=0;i<directories.length;i++){
            var id = directories[i];
            if( id[0] == '/' && id[3] == '.' && id.length>14  )
            {
                id = id.replace("/","");
                //console.log("Founded device %s, check if its already in db", id);
                findOwid(id, function(error, device, id){
                    if( error ){
                    } else if( device ){
                         //console.log("id "+device.id+" is already in db");
                    } else {
                        console.log("New OW sensor detected with id "+id);
                        var device = {
                            protocol: 'ow',
                            type: 'meter',
                            id: id,
                            hoard: {
                                enable: true,
                                archives: archives,
                                period: period
                            }
                        };
                        httpjs.postJSON( '/devices.json', device, function(error, data){
                            console.log(error);
                            console.log(data);
                            db.events.create( {
                                    msg: error?'OW device creation failed':'new ow-device detected with id: '+data.id,
                                    details: error?error:null,
                                    type: error?'fatal':'general',
                                    source: {
                                        component: 'onewire-service',
                                    }
                                }, function(){});
                        });
                    }
                });
            }
        }
        //queue for next ping in the next predefined interval
     });
    } catch(e) {
        console.log("OwException");
        console.log(e);
    }
}
OwService.prototype.read = function(device, callback)
{
    var path = "/"+device.id+"/temperature";
    console.log("Reading device: "+path);
    try {
       ow.read(path, function(result){
            if( result !== false && isNumber(result) ){
                console.log("result: %d", result);
                values = []; //[[result]]
                var unixStamp = parseInt(new Date().getTime() / 1000);
                for(var i=0;i<device.hoard.archives.length;i++)
                    values.push( [unixStamp, result] ); //because all hoard-archives need to be update
                httpjs.postJSON( '/devices/'+device.uuid+"/events.json",
                              { values: values, type: 'hoard' }, callback);
            }
            else{
                console.log("Invalid value");
                callback('fail', device);
            }
        });

    } catch(e) {
        console.log("OwException");
        console.log(e);
        callback(e, device);
    }
}
OwService.prototype.readAll = function(){
    console.log("readAll");
    console.log(instance);
    db.devices.find({protocol: 'ow', enable: true}, function(error, devs){
        if(error){
            console.log("getDevicesByProtocol::error");
            console.log(error);
        }
        else {
            for(var i=0;i<devs.length;i++){
               instance.read( devs[i], function(error, device){
                    if( error ){
                        db.devices.update( {uuid: device.uuid}, {enable: false}, function(){});
                        db.events.create( {
                            msg: 'OW read fail ('+device.id+'). Sensor Disabled. Check connection! ',
                            details: error,
                            type: 'fatal',
                            source: {
                                component: 'onewire-service',
                                uuid: device.uuid,
                            }
                        }, function(){});
                    }
               });

                //var cmd = "-t C N:"+ result;
                //console.log(cmd);
                //rrd.rrdExec( "update",  cmd, function(err){
                //    if(err){
                //        console.log(err);
                //    }
                //    else console.log("update success");
                //});
            }
        }
    });
}
// export the class
module.exports = OwService;<|endoftext|>


<commit_before>var Promise = require('./Promise');
var assign = require('object-assign');

// determine environment
var environment = require('./environment');

// used to prevent webpack from resolving requires on node libs
var node = {require: require};

// get the default worker script
function getDefaultWorker() {
  if (environment.platform == 'browser') {
    // test whether the browser supports all features that we need
    if (typeof Blob === 'undefined') {
      throw new Error('Blob not supported by the browser');
    }
    if (!window.URL || typeof window.URL.createObjectURL !== 'function') {
      throw new Error('URL.createObjectURL not supported by the browser');
    }

    // use embedded worker.js
    var blob = new Blob([require('./generated/embeddedWorker')], {type: 'text/javascript'});
    return window.URL.createObjectURL(blob);
  }
  else {
    // use exteral worker.js in current directory
    return __dirname + '/worker.js';
  }
}

// add debug flags to child processes if the node inspector is active
function resolveForkOptions(opts) {
  opts = opts || {};

  const execArgv = [];

  const inspectorActive = process.execArgv
    .indexOf('--inspect') !== -1;
  const debugBrk = process.execArgv
    .indexOf('--debug-brk') !== -1;

  if (inspectorActive) {
    execArgv.push('--inspect=' + opts.debugPort);

    if (debugBrk) {
      execArgv.push('--debug-brk');
    }
  }

  return assign({}, opts, {
    forkArgs: opts.forkArgs,
    forkOpts: assign({}, opts.forkOpts, {
      execArgv: (opts.forkOpts && opts.forkOpts.execArgv || [])
        .concat(execArgv)
    })
  });
};

/**
 * Converts a serialized error to Error
 * @param {Object} obj Error that has been serialized and parsed to object
 * @return {Error} The equivalent Error.
 */
function objectToError (obj) {
  var temp = new Error('')
  var props = Object.keys(obj)

  for (var i = 0; i < props.length; i++) {
    temp[props[i]] = obj[props[i]]
  }

  return temp
}

/**
 * A WorkerHandler controls a single worker. This worker can be a child process
 * on node.js or a WebWorker in a browser environment.
 * @param {String} [script] If no script is provided, a default worker with a
 *                          function run will be created.
 * @constructor
 */
function WorkerHandler(script, options) {
  this.script = script || getDefaultWorker();

  var forkOptions;

  if (environment.platform == 'browser') {
    // check whether Worker is supported by the browser
    // Workaround for a bug in PhantomJS (Or QtWebkit): https://github.com/ariya/phantomjs/issues/14534
    if (typeof Worker !== 'function' && (typeof Worker !== 'object' || typeof Worker.prototype.constructor !== 'function')) {
      throw new Error('Web workers not supported by the browser');
    }

    // create the web worker
    this.worker = new Worker(this.script);

    // add node.js API to the web worker
    this.worker.on = function (event, callback) {
      this.addEventListener(event, function (message) {
        callback(message.data);
      });
    };
    this.worker.send = function (message) {
      this.postMessage(message);
    };
  }
  else {
    // on node.js, create a child process
    forkOptions = resolveForkOptions(options);

    // call node.require to prevent child_process to be required when loading with AMD
    this.worker = node.require('child_process').fork(
      this.script,
      forkOptions.forkArgs,
      forkOptions.forkOpts
    );
  }

  var me = this;

  // The ready message is only sent if the worker.add method is called (And the default script is not used)
  if (!script) {
    this.worker.ready = true;
  }

  // queue for requests that are received before the worker is ready
  this.requestQueue = [];
  this.worker.on('message', function (response) {
    if (typeof response === 'string' && response === 'ready') {
      me.worker.ready = true;
      dispatchQueuedRequests();
    } else {
      // find the task from the processing queue, and run the tasks callback
      var id = response.id;
      var task = me.processing[id];
      if (task) {
        // remove the task from the queue
        delete me.processing[id];

        // test if we need to terminate
        if (me.terminating) {
          // complete worker termination if all tasks are finished
          me.terminate();
        }

        // resolve the task's promise
        if (response.error) {
          task.resolver.reject(objectToError(response.error));
        }
        else {
          task.resolver.resolve(response.result);
        }
      }
    }
  });

  // reject all running tasks on worker error
  function onError(error) {
    me.terminated = true;

    for (var id in me.processing) {
      if (me.processing.hasOwnProperty(id)) {
        me.processing[id].resolver.reject(error);
      }
    }
    me.processing = {};
  }

  // send all queued requests to worker
  function dispatchQueuedRequests()
  {
    me.requestQueue.forEach(me.worker.send.bind(me.worker));
    me.requestQueue = [];
  }

  // listen for worker messages error and exit
  this.worker.on('error', onError);
  this.worker.on('exit', function () {
    var error = new Error('Worker terminated unexpectedly');
    onError(error);
  });

  this.processing = {}; // queue with tasks currently in progress

  this.terminating = false;
  this.terminated = false;
  this.lastId = 0;
}

/**
 * Get a list with methods available on the worker.
 * @return {Promise.<String[], Error>} methods
 */
WorkerHandler.prototype.methods = function () {
  return this.exec('methods');
};

/**
 * Execute a method with given parameters on the worker
 * @param {String} method
 * @param {Array} [params]
 * @param {{resolve: Function, reject: Function}} [resolver]
 * @return {Promise.<*, Error>} result
 */
WorkerHandler.prototype.exec = function(method, params, resolver) {
  if (!resolver) {
    resolver = Promise.defer();
  }

  // generate a unique id for the task
  var id = ++this.lastId;

  // register a new task as being in progress
  this.processing[id] = {
    id: id,
    resolver: resolver
  };

  // build a JSON-RPC request
  var request = {
    id: id,
    method: method,
    params: params
  };

  if (this.terminated) {
    resolver.reject(new Error('Worker is terminated'));
  } else if (this.worker.ready) {
    // send the request to the worker
    this.worker.send(request);
  } else {
    this.requestQueue.push(request);
  }

  // on cancellation, force the worker to terminate
  var me = this;
  resolver.promise
      .catch(function (error) {
        if (error instanceof Promise.CancellationError || error instanceof Promise.TimeoutError) {
          // remove this task from the queue. It is already rejected (hence this
          // catch event), and else it will be rejected again when terminating
          delete me.processing[id];

          // terminate worker
          me.terminate(true);
        }
      });

  return resolver.promise;
};

/**
 * Test whether the worker is working or not
 * @return {boolean} Returns true if the worker is busy
 */
WorkerHandler.prototype.busy = function () {
  return Object.keys(this.processing).length > 0;
};

/**
 * Terminate the worker.
 * @param {boolean} [force=false]   If false (default), the worker is terminated
 *                                  after finishing all tasks currently in
 *                                  progress. If true, the worker will be
 *                                  terminated immediately.
 */
WorkerHandler.prototype.terminate = function (force) {
  if (force) {
    // cancel all tasks in progress
    for (var id in this.processing) {
      if (this.processing.hasOwnProperty(id)) {
        this.processing[id].resolver.reject(new Error('Worker terminated'));
      }
    }
    this.processing = {};
  }

  if (!this.busy()) {
    // all tasks are finished. kill the worker
    if (this.worker) {
      if (typeof this.worker.kill === 'function') {
        this.worker.kill();  // child process
      }
      else if (typeof this.worker.terminate === 'function') {
        this.worker.terminate(); // web worker
      }
      else {
        throw new Error('Failed to terminate worker');
      }
      this.worker = null;
    }
    this.terminating = false;
    this.terminated = true;
  }
  else {
    // we can't terminate immediately, there are still tasks being executed
    this.terminating = true;
  }
};

module.exports = WorkerHandler;
<commit_msg>Fixed WebStorm debug issue - look for '--inspect' within argument strings, instead of requiring exact match.<commit_after>var Promise = require('./Promise');
var assign = require('object-assign');

// determine environment
var environment = require('./environment');

// used to prevent webpack from resolving requires on node libs
var node = {require: require};

// get the default worker script
function getDefaultWorker() {
  if (environment.platform == 'browser') {
    // test whether the browser supports all features that we need
    if (typeof Blob === 'undefined') {
      throw new Error('Blob not supported by the browser');
    }
    if (!window.URL || typeof window.URL.createObjectURL !== 'function') {
      throw new Error('URL.createObjectURL not supported by the browser');
    }

    // use embedded worker.js
    var blob = new Blob([require('./generated/embeddedWorker')], {type: 'text/javascript'});
    return window.URL.createObjectURL(blob);
  }
  else {
    // use exteral worker.js in current directory
    return __dirname + '/worker.js';
  }
}

// add debug flags to child processes if the node inspector is active
function resolveForkOptions(opts) {
  opts = opts || {};

  const execArgv = [];

  var inspectorActive = false;
  process.execArgv.some(function(value) {
    if (value.indexOf('--inspect') !== -1) { inspectorActive = true; return true; }
  });
  const debugBrk = process.execArgv
    .indexOf('--debug-brk') !== -1;

  if (inspectorActive) {
    execArgv.push('--inspect=' + opts.debugPort);

    if (debugBrk) {
      execArgv.push('--debug-brk');
    }
  }

  return assign({}, opts, {
    forkArgs: opts.forkArgs,
    forkOpts: assign({}, opts.forkOpts, {
      execArgv: (opts.forkOpts && opts.forkOpts.execArgv || [])
        .concat(execArgv)
    })
  });
};

/**
 * Converts a serialized error to Error
 * @param {Object} obj Error that has been serialized and parsed to object
 * @return {Error} The equivalent Error.
 */
function objectToError (obj) {
  var temp = new Error('')
  var props = Object.keys(obj)

  for (var i = 0; i < props.length; i++) {
    temp[props[i]] = obj[props[i]]
  }

  return temp
}

/**
 * A WorkerHandler controls a single worker. This worker can be a child process
 * on node.js or a WebWorker in a browser environment.
 * @param {String} [script] If no script is provided, a default worker with a
 *                          function run will be created.
 * @constructor
 */
function WorkerHandler(script, options) {
  this.script = script || getDefaultWorker();

  var forkOptions;

  if (environment.platform == 'browser') {
    // check whether Worker is supported by the browser
    // Workaround for a bug in PhantomJS (Or QtWebkit): https://github.com/ariya/phantomjs/issues/14534
    if (typeof Worker !== 'function' && (typeof Worker !== 'object' || typeof Worker.prototype.constructor !== 'function')) {
      throw new Error('Web workers not supported by the browser');
    }

    // create the web worker
    this.worker = new Worker(this.script);

    // add node.js API to the web worker
    this.worker.on = function (event, callback) {
      this.addEventListener(event, function (message) {
        callback(message.data);
      });
    };
    this.worker.send = function (message) {
      this.postMessage(message);
    };
  }
  else {
    // on node.js, create a child process
    forkOptions = resolveForkOptions(options);

    // call node.require to prevent child_process to be required when loading with AMD
    this.worker = node.require('child_process').fork(
      this.script,
      forkOptions.forkArgs,
      forkOptions.forkOpts
    );
  }

  var me = this;

  // The ready message is only sent if the worker.add method is called (And the default script is not used)
  if (!script) {
    this.worker.ready = true;
  }

  // queue for requests that are received before the worker is ready
  this.requestQueue = [];
  this.worker.on('message', function (response) {
    if (typeof response === 'string' && response === 'ready') {
      me.worker.ready = true;
      dispatchQueuedRequests();
    } else {
      // find the task from the processing queue, and run the tasks callback
      var id = response.id;
      var task = me.processing[id];
      if (task) {
        // remove the task from the queue
        delete me.processing[id];

        // test if we need to terminate
        if (me.terminating) {
          // complete worker termination if all tasks are finished
          me.terminate();
        }

        // resolve the task's promise
        if (response.error) {
          task.resolver.reject(objectToError(response.error));
        }
        else {
          task.resolver.resolve(response.result);
        }
      }
    }
  });

  // reject all running tasks on worker error
  function onError(error) {
    me.terminated = true;

    for (var id in me.processing) {
      if (me.processing.hasOwnProperty(id)) {
        me.processing[id].resolver.reject(error);
      }
    }
    me.processing = {};
  }

  // send all queued requests to worker
  function dispatchQueuedRequests()
  {
    me.requestQueue.forEach(me.worker.send.bind(me.worker));
    me.requestQueue = [];
  }

  // listen for worker messages error and exit
  this.worker.on('error', onError);
  this.worker.on('exit', function () {
    var error = new Error('Worker terminated unexpectedly');
    onError(error);
  });

  this.processing = {}; // queue with tasks currently in progress

  this.terminating = false;
  this.terminated = false;
  this.lastId = 0;
}

/**
 * Get a list with methods available on the worker.
 * @return {Promise.<String[], Error>} methods
 */
WorkerHandler.prototype.methods = function () {
  return this.exec('methods');
};

/**
 * Execute a method with given parameters on the worker
 * @param {String} method
 * @param {Array} [params]
 * @param {{resolve: Function, reject: Function}} [resolver]
 * @return {Promise.<*, Error>} result
 */
WorkerHandler.prototype.exec = function(method, params, resolver) {
  if (!resolver) {
    resolver = Promise.defer();
  }

  // generate a unique id for the task
  var id = ++this.lastId;

  // register a new task as being in progress
  this.processing[id] = {
    id: id,
    resolver: resolver
  };

  // build a JSON-RPC request
  var request = {
    id: id,
    method: method,
    params: params
  };

  if (this.terminated) {
    resolver.reject(new Error('Worker is terminated'));
  } else if (this.worker.ready) {
    // send the request to the worker
    this.worker.send(request);
  } else {
    this.requestQueue.push(request);
  }

  // on cancellation, force the worker to terminate
  var me = this;
  resolver.promise
      .catch(function (error) {
        if (error instanceof Promise.CancellationError || error instanceof Promise.TimeoutError) {
          // remove this task from the queue. It is already rejected (hence this
          // catch event), and else it will be rejected again when terminating
          delete me.processing[id];

          // terminate worker
          me.terminate(true);
        }
      });

  return resolver.promise;
};

/**
 * Test whether the worker is working or not
 * @return {boolean} Returns true if the worker is busy
 */
WorkerHandler.prototype.busy = function () {
  return Object.keys(this.processing).length > 0;
};

/**
 * Terminate the worker.
 * @param {boolean} [force=false]   If false (default), the worker is terminated
 *                                  after finishing all tasks currently in
 *                                  progress. If true, the worker will be
 *                                  terminated immediately.
 */
WorkerHandler.prototype.terminate = function (force) {
  if (force) {
    // cancel all tasks in progress
    for (var id in this.processing) {
      if (this.processing.hasOwnProperty(id)) {
        this.processing[id].resolver.reject(new Error('Worker terminated'));
      }
    }
    this.processing = {};
  }

  if (!this.busy()) {
    // all tasks are finished. kill the worker
    if (this.worker) {
      if (typeof this.worker.kill === 'function') {
        this.worker.kill();  // child process
      }
      else if (typeof this.worker.terminate === 'function') {
        this.worker.terminate(); // web worker
      }
      else {
        throw new Error('Failed to terminate worker');
      }
      this.worker = null;
    }
    this.terminating = false;
    this.terminated = true;
  }
  else {
    // we can't terminate immediately, there are still tasks being executed
    this.terminating = true;
  }
};

module.exports = WorkerHandler;
<|endoftext|>


<commit_before>'use strict';

var d           = require('es5-ext/lib/Object/descriptor')
  , forEach     = require('es5-ext/lib/Object/for-each')
  , callable    = require('es5-ext/lib/Object/valid-callable')
  , unserialize = require('../utils/unserialize')
  , relation    = require('./')

  , isArray = Array.isArray, call = Function.prototype.call
  , defineProperties = Object.defineProperties
  , getOwnPropertyNames = Object.getOwnPropertyNames
  , getPrototypeOf = Object.getPrototypeOf, keys = Object.keys;

defineProperties(relation, {
	_assertSet_: d(function () {
		if (!this._isSet_) throw new TypeError("Property is not a set");
	}),
	count: d.gs(function () {
		var count;
		this._assertSet_();
		if (this.hasOwnProperty('_value')) return this._count_;
		count = 0;
		this.forEach(function () { ++count; });
		return count;
	}),
	_isSet_: d.gs(function () {
		return this.multiple &&
			((typeof this.__value !== 'function') || this.__value._id_);
	}),
	add: d(function (value) {
		var error;
		this._assertSet_();
		error = this.validateValue(value);
		if (error) throw error;
		return this.$add(value);
	}),
	$add: d(function (value) {
		var item, key;
		if (!this.ns.is(value)) value = this.ns.prototype.$create(value);
		key = this.ns._serialize_(value);
		item = this.hasOwnProperty(key) ? this[key] :
				this._itemPrototype_.$$createItem(key, value);
		item._signal_(true);
		return item;
	}),
	_getSetItem_: d(function (key, value) {
		if (!this.hasOwnProperty(key)) {
			if (value == null) value = unserialize(key);
			return this._itemPrototype_.$$createItem(key, value);
		}
		return this[key];
	}),
	delete: d(function (value) {
		var error;
		if ((error = this.validateDelete(value))) throw error;
		return this.$delete(value);
	}),
	validateDelete: d(function (value) {
		var key;
		this._assertSet_();
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return null;
		}

		value = this.ns.normalize(value);
		if (value == null) return null;
		if (!(key = this.ns._serialize_(value))) return null;
		if (this.propertyIsEnumerable(key)) {
			if ((this._count_ === 1) && this.required &&
					this.hasOwnProperty('_value')) {
				return new TypeError('Cannot remove the only value');
			}
		}
		return null;
	}),
	$delete: d(function (value) {
		var item, key;
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return null;
		}

		value = this.ns.normalize(value);
		if (value == null) return null;
		key = this.ns._serialize_(value);
		if (!key) return null;
		item = this.hasOwnProperty(key) ? this[key] :
				this._itemPrototype_.$$createItem(key, value);
		item._signal_();
		return item;
	}),
	has: d(function (value) {
		var key, proto;
		this._assertSet_();
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return false;
		}
		value = this.ns.normalize(value);
		if (value == null) return false;

		key = this.ns._serialize_(value);
		if (key == null) return false;

		if (this.propertyIsEnumerable(key)) return true;
		if (this.hasOwnProperty(key) || this.hasOwnProperty('_value')) {
			return false;
		}
		proto = getPrototypeOf(this);
		while (proto) {
			if (!proto.multiple) return false;
			if (proto.hasOwnProperty('_count_')) return proto.has(value);
			if (proto.hasOwnProperty('_value')) return false;
			proto = getPrototypeOf(proto);
		}
	}),
	forEach: d(function (cb/*, thisArg*/) {
		var thisArg = arguments[1], index = -1, proto
		  , ignores, iterate, setIgnore;
		this._assertSet_();
		callable(cb);
		forEach(this, function (value, name) {
			call.call(cb, thisArg, value.value, value, this, ++index);
		}, this, function (a, b) {
			return this[a].order - this[b].order;
		});

		if (this.hasOwnProperty('_value')) return;
		ignores = {};
		getOwnPropertyNames(this)
			.forEach(setIgnore = function (key) { ignores[key] = true; });
		proto = getPrototypeOf(this);
		iterate = function (key) {
			if (!ignores[key]) {
				call.call(cb, thisArg, proto[key].value, null, this, ++index);
			}
		};
		while (proto) {
			if (!proto.multiple) return;
			if (proto._count_) keys(proto).forEach(iterate, this);
			if (proto.hasOwnProperty('_value')) return;
			getOwnPropertyNames(proto).forEach(setIgnore);
			proto = getPrototypeOf(proto);
		}
	}),
	getItem: d(function (value) {
		var key;
		this._assertSet_();
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return null;
		}
		value = this.ns.normalize(value);
		if (value == null) return null;
		key = this.ns._serialize_(value);
		if (key == null) return null;
		return this.propertyIsEnumerable(key) ? this[key] : null;
	}),
	values: d.gs(function () {
		var arr;
		this._assertSet_();
		arr = [];
		this.forEach(function (item) { arr.push(item); });
		return arr;
	}),
	_clear_: d(function () {
		if (!this._count_) return;
		keys(this).forEach(function (key) {
			var item = this[key];
			item._order._signal_();
			item._signal_();
		}, this);
	}),
	_reset_: d(function (value) {
		var key, ns, map, item;
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			this._clear_();
			this._signal_(value);
			return;
		}
		if (isArray(value)) {
			if (!value.length) {
				this._clear_();
			} else {
				ns = this.ns;
				map = {};
				value.map(function (value, index) {
					if (!ns.is(value)) value = ns.prototype.$create(value);
					map[ns._serialize_(value)] = { value: value, index: index };
				}, this);
				keys(this).forEach(function (key) {
					var item = this[key];
					if (!map[key]) {
						item._order._signal_();
						item._signal_();
					} else {
						item._order._signal_(map[key].index);
						item._signal_(true);
						delete map[key];
					}
				}, this);
				forEach(map, function (value, key) {
					var item = this._getSetItem_(key, value.value);
					item._signal_(true);
					item._order._signal_(value.index);
				}, this);
			}
		} else {
			key = this.ns._serialize_(value);
			keys(this).forEach(function (lkey) {
				var item = this[lkey];
				if (lkey === key) return;
				item._order._signal_();
				item._signal_();
			}, this);
			item = this._getSetItem_(key, value);
			item._signal_(true);
			item._order._signal_(1);
		}
		this._signal_(null);
	})
});

require('./set-item');
<commit_msg>Reordered _getSetItem_ to be defined by getItem<commit_after>'use strict';

var d           = require('es5-ext/lib/Object/descriptor')
  , forEach     = require('es5-ext/lib/Object/for-each')
  , callable    = require('es5-ext/lib/Object/valid-callable')
  , unserialize = require('../utils/unserialize')
  , relation    = require('./')

  , isArray = Array.isArray, call = Function.prototype.call
  , defineProperties = Object.defineProperties
  , getOwnPropertyNames = Object.getOwnPropertyNames
  , getPrototypeOf = Object.getPrototypeOf, keys = Object.keys;

defineProperties(relation, {
	_assertSet_: d(function () {
		if (!this._isSet_) throw new TypeError("Property is not a set");
	}),
	count: d.gs(function () {
		var count;
		this._assertSet_();
		if (this.hasOwnProperty('_value')) return this._count_;
		count = 0;
		this.forEach(function () { ++count; });
		return count;
	}),
	_isSet_: d.gs(function () {
		return this.multiple &&
			((typeof this.__value !== 'function') || this.__value._id_);
	}),
	add: d(function (value) {
		var error;
		this._assertSet_();
		error = this.validateValue(value);
		if (error) throw error;
		return this.$add(value);
	}),
	$add: d(function (value) {
		var item, key;
		if (!this.ns.is(value)) value = this.ns.prototype.$create(value);
		key = this.ns._serialize_(value);
		item = this.hasOwnProperty(key) ? this[key] :
				this._itemPrototype_.$$createItem(key, value);
		item._signal_(true);
		return item;
	}),
	delete: d(function (value) {
		var error;
		if ((error = this.validateDelete(value))) throw error;
		return this.$delete(value);
	}),
	validateDelete: d(function (value) {
		var key;
		this._assertSet_();
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return null;
		}

		value = this.ns.normalize(value);
		if (value == null) return null;
		if (!(key = this.ns._serialize_(value))) return null;
		if (this.propertyIsEnumerable(key)) {
			if ((this._count_ === 1) && this.required &&
					this.hasOwnProperty('_value')) {
				return new TypeError('Cannot remove the only value');
			}
		}
		return null;
	}),
	$delete: d(function (value) {
		var item, key;
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return null;
		}

		value = this.ns.normalize(value);
		if (value == null) return null;
		key = this.ns._serialize_(value);
		if (!key) return null;
		item = this.hasOwnProperty(key) ? this[key] :
				this._itemPrototype_.$$createItem(key, value);
		item._signal_();
		return item;
	}),
	has: d(function (value) {
		var key, proto;
		this._assertSet_();
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return false;
		}
		value = this.ns.normalize(value);
		if (value == null) return false;

		key = this.ns._serialize_(value);
		if (key == null) return false;

		if (this.propertyIsEnumerable(key)) return true;
		if (this.hasOwnProperty(key) || this.hasOwnProperty('_value')) {
			return false;
		}
		proto = getPrototypeOf(this);
		while (proto) {
			if (!proto.multiple) return false;
			if (proto.hasOwnProperty('_count_')) return proto.has(value);
			if (proto.hasOwnProperty('_value')) return false;
			proto = getPrototypeOf(proto);
		}
	}),
	forEach: d(function (cb/*, thisArg*/) {
		var thisArg = arguments[1], index = -1, proto
		  , ignores, iterate, setIgnore;
		this._assertSet_();
		callable(cb);
		forEach(this, function (value, name) {
			call.call(cb, thisArg, value.value, value, this, ++index);
		}, this, function (a, b) {
			return this[a].order - this[b].order;
		});

		if (this.hasOwnProperty('_value')) return;
		ignores = {};
		getOwnPropertyNames(this)
			.forEach(setIgnore = function (key) { ignores[key] = true; });
		proto = getPrototypeOf(this);
		iterate = function (key) {
			if (!ignores[key]) {
				call.call(cb, thisArg, proto[key].value, null, this, ++index);
			}
		};
		while (proto) {
			if (!proto.multiple) return;
			if (proto._count_) keys(proto).forEach(iterate, this);
			if (proto.hasOwnProperty('_value')) return;
			getOwnPropertyNames(proto).forEach(setIgnore);
			proto = getPrototypeOf(proto);
		}
	}),
	_getSetItem_: d(function (key, value) {
		if (!this.hasOwnProperty(key)) {
			if (value == null) value = unserialize(key);
			return this._itemPrototype_.$$createItem(key, value);
		}
		return this[key];
	}),
	getItem: d(function (value) {
		var key;
		this._assertSet_();
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			return null;
		}
		value = this.ns.normalize(value);
		if (value == null) return null;
		key = this.ns._serialize_(value);
		if (key == null) return null;
		return this.propertyIsEnumerable(key) ? this[key] : null;
	}),
	values: d.gs(function () {
		var arr;
		this._assertSet_();
		arr = [];
		this.forEach(function (item) { arr.push(item); });
		return arr;
	}),
	_clear_: d(function () {
		if (!this._count_) return;
		keys(this).forEach(function (key) {
			var item = this[key];
			item._order._signal_();
			item._signal_();
		}, this);
	}),
	_reset_: d(function (value) {
		var key, ns, map, item;
		if ((value == null) || ((typeof value === 'function') && !value._id_)) {
			this._clear_();
			this._signal_(value);
			return;
		}
		if (isArray(value)) {
			if (!value.length) {
				this._clear_();
			} else {
				ns = this.ns;
				map = {};
				value.map(function (value, index) {
					if (!ns.is(value)) value = ns.prototype.$create(value);
					map[ns._serialize_(value)] = { value: value, index: index };
				}, this);
				keys(this).forEach(function (key) {
					var item = this[key];
					if (!map[key]) {
						item._order._signal_();
						item._signal_();
					} else {
						item._order._signal_(map[key].index);
						item._signal_(true);
						delete map[key];
					}
				}, this);
				forEach(map, function (value, key) {
					var item = this._getSetItem_(key, value.value);
					item._signal_(true);
					item._order._signal_(value.index);
				}, this);
			}
		} else {
			key = this.ns._serialize_(value);
			keys(this).forEach(function (lkey) {
				var item = this[lkey];
				if (lkey === key) return;
				item._order._signal_();
				item._signal_();
			}, this);
			item = this._getSetItem_(key, value);
			item._signal_(true);
			item._order._signal_(1);
		}
		this._signal_(null);
	})
});

require('./set-item');
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * 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 Ajax.org B.V. 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 AJAX.ORG B.V. 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.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var RubyHighlightRules = require("./ruby_highlight_rules").RubyHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var Range = require("../range").Range;
var FoldMode = require("./folding/coffee").FoldMode;

var Mode = function() {
    this.HighlightRules = RubyHighlightRules;
    this.$outdent = new MatchingBraceOutdent();
    this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);

(function() {

    this.lineCommentStart = "#";

    this.getNextLineIndent = function(state, line, tab) {
        var indent = this.$getIndent(line);

        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
        var tokens = tokenizedLine.tokens;

        if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
        }

        if (state == "start") {
            var match = line.match(/^.*[\{\(\[]\s*$/);
            var startingClassOrMethod = line.match(/^\s*(class|def|module)\s.*$/);
            var startingDoBlock = line.match(/.*do(\s*|\s+\|.*\|\s*)$/);
            var startingConditional = line.match(/^\s*(if|else)\s*/)
            if (match || startingClassOrMethod || startingDoBlock || startingConditional) {
                indent += tab;
            }
        }

        return indent;
    };

    this.checkOutdent = function(state, line, input) {
        return /^\s+(end|else)$/.test(line + input) || this.$outdent.checkOutdent(line, input);
    };

    this.autoOutdent = function(state, session, row) {
        var line = session.getLine(row);
        if (/}/.test(line))
            return this.$outdent.autoOutdent(session, row);
        var indent = this.$getIndent(line);
        var prevLine = session.getLine(row - 1);
        var prevIndent = this.$getIndent(prevLine);
        var tab = session.getTabString();
        if (prevIndent.length <= indent.length) {
            if (indent.slice(-tab.length) == tab)
                session.remove(new Range(row, indent.length-tab.length, row, indent.length));
        }
    };

    this.$id = "ace/mode/ruby";
}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>Enabled C-style behaviors for Ruby which are pretty much accurate.<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * 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 Ajax.org B.V. 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 AJAX.ORG B.V. 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.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var RubyHighlightRules = require("./ruby_highlight_rules").RubyHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var Range = require("../range").Range;
var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
var FoldMode = require("./folding/coffee").FoldMode;

var Mode = function() {
    this.HighlightRules = RubyHighlightRules;
    this.$outdent = new MatchingBraceOutdent();
    this.$behaviour = new CstyleBehaviour();
    this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);

(function() {

    this.lineCommentStart = "#";

    this.getNextLineIndent = function(state, line, tab) {
        var indent = this.$getIndent(line);

        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
        var tokens = tokenizedLine.tokens;

        if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
        }

        if (state == "start") {
            var match = line.match(/^.*[\{\(\[]\s*$/);
            var startingClassOrMethod = line.match(/^\s*(class|def|module)\s.*$/);
            var startingDoBlock = line.match(/.*do(\s*|\s+\|.*\|\s*)$/);
            var startingConditional = line.match(/^\s*(if|else)\s*/)
            if (match || startingClassOrMethod || startingDoBlock || startingConditional) {
                indent += tab;
            }
        }

        return indent;
    };

    this.checkOutdent = function(state, line, input) {
        return /^\s+(end|else)$/.test(line + input) || this.$outdent.checkOutdent(line, input);
    };

    this.autoOutdent = function(state, session, row) {
        var line = session.getLine(row);
        if (/}/.test(line))
            return this.$outdent.autoOutdent(session, row);
        var indent = this.$getIndent(line);
        var prevLine = session.getLine(row - 1);
        var prevIndent = this.$getIndent(prevLine);
        var tab = session.getTabString();
        if (prevIndent.length <= indent.length) {
            if (indent.slice(-tab.length) == tab)
                session.remove(new Range(row, indent.length-tab.length, row, indent.length));
        }
    };

    this.$id = "ace/mode/ruby";
}).call(Mode.prototype);

exports.Mode = Mode;
});
<|endoftext|>