<commit_before>var engine;
if (typeof E === 'undefined') {
    engine = global.engine;
} else {
    engine = E;
    global = window;
}

// regular expression patterns
var find_tmpl = /\{([\w\.]+)\}/g;
var find_braces = /\{|\}/g;

/**
 * Create a new flow event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
engine.flow = function (module_instance, outConfig, adapter) {

    /**
     * The flow event handler.
     *
     * @public
     * @param {object} The event object.
     * @param {object} The event data.
     */
    return function handler (event, _data) {

        // create an event object
        event = event || {};
        event.ori = event.ori || module_instance._name;

        // plug external events
        adapter && adapter.handler(event, adapter.data);

        // extend event with location data (hash, search, path)
        global.location && handleStateValues(event);

        // loop through out configs
        for (var i = 0, config, to; i < outConfig.length; ++i) {
            config = outConfig[i];

            // check if "to" module instance exists and role has access
            if (
                (config.to && !(module_instance = engine.instances[config.to])) ||
                (event.role && !engine.roleAccess(module_instance, event.role))
            ) {
                continue;
            };

            // check if event loads module instnaces
            if (config.load) {

                // load module instances
                for (var l = 0; l < config.load.length; ++l) {
                    engine.module(config.load[l])
                }

                // remove load config, after module instances are loaded
                delete config.load;
            }

            // copy the static data or create a new data object
            var data = config.data ? JSON.parse(JSON.stringify(config.data)) : {};

            // complete dynamic paths
            for (var key in data) {
                if (typeof data[key] === 'string' && data[key].indexOf('{') > -1) {
                    data[key] = parsePath(data[key], event, data, module_instance)
                }
            }

            // merge argument data to data object
            if (_data) {
                for (var key in _data) {
                    data[key] = _data[key];
                }
            }

            // merge static and dynamic data
            data = handleDataMerging(config, event, data, module_instance);

            // emit route
            if (config.route) {
                engine.route(parsePath(config.route, event, data, module_instance), event);
            }

            // emit event
            if (config.emit) {
                module_instance.emit(config.emit, event, data);
            }

            // call method
            if (config.call) {

                // find call method when the event handler is called
                if (typeof config.call === 'string') {
                    config.call = engine.path(config.call, [module_instance]) || function () {};
                }

                // call method
                config.call.call(module_instance, event, data);
            }
        }
    };
}

/**
 * Extend event object with location data.
 *
 * @private
 * @param {object} The event object.
 */
function handleStateValues (event) {

    // add pathname to data object
    event._path = global.location.pathname.substr(1).split('/');

    // parse and append url search to data
    if (global.location.search && !event._search) {
        event._search = searchToJSON();
    }

    // append url hash to data
    if (global.location.hash && !event._hash) {
        event._hash = global.location.hash.substr(1);
    }
}

/**
 * Merge dynamic data to the event data object.
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The event config.
 * @param {object} The event data object.
 */
function handleDataMerging (config, event, data, module_instance) {

    // add dynamic data to the data object
    if (config.set) {

        // add data to the data object
        for (var key in config.set) {

            // parse path
            var path = config.set[key];

            // get an attribute value from a dom element or the element itself
            if (path[0] === '$') {
                path = path.substr(1).split(':');

                // get find an element in the document
                path[0] = document.querySelector(path[0]);

                // set data key to the dom attribute value or the dom element
                data[key] = path[1] && path[0][path[1]] !== undefined ? path[0][path[1]] : path[0];

            // get search value with a path: 1. events, 2. data, 3. instance, 4. window
            } else {
                data[key] = engine.path(path, [event, data, module_instance]);
            }
        }

        // create deep object out of flat keys
        data = engine.deep(data);
    }

    return data;
}

/**
 * Replace data fields in a string.
 *
 * @private
 * @param {string} The string.
 * @param {object} The data context.
 */
function parsePath (path, event, data, module_instance) {
    var match = path.match(find_tmpl);

    // replace route with data
    if (match) {
        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = engine.path(match[i].replace(find_braces, ''), [event, data, module_instance]);

            // replace value in route
            if (typeof value !== 'undefined') {
                path = path.replace(match[i], value);
            }
        }
    }

    return path;
}

/**
 * Parse a state search string to JSON.
 * Credentials: http://snipplr.com/view/70905/search-string-to-json/
 *
 * @private
 */
function searchToJSON(){
    var rep = {'?':'{"','=':'":"','&':'","'};
    var s = state.search.replace(/[\?\=\&]/g, function(r) {
        return rep[r];
    });
    return JSON.parse(s.length? s+'"}' : "{}");
}
<commit_msg>engine and global are now in the module namespace<commit_after>// regular expression patterns
var find_tmpl = /\{([\w\.]+)\}/g;
var find_braces = /\{|\}/g;

/**
 * Create a new flow event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
engine.flow = function (module_instance, outConfig, adapter) {

    /**
     * The flow event handler.
     *
     * @public
     * @param {object} The event object.
     * @param {object} The event data.
     */
    return function handler (event, _data) {

        // create an event object
        event = event || {};
        event.ori = event.ori || module_instance._name;

        // plug external events
        adapter && adapter.handler(event, adapter.data);

        // extend event with location data (hash, search, path)
        global.location && handleStateValues(event);

        // loop through out configs
        for (var i = 0, config, to; i < outConfig.length; ++i) {
            config = outConfig[i];

            // check if "to" module instance exists and role has access
            if (
                (config.to && !(module_instance = engine.instances[config.to])) ||
                (event.role && !engine.roleAccess(module_instance, event.role))
            ) {
                continue;
            };

            // check if event loads module instnaces
            if (config.load) {

                // load module instances
                for (var l = 0; l < config.load.length; ++l) {
                    engine.module(config.load[l])
                }

                // remove load config, after module instances are loaded
                delete config.load;
            }

            // copy the static data or create a new data object
            var data = config.data ? JSON.parse(JSON.stringify(config.data)) : {};

            // complete dynamic paths
            for (var key in data) {
                if (typeof data[key] === 'string' && data[key].indexOf('{') > -1) {
                    data[key] = parsePath(data[key], event, data, module_instance)
                }
            }

            // merge argument data to data object
            if (_data) {
                for (var key in _data) {
                    data[key] = _data[key];
                }
            }

            // merge static and dynamic data
            data = handleDataMerging(config, event, data, module_instance);

            // emit route
            if (config.route) {
                engine.route(parsePath(config.route, event, data, module_instance), event);
            }

            // emit event
            if (config.emit) {
                module_instance.emit(config.emit, event, data);
            }

            // call method
            if (config.call) {

                // find call method when the event handler is called
                if (typeof config.call === 'string') {
                    config.call = engine.path(config.call, [module_instance]) || function () {};
                }

                // call method
                config.call.call(module_instance, event, data);
            }
        }
    };
}

/**
 * Extend event object with location data.
 *
 * @private
 * @param {object} The event object.
 */
function handleStateValues (event) {

    // add pathname to data object
    event._path = global.location.pathname.substr(1).split('/');

    // parse and append url search to data
    if (global.location.search && !event._search) {
        event._search = searchToJSON();
    }

    // append url hash to data
    if (global.location.hash && !event._hash) {
        event._hash = global.location.hash.substr(1);
    }
}

/**
 * Merge dynamic data to the event data object.
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The event config.
 * @param {object} The event data object.
 */
function handleDataMerging (config, event, data, module_instance) {

    // add dynamic data to the data object
    if (config.set) {

        // add data to the data object
        for (var key in config.set) {

            // parse path
            var path = config.set[key];

            // get an attribute value from a dom element or the element itself
            if (path[0] === '$') {
                path = path.substr(1).split(':');

                // get find an element in the document
                path[0] = document.querySelector(path[0]);

                // set data key to the dom attribute value or the dom element
                data[key] = path[1] && path[0][path[1]] !== undefined ? path[0][path[1]] : path[0];

            // get search value with a path: 1. events, 2. data, 3. instance, 4. window
            } else {
                data[key] = engine.path(path, [event, data, module_instance]);
            }
        }

        // create deep object out of flat keys
        data = engine.deep(data);
    }

    return data;
}

/**
 * Replace data fields in a string.
 *
 * @private
 * @param {string} The string.
 * @param {object} The data context.
 */
function parsePath (path, event, data, module_instance) {
    var match = path.match(find_tmpl);

    // replace route with data
    if (match) {
        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = engine.path(match[i].replace(find_braces, ''), [event, data, module_instance]);

            // replace value in route
            if (typeof value !== 'undefined') {
                path = path.replace(match[i], value);
            }
        }
    }

    return path;
}

/**
 * Parse a state search string to JSON.
 * Credentials: http://snipplr.com/view/70905/search-string-to-json/
 *
 * @private
 */
function searchToJSON(){
    var rep = {'?':'{"','=':'":"','&':'","'};
    var s = state.search.replace(/[\?\=\&]/g, function(r) {
        return rep[r];
    });
    return JSON.parse(s.length? s+'"}' : "{}");
}
<|endoftext|>


<commit_before>// regular expression patterns
var find_tmpl = /\{([\w\.]+)\}/g;
var find_braces = /\{|\}/g;

/**
 * Create a new config event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
engine.flow = function (module_instance, config, adapter) {

    /*
        IDEA: - make events strict again (events[event]) -> performance gain
              - handle routes separately (on(route, engine.config())) -> better maintainabillity
              - route handling in a separate module, yes
    */

    /**
     * The config event handler.
     *
     * @public
     * @param {object} The event object.
     * @param {object} The event data.
     */
    return function handler (eventStream) {

        // reslove data fields and clone the config config object
        config = resolveAndClone(config, module_instance, adapter);

        // load module instances
        if (config.load) {
            // load module instances
            for (var m = 0, ml = config.load.length; m < ml; ++m) {
                engine.module(config.load[m]);
            }
        }

        // route to url
        if (config.route) {
            engine.route(config.route);
        }

        // check flow content
        if (config.flow && config.flow.length) {

            // execute the flow configs
            for (var i = 0, l = config.flow.length, flow, key; i < l; ++i) {
                flow = config.flow[i];

                // get target module instance, or continue if not found
                // and check module instance acces for server side
                if (
                    (flow.to && !(module_instance = engine.instances[parsePath(flow.to, data, module_instance)])) &&
                    (eventStream.role && !engine.roleAccess(module_instance, eventStream.role))
                ) {
                    continue;
                }

                /*
                TODO: - pipe to "serverEvent:instance"
                */
                if (flow.to && flow.to.indexOf(':') > 0) {
                    var serverEvent = flow.to.split(':')[0];

                    var link = module_instance.link(serverEvent, function () {
                        //..
                    });

                    // ..pipe link to eventStream?
                    // ..send config config as data to server?
                }

                // pipe event to another event
                if (flow.pipe) {
                    eventStream.pipe(module_instance.event(flow.pipe));
                }

                // append method call event data handlers
                if (flow.call) {
                    eventStream.data(flow.call, module_instance);
                }
            }
        }

        // send first data event with the configured config data
        eventStream.emit(null, config.data);
    };
};

/**
 * Resolve data fields in for incoming configs.
 *
 * @private
 * @param {object} The config config.
 * @param {object} The data object.
 * @param {object} The module instance.
 */
function resolveAndClone (config, module_instance, adapter) {

    var parsedFlow = {
        data: {}
    };
    var data = parsedFlow.data;
    var key;

    // extend data with location data (hash, search, path)
    if (global.location) {
        handleStateValues(data);
    }

    // add custom data to the first data emit
    if (adapter) {
        adapter.handler(data, adapter.data);
    }

    // "data": {"key": "{value}"}
    if (config.data) {
        for (key in config.data) {

            // parse the data field values
            parsedFlow.data[key] = parsePath(config.data[key], data, module_instance);
        }
    }

    // search for path in data and module instance and set it to the cloned config
    // "set": {"key": "{path}", "key": "${#css:attr}"}
    if (config.set) {
        for (key in config.set) {
            parsedFlow.data[key] = parsePath(config.set[key], data, module_instance, true);
        }
    }

    // create nest objects with flat keys
    if (config.data || config.set) {
        parsedFlow.data = engine.deep(parsedFlow.data);
    }

    // "load": ["{instance}"]
    if (config.load) {
        parsedFlow.load = [];

        for (var l = 0, ll = config.load.length; l < ll; ++l) {
            parsedFlow.load[l] = parsePath(config.load[l], data, module_instance);
        }
    }

    // "route": "{path}"
    if (config.route) {
        parsedFlow.route = parsePath(config.route, data, module_instance);
    }

    if (config.flow && config.flow.length) {
        parsedFlow.flow = [];

        for (var f = 0, lf = config.flow.length, flow, pFlow; f < lf; ++f) {
            flow = config.flow[f];
            pFlow = {};

            // "call": "{method}"
            if (flow.call) {
                pFlow.call = parsePath(flow.call, data, module_instance, true);
            }

            // "pipe": "{event}"
            if (flow.pipe) {
                pFlow.pipe = parsePath(flow.pipe, data, module_instance);
            }

            // "to": {instance}
            if (flow.to) {
                pFlow.to = parsePath(flow.to, data, module_instance);
            }

            // push flow into parsed flow object
            parsedFlow.flow[f] = pFlow;
        }
    }

    return parsedFlow;
}

/**
 * Extend event object with location data.
 *
 * @private
 * @param {object} The event object.
 */
function handleStateValues (data) {

    // add pathname to data object
    data._path = global.location.pathname.substr(1).split('/');

    // parse and append url search to data
    if (global.location.search && !data._search) {
        data._search = searchToJSON(global.location.search);
    }

    // append url hash to data
    if (global.location.hash && !data._hash) {
        data._hash = global.location.hash.substr(1);
    }
}

/**
 * Parse a state search string to JSON.
 * Credentials: http://snipplr.com/view/70905/search-string-to-json/
 *
 * @private
 */
function searchToJSON(search) {
    var rep = {'?':'{"','=':'":"','&':'","'};
    var s = search.replace(/[\?\=\&]/g, function(r) {
        return rep[r];
    });
    return JSON.parse(s.length? s+'"}' : "{}");
}

/**
 * Replace data fields in a string.
 *
 * @private
 * @param {string} The string.
 * @param {object} The data context.
 */
function parsePath (path, data, module_instance, getValue) {

    if (path.indexOf('{') < 0) {
        return getValue ? getPathValue(path, data, module_instance) : path;
    }

    var match = path.match(find_tmpl);

    // replace route with data
    if (match) {
        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = engine.path(match[i].replace(find_braces, ''), [data, module_instance]);

            // replace value in route
            if (typeof value !== 'undefined') {
                path = typeof value === 'object' ? value : path.replace(match[i], value);
            }
        }
    }

    // get path value or return path
    return getValue ? getPathValue(path, data, module_instance) : path;
}

/**
 * Merge dynamic data to the event data object.
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The event config.
 * @param {object} The event data object.
 */
function getPathValue (path, data, module_instance) {

    // get an attribute value from a dom element or the element itself
    if (path[0] === '$') {
        path = path.substr(1).split(':');

        // get find an element in the document
        path[0] = document.querySelector(path[0]);

        // set data key to the dom attribute value or the dom element
        return path[1] && path[0][path[1]] !== undefined ? path[0][path[1]] : path[0];

    }

    // return search value with a path: 1. data, 3. instance, 4. global
    return engine.path(path, [data, module_instance, global]);
}

<commit_msg>remove comments<commit_after>// regular expression patterns
var find_tmpl = /\{([\w\.]+)\}/g;
var find_braces = /\{|\}/g;

/**
 * Create a new config event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
engine.flow = function (module_instance, config, adapter) {

    /**
     * The config event handler.
     *
     * @public
     * @param {object} The event object.
     * @param {object} The event data.
     */
    return function handler (eventStream) {

        // reslove data fields and clone the config config object
        config = resolveAndClone(config, module_instance, adapter);

        // load module instances
        if (config.load) {
            // load module instances
            for (var m = 0, ml = config.load.length; m < ml; ++m) {
                engine.module(config.load[m]);
            }
        }

        // route to url
        if (config.route) {
            engine.route(config.route);
        }

        // check flow content
        if (config.flow && config.flow.length) {

            // execute the flow configs
            for (var i = 0, l = config.flow.length, flow, key; i < l; ++i) {
                flow = config.flow[i];

                // get target module instance, or continue if not found
                // and check module instance acces for server side
                if (
                    (flow.to && !(module_instance = engine.instances[parsePath(flow.to, data, module_instance)])) &&
                    (eventStream.role && !engine.roleAccess(module_instance, eventStream.role))
                ) {
                    continue;
                }

                /*
                TODO: - pipe to "serverEvent:instance"
                */
                if (flow.to && flow.to.indexOf(':') > 0) {
                    var serverEvent = flow.to.split(':')[0];

                    var link = module_instance.link(serverEvent, function () {
                        //..
                    });

                    // ..pipe link to eventStream?
                    // ..send config config as data to server?
                }

                // pipe event to another event
                if (flow.pipe) {
                    eventStream.pipe(module_instance.event(flow.pipe));
                }

                // append method call event data handlers
                if (flow.call) {
                    eventStream.data(flow.call, module_instance);
                }
            }
        }

        // send first data event with the configured config data
        eventStream.emit(null, config.data);
    };
};

/**
 * Resolve data fields in for incoming configs.
 *
 * @private
 * @param {object} The config config.
 * @param {object} The data object.
 * @param {object} The module instance.
 */
function resolveAndClone (config, module_instance, adapter) {

    var parsedFlow = {
        data: {}
    };
    var data = parsedFlow.data;
    var key;

    // extend data with location data (hash, search, path)
    if (global.location) {
        handleStateValues(data);
    }

    // add custom data to the first data emit
    if (adapter) {
        adapter.handler(data, adapter.data);
    }

    // "data": {"key": "{value}"}
    if (config.data) {
        for (key in config.data) {

            // parse the data field values
            parsedFlow.data[key] = parsePath(config.data[key], data, module_instance);
        }
    }

    // search for path in data and module instance and set it to the cloned config
    // "set": {"key": "{path}", "key": "${#css:attr}"}
    if (config.set) {
        for (key in config.set) {
            parsedFlow.data[key] = parsePath(config.set[key], data, module_instance, true);
        }
    }

    // create nest objects with flat keys
    if (config.data || config.set) {
        parsedFlow.data = engine.deep(parsedFlow.data);
    }

    // "load": ["{instance}"]
    if (config.load) {
        parsedFlow.load = [];

        for (var l = 0, ll = config.load.length; l < ll; ++l) {
            parsedFlow.load[l] = parsePath(config.load[l], data, module_instance);
        }
    }

    // "route": "{path}"
    if (config.route) {
        parsedFlow.route = parsePath(config.route, data, module_instance);
    }

    if (config.flow && config.flow.length) {
        parsedFlow.flow = [];

        for (var f = 0, lf = config.flow.length, flow, pFlow; f < lf; ++f) {
            flow = config.flow[f];
            pFlow = {};

            // "call": "{method}"
            if (flow.call) {
                pFlow.call = parsePath(flow.call, data, module_instance, true);
            }

            // "pipe": "{event}"
            if (flow.pipe) {
                pFlow.pipe = parsePath(flow.pipe, data, module_instance);
            }

            // "to": {instance}
            if (flow.to) {
                pFlow.to = parsePath(flow.to, data, module_instance);
            }

            // push flow into parsed flow object
            parsedFlow.flow[f] = pFlow;
        }
    }

    return parsedFlow;
}

/**
 * Extend event object with location data.
 *
 * @private
 * @param {object} The event object.
 */
function handleStateValues (data) {

    // add pathname to data object
    data._path = global.location.pathname.substr(1).split('/');

    // parse and append url search to data
    if (global.location.search && !data._search) {
        data._search = searchToJSON(global.location.search);
    }

    // append url hash to data
    if (global.location.hash && !data._hash) {
        data._hash = global.location.hash.substr(1);
    }
}

/**
 * Parse a state search string to JSON.
 * Credentials: http://snipplr.com/view/70905/search-string-to-json/
 *
 * @private
 */
function searchToJSON(search) {
    var rep = {'?':'{"','=':'":"','&':'","'};
    var s = search.replace(/[\?\=\&]/g, function(r) {
        return rep[r];
    });
    return JSON.parse(s.length? s+'"}' : "{}");
}

/**
 * Replace data fields in a string.
 *
 * @private
 * @param {string} The string.
 * @param {object} The data context.
 */
function parsePath (path, data, module_instance, getValue) {

    if (path.indexOf('{') < 0) {
        return getValue ? getPathValue(path, data, module_instance) : path;
    }

    var match = path.match(find_tmpl);

    // replace route with data
    if (match) {
        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = engine.path(match[i].replace(find_braces, ''), [data, module_instance]);

            // replace value in route
            if (typeof value !== 'undefined') {
                path = typeof value === 'object' ? value : path.replace(match[i], value);
            }
        }
    }

    // get path value or return path
    return getValue ? getPathValue(path, data, module_instance) : path;
}

/**
 * Merge dynamic data to the event data object.
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The event config.
 * @param {object} The event data object.
 */
function getPathValue (path, data, module_instance) {

    // get an attribute value from a dom element or the element itself
    if (path[0] === '$') {
        path = path.substr(1).split(':');

        // get find an element in the document
        path[0] = document.querySelector(path[0]);

        // set data key to the dom attribute value or the dom element
        return path[1] && path[0][path[1]] !== undefined ? path[0][path[1]] : path[0];

    }

    // return search value with a path: 1. data, 3. instance, 4. global
    return engine.path(path, [data, module_instance, global]);
}

<|endoftext|>


<commit_before>var wesocketReconnectTimeoutId;

// the chache for active links
engine._links = {};

// add create Link to global engine object
engine.link = createLink;
engine.link.message = messageHandler;

// reset links cache on reload
/*engine.on('reload', function () {
    engine._links = {};

    // close the websocket and reconnect immedialtey
    engine.socket.close(3000);
});*/

// link factory
module.exports = link;

/**
 * Connect to the server and start listening to messages.
 *
 * @public
 */
function listen () {

    // reset websocket reconnect timer
    if (wesocketReconnectTimeoutId) {
        clearTimeout(wesocketReconnectTimeoutId);
        wesocketReconnectTimeoutId = 0;
    }

    // dont load entrypoint module instance if socket tries to reconnect
    var loadModule = engine.socket ? false : true;

    // create the websocket
    var websocket = engine.socket = new WebSocket('ws://' + window.location.host + '/');

    /**
     * Load the entrypoint module instance on socket open.
     *
     * @private
     */
    websocket.onopen = function () {
        engine.module();
    };

    /**
     * Message handler.
     *
     * @private
     * @param {string} The message string.
     */
    websocket.onmessage = function (message) {
        engine.link.message(message.data, websocket);
    };

    /**
     * Reconnect socket on close.
     *
     * @private
     */
    websocket.onclose = function (closeEvent) {

        // reload imemdiately, when socket is closed by reload
        if (closeEvent.code === 3000) {
            engine.listen();

        // every other case, engine tries to realod after ca. 3 seconds
        } else {
            wesocketReconnectTimeoutId = setTimeout(engine.listen, 3333);
        }
    };
}

var httpLink = {};

/**
 * Send and recive data with the Link class.
 *
 * @class EventStream
 */
var localLink = {

    /**
     * Send a data message over the link.
     *
     * @public
     * @param {object} The error data.
     * @param {object} The data object.
     */
    emit: function (err, data) {

        // call data handlers with err and data as arguments
        for (var i = 0, l = this._h.length; i < l; ++i) {
            //call data handler with eventStream instance as function scope
            this._h[i][0].call(this._h[i][1], err, data);
        }
        return this;
    },

    /**
     * Add a data handler, to receive data.
     *
     * @public
     * @param {function} The data handler method.
     */
    data: function (handler, module_instance) {
        this._h.push([handler, module_instance || this._mi]);
        return this;
    },

    // pipe data to an event stream
    pipe: function (eventStream) {
        var self = this;
        self.data(function (err, data) {
            eventStream.emit(err, data);
        });
    }
};

/**
 * Send and recive data with the Link class.
 *
 * @class Link
 */
var wsLink = {

    /**
     * Send a data message over the link.
     *
     * @public
     * @param {object} The error data.
     * @param {object} The data object.
     */
    send: function (err, data) {

        // send message
        send.call(this, 1, err, data);
        return this;
    },

    /**
     * Add a data handler, to receive data.
     *
     * @public
     * @param {function} The data handler method.
     */
    data: function (handler) {
        this._h.push(handler);
        return this;
    },

    /**
     * Destroy the link with an error or data.
     *
     * @public
     * @param {object} The error data.
     * @param {object} The data object.
     */
    end: function (err, data) {
        var self = this;

        // send end message, before ending the link
        send.call(self, 0, err, data, function (error) {
            end(self, error || err, data);
        });
    }
};

/**
 * Link factory.
 *
 * @public
 * @param {string} The event stream name.
 * @param {string} The destination instance.
 */
function link (name, to) {

    var instance = this;
    var transmitter;

    // emit to all local instances
    if (typeof to === 'boolean') {
        instance = null;
    }

    // emit to local or server instance
    if (typeof to === 'string') {

        // get correct link type

        // type ws
        // type http

        // type local
        if (!(instance = engine.instances[name.to])) {
            return;
        }

        // create local transmitter
        transmitter = createTransmitter(instance);
    }

    // fire events on a single instance
    if (instance) {
        instance.emit(name, transmitter);

    // fire events on all instances
    } else {
        for (instance in engine.instances) {
            engine.instances[instance].emit(name, transmitter);
        }
    }

    return transmitter;
}

// event stream factory
function createTransmitter (neuron) {

    // create event stream object
    var transmitter = engine.clone(Transmitter);
    transmitter._n = neuron;
    transmitter._h = [];

    return transmitter;
}

/**
 * Create a connected link.
 *
 * @public
 * @param {object} The link configuration.
 * @param {function} The connection end handler.
 * @param {string} Optional custom link id.
 */
function createLink (event, callOnEnd, id, socket, session) {

    // create link object
    var link = engine.clone(wsLink);

    // add instance to link
    link._ = this;

    // attach socket or get local websocket (only client)
    link.socket = socket || engine.socket;

    // data handlers
    link._h = [],

    // creae a unique link id
    link.id = id || engine.uid(3);

    // attach end callback
    link._end = callOnEnd;

    // save link event
    link.event = event;

    // save session data in link
    if (session) {
        link.session = session;
        link[engine.session_role] = session[engine.session_role];
        link[engine.session_user] = session[engine.session_user];
        link[engine.session_locale] = session[engine.session_locale];
    }

    // save in the module instances link cache
    this._links[link.id] = link;

    // return link object
    return link;
}

/**
 * Handle websocket messages.
 *
 * @public
 * @param {sring} The message data.
 * @param {object} The websocket.
 * @param {object} The session object.
 */
function messageHandler (message, websocket, session) {

    // parse message
    // protocoll: [type, instance, event, id, err, data]
    try {
        message = JSON.parse(message);
    } catch (error) {
        return;
    }

    // extract data from parsed message
    var type = message[0];
    var instance = message[1];
    var event = message[2];
    var id = message[3];
    var err = message[4];
    var data = message[5];

    if (engine.module.eventAccess) {

        // get module instance
        instance = engine.module.eventAccess(session[engine.session_role], instance ? instance : '@', event);

    } else {

        // get module instance
        instance = instance ? engine.instances[instance] : engine;
    }

    // return if instance doesn't exists
    if (!instance) {
        return;
    }

    // get the link object
    var link = instance._links[id];

    // create link and emit link event
    if (!link) {

        // create a new link with a custom id
        link = createLink.call(instance, event, null, id, websocket, session);

        // ensure socket on link
        link.socket = link.socket || websocket;

        // emit the new crated link
        if (instance.emit) {
            instance.emit(event, link);
        } else {
            instance.event(event).emit(link);
        }
    }

    // handle message types
    switch (type) {

        // END
        case 0:
            end(link, err, data);
            break;

        // DATA
        case 1:

            // call data handlers
            if (link._h.length) {
                for (var i = 0; i < link._h.length; ++i) {
                    link._h[i].call(link._, err, data);
                }
            }
    }
}

/**
 * Create and send a websocket message.send
 *
 * @private
 * @param {number} The message type.
 * @param {object} The error object.
 * @param {object} The data object.
 */
function send (type, err, data, ack) {

    // create message
    var message = [type, this._._name || 0, this.event, this.id, err ? err.toString() : 0];

    // add the data to the message
    if (typeof data !== 'undefined') {
        message[5] = data;
    }

    // encode message (string)
    try {
        message = JSON.stringify(message);

    // return error
    } catch (err) {
        return err;
    }

    // send message
    this.socket.send(message, ack);

    // call the acknowledge handler
    if (engine.client && ack) {
        ack();
    }
}

/**
 * Destroy a link
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The link object.
 */
function end (link, err, data) {

    // call the end handler
    link._end && link._end(err, data);

    // destroy link
    delete link._._links[link.id];
}

<commit_msg>working on event stream class<commit_after>var utils = require('./utils');
var wesocketReconnectTimeoutId;

// the chache for active links
engine._links = {};

// add create Link to global engine object
engine.link = createLink;
engine.link.message = messageHandler;

// reset links cache on reload
/*engine.on('reload', function () {
    engine._links = {};

    // close the websocket and reconnect immedialtey
    engine.socket.close(3000);
});*/

// link factory
module.exports = createTransmitter;

var EventStream = {

    // handler for incoming data
    data: function (handler, module_instance) {
        this._h.push([handler, module_instance || this._]);
        return this;
    },

    // send data
    write: function (err, data) {

        // ..write to out streams
        for (var o = 0, ol = this._o.length, out; o < ol; ++o) {

            // get outgoing handlers
            out = this._o[o]._h;

            // call data handlers with err and data as arguments
            for (var i = 0, l = out.length; i < l; ++i) {

                //call data handler with eventStream instance as function scope
                out[i][0].call(out[i][1], err, data);
            }
        }
        return this;
    },

    end: function () {
        return this;
    },

    // pipe data to an event stream
    pipe: function (eventStream) {

        // ..append out stream
        this._o.push(eventStream);

        return eventStream;
    }
};

var httpLink = {};

/**
 * Send and recive data with the Link class.
 *
 * @class EventStream
 */
var localLink = {

    /**
     * Send a data message over the link.
     *
     * @public
     * @param {object} The error data.
     * @param {object} The data object.
     */
    emit: function (err, data) {

        // call data handlers with err and data as arguments
        for (var i = 0, l = this._h.length; i < l; ++i) {
            //call data handler with eventStream instance as function scope
            this._h[i][0].call(this._h[i][1], err, data);
        }
        return this;
    },

    /**
     * Add a data handler, to receive data.
     *
     * @public
     * @param {function} The data handler method.
     */
    data: function (handler, module_instance) {
        this._h.push([handler, module_instance || this._mi]);
        return this;
    },

    // pipe data to an event stream
    pipe: function (eventStream) {
        var self = this;
        self.data(function (err, data) {
            eventStream.emit(err, data);
        });
    }
};

/**
 * Send and recive data with the Link class.
 *
 * @class wsLink
 */
var wsLink = {

    /**
     * Send a data message over the link.
     *
     * @public
     * @param {object} The error data.
     * @param {object} The data object.
     */
    send: function (err, data) {

        // send message
        send.call(this, 1, err, data);
        return this;
    },

    /**
     * Add a data handler, to receive data.
     *
     * @public
     * @param {function} The data handler method.
     */
    data: function (handler) {
        this._h.push(handler);
        return this;
    },

    /**
     * Destroy the link with an error or data.
     *
     * @public
     * @param {object} The error data.
     * @param {object} The data object.
     */
    end: function (err, data) {
        var self = this;

        // send end message, before ending the link
        send.call(self, 0, err, data, function (error) {
            end(self, error || err, data);
        });
    }
};

/**
 * Link factory.
 *
 * @public
 * @param {string} The event stream name.
 * @param {string} The destination instance.
 */
function link (name, to) {

    var instance = this;
    var transmitter;

    // emit to all local instances
    if (typeof to === 'boolean') {
        instance = null;
    }

    // emit to local or server instance
    if (typeof to === 'string') {

        // get correct link type

        // type ws
        // type http

        // type local
        if (!(instance = engine.instances[name.to])) {
            return;
        }

        // create local transmitter
        transmitter = createTransmitter(instance);
    }

    // fire events on a single instance
    if (instance) {
        instance.emit(name, transmitter);

    // fire events on all instances
    } else {
        for (instance in engine.instances) {
            engine.instances[instance].emit(name, transmitter);
        }
    }

    return transmitter;
}

// event stream factory
function createTransmitter (module_instance) {

    // create event stream object
    var transmitter = utils.clone(EventStream);
    transmitter._ = module_instance;
    transmitter._h = [];
    transmitter._o = [];

    return transmitter;
}

/**
 * Create a connected link.
 *
 * @public
 * @param {object} The link configuration.
 * @param {function} The connection end handler.
 * @param {string} Optional custom link id.
 */
function createLink (event, callOnEnd, id, socket, session) {

    // create link object
    var link = engine.clone(wsLink);

    // add instance to link
    link._ = this;

    // attach socket or get local websocket (only client)
    link.socket = socket || engine.socket;

    // data handlers
    link._h = [],

    // creae a unique link id
    link.id = id || engine.uid(3);

    // attach end callback
    link._end = callOnEnd;

    // save link event
    link.event = event;

    // save session data in link
    if (session) {
        link.session = session;
        link[engine.session_role] = session[engine.session_role];
        link[engine.session_user] = session[engine.session_user];
        link[engine.session_locale] = session[engine.session_locale];
    }

    // save in the module instances link cache
    this._links[link.id] = link;

    // return link object
    return link;
}

/**
 * Handle websocket messages.
 *
 * @public
 * @param {sring} The message data.
 * @param {object} The websocket.
 * @param {object} The session object.
 */
function messageHandler (message, websocket, session) {

    // parse message
    // protocoll: [type, instance, event, id, err, data]
    try {
        message = JSON.parse(message);
    } catch (error) {
        return;
    }

    // extract data from parsed message
    var type = message[0];
    var instance = message[1];
    var event = message[2];
    var id = message[3];
    var err = message[4];
    var data = message[5];

    if (engine.module.eventAccess) {

        // get module instance
        instance = engine.module.eventAccess(session[engine.session_role], instance ? instance : '@', event);

    } else {

        // get module instance
        instance = instance ? engine.instances[instance] : engine;
    }

    // return if instance doesn't exists
    if (!instance) {
        return;
    }

    // get the link object
    var link = instance._links[id];

    // create link and emit link event
    if (!link) {

        // create a new link with a custom id
        link = createLink.call(instance, event, null, id, websocket, session);

        // ensure socket on link
        link.socket = link.socket || websocket;

        // emit the new crated link
        if (instance.emit) {
            instance.emit(event, link);
        } else {
            instance.event(event).emit(link);
        }
    }

    // handle message types
    switch (type) {

        // END
        case 0:
            end(link, err, data);
            break;

        // DATA
        case 1:

            // call data handlers
            if (link._h.length) {
                for (var i = 0; i < link._h.length; ++i) {
                    link._h[i].call(link._, err, data);
                }
            }
    }
}

/**
 * Create and send a websocket message.send
 *
 * @private
 * @param {number} The message type.
 * @param {object} The error object.
 * @param {object} The data object.
 */
function send (type, err, data, ack) {

    // create message
    var message = [type, this._._name || 0, this.event, this.id, err ? err.toString() : 0];

    // add the data to the message
    if (typeof data !== 'undefined') {
        message[5] = data;
    }

    // encode message (string)
    try {
        message = JSON.stringify(message);

    // return error
    } catch (err) {
        return err;
    }

    // send message
    this.socket.send(message, ack);

    // call the acknowledge handler
    if (engine.client && ack) {
        ack();
    }
}

/**
 * Destroy a link
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The link object.
 */
function end (link, err, data) {

    // call the end handler
    link._end && link._end(err, data);

    // destroy link
    delete link._._links[link.id];
}

/**
 * Connect to the server and start listening to messages.
 *
 * @public
 */
function listen () {

    // reset websocket reconnect timer
    if (wesocketReconnectTimeoutId) {
        clearTimeout(wesocketReconnectTimeoutId);
        wesocketReconnectTimeoutId = 0;
    }

    // dont load entrypoint module instance if socket tries to reconnect
    var loadModule = engine.socket ? false : true;

    // create the websocket
    var websocket = engine.socket = new WebSocket('ws://' + window.location.host + '/');

    /**
     * Load the entrypoint module instance on socket open.
     *
     * @private
     */
    websocket.onopen = function () {
        engine.module();
    };

    /**
     * Message handler.
     *
     * @private
     * @param {string} The message string.
     */
    websocket.onmessage = function (message) {
        engine.link.message(message.data, websocket);
    };

    /**
     * Reconnect socket on close.
     *
     * @private
     */
    websocket.onclose = function (closeEvent) {

        // reload imemdiately, when socket is closed by reload
        if (closeEvent.code === 3000) {
            engine.listen();

        // every other case, engine tries to realod after ca. 3 seconds
        } else {
            wesocketReconnectTimeoutId = setTimeout(engine.listen, 3333);
        }
    };
}
<|endoftext|>


<commit_before>(function(window) {
    'use strict';

    window.load = new LoadProto();

    function LoadProto() {
        function load(src, callback) {
            var ext = getExt(src);

            switch (ext) {
            case '.js':
                load.js(src, callback);
                break;

            case '.css':
                load.css(src, callback);
                break;

            case '.json':
                load.json(src, callback);
                break;
            }
        }

        load.js     = function(src, callback) {
            var id  = getIdBySrc(src),
                el  = document.getElementById(id);

            if (el) {
                callback();
            } else {
                el      = document.createElement('script');
                el.id   = id;
                el.src  = src;
                el.addEventListener('load', callback);

                document.body.appendChild(el);
            }

            return el;
        };

        load.css    = function(src, callback) {
            var id  = getIdBySrc(src),
                el  = document.getElementById(id);

            if (el) {
                callback();
            } else {
                el      = document.createElement('link');
                el.id   = getIdBySrc(src);
                el.rel  = 'stylesheet';
                el.href = src;
                el.addEventListener('load', callback);

                document.head.appendChild(el);
            }

            return el;
        };

        load.json   = function(url, callback) {
            var request = new XMLHttpRequest();

            request.open('GET', url, true);

            request.addEventListener('load', function() {
                var data;

                if (request.status >= 200 && request.status < 400){
                    data = JSON.parse(request.responseText);
                    callback(null, data);
                }
            });

            request.addEventListener('error', callback);

            request.send();
        };

        load.series = function(urls, callback) {
            var url = urls.shift();

            if (!url)
                callback();
            else
                load(url, function() {
                    load.series(urls, callback);
                });
        };

        load.parallel = function(urls, callback) {
            var i       = urls.length,
                func    = function() {
                    --i;

                    if (!i)
                        callback();
                };

            urls.forEach(function(url) {
                load(url, func);
            });
        };

        function getExt(name) {
            var ret     = '',
                dot,
                isStr   = typeof name === 'string';

            if (isStr) {
                dot = name.lastIndexOf('.');

                if (~dot)
                    ret = name.substr(dot);
            }

            return ret;
        }

        function getIdBySrc(src) {
            var num, sub, id,
                isStr       = typeof src === 'string';

            if (isStr) {
                if (~src.indexOf(':'))
                    src += '-join';

                num    = src.lastIndexOf('/') + 1,
                sub    = src.substr(src, num),
                id     = src.replace(sub, '');

                /* убираем точки */
                while (id.indexOf('.') > 0)
                    id = id.replace('.', '-');
            }

            return id;
        }

        return load;
    }
})(window);
<commit_msg>chore(load) "," -> ";"<commit_after>(function(window) {
    'use strict';

    window.load = new LoadProto();

    function LoadProto() {
        function load(src, callback) {
            var ext = getExt(src);

            switch (ext) {
            case '.js':
                load.js(src, callback);
                break;

            case '.css':
                load.css(src, callback);
                break;

            case '.json':
                load.json(src, callback);
                break;
            }
        }

        load.js     = function(src, callback) {
            var id  = getIdBySrc(src),
                el  = document.getElementById(id);

            if (el) {
                callback();
            } else {
                el      = document.createElement('script');
                el.id   = id;
                el.src  = src;
                el.addEventListener('load', callback);

                document.body.appendChild(el);
            }

            return el;
        };

        load.css    = function(src, callback) {
            var id  = getIdBySrc(src),
                el  = document.getElementById(id);

            if (el) {
                callback();
            } else {
                el      = document.createElement('link');
                el.id   = getIdBySrc(src);
                el.rel  = 'stylesheet';
                el.href = src;
                el.addEventListener('load', callback);

                document.head.appendChild(el);
            }

            return el;
        };

        load.json   = function(url, callback) {
            var request = new XMLHttpRequest();

            request.open('GET', url, true);

            request.addEventListener('load', function() {
                var data;

                if (request.status >= 200 && request.status < 400){
                    data = JSON.parse(request.responseText);
                    callback(null, data);
                }
            });

            request.addEventListener('error', callback);

            request.send();
        };

        load.series = function(urls, callback) {
            var url = urls.shift();

            if (!url)
                callback();
            else
                load(url, function() {
                    load.series(urls, callback);
                });
        };

        load.parallel = function(urls, callback) {
            var i       = urls.length,
                func    = function() {
                    --i;

                    if (!i)
                        callback();
                };

            urls.forEach(function(url) {
                load(url, func);
            });
        };

        function getExt(name) {
            var ret     = '',
                dot,
                isStr   = typeof name === 'string';

            if (isStr) {
                dot = name.lastIndexOf('.');

                if (~dot)
                    ret = name.substr(dot);
            }

            return ret;
        }

        function getIdBySrc(src) {
            var num, sub, id,
                isStr       = typeof src === 'string';

            if (isStr) {
                if (~src.indexOf(':'))
                    src += '-join';

                num    = src.lastIndexOf('/') + 1;
                sub    = src.substr(src, num);
                id     = src.replace(sub, '');

                /* убираем точки */
                while (id.indexOf('.') > 0)
                    id = id.replace('.', '-');
            }

            return id;
        }

        return load;
    }
})(window);
<|endoftext|>


<commit_before>var CloudCommander, CloudFunc, $;
/* object contains jQuery-contextMenu
 * https://github.com/medialize/jQuery-contextMenu
 */
CloudCommander.Menu              = new CloudCommander.Util();

CloudCommander.Menu.dir          = './lib/client/menu/';

/* function return configureation
 * for FancyBox open and
 * onclick (it shoud be
 * different objects)
 */
CloudCommander.Menu.getConfig    = (function(){
    return{
        // define which elements trigger this menu
        selector: 'li',
        // define the elements of the menu
        items: {
            view: {name: "View", callback: function(key, opt){
                if(typeof CloudCommander.Viewer === 'function')
                    CloudCommander.Viewer();
                else{
                    var lViewer = CloudCommander.Viewer.get();
                    if(lViewer && lViewer.show)
                        lViewer.show()
                }
            }},
            edit: {name: "Edit", callback: function(key, opt){
                if(typeof CloudCommander.Editor === 'function')
                    CloudCommander.Editor();
                else{
                    var lEditor = CloudCommander.Editor.get();
                    if(lEditor && lEditor.show)
                        lEditor.show()
                }

            }}
        }
        // there's more, have a look at the demos and docs...
    };
});

/* function loads css and js of Menu
 * @pParent     - this
 * @pPosition   -  position of menu
 */
CloudCommander.Menu.load         = (function(pParent, pPosition){
    return function(){
        var ljsLoad_f = function(){
            var lUISrc      = pParent.dir + 'jquery.ui.position.js';
            var lMenuSrc    = pParent.dir + 'jquery.contextMenu.js';

            pParent.jsload(lUISrc, function(){
                pParent.jsload(lMenuSrc, pParent.show(pParent, pPosition));
            });
        };

        var lSrc = pParent.dir +'jquery.contextMenu.css';

        pParent.cssLoad({
            src  : lSrc,
            func : {
                onload: ljsLoad_f
            }
        });
    }();
});

CloudCommander.Menu.set          = (function(){
    if(!this.seted){
        $.contextMenu(this.getConfig());

        var lThis = this;

        var lFunc_f = document.onclick;
        /*
         * Menu works in some crazy way so need a
         * little hack to get every thing work out.
         * When menu shows up, it drawing invisible
         * layer wich hides all elements of
         * Cloud Commander so it could not handle
         * onclick events. To get every thing work
         * how expected we hide out invisible layer
         * so for observer it is nothing special
         * is not going on. All magic happening in
         * DOM tree
         */
        document.onclick = function(pEvent){
            if(pEvent.x && pEvent.y){
                var lLayer = lThis.getById('context-menu-layer')
                var lStyle;

                if(lLayer)
                    lStyle = lLayer.style.cssText;
                /* hide invisible menu layer */
                if(lStyle)
                    lLayer.style.cssText = lStyle
                        .replace('z-index: 1', 'z-index:-1')

                /* get element by point */
                var lElement = document.elementFromPoint(pEvent.x, pEvent.y)
                if (lElement.tagName === 'A')
                    lThis.setCurrentFile(lElement
                        .parentElement.parentElement);
                else if(lElement.tagName === 'SPAN')
                    lThis.setCurrentFile(lElement
                        .parentElement);

                /* show invisible menu layer */
                if(lLayer && lStyle)
                    lLayer.style.cssText = lStyle;

                /* if document.onclick was set up
                 * before us, it's best time to call it
                 */
                if(typeof lFunc_f === 'function')
                    lFunc_f();
            }
        }

        this.seted = true;
    }
});
CloudCommander.Menu.seted        = false;

CloudCommander.Menu.show         = (function(pParent, pPosition){
    return function(){
        pParent.set();

        if(pPosition && pPosition.x && pPosition.y)
            $('li').contextMenu(pPosition)
        else
            $('li').contextMenu();
    }
});

CloudCommander.Menu.Keys                     = (function(pPosition){
    "use strict";

    var lCallBack_f = (function(){
        var key_event = (function(){
            return function(event){
                /* если клавиши можно обрабатывать */
                if(CloudCommander.keyBinded)
                    /* if shift + F10 pressed */
                    if(event.keyCode === CloudCommander.KEY.F10 &&
                        event.shiftKey){
                        CloudCommander.Menu.show();

                    event.preventDefault();
                    }
            };
        });

        /* добавляем обработчик клавишь */
        if (document.addEventListener)
            document.addEventListener('keydown', key_event(),false);

        else{
            var lFunc;
            if(typeof document.onkeydown === 'function')
                lFunc = document.onkeydown;

            document.onkeydown = function(){
                if(lFunc)
                    lFunc();

                key_event();
            };
        }

        /* showing context menu preview*/
        CloudCommander.Menu.show();
    });

    CloudCommander.Menu.load(this, pPosition);
});<commit_msg>minor changes<commit_after>var CloudCommander, CloudFunc, $;
/* object contains jQuery-contextMenu
 * https://github.com/medialize/jQuery-contextMenu
 */
CloudCommander.Menu              = new CloudCommander.Util();

CloudCommander.Menu.dir          = './lib/client/menu/';

/* function return configureation
 * for menu
 */
CloudCommander.Menu.getConfig    = (function(){
    return{
        // define which elements trigger this menu
        selector: 'li',
        // define the elements of the menu
        items: {
            view: {name: "View", callback: function(key, opt){
                if(typeof CloudCommander.Viewer === 'function')
                    CloudCommander.Viewer();
                else{
                    var lViewer = CloudCommander.Viewer.get();
                    if(lViewer && lViewer.show)
                        lViewer.show()
                }
            }},
            edit: {name: "Edit", callback: function(key, opt){
                if(typeof CloudCommander.Editor === 'function')
                    CloudCommander.Editor();
                else{
                    var lEditor = CloudCommander.Editor.get();
                    if(lEditor && lEditor.show)
                        lEditor.show()
                }

            }}
        }
    };
});

/* function loads css and js of Menu
 * @pParent     - this
 * @pPosition   -  position of menu
 */
CloudCommander.Menu.load         = (function(pParent, pPosition){
    return function(){
        var ljsLoad_f = function(){
            var lUISrc      = pParent.dir + 'jquery.ui.position.js';
            var lMenuSrc    = pParent.dir + 'jquery.contextMenu.js';

            pParent.jsload(lUISrc, function(){
                pParent.jsload(lMenuSrc, pParent.show(pParent, pPosition));
            });
        };

        var lSrc = pParent.dir +'jquery.contextMenu.css';

        pParent.cssLoad({
            src  : lSrc,
            func : {
                onload: ljsLoad_f
            }
        });
    }();
});

CloudCommander.Menu.set          = (function(){
    if(!this.seted){
        $.contextMenu(this.getConfig());

        var lThis = this;

        var lFunc_f = document.onclick;
        /*
         * Menu works in some crazy way so need a
         * little hack to get every thing work out.
         * When menu shows up, it drawing invisible
         * layer wich hides all elements of
         * Cloud Commander so it could not handle
         * onclick events. To get every thing work
         * how expected we hide out invisible layer
         * so for observer it is nothing special
         * is not going on. All magic happening in
         * DOM tree
         */
        document.onclick = function(pEvent){
            if(pEvent.x && pEvent.y){
                var lLayer = lThis.getById('context-menu-layer')
                var lStyle;

                if(lLayer)
                    lStyle = lLayer.style.cssText;
                /* hide invisible menu layer */
                if(lStyle)
                    lLayer.style.cssText = lStyle
                        .replace('z-index: 1', 'z-index:-1')

                /* get element by point */
                var lElement = document.elementFromPoint(pEvent.x, pEvent.y)
                if (lElement.tagName === 'A')
                    lThis.setCurrentFile(lElement
                        .parentElement.parentElement);
                else if(lElement.tagName === 'SPAN')
                    lThis.setCurrentFile(lElement
                        .parentElement);

                /* show invisible menu layer */
                if(lLayer && lStyle)
                    lLayer.style.cssText = lStyle;

                /* if document.onclick was set up
                 * before us, it's best time to call it
                 */
                if(typeof lFunc_f === 'function')
                    lFunc_f();
            }
        }

        this.seted = true;
    }
});

CloudCommander.Menu.seted        = false;

/* function shows menu for the first time
 * right away after loading
 */
CloudCommander.Menu.show         = (function(pParent, pPosition){
    return function(){
        pParent.set();

        if(pPosition && pPosition.x && pPosition.y)
            $('li').contextMenu(pPosition)
        else
            $('li').contextMenu();
    }
});

/* key binding function */
CloudCommander.Menu.Keys                     = (function(pPosition){
    "use strict";

    var lCallBack_f = (function(){
        var key_event = (function(){
            return function(event){
                /* если клавиши можно обрабатывать */
                if(CloudCommander.keyBinded)
                    /* if shift + F10 pressed */
                    if(event.keyCode === CloudCommander.KEY.F10 &&
                        event.shiftKey){
                        CloudCommander.Menu.show();

                    event.preventDefault();
                    }
            };
        });

        /* добавляем обработчик клавишь */
        if (document.addEventListener)
            document.addEventListener('keydown', key_event(),false);

        else{
            var lFunc;
            if(typeof document.onkeydown === 'function')
                lFunc = document.onkeydown;

            document.onkeydown = function(){
                if(lFunc)
                    lFunc();

                key_event();
            };
        }

        /* showing context menu preview*/
        CloudCommander.Menu.show();
    });

    CloudCommander.Menu.load(this, pPosition);
});<|endoftext|>


<commit_before>/**
 * Created by mwmaleks on 23.12.13.
 */

var   spawn =   require('child_process').spawn
    , _ =       require('underscore.deferred')
    , fs =      require('fs')
    , path =    require('path')
    , dirPath = path.join( process.cwd(), 'ssl')
    ;

function _path(fileName) { return path.join( dirPath, fileName ) }

function isObject(obj) {
    return Object.prototype.toString.call(obj) === '[object Object]';
}

function isBool(bool) {
    return Object.prototype.toString.call(bool) === '[object Boolean]';
}

function getOptions() {
    var defaultOptions = {
        bitSize: 4096,
        clientFileName :'client001',
        C:'EX',
        ST: 'Example',
        L: 'Example',
        O: 'Example',
        OU: 'Example',
        CN: 'Example',
        emailAddress: 'example@example.ex',
        clientPass: 'q1w2e3r4t5y6',
        caFileName: 'ca',
        serial: '01',
        days: 365,
        isEncryptionRequired : false
    };
    return arguments.length > 0 && isObject(arguments[0]) ? {
        bitSize: arguments[0].bitSize,
        clientFileName: arguments[0].clientFileName,
        C: arguments[0].country || arguments[0].C || defaultOptions.C,
        ST: arguments[0].state || arguments[0].ST || defaultOptions.ST,
        L: arguments[0].locality || arguments[0].L || defaultOptions.L,
        O: arguments[0].organization || arguments[0].O || defaultOptions.O,
        OU: arguments[0].organizationUnit || arguments[0].OU || defaultOptions.OU,
        CN: arguments[0].commonName || arguments[0].CN || defaultOptions.CN,
        emailAddress: arguments[0].emailAddress || defaultOptions.emailAddress,
        clientPass: arguments[0].clientPass || defaultOptions.clientPass,
        caFileName: arguments[0].caFileName || defaultOptions.caFileName,
        serial: arguments[0].serial|| defaultOptions.serial,
        days: arguments[0].days || defaultOptions.days,
        isEncryptionRequired : arguments[0].isEncryptionRequired || defaultOptions.isEncryptionRequired
    } : defaultOptions;
}

var spawnOpenSSL = function( params ) {

    var   openssl = spawn( 'openssl', params, {
            cwd: dirPath,
            env: process.env,
            customFds: [-1, -1, -1],
            setsid: false
          })
        , code = -1
        , stdout = ''
        , stderr = ''
        , deferredSpawnOpenSSL = _.Deferred()
        ;

    openssl.stdout.on('data', function (data) {
        stdout += (data || '').toString();
    });

    openssl.stderr.on('data', function (data) {
        stderr += (data || '').toString();
    });

    var   deferredOnExit  = _.Deferred()
        , deferredOnClose = _.Deferred()
        ;

    openssl.on( 'exit', function (code) {
        deferredOnExit.resolve(code);
    });

    openssl.on( 'close', function () {
        stdout = new Buffer( stdout, 'binary' ).toString('utf-8');
        stderr = new Buffer( stderr, 'binary' ).toString('utf-8');
        deferredOnClose.resolve();
    });
    _.when( deferredOnExit, deferredOnExit).done( function() {
//      arguments = code from exit event
        if ( arguments[0] ) {
            deferredSpawnOpenSSL.reject(
                new Error('Invalid openssl exit code: ' + code + '\n% openssl ' + params.join(' ') + '\n' + stderr)
                , code
            );
        } else
            deferredSpawnOpenSSL.resolve( code, stdout, stderr );

    });

    return deferredSpawnOpenSSL;
};

var execOpenSSL = function( params, options ) {

    var deferredExecOpenSSL = _.Deferred();

    spawnOpenSSL(params).done( function( code, stdout, stderr) {

        if ( params.indexOf('-fingerprint') !== -1 ) {

            var _fingerprint = stdout.match(/Fingerprint=([0-9a-fA-F:]+)$/m);
            if ( _fingerprint ) {
                deferredExecOpenSSL.resolve( _fingerprint[1] );
            } else {
                deferredExecOpenSSL.reject( new Error('No fingerprint got') );
            }
        } else
            deferredExecOpenSSL.resolve( options );

    })
    .fail( function(err) {
        deferredExecOpenSSL.reject(err);
    });
    return deferredExecOpenSSL;
};

var generateCSRSubject = function(options) {

    var csrData = {
            C: options.C,
            ST: options.ST,
            L: options.L,
            O: options.O,
            OU: options.OU,
            CN: options.CN,
            emailAddress: options.emailAddress
        }
        , csrBuilder = []
        ;

    Object.keys(csrData).forEach( function(key) {
        if ( csrData[key] ) {
            csrBuilder.push( '/' + key + '=' + csrData[key].replace(/[^\w \.\-@]+/g, ' ').trim() );
        }
    });
    return csrBuilder.join('');
};

var  createClientKey  = function(options) {

    var   certFilesExist
        , params =  [ 'genrsa' ]
        ;

    //  check if clientFileName already used
    certFilesExist = ['.key', '.crt', '.p12' ].reduce( function(accum, item) {
        accum = isBool(accum) ? accum : false;
        return accum || fs.existsSync( _path( options.clientFileName + item ) );
    });

    if ( certFilesExist )
        throw options.clientFileName + ' already exists';

    options.isEncryptionRequired && params.push('-des3');
    params.push('-out', options.clientFileName + '.key');

//      create key
    return execOpenSSL( params , options );
};

var createCSR =  function( options ) {

    var opt = getOptions.apply( this, arguments )
        ;
    if ( !fs.existsSync( _path(opt.clientFileName + '.key')))
        throw 'there is no such keyFile :';

    return execOpenSSL( [
        'req',
        '-new',
        '-key',
        opt.clientFileName + '.key',
        '-subj',
        generateCSRSubject(opt),
        '-out',
        opt.clientFileName + '.csr'
    ], opt );
};

var createClientCRT = function(options) {

    var  opt = getOptions.apply( this, arguments)
        ,filesExist
        ;

    filesExist = fs.existsSync( _path(opt.caFileName + '.crt'))
        && fs.existsSync( _path(opt.caFileName + '.key'))
        && fs.existsSync( _path(opt.clientFileName + '.key'));

    if ( !filesExist )
        throw 'createClientCRT received wrong files';

    return execOpenSSL( [
        'x509',
        '-req',
        '-days',
        opt.days,
        '-in',
        opt.clientFileName + '.csr',
        '-CA',
        opt.caFileName + '.crt',
        '-CAkey',
        opt.caFileName + '.key',
        '-set_serial',
        opt.serial,
        '-out',
        opt.clientFileName + '.crt'

    ], opt);
};

var createPKS12 = function( params, options ) {

    var   opt = getOptions.apply( this, arguments )
        , filesExist
        ;

        filesExist = fs.existsSync( _path( opt.clientFileName + '.crt') )
        && fs.existsSync( _path( opt.clientFileName + '.key') )
        && fs.existsSync( _path( opt.caFileName + '.crt'));

    if ( !filesExist )
        throw 'some of ' + opt.clientFileName + '.crt or '
            + opt.clientFileName + '.key or '
            + opt.caFileName + '.crt not found';

    return execOpenSSL([
        'pkcs12',
        '-export',
        '-in',
        opt.clientFileName + '.crt',
        '-inkey',
        opt.clientFileName + '.key',
        '-certfile',
        opt.caFileName + '.crt',
        '-out',
        opt.clientFileName + '.p12',
        '-passout',
        'pass:' + opt.clientPass

    ], options)
};

var getFingerprint = function( params, options ) {

    var opt = getOptions.apply( this, arguments );

    if ( !fs.existsSync( _path( opt.clientFileName + '.crt')) )
        throw 'file ' + opt.clientFileName + '.crt not found' ;

    return execOpenSSL( [
        'x509',
        '-in',
        opt.clientFileName + '.crt',
        '-sha1',
        '-noout',
        '-fingerprint'
    ], options );
};

var createClientSSL = function(options) {

    var opt = getOptions.apply( this, arguments) ;

    if ( !fs.existsSync(dirPath) )
        fs.mkdirSync(dirPath);

    if ( opt.clientFileName == null )
        throw 'clientFileName not provided';

    return createClientKey(options)
        .then( createCSR )
        .then( createClientCRT )
        .then( createPKS12 )
        .then( getFingerprint );

    // next .done(function(fingerprint) { ... });
};

exports.createClientSSL = createClientSSL;<commit_msg>used prams instead arguments<commit_after>/**
 * Created by mwmaleks on 23.12.13.
 */

var   spawn =   require('child_process').spawn
    , _ =       require('underscore.deferred')
    , fs =      require('fs')
    , path =    require('path')
    , dirPath = path.join( process.cwd(), 'ssl')
    ;

function _path(fileName) { return path.join( dirPath, fileName ) }

function isObject(obj) {
    return Object.prototype.toString.call(obj) === '[object Object]';
}

function isBool(bool) {
    return Object.prototype.toString.call(bool) === '[object Boolean]';
}

function getOptions(options) {
    var defaultOptions = {
        bitSize: 4096,
        clientFileName :'client001',
        C:'EX',
        ST: 'Example',
        L: 'Example',
        O: 'Example',
        OU: 'Example',
        CN: 'Example',
        emailAddress: 'example@example.ex',
        clientPass: 'q1w2e3r4t5y6',
        caFileName: 'ca',
        serial: '01',
        days: 365,
        isEncryptionRequired : false
    };
    return isObject(options) ? {
        bitSize: options.bitSize,
        clientFileName: options.clientFileName,
        C: options.country || options.C || defaultOptions.C,
        ST: options.state || options.ST || defaultOptions.ST,
        L: options.locality || options.L || defaultOptions.L,
        O: options.organization || options.O || defaultOptions.O,
        OU: options.organizationUnit || options.OU || defaultOptions.OU,
        CN: options.commonName || options.CN || defaultOptions.CN,
        emailAddress: options.emailAddress || defaultOptions.emailAddress,
        clientPass: options.clientPass || defaultOptions.clientPass,
        caFileName: options.caFileName || defaultOptions.caFileName,
        serial: options.serial|| defaultOptions.serial,
        days: options.days || defaultOptions.days,
        isEncryptionRequired : options.isEncryptionRequired || defaultOptions.isEncryptionRequired
    } : defaultOptions;
}

var spawnOpenSSL = function( params ) {

    var   openssl = spawn( 'openssl', params, {
            cwd: dirPath,
            env: process.env,
            customFds: [-1, -1, -1],
            setsid: false
          })
        , code = -1
        , stdout = ''
        , stderr = ''
        , deferredSpawnOpenSSL = _.Deferred()
        ;

    openssl.stdout.on('data', function (data) {
        stdout += (data || '').toString();
    });

    openssl.stderr.on('data', function (data) {
        stderr += (data || '').toString();
    });

    var   deferredOnExit  = _.Deferred()
        , deferredOnClose = _.Deferred()
        ;

    openssl.on( 'exit', function (code) {
        deferredOnExit.resolve(code);
    });

    openssl.on( 'close', function () {
        stdout = new Buffer( stdout, 'binary' ).toString('utf-8');
        stderr = new Buffer( stderr, 'binary' ).toString('utf-8');
        deferredOnClose.resolve();
    });
    _.when( deferredOnExit, deferredOnExit).done( function() {
//      arguments = code from exit event
        if ( arguments[0] ) {
            deferredSpawnOpenSSL.reject(
                new Error('Invalid openssl exit code: ' + code + '\n% openssl ' + params.join(' ') + '\n' + stderr)
                , code
            );
        } else
            deferredSpawnOpenSSL.resolve( code, stdout, stderr );

    });

    return deferredSpawnOpenSSL;
};

var execOpenSSL = function( params, options ) {

    var deferredExecOpenSSL = _.Deferred();

    spawnOpenSSL(params).done( function( code, stdout, stderr) {

        if ( params.indexOf('-fingerprint') !== -1 ) {

            var _fingerprint = stdout.match(/Fingerprint=([0-9a-fA-F:]+)$/m);
            if ( _fingerprint ) {
                deferredExecOpenSSL.resolve( _fingerprint[1] );
            } else {
                deferredExecOpenSSL.reject( new Error('No fingerprint got') );
            }
        } else
            deferredExecOpenSSL.resolve( options );

    })
    .fail( function(err) {
        deferredExecOpenSSL.reject(err);
    });
    return deferredExecOpenSSL;
};

var generateCSRSubject = function(options) {

    var csrData = {
            C: options.C,
            ST: options.ST,
            L: options.L,
            O: options.O,
            OU: options.OU,
            CN: options.CN,
            emailAddress: options.emailAddress
        }
        , csrBuilder = []
        ;

    Object.keys(csrData).forEach( function(key) {
        if ( csrData[key] ) {
            csrBuilder.push( '/' + key + '=' + csrData[key].replace(/[^\w \.\-@]+/g, ' ').trim() );
        }
    });
    return csrBuilder.join('');
};

var  createClientKey  = function(options) {

    var   certFilesExist
        , params =  [ 'genrsa' ]
        ;

    //  check if clientFileName already used
    certFilesExist = ['.key', '.crt', '.p12' ].reduce( function(accum, item) {
        accum = isBool(accum) ? accum : false;
        return accum || fs.existsSync( _path( options.clientFileName + item ) );
    });

    if ( certFilesExist )
        throw options.clientFileName + ' already exists';

    options.isEncryptionRequired && params.push('-des3');
    params.push('-out', options.clientFileName + '.key');

//      create key
    return execOpenSSL( params , options );
};

var createCSR =  function( options ) {

    var opt = getOptions.apply( this, arguments )
        ;
    if ( !fs.existsSync( _path(opt.clientFileName + '.key')))
        throw 'there is no such keyFile :';

    return execOpenSSL( [
        'req',
        '-new',
        '-key',
        opt.clientFileName + '.key',
        '-subj',
        generateCSRSubject(opt),
        '-out',
        opt.clientFileName + '.csr'
    ], opt );
};

var createClientCRT = function(options) {

    var  opt = getOptions.apply( this, arguments)
        ,filesExist
        ;

    filesExist = fs.existsSync( _path(opt.caFileName + '.crt'))
        && fs.existsSync( _path(opt.caFileName + '.key'))
        && fs.existsSync( _path(opt.clientFileName + '.key'));

    if ( !filesExist )
        throw 'createClientCRT received wrong files';

    return execOpenSSL( [
        'x509',
        '-req',
        '-days',
        opt.days,
        '-in',
        opt.clientFileName + '.csr',
        '-CA',
        opt.caFileName + '.crt',
        '-CAkey',
        opt.caFileName + '.key',
        '-set_serial',
        opt.serial,
        '-out',
        opt.clientFileName + '.crt'

    ], opt);
};

var createPKS12 = function( params, options ) {

    var   opt = getOptions.apply( this, arguments )
        , filesExist
        ;

        filesExist = fs.existsSync( _path( opt.clientFileName + '.crt') )
        && fs.existsSync( _path( opt.clientFileName + '.key') )
        && fs.existsSync( _path( opt.caFileName + '.crt'));

    if ( !filesExist )
        throw 'some of ' + opt.clientFileName + '.crt or '
            + opt.clientFileName + '.key or '
            + opt.caFileName + '.crt not found';

    return execOpenSSL([
        'pkcs12',
        '-export',
        '-in',
        opt.clientFileName + '.crt',
        '-inkey',
        opt.clientFileName + '.key',
        '-certfile',
        opt.caFileName + '.crt',
        '-out',
        opt.clientFileName + '.p12',
        '-passout',
        'pass:' + opt.clientPass

    ], options)
};

var getFingerprint = function( params, options ) {

    var opt = getOptions.apply( this, arguments );

    if ( !fs.existsSync( _path( opt.clientFileName + '.crt')) )
        throw 'file ' + opt.clientFileName + '.crt not found' ;

    return execOpenSSL( [
        'x509',
        '-in',
        opt.clientFileName + '.crt',
        '-sha1',
        '-noout',
        '-fingerprint'
    ], options );
};

var createClientSSL = function(options) {

    var opt = getOptions.apply( this, arguments) ;

    if ( !fs.existsSync(dirPath) )
        fs.mkdirSync(dirPath);

    if ( opt.clientFileName == null )
        throw 'clientFileName not provided';

    return createClientKey(options)
        .then( createCSR )
        .then( createClientCRT )
        .then( createPKS12 )
        .then( getFingerprint );

    // next .done(function(fingerprint) { ... });
};

exports.createClientSSL = createClientSSL;<|endoftext|>


<commit_before>// Copyright (c) 2018, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ,
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
"use strict";

class ClientStateCompilerOptions {
    constructor(jsondata) {
        this.binary = false;
        this.commentOnly = true;
        this.demangle = true;
        this.directives = true;
        this.execute = false;
        this.intel = true;
        this.labels = true;
        this.trim = false;

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.binary !== 'undefined') this.binary = jsondata.binary;
        if (typeof jsondata.commentOnly !== 'undefined') this.commentOnly = jsondata.commentOnly;
        if (typeof jsondata.demangle !== 'undefined') this.demangle = jsondata.demangle;
        if (typeof jsondata.directives !== 'undefined') this.directives = jsondata.directives;
        if (typeof jsondata.execute !== 'undefined') this.execute = jsondata.execute;
        if (typeof jsondata.intel !== 'undefined') this.intel = jsondata.intel;
        if (typeof jsondata.labels !== 'undefined') this.labels = jsondata.labels;
        if (typeof jsondata.trim !== 'undefined') this.trim = jsondata.trim;
    }
}

class ClientStateCompiler {
    constructor(jsondata) {
        if (jsondata) {
            this.fromJsonData(jsondata);
        } else {
            this.id = "";
            this.options = "";
            this.filters = new ClientStateCompilerOptions();
            this.libs = [];
            this.specialoutputs = [];
            this.tools = [];
        }
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.id !== 'undefined') {
            this.id = jsondata.id;
        } else if (typeof jsondata.compilerId !== 'undefined') {
            this.id = jsondata.compilerId;
        } else {
            this.id = "";
        }

        this.options = jsondata.options;
        this.filters = new ClientStateCompilerOptions(jsondata.filters);
        if (typeof jsondata.libs !== 'undefined') {
            this.libs = jsondata.libs;
        } else {
            this.libs = [];
        }
        if (typeof jsondata.specialoutputs !== 'undefined') {
            this.specialoutputs = jsondata.specialoutputs;
        } else {
            this.specialoutputs = [];
        }

        if (typeof jsondata.tools !== 'undefined') {
            this.tools = jsondata.tools;
        } else {
            this.tools = [];
        }
    }
}

class ClientStateExecutor {
    constructor(jsondata) {
        if (jsondata) {
            this.fromJsonData(jsondata);
        } else {
            this.compiler = new ClientStateCompiler();
            this.compilerVisible = false;
            this.compilerOutputVisible = false;
            this.arguments = [];
            this.argumentsVisible = false;
            this.stdin = "";
            this.stdinVisible = false;
        }
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.compilerVisible !== 'undefined')
            this.compilerVisible = jsondata.compilerVisible;
        if (typeof jsondata.compilerOutputVisible !== 'undefined')
            this.compilerOutputVisible = jsondata.compilerOutputVisible;
        if (typeof jsondata.arguments !== 'undefined')
            this.arguments = jsondata.arguments;
        if (typeof jsondata.argumentsVisible !== 'undefined')
            this.argumentsVisible = jsondata.argumentsVisible;
        if (typeof jsondata.stdin !== 'undefined')
            this.stdin = jsondata.stdin;
        if (typeof jsondata.stdinVisible !== 'undefined')
            this.stdinVisible = jsondata.stdinVisible;

        this.compiler = new ClientStateCompiler(JSON.stringify(jsondata.compiler));
    }
}

class ClientStateConformanceView {
    constructor(jsondata) {
        this.libs = [];
        this.compilers = [];

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        this.libs = jsondata.libs;
        jsondata.compilers.forEach((compilerdata) => {
            this.compilers.push(new ClientStateCompiler(compilerdata));
        });
    }
}

class ClientStateSession {
    constructor(jsondata) {
        this.id = false;
        this.language = "";
        this.source = "";
        this.conformanceview = false;
        this.compilers = [];
        this.executors = [];

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.id !== 'undefined') this.id = jsondata.id;
        this.language = jsondata.language;
        this.source = jsondata.source;
        if (typeof jsondata.conformanceview !== 'undefined') {
            if (jsondata.conformanceview) {
                this.conformanceview = new ClientStateConformanceView(jsondata.conformanceview);
            } else {
                this.conformanceview = false;
            }
        }

        jsondata.compilers.forEach((compilerdata) => {
            this.compilers.push(new ClientStateCompiler(compilerdata));
        });
    }

    findOrCreateCompiler(id) {
        let compiler = null;
        if (id <= this.compilers.length) {
            compiler = this.compilers[id - 1];
            return compiler;
        }

        for (let idx = this.compilers.length; idx < id; idx++) {
            compiler = new ClientStateCompiler();
            this.compilers.push(compiler);
        }

        return compiler;
    }

    countNumberOfSpecialOutputsAndTools() {
        let count = 0;

        if (this.conformanceview) count++;

        this.compilers.forEach((compiler) => {
            count += compiler.specialoutputs.length;
            if (compiler.tools) count += compiler.tools.length;
        });

        return count;
    }
}

class ClientState {
    constructor(jsondata) {
        this.sessions = [];

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        jsondata.sessions.forEach((sessiondata) => {
            this.sessions.push(new ClientStateSession(sessiondata));
        });
    }

    findOrCreateSession(id) {
        let session = null;
        for (let idxSession = 0; idxSession < this.sessions.length; idxSession++) {
            session = this.sessions[idxSession];

            if (session.id === id) {
                return session;
            }
        }

        session = new ClientStateSession();
        session.id = id;
        this.sessions.push(session);

        return session;
    }
}

module.exports = {
    State: ClientState,
    Session: ClientStateSession,
    Compiler: ClientStateCompiler,
    Executor: ClientStateExecutor,
    CompilerOptions: ClientStateCompilerOptions,
    ConformanceView: ClientStateConformanceView
};
<commit_msg>clientstate executors bugfix<commit_after>// Copyright (c) 2018, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ,
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
"use strict";

class ClientStateCompilerOptions {
    constructor(jsondata) {
        this.binary = false;
        this.commentOnly = true;
        this.demangle = true;
        this.directives = true;
        this.execute = false;
        this.intel = true;
        this.labels = true;
        this.trim = false;

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.binary !== 'undefined') this.binary = jsondata.binary;
        if (typeof jsondata.commentOnly !== 'undefined') this.commentOnly = jsondata.commentOnly;
        if (typeof jsondata.demangle !== 'undefined') this.demangle = jsondata.demangle;
        if (typeof jsondata.directives !== 'undefined') this.directives = jsondata.directives;
        if (typeof jsondata.execute !== 'undefined') this.execute = jsondata.execute;
        if (typeof jsondata.intel !== 'undefined') this.intel = jsondata.intel;
        if (typeof jsondata.labels !== 'undefined') this.labels = jsondata.labels;
        if (typeof jsondata.trim !== 'undefined') this.trim = jsondata.trim;
    }
}

class ClientStateCompiler {
    constructor(jsondata) {
        if (jsondata) {
            this.fromJsonData(jsondata);
        } else {
            this.id = "";
            this.options = "";
            this.filters = new ClientStateCompilerOptions();
            this.libs = [];
            this.specialoutputs = [];
            this.tools = [];
        }
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.id !== 'undefined') {
            this.id = jsondata.id;
        } else if (typeof jsondata.compilerId !== 'undefined') {
            this.id = jsondata.compilerId;
        } else {
            this.id = "";
        }

        this.options = jsondata.options;
        this.filters = new ClientStateCompilerOptions(jsondata.filters);
        if (typeof jsondata.libs !== 'undefined') {
            this.libs = jsondata.libs;
        } else {
            this.libs = [];
        }
        if (typeof jsondata.specialoutputs !== 'undefined') {
            this.specialoutputs = jsondata.specialoutputs;
        } else {
            this.specialoutputs = [];
        }

        if (typeof jsondata.tools !== 'undefined') {
            this.tools = jsondata.tools;
        } else {
            this.tools = [];
        }
    }
}

class ClientStateExecutor {
    constructor(jsondata) {
        if (jsondata) {
            this.fromJsonData(jsondata);
        } else {
            this.compiler = new ClientStateCompiler();
            this.compilerVisible = false;
            this.compilerOutputVisible = false;
            this.arguments = [];
            this.argumentsVisible = false;
            this.stdin = "";
            this.stdinVisible = false;
        }
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.compilerVisible !== 'undefined')
            this.compilerVisible = jsondata.compilerVisible;
        if (typeof jsondata.compilerOutputVisible !== 'undefined')
            this.compilerOutputVisible = jsondata.compilerOutputVisible;
        if (typeof jsondata.arguments !== 'undefined')
            this.arguments = jsondata.arguments;
        if (typeof jsondata.argumentsVisible !== 'undefined')
            this.argumentsVisible = jsondata.argumentsVisible;
        if (typeof jsondata.stdin !== 'undefined')
            this.stdin = jsondata.stdin;
        if (typeof jsondata.stdinVisible !== 'undefined')
            this.stdinVisible = jsondata.stdinVisible;

        this.compiler = new ClientStateCompiler(jsondata.compiler);
    }
}

class ClientStateConformanceView {
    constructor(jsondata) {
        this.libs = [];
        this.compilers = [];

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        this.libs = jsondata.libs;
        jsondata.compilers.forEach((compilerdata) => {
            this.compilers.push(new ClientStateCompiler(compilerdata));
        });
    }
}

class ClientStateSession {
    constructor(jsondata) {
        this.id = false;
        this.language = "";
        this.source = "";
        this.conformanceview = false;
        this.compilers = [];
        this.executors = [];

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        if (typeof jsondata.id !== 'undefined') this.id = jsondata.id;
        this.language = jsondata.language;
        this.source = jsondata.source;
        if (typeof jsondata.conformanceview !== 'undefined') {
            if (jsondata.conformanceview) {
                this.conformanceview = new ClientStateConformanceView(jsondata.conformanceview);
            } else {
                this.conformanceview = false;
            }
        }

        jsondata.compilers.forEach((compilerdata) => {
            this.compilers.push(new ClientStateCompiler(compilerdata));
        });

        jsondata.executors.forEach((executor) => {
            this.executors.push(new ClientStateExecutor(executor));
        });
    }

    findOrCreateCompiler(id) {
        let compiler = null;
        if (id <= this.compilers.length) {
            compiler = this.compilers[id - 1];
            return compiler;
        }

        for (let idx = this.compilers.length; idx < id; idx++) {
            compiler = new ClientStateCompiler();
            this.compilers.push(compiler);
        }

        return compiler;
    }

    countNumberOfSpecialOutputsAndTools() {
        let count = 0;

        if (this.conformanceview) count++;

        this.compilers.forEach((compiler) => {
            count += compiler.specialoutputs.length;
            if (compiler.tools) count += compiler.tools.length;
        });

        return count;
    }
}

class ClientState {
    constructor(jsondata) {
        this.sessions = [];

        if (jsondata) this.fromJsonData(jsondata);
    }

    fromJsonData(jsondata) {
        jsondata.sessions.forEach((sessiondata) => {
            this.sessions.push(new ClientStateSession(sessiondata));
        });
    }

    findOrCreateSession(id) {
        let session = null;
        for (let idxSession = 0; idxSession < this.sessions.length; idxSession++) {
            session = this.sessions[idxSession];

            if (session.id === id) {
                return session;
            }
        }

        session = new ClientStateSession();
        session.id = id;
        this.sessions.push(session);

        return session;
    }
}

module.exports = {
    State: ClientState,
    Session: ClientStateSession,
    Compiler: ClientStateCompiler,
    Executor: ClientStateExecutor,
    CompilerOptions: ClientStateCompilerOptions,
    ConformanceView: ClientStateConformanceView
};
<|endoftext|>