<commit_before>/* global atom */
"use strict";

const CompositeDisposable = require("atom").CompositeDisposable;
const path = require("path");
const child_process = require("child_process");

var user_os = process.platform;

var os_defaults = {
      "linux":{terminal:"gnome-terminal", default_command:"julia \"{file}\""},
      "win32":{terminal:"cmd", default_command:"julia.exe \"{file}\""}
};

var terminal = os_defaults[user_os].terminal;
var default_command = os_defaults[user_os].default_command;

function set_command_args(terminal, ca){
  console.log(ca);
  var args = "";
  if (terminal=="cmd") {
    args = ["/c", "start", __dirname + "/../bin/cp.exe"].concat(ca);

  } else if (terminal=="gnome-terminal") {
    var filename = ca[1];
    console.log("filename", filename)
    args = ["-e", "bash -c 'julia '"+ filename +"';exec $SHELL'"];
  };
  return args;
};

module.exports = {
    activate: () => {
        this.subscriptions = new CompositeDisposable();
        this.subscriptions.add(
            atom.commands.add("atom-text-editor", "Julia run: run-f5", run_f5),
            atom.commands.add("atom-text-editor", "Julia run: run-f6", run_f6)
        );
    },
    deactivate: () => {
        this.subscriptions.dispose();
    },
    config: {
        f5_command: {
            title: "Command of F5",
            description: "{file} stands for current file path",
            type: "string",
            default: default_command
        },
        f6_command: {
            title: "Command of F6",
            description: "{file} stands for current file path",
            type: "string",
            default: default_command
        },
        disable_notifications: {
            title: "Disable success notifications",
            description: "Disable notifications while saving and running",
            type: "boolean",
            default: false
        },
        disable_notifications_on_fail: {
            title: "Disable failure notifications",
            description: "Disable notifications when extension name does not match",
            type: "boolean",
            default: false
        }
    },
    subscriptions: null
};

function run_f5() {
    run(atom.config.get("atom-julia-run.f5_command"));
}

function run_f6() {
    run(atom.config.get("atom-julia-run.f6_command"));
}

function run(command) {
    var editor = atom.workspace.getActiveTextEditor();
    if (!editor) {
        return;
    }
    var file = editor.buffer.file;
    if (!file) {
        notification("warning", "You have to create the file first.", true);
        return;
    }
    notification("info", "Saving...");
    editor.save();
    var info = path.parse(file.path);
    if (info.ext != ".jl") {
        notification("warning", format("{0} is not a .jl file, exit.", [info.base]));
        return;
    }
    notification("info", format("Running {0} ...", [info.base]));
    var ca = command.split(" ");
    ca.forEach(function(k, i, a) {
        a[i] = format(k, {
            "file": file.path,
            "dir": info.dir,
            "name": info.name,
            "ext": info.ext,
        });
    });

    var args = set_command_args(terminal, ca)
    console.log(args)
    var child = child_process.spawn(terminal ,args,
                                    {cwd: info.dir,
                                     detached: true});
    child.unref();
}

function notification(type, message, always) {
    if (type == "info") {
        if (always || !atom.config.get("atom-julia-run.disable_notifications")) {
            atom.notifications.add("info", message);
        }
    } else if (type == "warning") {
        if (always || !atom.config.get("atom-julia-run.disable_notifications_on_fail")) {
            atom.notifications.add("warning", message);
        }
    }
}

function format(string, array) {
    return string.replace(/{(.*?)}/g, k => array[k.substring(1, k.length - 1)]);
}
<commit_msg>Remove hard code from language binary name in args<commit_after>/* global atom */
"use strict";

const CompositeDisposable = require("atom").CompositeDisposable;
const path = require("path");
const child_process = require("child_process");

var user_os = process.platform;

var os_defaults = {
      "linux":{terminal:"gnome-terminal", default_command:"julia \"{file}\""},
      "win32":{terminal:"cmd", default_command:"julia.exe \"{file}\""}
};

var terminal = os_defaults[user_os].terminal;
var default_command = os_defaults[user_os].default_command;

function set_command_args(terminal, ca){
  console.log(ca);
  var args = "";
  if (terminal=="cmd") {
    args = ["/c", "start", __dirname + "/../bin/cp.exe"].concat(ca);

  } else if (terminal=="gnome-terminal") {
    var language_binary = ca[0];
    var filename = ca[1];
    console.log("filename", filename)
    args = ["-e", "bash -c '" + language_binary + " " + filename + ";exec $SHELL'"];
    console.log("args:", args)
  };
  return args;
};

module.exports = {
    activate: () => {
        this.subscriptions = new CompositeDisposable();
        this.subscriptions.add(
            atom.commands.add("atom-text-editor", "Julia run: run-f5", run_f5),
            atom.commands.add("atom-text-editor", "Julia run: run-f6", run_f6)
        );
    },
    deactivate: () => {
        this.subscriptions.dispose();
    },
    config: {
        f5_command: {
            title: "Command of F5",
            description: "{file} stands for current file path",
            type: "string",
            default: default_command
        },
        f6_command: {
            title: "Command of F6",
            description: "{file} stands for current file path",
            type: "string",
            default: default_command
        },
        disable_notifications: {
            title: "Disable success notifications",
            description: "Disable notifications while saving and running",
            type: "boolean",
            default: false
        },
        disable_notifications_on_fail: {
            title: "Disable failure notifications",
            description: "Disable notifications when extension name does not match",
            type: "boolean",
            default: false
        }
    },
    subscriptions: null
};

function run_f5() {
    run(atom.config.get("atom-julia-run.f5_command"));
}

function run_f6() {
    run(atom.config.get("atom-julia-run.f6_command"));
}

function run(command) {
    var editor = atom.workspace.getActiveTextEditor();
    if (!editor) {
        return;
    }
    var file = editor.buffer.file;
    if (!file) {
        notification("warning", "You have to create the file first.", true);
        return;
    }
    notification("info", "Saving...");
    editor.save();
    var info = path.parse(file.path);
    if (info.ext != ".jl") {
        notification("warning", format("{0} is not a .jl file, exit.", [info.base]));
        return;
    }
    notification("info", format("Running {0} ...", [info.base]));
    var ca = command.split(" ");
    ca.forEach(function(k, i, a) {
        a[i] = format(k, {
            "file": file.path,
            "dir": info.dir,
            "name": info.name,
            "ext": info.ext,
        });
    });

    var args = set_command_args(terminal, ca)
    console.log(args)
    var child = child_process.spawn(terminal ,args,
                                    {cwd: info.dir,
                                     detached: true});
    child.unref();
}

function notification(type, message, always) {
    if (type == "info") {
        if (always || !atom.config.get("atom-julia-run.disable_notifications")) {
            atom.notifications.add("info", message);
        }
    } else if (type == "warning") {
        if (always || !atom.config.get("atom-julia-run.disable_notifications_on_fail")) {
            atom.notifications.add("warning", message);
        }
    }
}

function format(string, array) {
    return string.replace(/{(.*?)}/g, k => array[k.substring(1, k.length - 1)]);
}
<|endoftext|>


<commit_before>/*global require, exports */
/*jslint devel: true */

(function () {
    'use strict';

    var atomize = require('atomize-client'),
        cereal = require('cereal'),
        sockjs = require('sockjs'),
        events = require('events'),
        sockjs_opts = {sockjs_url: "http://cdn.sockjs.org/sockjs-0.1.min.js",
                       log: function () {}},
        globalTVarCount = 0,
        globalTVars = {},
        globalLocal = {},
        create, util, rootTVar;

    util = (function () {
        return {
            isPrimitive: function (obj) {
                return obj !== Object(obj);
            },

            hasOwnProp: ({}).hasOwnProperty,

            shallowCopy: function (src, dest) {
                var keys = Object.keys(src),
                    i;
                for (i = 0; i < keys.length; i += 1) {
                    dest[keys[i]] = src[keys[i]];
                }
            },

            lift: function (src, dest, fields) {
                var i;
                for (i = 0; i < fields.length; i += 1) {
                    dest[fields[i]] = src[fields[i]].bind(src);
                }
            }
        };
    }());

    function TVar(id, isArray, raw, creator) {
        this.creator = creator;
        this.raw = isArray ? [] : {};
        util.shallowCopy(raw, this.raw);
        this.isArray = isArray;
        this.id = id;
        this.version = 0;
        this.observers = [];
    }
    TVar.prototype = {
        subscribe: function (fun) {
            this.observers.push(fun);
        },

        bump: function (future) {
            // create a fresh observers array otherwise, if on the
            // server side firing the observer creates a new
            // subscription, you can go into a loop!
            var observers = this.observers,
                i;
            this.version += 1;
            this.observers = [];
            for (i = 0; i < observers.length; i += 1) {
                (observers[i])(this, future);
            }
        }
    };

    TVar.create = function (isArray, value, creator) {
        var globalTVar;
        globalTVarCount += 1;
        globalTVar = new TVar(globalTVarCount, isArray, value, creator);
        globalTVars[globalTVar.id] = globalTVar;
        return globalTVar;
    };

    function CoalescingObserver() {
        this.map = new cereal.Map();
        this.keys = [];
    }
    CoalescingObserver.prototype = {
        insert: function (key, value) {
            if (!this.map.has(key)) {
                this.keys.push(key);
            }
            this.map.set(key, value);
        },

        force: function () {
            var i;
            for (i = 0; i < this.keys.length; i += 1) {
                (this.map.get(this.keys[i]))();
            }
            this.keys = [];
            this.map = new cereal.Map();
        }
    }

    function Client(connection, serverEventEmitter) {
        this.emitter = new events.EventEmitter();
        util.lift(this.emitter, this,
                  ['on', 'once', 'removeListener', 'removeAllListeners', 'emit']);

        this.connection = connection;
        this.localGlobal = {};
        this.localGlobal[rootTVar.id] = rootTVar.id;
        this.globalLocal = {};
        this.globalLocal[rootTVar.id] = rootTVar.id;
        globalLocal[connection.id] = this.globalLocal;
        this.minTVarId = 0;

        connection.on('data', this.data.bind(this));
        connection.on('close', this.close.bind(this));
        serverEventEmitter.emit('connection', this);
    }

    Client.prototype = {
        isAuthenticated: false,

        data: function (message) {
            if (this.isAuthenticated) {
                this.dispatch(message);
            } else {
                this.emit('data', message, this);
            }
        },

        close: function () {
            this.emit('close', this);
            delete globalLocal[this.connection.id];
        },

        write: function (msg) {
            this.connection.write(cereal.stringify(msg));
        },

        read: function (msg) {
            return cereal.parse(msg);
        },

        dispatch: function (msg) {
            var txnLog = this.read(msg);
            switch (txnLog.type) {
            case "commit":
                this.commit(txnLog);
                break;
            case "retry":
                this.retry(txnLog);
                break;
            default:
                console.log("Received unexpected message from client:");
                console.log(txnLog);
            }
        },

        create: function (txnLog, updates) {
            var keys = Object.keys(txnLog.created),
                ok = true,
                i, localTVar, globalTVar;

            for (i = 0; i < keys.length; i += 1) {
                localTVar = txnLog.created[keys[i]];
                localTVar.id = keys[i];

                globalTVar = TVar.create(localTVar.isArray, localTVar.value, this);
                this.localGlobal[localTVar.id] = globalTVar.id;
                this.globalLocal[globalTVar.id] = localTVar.id;
            }

            return ok;
        },

        checkThing: function (thing, updates) {
            var keys = Object.keys(thing),
                ok = true,
                i, localTVar, globalTVar;

            for (i = 0; i < keys.length; i += 1) {
                localTVar = thing[keys[i]];
                localTVar.id = keys[i];
                globalTVar = globalTVars[this.localGlobal[localTVar.id]];
                if (localTVar.version !== globalTVar.version) {
                    updates[globalTVar.id] = true;
                    ok = false;
                }
            }

            return ok;
        },

        checkReads: function (txnLog, updates) {
            return this.checkThing(txnLog.read, updates);
        },

        checkWrites: function (txnLog, updates) {
            return this.checkThing(txnLog.written, updates);
        },

        retry: function (txnLog) {
            var txnId = txnLog.txnId,
                updates = {},
                ok, self, fired, observer, keys, i, localTVar, globalTVar;

            ok = this.checkReads(txnLog, updates);

            if (ok) {
                self = this;
                fired = false;
                observer = function (globalTVar, future) {
                    updates[globalTVar.id] = true;
                    future.insert(
                        updates,
                        function () {
                            if (!fired) {
                                fired = true;
                                self.write(self.createUpdates(updates, txnId));
                                self.write({type: "retry", txnId: txnId});
                            }
                        });
                };

                keys = Object.keys(txnLog.read);
                for (i = 0; i < keys.length; i += 1) {
                    localTVar = txnLog.read[keys[i]];
                    localTVar.id = keys[i];
                    globalTVar = globalTVars[this.localGlobal[localTVar.id]];
                    globalTVar.subscribe(observer);
                }
            } else {
                // oh good, need to do updates already and can then
                // immediately restart the txn.
                this.write(this.createUpdates(updates, txnId));
                this.write({type: "retry", txnId: txnId});
            }

        },

        commit: function (txnLog) {
            var txnId = txnLog.txnId,
                updates = {},
                ok, keys, i, j, localTVar, globalTVar, future, names, name, value;

            // Prevent a short-cut impl of && from causing us problems
            ok = this.create(txnLog, updates);
            ok = this.checkReads(txnLog, updates) && ok;
            ok = this.checkWrites(txnLog, updates) && ok;

            // Regardless of success, we have grabbed the creates. We
            // should now bump their versions from 0 to 1.
            keys = Object.keys(txnLog.created);
            for (i = 0; i < keys.length; i += 1) {
                localTVar = txnLog.created[keys[i]];
                localTVar.id = keys[i];
                globalTVar = globalTVars[this.localGlobal[localTVar.id]];
                globalTVar.bump();
            }

            if (ok && this.onPreCommit(txnLog)) {
                // send out the success message first. This a)
                // improves performance; and more importantly b)
                // ensures that any updates that end up being sent to
                // the same client (due to pending retries) get
                // received after the success msg and thus we don't
                // fall out of step with vsns
                this.write({type: "commit", txnId: txnId, result: "success"});

                future = new CoalescingObserver();

                keys = Object.keys(txnLog.written);
                for (i = 0; i < keys.length; i += 1) {
                    localTVar = txnLog.written[keys[i]];
                    localTVar.id = keys[i];
                    globalTVar = globalTVars[this.localGlobal[localTVar.id]];
                    names = Object.keys(localTVar.children);
                    for (j = 0; j < names.length; j += 1) {
                        name = names[j];
                        value = localTVar.children[name];
                        if (undefined !== value.tvar) {
                            value.value = {tvar: this.localGlobal[value.tvar]};
                            delete value.tvar;
                            Object.defineProperty(globalTVar.raw, name, value);
                        } else if (undefined !== value.deleted) {
                            delete globalTVar.raw[name];
                        } else {
                            // mess for dealing with arrays, and some proxy stuff
                            if (globalTVar.isArray && 'length' === name) {
                                globalTVar.raw[name] = value.value;
                            } else {
                                Object.defineProperty(globalTVar.raw, name, value);
                            }
                        }
                    }
                    globalTVar.bump(future);
                }

                future.force();
            } else {
                this.write(this.createUpdates(updates, txnId));
                this.write({type: "commit", txnId: txnId, result: "failure"});
            }
        },

        onPreCommit: function (txnLog) {
            return true;
        },

        createUpdates: function (updates, txnId) {
            var keys = Object.keys(updates),
                txnLog = {type: "updates", updates: {}, txnId: txnId},
                key, globalTVar, localTVar, names, name, i, desc;

            while (0 < keys.length) {
                key = keys.shift();
                globalTVar = globalTVars[key];
                localTVar = {version: globalTVar.version,
                             value:   {},
                             isArray: globalTVar.raw.constructor === Array}; // this is wrong!

                if (undefined === this.globalLocal[globalTVar.id]) {
                    this.minTVarId -= 1;
                    txnLog.updates[this.minTVarId] = localTVar;
                    this.localGlobal[this.minTVarId] = globalTVar.id;
                    this.globalLocal[globalTVar.id] = this.minTVarId;
                } else {
                    txnLog.updates[this.globalLocal[globalTVar.id]] = localTVar;
                }

                names = Object.getOwnPropertyNames(globalTVar.raw);
                for (i = 0; i < names.length; i += 1) {
                    name = names[i];
                    desc = Object.getOwnPropertyDescriptor(globalTVar.raw, name);
                    if (util.hasOwnProp.call(desc.value, 'tvar')) {
                        localTVar.value[name] = desc;
                        if (undefined === this.globalLocal[desc.value.tvar]) {
                            this.minTVarId -= 1;
                            this.localGlobal[this.minTVarId] = desc.value.tvar;
                            this.globalLocal[desc.value.tvar] = this.minTVarId;
                            keys.push(desc.value.tvar);
                            desc.tvar = this.minTVarId;
                        } else {
                            desc.tvar = this.globalLocal[desc.value.tvar];
                        }
                        delete desc.value;
                    } else {
                        localTVar.value[name] = desc;
                    }
                }
            }
            return txnLog;
        }
    };

    function ServerEventEmitter () {
        this.emitter = new events.EventEmitter();
        util.lift(this.emitter, this,
                  ['on', 'once', 'removeListener', 'removeAllListeners', 'emit']);
        this.on('connection', this.defaultAuthenticator.bind(this));
    }

    ServerEventEmitter.prototype = {
        connection: function (connection) {
            new Client(connection, this);
        },

        defaultAuthenticator: function (client) {
            if (1 === this.emitter.listeners('connection').length) {
                // nothing installed other than us, just let it straight through!
                client.isAuthenticated = true;
            }
        }
    };

    create = function (http, path, root) {
        var server = sockjs.createServer(sockjs_opts),
            emitter = new ServerEventEmitter();

        server.on('connection', emitter.connection.bind(emitter));
        http.addListener('upgrade', function (req, res) { res.end(); });
        server.installHandlers(http, {prefix: path});

        if (undefined === root || null === root) {
            root = {};
        }
        globalTVarCount = 1;
        rootTVar = new TVar(globalTVarCount, Array.isArray(root), root, undefined);
        globalTVars[rootTVar.id] = rootTVar;
        rootTVar.bump(); // Need 2 bumps to ensure we're ahead of any clients.
        rootTVar.bump();

        emitter.client = function () { return new atomize.Atomize(Client, emitter); };

        return emitter;
    };

    exports.create = create;
}());
<commit_msg>Some docs; some abstraction<commit_after>/*global require, exports */
/*jslint devel: true */

/* ***************************************************************************
# AtomizeJS Node Server

Distributed objects are represented by TVar objects. When an object is
created, its value is passed directly into the TVar constructor which
takes a copy of it, and sets up version tracking and observer
patterns.  TVars have global IDs, which are not communicated to
clients, and client-local IDs, which are. Thus each client maintains a
mapping from client-local IDs to global IDs, and vice versa. Thus you
can think of global IDs as being abstract physical addresses, and
client-local IDs as being abstract virtual addresses, if you want to
think in OS terms.

Updates to an object's fields appear as property descriptors within
the transaction log, received from clients. If the descriptor object
has a 'tvar' field, then the descriptor's 'value' field is set to be
the corresponding global TVar ID. Thus the TVar's 'raw' object will
contain fields with abstract pointers of the form {'tvar': id}. If the
field's value is a primitive, then the value is applied directly to
the TVar's 'raw' object, modulo some rubbish for coping with the fact
that for some daft reason you can't do Object.defineProperty on an
Array's 'length' field. Fields which have been deleted by clients are
indicated as such in the transaction log received from the client and
get directly deleted from the TVar's 'raw' object.

*  ***************************************************************************/

(function () {
    'use strict';

    var atomize = require('atomize-client'),
        cereal = require('cereal'),
        sockjs = require('sockjs'),
        events = require('events'),
        sockjs_opts = {sockjs_url: "http://cdn.sockjs.org/sockjs-0.1.min.js",
                       log: function () {}},
        globalTVarCount = 0,
        globalTVars = {},
        globalLocal = {},
        create, util, rootTVar;

    util = (function () {
        return {
            isPrimitive: function (obj) {
                return obj !== Object(obj);
            },

            hasOwnProp: ({}).hasOwnProperty,

            shallowCopy: function (src, dest) {
                var keys = Object.keys(src),
                    i;
                for (i = 0; i < keys.length; i += 1) {
                    dest[keys[i]] = src[keys[i]];
                }
            },

            lift: function (src, dest, fields) {
                var i;
                for (i = 0; i < fields.length; i += 1) {
                    dest[fields[i]] = src[fields[i]].bind(src);
                }
            }
        };
    }());

    function TVar(id, isArray, raw, creator) {
        this.creator = creator;
        this.raw = isArray ? [] : {};
        util.shallowCopy(raw, this.raw);
        this.isArray = isArray;
        this.id = id;
        this.version = 0;
        this.observers = [];
    }
    TVar.prototype = {
        subscribe: function (fun) {
            this.observers.push(fun);
        },

        bump: function (future) {
            // create a fresh observers array otherwise, if on the
            // server side firing the observer creates a new
            // subscription, you can go into a loop!
            var observers = this.observers,
                i;
            this.version += 1;
            this.observers = [];
            for (i = 0; i < observers.length; i += 1) {
                (observers[i])(this, future);
            }
        }
    };

    TVar.create = function (isArray, value, creator) {
        var globalTVar;
        globalTVarCount += 1;
        globalTVar = new TVar(globalTVarCount, isArray, value, creator);
        globalTVars[globalTVar.id] = globalTVar;
        return globalTVar;
    };

    function CoalescingObserver() {
        this.map = new cereal.Map();
        this.keys = [];
    }
    CoalescingObserver.prototype = {
        insert: function (key, value) {
            if (!this.map.has(key)) {
                this.keys.push(key);
            }
            this.map.set(key, value);
        },

        force: function () {
            var i;
            for (i = 0; i < this.keys.length; i += 1) {
                (this.map.get(this.keys[i]))();
            }
            this.keys = [];
            this.map = new cereal.Map();
        }
    }

    function Client(connection, serverEventEmitter) {
        this.emitter = new events.EventEmitter();
        util.lift(this.emitter, this,
                  ['on', 'once', 'removeListener', 'removeAllListeners', 'emit']);

        this.connection = connection;
        this.localGlobal = {};
        this.globalLocal = {};
        globalLocal[connection.id] = this.globalLocal;
        this.minTVarId = 0;

        connection.on('data', this.data.bind(this));
        connection.on('close', this.close.bind(this));
        serverEventEmitter.emit('connection', this);

        this.addToMapping(rootTVar.id, rootTVar.id);
    }

    Client.prototype = {
        isAuthenticated: false,

        data: function (message) {
            if (this.isAuthenticated) {
                this.dispatch(message);
            } else {
                this.emit('data', message, this);
            }
        },

        close: function () {
            this.emit('close', this);
            delete globalLocal[this.connection.id];
        },

        write: function (msg) {
            this.connection.write(cereal.stringify(msg));
        },

        read: function (msg) {
            return cereal.parse(msg);
        },

        dispatch: function (msg) {
            var txnLog = this.read(msg);
            switch (txnLog.type) {
            case "commit":
                this.commit(txnLog);
                break;
            case "retry":
                this.retry(txnLog);
                break;
            default:
                console.log("Received unexpected message from client:");
                console.log(txnLog);
            }
        },

        addToMapping: function (globalTVarId, localTVarId) {
            if (undefined === localTVarId) {
                this.minTVarId -= 1;
                localTVarId = this.minTVarId;
            }
            this.localGlobal[localTVarId] = globalTVarId;
            this.globalLocal[globalTVarId] = localTVarId;
            return localTVarId;
        },

        toGlobalTVar: function (localTVarId) {
            return globalTVars[this.localGlobal[localTVarId]];
        },

        toGlobalTVarID: function (localTVarId) {
            return this.localGlobal[localTVarId];
        },

        toLocalTVarID: function (globalTVarId) {
            return this.globalLocal[globalTVarId];
        },

        create: function (txnLog) {
            var keys = Object.keys(txnLog.created),
                ok = true,
                i, localTVar, globalTVar;

            for (i = 0; i < keys.length; i += 1) {
                localTVar = txnLog.created[keys[i]];
                globalTVar = TVar.create(localTVar.isArray, localTVar.value, this);
                this.addToMapping(globalTVar.id, keys[i]);
            }

            return ok;
        },

        checkThing: function (thing, updates) {
            var keys = Object.keys(thing),
                ok = true,
                i, localTVar, globalTVar;

            for (i = 0; i < keys.length; i += 1) {
                localTVar = thing[keys[i]];
                globalTVar = this.toGlobalTVar(keys[i]);
                if (localTVar.version !== globalTVar.version) {
                    updates[globalTVar.id] = true;
                    ok = false;
                }
            }

            return ok;
        },

        checkReads: function (txnLog, updates) {
            return this.checkThing(txnLog.read, updates);
        },

        checkWrites: function (txnLog, updates) {
            return this.checkThing(txnLog.written, updates);
        },

        retry: function (txnLog) {
            var txnId = txnLog.txnId,
                updates = {},
                ok, self, fired, observer, keys, i, localTVar, globalTVar;

            ok = this.checkReads(txnLog, updates);

            if (ok) {
                self = this;
                fired = false;
                observer = function (globalTVar, future) {
                    updates[globalTVar.id] = true;
                    future.insert(
                        updates,
                        function () {
                            if (!fired) {
                                fired = true;
                                self.write(self.createUpdates(updates, txnId));
                                self.write({type: "retry", txnId: txnId});
                            }
                        });
                };

                keys = Object.keys(txnLog.read);
                for (i = 0; i < keys.length; i += 1) {
                    (this.toGlobalTVar(keys[i])).subscribe(observer);
                }
            } else {
                // oh good, need to do updates already and can then
                // immediately restart the txn.
                this.write(this.createUpdates(updates, txnId));
                this.write({type: "retry", txnId: txnId});
            }

        },

        commit: function (txnLog) {
            var txnId = txnLog.txnId,
                updates = {},
                ok, keys, i, j, localTVar, globalTVar, future, names, name, value;

            // Prevent a short-cut impl of && from causing us problems
            ok = this.create(txnLog);
            ok = this.checkReads(txnLog, updates) && ok;
            ok = this.checkWrites(txnLog, updates) && ok;

            // Regardless of success, we have grabbed the creates. We
            // should now bump their versions from 0 to 1.
            keys = Object.keys(txnLog.created);
            for (i = 0; i < keys.length; i += 1) {
                this.toGlobalTVar(keys[i]).bump();
            }

            if (ok && this.onPreCommit(txnLog)) {
                // send out the success message first. This a)
                // improves performance; and more importantly b)
                // ensures that any updates that end up being sent to
                // the same client (due to pending retries) get
                // received after the success msg and thus we don't
                // fall out of step with vsns
                this.write({type: "commit", txnId: txnId, result: "success"});

                future = new CoalescingObserver();

                keys = Object.keys(txnLog.written);
                for (i = 0; i < keys.length; i += 1) {
                    localTVar = txnLog.written[keys[i]];
                    globalTVar = this.toGlobalTVar(keys[i]);
                    names = Object.keys(localTVar.children);
                    for (j = 0; j < names.length; j += 1) {
                        name = names[j];
                        value = localTVar.children[name];
                        if (undefined !== value.tvar) {
                            value.value = {tvar: this.toGlobalTVarID(value.tvar)};
                            delete value.tvar;
                            Object.defineProperty(globalTVar.raw, name, value);
                        } else if (undefined !== value.deleted) {
                            delete globalTVar.raw[name];
                        } else {
                            // mess for dealing with arrays, and some proxy stuff
                            if (globalTVar.isArray && 'length' === name) {
                                globalTVar.raw[name] = value.value;
                            } else {
                                Object.defineProperty(globalTVar.raw, name, value);
                            }
                        }
                    }
                    globalTVar.bump(future);
                }

                future.force();
            } else {
                this.write(this.createUpdates(updates, txnId));
                this.write({type: "commit", txnId: txnId, result: "failure"});
            }
        },

        onPreCommit: function (txnLog) {
            return true;
        },

        createUpdates: function (updates, txnId) {
            var keys = Object.keys(updates),
                txnLog = {type: "updates", updates: {}, txnId: txnId},
                key, globalTVar, localTVar, names, name, i, desc;

            while (0 < keys.length) {
                key = keys.shift();
                globalTVar = globalTVars[key];
                localTVar = {version: globalTVar.version,
                             value:   {},
                             isArray: globalTVar.isArray};

                if (undefined === this.toLocalTVarID(globalTVar.id)) {
                    txnLog.updates[this.addToMapping(globalTVar.id)] = localTVar;
                } else {
                    txnLog.updates[this.toLocalTVarID(globalTVar.id)] = localTVar;
                }

                names = Object.getOwnPropertyNames(globalTVar.raw);
                for (i = 0; i < names.length; i += 1) {
                    name = names[i];
                    desc = Object.getOwnPropertyDescriptor(globalTVar.raw, name);
                    if (util.hasOwnProp.call(desc.value, 'tvar')) {
                        localTVar.value[name] = desc;
                        if (undefined === this.toLocalTVarID(desc.value.tvar)) {
                            keys.push(desc.value.tvar); // push the global id
                            desc.tvar = this.addToMapping(desc.value.tvar);
                        } else {
                            desc.tvar = this.toLocalTVarID(desc.value.tvar);
                        }
                        delete desc.value;
                    } else {
                        localTVar.value[name] = desc;
                    }
                }
            }
            return txnLog;
        }
    };

    function ServerEventEmitter () {
        this.emitter = new events.EventEmitter();
        util.lift(this.emitter, this,
                  ['on', 'once', 'removeListener', 'removeAllListeners', 'emit']);
        this.on('connection', this.defaultAuthenticator.bind(this));
    }

    ServerEventEmitter.prototype = {
        connection: function (connection) {
            new Client(connection, this);
        },

        defaultAuthenticator: function (client) {
            if (1 === this.emitter.listeners('connection').length) {
                // nothing installed other than us, just let it straight through!
                client.isAuthenticated = true;
            }
        }
    };

    create = function (http, path, root) {
        var server = sockjs.createServer(sockjs_opts),
            emitter = new ServerEventEmitter();

        server.on('connection', emitter.connection.bind(emitter));
        http.addListener('upgrade', function (req, res) { res.end(); });
        server.installHandlers(http, {prefix: path});

        if (undefined === root || null === root) {
            root = {};
        }
        globalTVarCount = 1;
        rootTVar = new TVar(globalTVarCount, Array.isArray(root), root, undefined);
        globalTVars[rootTVar.id] = rootTVar;
        rootTVar.bump(); // Need 2 bumps to ensure we're ahead of any clients.
        rootTVar.bump();

        emitter.client = function () { return new atomize.Atomize(Client, emitter); };

        return emitter;
    };

    exports.create = create;
}());
<|endoftext|>


<commit_before>import {
  RECEIVE_NODES_CONTENT,
  RECEIVE_NODES_FINISHED,
  UPDATE_REF,

  UPDATE_NODE,
  CREATE_NODE,
  DELETE_NODE,

  START_LISTERNING_TO_FLAT,
  DISABLE_DRAGABLE_FLAT,
  ENABLE_DRAGABLE_FLAT,
  NODE_CUT
} from './action-types';

import { getUniqueId } from "utils/node"
import { pasteNode } from "utils/firebase"
import { getParent, nodeGetAllChildrenId} from "utils/node2"

export function nodeCut(key){
  return (dispatch, getState) => {
    dispatch({
      type: NODE_CUT,
      payload: key,
    })
  }
}

export function nodePaste(key){
  return (dispatch, getState) => {
    const { flat, firebase , auth} = getState();
    let rootRef = firebase.tree.child(auth.userRef+"/flats/")

    let ref = rootRef
    let obj = flat.content
    let cid = flat.cut
    let nid = key

    let cNode = obj[cid]
    let nParent = getParent( nid, obj)
    let cParent = getParent( cid, obj)

    if (cParent==nParent &&
        (obj[nParent].children.indexOf(nid)-obj[nParent].children.indexOf(cid) == -1)){
      console.log("1.2 -> 1.1")
    }else if(nodeGetAllChildrenId(cid, obj).indexOf(nid) > -1){
      console.log('1.1 -> 1')
    }else{
      //cut
      let currentchildren = obj[cParent].children
      currentchildren.splice(currentchildren.indexOf(cid),1) //!!!!

      //paste
      let newchildren = obj[nParent].children
      let index = newchildren.indexOf(nid)+1
      let _index =-( newchildren.length - index)

      if ((index == newchildren.length) || (newchildren.length == 1)){
        newchildren = [...newchildren, cid]
      }else{
        newchildren = [...newchildren.slice(0,index), cid, ...newchildren.slice(_index)]
      }

      if (nParent != cParent){
        dispatch(nodeUpdate(Object.assign({}, obj[cParent], {children: currentchildren})))
      }

      dispatch(nodeUpdate(Object.assign({}, obj[nParent], {children: newchildren})))

    }

  }
}

export function disableDragableFlat(){
  return (dispatch, getState) => {
    dispatch({
      type: DISABLE_DRAGABLE_FLAT,
    })
  }
}

export function enableDragableFlat(){
  return (dispatch, getState) => {
    dispatch({
      type: ENABLE_DRAGABLE_FLAT,
    })
  }
}

export function createRoot(){
  return (dispatch, getState) => {
    const { auth, firebase } = getState();

    let rootRef = firebase.tree.child(auth.userRef+"/flats/")

    const newNode = {
      key: "root"
    }

    rootRef.child("root").set(newNode, (err)=>{
      if (err){
        console.log("createRoot failed!", err)
      }else{
        console.log("createRoot success")
      }
    })
  }
}

export function nodeUpdate(payload) {
  console.log("nodeUpdate", payload)
  return (dispatch, getState) => {
    const { flat, firebase } = getState();
    flat.ref.child(payload.key).update(payload)

    dispatch({
      type: UPDATE_NODE,
      payload: {[payload.key]:payload}
    })
  }
}

export function nodeCreate(payload) {

  console.log("nodeCreate", payload)
  return (dispatch, getState) => {
    const { flat, firebase } = getState();

    //add rollback
    flat.ref.child(payload.key).set(payload, (err)=>{
      console.log(err)
    })

    dispatch({
      type: CREATE_NODE,
      payload: {[payload.key]:payload}
    })

  }
}

export function nodeDelete(payload){
  return (dispatch, getState) => {
    const { flat, firebase } = getState();

    const cNodeKey = payload
    const obj = flat.content

    let parentKey = getParent(cNodeKey, obj)
    let parent = obj[parentKey]
    let deleteList = nodeGetAllChildrenId(cNodeKey, obj)
    deleteList.push(cNodeKey)
    let children = obj[parentKey].children
    children.splice(children.indexOf(cNodeKey), 1)
    parent.children = children

    dispatch(nodeUpdate(parent))

    deleteList.forEach(i=>{
      flat.ref.child(i).remove()
      dispatch({
        type: DELETE_NODE,
        payload: {key: i}
      })
    })
  }
}
//node with markdown
export function nodeUpdateMd(payload) {
  return (dispatch, getState) => {
    const { flat, firebase, md} = getState();
    let fnd = md.articles.filter(i=>{
      return i.header == payload.md
    })
    payload.md = fnd[0]?fnd[0].key:null
    flat.ref.child(payload.key).update(payload)
  }
}

export function nodeUpdateLayout(key, payload) {
  return (dispatch, getState) => {
    const { flat, firebase } = getState();

    const newlayout = payload.layout.map(i=>(
      {
      i:i.i,
      x:i.x,
      y:i.y,
      w:i.w,
      h:i.h, }
    ))
    payload.layout = newlayout
    dispatch(nodeUpdate(payload))
  }
}

export function nodeCreateChild(key) {
  return (dispatch, getState) => {
    const { flat, firebase } = getState();
    let list = flat.list

    const newNode = {
      key: getUniqueId()
    }
    createChildNode(key, list, flat.ref, newNode )
  }
}

//get all nodes and listening to delete/update/add
export function startListening(){
  return (dispatch, getState) => {
    const { auth, firebase } = getState();

    let rootRef = firebase.tree.child(auth.userRef+"/flats/")
    dispatch({
      type: UPDATE_REF,
      payload: rootRef,
    })

    function get(ref, key, limit ){
      console.log("get!")
      console.log(ref)
       if (key){
         ref.orderByKey().startAt(key).limitToFirst(limit).once("value",function(snapshot){
             let val = snapshot.val()
             console.log(val)
             dispatch({
               type: RECEIVE_NODES_CONTENT,
               payload: val,
             })
             let keys = Object.keys(val).sort()
             //keys.forEach(i=>console.log(i))
             if (keys.length==limit){
               get(ref, keys[limit-1], limit)
             }else{
               dispatch({
                 type: RECEIVE_NODES_FINISHED,
               })
             }
         })
       }else{
         ref.orderByKey().limitToFirst(limit).once("value",function(snapshot){
             let val = snapshot.val()
             console.log(val)
             dispatch({
               type: RECEIVE_NODES_CONTENT,
               payload: val,
             })

             let keys = Object.keys(val).sort()
             //keys.forEach(i=>console.log(i))
             if (keys.length==limit){
               get(ref, keys[limit-1], limit)
             }else{
               dispatch({
                 type: RECEIVE_NODES_FINISHED,
               })
             }
         })
       }
    }

    //get till last
    get(rootRef, null, 100)

  }
}

<commit_msg>register auto generate root -- need refractor<commit_after>import {
  RECEIVE_NODES_CONTENT,
  RECEIVE_NODES_FINISHED,
  UPDATE_REF,

  UPDATE_NODE,
  CREATE_NODE,
  DELETE_NODE,

  START_LISTERNING_TO_FLAT,
  DISABLE_DRAGABLE_FLAT,
  ENABLE_DRAGABLE_FLAT,
  NODE_CUT
} from './action-types';

import { getUniqueId } from "utils/node"
import { pasteNode } from "utils/firebase"
import { getParent, nodeGetAllChildrenId} from "utils/node2"

export function nodeCut(key){
  return (dispatch, getState) => {
    dispatch({
      type: NODE_CUT,
      payload: key,
    })
  }
}

export function nodePaste(key){
  return (dispatch, getState) => {
    const { flat, firebase , auth} = getState();
    let rootRef = firebase.tree.child(auth.userRef+"/flats/")

    let ref = rootRef
    let obj = flat.content
    let cid = flat.cut
    let nid = key

    let cNode = obj[cid]
    let nParent = getParent( nid, obj)
    let cParent = getParent( cid, obj)

    if (cParent==nParent &&
        (obj[nParent].children.indexOf(nid)-obj[nParent].children.indexOf(cid) == -1)){
      console.log("1.2 -> 1.1")
    }else if(nodeGetAllChildrenId(cid, obj).indexOf(nid) > -1){
      console.log('1.1 -> 1')
    }else{
      //cut
      let currentchildren = obj[cParent].children
      currentchildren.splice(currentchildren.indexOf(cid),1) //!!!!

      //paste
      let newchildren = obj[nParent].children
      let index = newchildren.indexOf(nid)+1
      let _index =-( newchildren.length - index)

      if ((index == newchildren.length) || (newchildren.length == 1)){
        newchildren = [...newchildren, cid]
      }else{
        newchildren = [...newchildren.slice(0,index), cid, ...newchildren.slice(_index)]
      }

      if (nParent != cParent){
        dispatch(nodeUpdate(Object.assign({}, obj[cParent], {children: currentchildren})))
      }

      dispatch(nodeUpdate(Object.assign({}, obj[nParent], {children: newchildren})))

    }

  }
}

export function disableDragableFlat(){
  return (dispatch, getState) => {
    dispatch({
      type: DISABLE_DRAGABLE_FLAT,
    })
  }
}

export function enableDragableFlat(){
  return (dispatch, getState) => {
    dispatch({
      type: ENABLE_DRAGABLE_FLAT,
    })
  }
}

export function createRoot(){
  return (dispatch, getState) => {
    const { auth, firebase } = getState();

    let rootRef = firebase.tree.child(auth.userRef+"/flats/")

    const newNode = {
      key: "root"
    }

    rootRef.child("root").set(newNode, (err)=>{
      if (err){
        console.log("createRoot failed!", err)
      }else{
        console.log("createRoot success")
      }
    })
  }
}

export function nodeUpdate(payload) {
  console.log("nodeUpdate", payload)
  return (dispatch, getState) => {
    const { flat, firebase } = getState();
    flat.ref.child(payload.key).update(payload)

    dispatch({
      type: UPDATE_NODE,
      payload: {[payload.key]:payload}
    })
  }
}

export function nodeCreate(payload) {

  console.log("nodeCreate", payload)
  return (dispatch, getState) => {
    const { flat, firebase } = getState();

    //add rollback
    flat.ref.child(payload.key).set(payload, (err)=>{
      console.log(err)
    })

    dispatch({
      type: CREATE_NODE,
      payload: {[payload.key]:payload}
    })

  }
}

export function nodeDelete(payload){
  return (dispatch, getState) => {
    const { flat, firebase } = getState();

    const cNodeKey = payload
    const obj = flat.content

    let parentKey = getParent(cNodeKey, obj)
    let parent = obj[parentKey]
    let deleteList = nodeGetAllChildrenId(cNodeKey, obj)
    deleteList.push(cNodeKey)
    let children = obj[parentKey].children
    children.splice(children.indexOf(cNodeKey), 1)
    parent.children = children

    dispatch(nodeUpdate(parent))

    deleteList.forEach(i=>{
      flat.ref.child(i).remove()
      dispatch({
        type: DELETE_NODE,
        payload: {key: i}
      })
    })
  }
}
//node with markdown
export function nodeUpdateMd(payload) {
  return (dispatch, getState) => {
    const { flat, firebase, md} = getState();
    let fnd = md.articles.filter(i=>{
      return i.header == payload.md
    })
    payload.md = fnd[0]?fnd[0].key:null
    flat.ref.child(payload.key).update(payload)
  }
}

export function nodeUpdateLayout(key, payload) {
  return (dispatch, getState) => {
    const { flat, firebase } = getState();

    const newlayout = payload.layout.map(i=>(
      {
      i:i.i,
      x:i.x,
      y:i.y,
      w:i.w,
      h:i.h, }
    ))
    payload.layout = newlayout
    dispatch(nodeUpdate(payload))
  }
}

export function nodeCreateChild(key) {
  return (dispatch, getState) => {
    const { flat, firebase } = getState();
    let list = flat.list

    const newNode = {
      key: getUniqueId()
    }
    createChildNode(key, list, flat.ref, newNode )
  }
}

//get all nodes and listening to delete/update/add
export function startListening(){
  return (dispatch, getState) => {
    const { auth, firebase } = getState();

    let rootRef = firebase.tree.child(auth.userRef+"/flats/")
    dispatch({
      type: UPDATE_REF,
      payload: rootRef,
    })

    function get(ref, key, limit ){
      console.log("get!")
      console.log(ref)
       if (key){
         ref.orderByKey().startAt(key).limitToFirst(limit).once("value",function(snapshot){
             let val = snapshot.val()
             console.log(val)
             dispatch({
               type: RECEIVE_NODES_CONTENT,
               payload: val,
             })
             let keys = Object.keys(val).sort()
             //keys.forEach(i=>console.log(i))
             if (keys.length==limit){
               get(ref, keys[limit-1], limit)
             }else{
               dispatch({
                 type: RECEIVE_NODES_FINISHED,
               })
             }
         })
       }else{
         ref.orderByKey().limitToFirst(limit).once("value",function(snapshot){
             let val = snapshot.val()
             console.log(val)
             dispatch({
               type: RECEIVE_NODES_CONTENT,
               payload: val,
             })

             console.log(val)

             if (val === null){ //when init

               dispatch( nodeCreate({key:"root", content:"root"}))

               dispatch({
                 type: RECEIVE_NODES_FINISHED,
               })
             }else{
               let keys = Object.keys(val).sort()
               //keys.forEach(i=>console.log(i))
               if (keys.length==limit){
                 get(ref, keys[limit-1], limit)
               }else{
                 dispatch({
                   type: RECEIVE_NODES_FINISHED,
                 })
               }
             }
         })
       }
    }

    //get till last
    get(rootRef, null, 100)

  }
}

<|endoftext|>


<commit_before>/*!
 * x509.js - x509 handling for bcoin
 * Copyright (c) 2016, Christopher Jeffrey (MIT License).
 * https://github.com/bcoin-org/bcoin
 */

'use strict';

var bn = require('bn.js');
var asn1 = require('./asn1');
var elliptic = require('elliptic');
var utils = require('../utils');

var crypto;

try {
  crypto = require('cryp' + 'to');
} catch (e) {
  ;
}

var pk = exports;
var rsa = {};
var ecdsa = {};
var native = {};

rsa.prefixes = {
  md5: new Buffer('3020300c06082a864886f70d020505000410', 'hex'),
  sha1: new Buffer('3021300906052b0e03021a05000414', 'hex'),
  sha224: new Buffer('302d300d06096086480165030402040500041c', 'hex'),
  sha256: new Buffer('3031300d060960864801650304020105000420', 'hex'),
  sha384: new Buffer('3041300d060960864801650304020205000430', 'hex'),
  sha512: new Buffer('3051300d060960864801650304020305000440', 'hex'),
  md5sha1: new Buffer(0),
  ripemd160: new Buffer('30203008060628cf060300310414', 'hex')
};

// Ported from:
// https://github.com/golang/go/blob/master/src/crypto/rsa/pkcs1v15.go

rsa.verify = function verify(hashAlg, msg, sig, key) {
  var hash = utils.hash(hashAlg, msg);
  var prefix = rsa.prefixes[hashAlg];
  var len = prefix.length + hash.length;
  var pub = asn1.parseRSAPublic(key);
  var N = new bn(pub.modulus);
  var e = new bn(pub.publicExponent);
  var k = Math.ceil(N.bitLength() / 8);
  var m, em, ok, i;

  if (k < len + 11)
    throw new Error('Message too long.');

  m = rsa.encrypt(N, e, sig);
  em = leftpad(m, k);

  ok = ceq(em[0], 0x00);
  ok &= ceq(em[1], 0x01);
  ok &= utils.ccmp(em.slice(k - hash.length, k), hash);
  ok &= utils.ccmp(em.slice(k - len, k - hash.length), prefix);
  ok &= ceq(em[k - len - 1], 0x00);

  for (i = 2; i < k - len - 1; i++)
    ok &= ceq(em[i], 0xff);

  return ok === 1;
};

rsa.sign = function sign(hashAlg, msg, key) {
  var hash = utils.hash(hashAlg, msg);
  var prefix = rsa.prefixes[hashAlg];
  var len = prefix.length + hash.length;
  var priv = asn1.parseRSAPrivate(key);
  var N = new bn(priv.modulus);
  var D = new bn(priv.privateExponent);
  var k = Math.ceil(N.bitLength() / 8);
  var i, em;

  if (k < len + 11)
    throw new Error('Message too long.');

  em = new Buffer(k);
  em.fill(0);

  em[1] = 0x01;
  for (i = 2; i < k - len - 1; i++)
    em[i] = 0xff;

  prefix.copy(em, k - len);
  hash.copy(em, k - hash.length);

  return rsa.decrypt(N, D, em);
};

rsa.decrypt = function decrypt(N, D, m) {
  var c = new bn(m);

  if (c.cmp(N) > 0)
    throw new Error('Cannot decrypt.');

  return c
    .toRed(bn.red(N))
    .redPow(D)
    .fromRed()
    .toArrayLike(Buffer, 'be');
};

rsa.encrypt = function encrypt(N, e, m) {
  return new bn(m)
    .toRed(bn.red(N))
    .redPow(e)
    .fromRed()
    .toArrayLike(Buffer, 'be');
};

ecdsa.verify = function verify(curve, msg, hashAlg, key, sig) {
  var hash = utils.hash(hashAlg, msg);
  var ec = elliptic.ec(curve);
  return ec.verify(hash, sig, key);
};

ecdsa.sign = function sign(curve, msg, hashAlg, key) {
  var hash = utils.hash(hashAlg, msg);
  var ec = elliptic.ec(curve);
  return ec.sign(hash, key);
};

native.verify = function verify(alg, hash, msg, sig, key) {
  var algo, verify;

  if (!crypto)
    return false;

  algo = normalizeAlg(alg, hash);
  verify = crypto.createVerify(algo);
  verify.update(msg);

  return verify.verify(key, sig);
};

native.sign = function _sign(alg, hash, msg, key) {
  var algo, sig;

  if (!crypto)
    return false;

  algo = normalizeAlg(alg, hash);
  sig = crypto.createSign(algo);
  sig.update(msg);
  return sig.sign(key);
};

pk.pemTag = {
  dsa: 'DSA',
  rsa: 'RSA',
  ecdsa: 'EC'
};

pk.toPEM = function toPEM(key, type) {
  var tag = pk.pemTag[key.alg];
  var pem = asn1.toPEM(key.data, tag, type);

  // Key parameters, usually present
  // if selecting an EC curve.
  if (key.params)
    pem += asn1.toPEM(key.params, tag, 'parameters');

  return pem;
};

pk._verify = function verify(hash, msg, sig, key) {
  var pem;
  switch (key.alg) {
    case 'dsa':
      pem = pk.toPEM(key, 'public key');
      return native.verify(key.alg, hash, msg, sig, pem);
    case 'rsa':
      if (crypto) {
        pem = pk.toPEM(key, 'public key');
        return native.verify(key.alg, hash, msg, sig, pem);
      }
      return rsa.verify(hash, msg, sig, key.data);
    case 'ecdsa':
      if (!key.curve)
        throw new Error('No curve present.');
      return ecdsa.verify(key.curve, hash, msg, sig, key.data);
    default:
      throw new Error('Unsupported algorithm.');
  }
};

pk.verify = function verify(hash, msg, sig, key) {
  try {
    return pk._verify(hash, msg, sig, key);
  } catch (e) {
    return false;
  }
};

pk.sign = function sign(hash, msg, key) {
  var pem;
  switch (key.alg) {
    case 'dsa':
      pem = pk.toPEM(key, 'private key');
      return native.sign(key.alg, hash, msg, pem);
    case 'rsa':
      if (crypto) {
        pem = pk.toPEM(key, 'private key');
        return native.sign(key.alg, hash, msg, pem);
      }
      return rsa.sign(hash, msg, key.data);
    case 'ecdsa':
      if (!key.curve)
        throw new Error('No curve present.');
      return ecdsa.sign(key.curve, hash, msg, key.data);
    default:
      throw new Error('Unsupported algorithm.');
  }
};

function ceq(a, b) {
	var r = ~(a ^ b) & 0xff;
	r &= r >>> 4;
	r &= r >>> 2;
	r &= r >>> 1;
	return r === 1;
}

function leftpad(input, size) {
  var n = input.length;
  var out;

  if (n > size)
    n = size;

  out = new Buffer(size);
  out.fill(0);

  input.copy(out, out.length - n);

  return out;
}

function normalizeAlg(alg, hash) {
  var name = alg.toUpperCase() + '-' + hash.toUpperCase();

  switch (name) {
    case 'ECDSA-SHA1':
      name = 'ecdsa-with-SHA1';
      break;
    case 'ECDSA-SHA256':
      name = 'ecdsa-with-SHA256';
      break;
  }

  return name;
}

pk.rsa = rsa;
pk.ecdsa = ecdsa;
pk.native = native;
<commit_msg>bip70: whitespace.<commit_after>/*!
 * x509.js - x509 handling for bcoin
 * Copyright (c) 2016, Christopher Jeffrey (MIT License).
 * https://github.com/bcoin-org/bcoin
 */

'use strict';

var bn = require('bn.js');
var asn1 = require('./asn1');
var elliptic = require('elliptic');
var utils = require('../utils');

var crypto;

try {
  crypto = require('cryp' + 'to');
} catch (e) {
  ;
}

var pk = exports;
var rsa = {};
var ecdsa = {};
var native = {};

rsa.prefixes = {
  md5: new Buffer('3020300c06082a864886f70d020505000410', 'hex'),
  sha1: new Buffer('3021300906052b0e03021a05000414', 'hex'),
  sha224: new Buffer('302d300d06096086480165030402040500041c', 'hex'),
  sha256: new Buffer('3031300d060960864801650304020105000420', 'hex'),
  sha384: new Buffer('3041300d060960864801650304020205000430', 'hex'),
  sha512: new Buffer('3051300d060960864801650304020305000440', 'hex'),
  md5sha1: new Buffer(0),
  ripemd160: new Buffer('30203008060628cf060300310414', 'hex')
};

// Ported from:
// https://github.com/golang/go/blob/master/src/crypto/rsa/pkcs1v15.go

rsa.verify = function verify(hashAlg, msg, sig, key) {
  var hash = utils.hash(hashAlg, msg);
  var prefix = rsa.prefixes[hashAlg];
  var len = prefix.length + hash.length;
  var pub = asn1.parseRSAPublic(key);
  var N = new bn(pub.modulus);
  var e = new bn(pub.publicExponent);
  var k = Math.ceil(N.bitLength() / 8);
  var m, em, ok, i;

  if (k < len + 11)
    throw new Error('Message too long.');

  m = rsa.encrypt(N, e, sig);
  em = leftpad(m, k);

  ok = ceq(em[0], 0x00);
  ok &= ceq(em[1], 0x01);
  ok &= utils.ccmp(em.slice(k - hash.length, k), hash);
  ok &= utils.ccmp(em.slice(k - len, k - hash.length), prefix);
  ok &= ceq(em[k - len - 1], 0x00);

  for (i = 2; i < k - len - 1; i++)
    ok &= ceq(em[i], 0xff);

  return ok === 1;
};

rsa.sign = function sign(hashAlg, msg, key) {
  var hash = utils.hash(hashAlg, msg);
  var prefix = rsa.prefixes[hashAlg];
  var len = prefix.length + hash.length;
  var priv = asn1.parseRSAPrivate(key);
  var N = new bn(priv.modulus);
  var D = new bn(priv.privateExponent);
  var k = Math.ceil(N.bitLength() / 8);
  var i, em;

  if (k < len + 11)
    throw new Error('Message too long.');

  em = new Buffer(k);
  em.fill(0);

  em[1] = 0x01;
  for (i = 2; i < k - len - 1; i++)
    em[i] = 0xff;

  prefix.copy(em, k - len);
  hash.copy(em, k - hash.length);

  return rsa.decrypt(N, D, em);
};

rsa.decrypt = function decrypt(N, D, m) {
  var c = new bn(m);

  if (c.cmp(N) > 0)
    throw new Error('Cannot decrypt.');

  return c
    .toRed(bn.red(N))
    .redPow(D)
    .fromRed()
    .toArrayLike(Buffer, 'be');
};

rsa.encrypt = function encrypt(N, e, m) {
  return new bn(m)
    .toRed(bn.red(N))
    .redPow(e)
    .fromRed()
    .toArrayLike(Buffer, 'be');
};

ecdsa.verify = function verify(curve, msg, hashAlg, key, sig) {
  var hash = utils.hash(hashAlg, msg);
  var ec = elliptic.ec(curve);
  return ec.verify(hash, sig, key);
};

ecdsa.sign = function sign(curve, msg, hashAlg, key) {
  var hash = utils.hash(hashAlg, msg);
  var ec = elliptic.ec(curve);
  return ec.sign(hash, key);
};

native.verify = function verify(alg, hash, msg, sig, key) {
  var algo, verify;

  if (!crypto)
    return false;

  algo = normalizeAlg(alg, hash);
  verify = crypto.createVerify(algo);
  verify.update(msg);

  return verify.verify(key, sig);
};

native.sign = function _sign(alg, hash, msg, key) {
  var algo, sig;

  if (!crypto)
    return false;

  algo = normalizeAlg(alg, hash);
  sig = crypto.createSign(algo);
  sig.update(msg);
  return sig.sign(key);
};

pk.pemTag = {
  dsa: 'DSA',
  rsa: 'RSA',
  ecdsa: 'EC'
};

pk.toPEM = function toPEM(key, type) {
  var tag = pk.pemTag[key.alg];
  var pem = asn1.toPEM(key.data, tag, type);

  // Key parameters, usually present
  // if selecting an EC curve.
  if (key.params)
    pem += asn1.toPEM(key.params, tag, 'parameters');

  return pem;
};

pk._verify = function verify(hash, msg, sig, key) {
  var pem;
  switch (key.alg) {
    case 'dsa':
      pem = pk.toPEM(key, 'public key');
      return native.verify(key.alg, hash, msg, sig, pem);
    case 'rsa':
      if (crypto) {
        pem = pk.toPEM(key, 'public key');
        return native.verify(key.alg, hash, msg, sig, pem);
      }
      return rsa.verify(hash, msg, sig, key.data);
    case 'ecdsa':
      if (!key.curve)
        throw new Error('No curve present.');
      return ecdsa.verify(key.curve, hash, msg, sig, key.data);
    default:
      throw new Error('Unsupported algorithm.');
  }
};

pk.verify = function verify(hash, msg, sig, key) {
  try {
    return pk._verify(hash, msg, sig, key);
  } catch (e) {
    return false;
  }
};

pk.sign = function sign(hash, msg, key) {
  var pem;
  switch (key.alg) {
    case 'dsa':
      pem = pk.toPEM(key, 'private key');
      return native.sign(key.alg, hash, msg, pem);
    case 'rsa':
      if (crypto) {
        pem = pk.toPEM(key, 'private key');
        return native.sign(key.alg, hash, msg, pem);
      }
      return rsa.sign(hash, msg, key.data);
    case 'ecdsa':
      if (!key.curve)
        throw new Error('No curve present.');
      return ecdsa.sign(key.curve, hash, msg, key.data);
    default:
      throw new Error('Unsupported algorithm.');
  }
};

function ceq(a, b) {
  var r = ~(a ^ b) & 0xff;
  r &= r >>> 4;
  r &= r >>> 2;
  r &= r >>> 1;
  return r === 1;
}

function leftpad(input, size) {
  var n = input.length;
  var out;

  if (n > size)
    n = size;

  out = new Buffer(size);
  out.fill(0);

  input.copy(out, out.length - n);

  return out;
}

function normalizeAlg(alg, hash) {
  var name = alg.toUpperCase() + '-' + hash.toUpperCase();

  switch (name) {
    case 'ECDSA-SHA1':
      name = 'ecdsa-with-SHA1';
      break;
    case 'ECDSA-SHA256':
      name = 'ecdsa-with-SHA256';
      break;
  }

  return name;
}

pk.rsa = rsa;
pk.ecdsa = ecdsa;
pk.native = native;
<|endoftext|>


<commit_before>var injector    = require( 'injector' )
  , Class       = injector.getInstance( 'Class' )
  , path        = require( 'path' )
  , async       = require( 'async' )
  , fs          = require( 'fs' )
  , i           = require( 'i' )()
  , moduleDebug = require('debug')( 'Modules' )
  , config      = injector.getInstance( 'config' )
  , modules     = {}
  , Module;

Module = exports.Class = Class.extend(
{
    moduleFolders: [
        'exceptions',
        'classes',
        'models',
        'services',
        'controllers',
        'tasks'
    ],

    injectableFolders: [
        'models',
        'controllers',
        'services'
    ],

    excludedFiles: [
        'index.js',
        'module.js',
        'Gruntfile.js',
        'package.json'
    ]
},
{
    name: null,

    config: null,

    path: null,

    pkg: null,

    paths: null,

    setup: function( _name, _path, _pkg ) {
        // Set our module name
        this.name = _name;

        // Set our config if there is any
        this.config = typeof config[ _name ] === 'object'
            ? config[ _name ]
            : {};

        // Set the modules location
        this.path = _path;

        // Set the modules package.json
        this.pkg = _pkg;

        // Allow some code to be executed before the main setup
        this.hook( 'preSetup' );

        // Add the modules path to our list of paths
        this.paths = [ _path ];

        // Add our moduleFolders to the list of paths, and our injector paths
        this.Class.moduleFolders.forEach( this.proxy( 'addFolderToPath', injector ) );

        // Fire the preInit hook
        this.hook( 'preInit' );

        // Return no arguments to init
        return [];
    },

    hook: function( hookName ) {
        if ( typeof this[ hookName ] === 'function' ) {
            this.debug( 'calling ' + hookName + '() hook...' );

            // @TODO implement injector.injectSync() for use cases like this
            this[ hookName ]();
        }
    },

    addFolderToPath: function( injector, folder ) {
        var folderPath      = path.join( this.path, folder )
          , folders         = folder.split( '/' )
          , currentFolder   = null
          , rootFolder      = null
          , obj             = {}
          , lastFolder      = obj;

        while ( folders.length > 0 ) {
            currentFolder = folders.shift();
            if ( rootFolder === null ) {
                rootFolder = currentFolder;
                if ( this[ rootFolder ] !== undefined  ) {
                    lastFolder = obj = this[ rootFolder ];
                }
            } else {
                if ( lastFolder[ currentFolder ] === undefined ) {
                    lastFolder[ currentFolder ] = {};
                }
                lastFolder = lastFolder[ currentFolder ];
            }
        }

        this[ rootFolder ] = obj;
        this.paths.push( folderPath );
        injector._inherited.factoriesDirs.push( folderPath );
    },

    loadResources: function() {
        async.forEach(
            this.paths,
            this.proxy( 'inspectPathForResources' ),
            this.proxy( 'resourcesLoaded' )
        );
    },

    resourcesLoaded: function( err ) {
        this.debug( 'Resources Loaded' );
        this.emit( 'resourcesLoaded', err || null );
    },

    inspectPathForResources: function( pathToInspect, callback ) {
        var that = this;

        if ( fs.existsSync( pathToInspect + path.sep ) ) {
            fs.readdir( pathToInspect + path.sep, function( err, files ) {
                async.forEach( files, that.proxy( 'addResource', pathToInspect ), callback );
            });
        } else {
            callback( null );
        }
    },

    addResource: function( pathToInspect, file, callback ) {
        if ( file.match(/.+\.js$/g) !== null && this.Class.excludedFiles.indexOf( file ) === -1 ) {
            var folders         = pathToInspect.split( path.sep )
              , name            = file.replace( '.js', '' )
              , currentFolder   = null
              , insideModule    = false
              , rootFolder      = null
              , lastFolder      = this
              , that            = this
              , traceError      = new Error( 'Load Timeout for ' + file )
              , loadTimeout     = setTimeout( function() {
                    that.debug( traceError );
                    process.exit( 1 );
                }, 10000 )
              , resource;

            while ( folders.length > 0 ) {
                currentFolder = folders.shift();
                if ( insideModule === false && currentFolder === this.name ) {
                    // Make sure that this is the LAST instance of the name
                    if ( folders.indexOf( this.name ) === -1 ) {
                        insideModule = true;
                    }
                } else if ( insideModule === true ) {
                    if ( rootFolder === null ) {
                        rootFolder = currentFolder;
                        if ( this[ rootFolder ] !== undefined  ) {
                            lastFolder = this[ rootFolder ];
                        }
                    } else {
                        lastFolder = lastFolder[ currentFolder ];
                    }
                }
            }

            // Load the resource
            resource = require( [ pathToInspect, path.sep, file ].join( '' ) );

            // Do not load dependencies that can be injected
            if ( this.Class.injectableFolders.indexOf( rootFolder ) === -1 ) {

                if ( this.Class.injectableFolders.indexOf( name ) === -1 )  {
                    // Add the resource to the injector
                    if ( name !== 'routes' ) {
                        this.debug( 'Adding ' + name + ' to the injector' );
                        injector.instance( name, resource );
                    }

                    // Add the resource to the last object we found
                    lastFolder[ name ] = resource;
                    clearTimeout( loadTimeout );
                    callback( null );
                } else {
                    clearTimeout( loadTimeout );
                    callback( null );
                }
            } else {
                this.debug( 'Loading ' + name + ' using the injector...' );
                injector.inject( resource, function( resource ) {
                    injector.instance( name, resource );
                    lastFolder[ name ] = resource;
                    clearTimeout( loadTimeout );
                    callback( null );
                });
            }
        } else {
            callback( null );
        }
    },

    initRoutes: function() {
        if ( typeof this.routes === 'function' ) {
            this.debug( 'calling initRoutes() hook...' );
            injector.inject( this.routes );
        }
    }
});

exports.extend = function() {
    var Reg             = new RegExp( '.*\\(([^\\)]+)\\:.*\\:.*\\)', 'ig' )
      , stack           = new Error().stack.split( '\n' )
      , extendingArgs   = [].slice.call( arguments )
      , Static          = ( extendingArgs.length === 2 ) ? extendingArgs.shift() : {}
      , Proto           = extendingArgs.shift()
      , modulePath
      , moduleName
      , pkg;

    // Get rid of the Error at the start
    stack.shift();

    if ( Reg.test( stack[ 1 ] ) ) {
        modulePath = RegExp.$1.split( path.sep );
        modulePath = modulePath.splice( 0, modulePath.length - 1 ).join( path.sep );
        pkg        = [ modulePath, 'package.json' ];
        moduleName = path.basename( modulePath );
    } else {
        throw new Error( 'Error loading module, unable to determine modules location and name.' );
    }

    if ( modules[ moduleName ] !== undefined ) {
        moduleDebug( 'Returning previously defined module ' + moduleName + '...' );
        return modules[ moduleName ];
    }

    moduleDebug( 'Setting up ' + moduleName + ' module from path ' + modulePath + '...' );
    if ( Static.extend ) {
        moduleDebug( 'You cannot override the extend() function provided by the CleverStack Module Class!' );
        delete Static.extend;
    }

    if ( fs.existsSync( pkg ) ) {
        moduleDebug( 'Loading ' + pkg + '...' );
        pkg = require( pkg );
    } else {
        pkg = false;
    }

    Proto._camelName = i.camelize( moduleName.replace( /\-/ig, '_' ), false );
    moduleDebug( 'Creating debugger with name ' + Proto._camelName + '...' );
    Proto.debug = require( 'debug' )( Proto._camelName );

    moduleDebug( 'Creating module class...' );
    var Klass = Module.callback( 'extend' )( Static, Proto )
      , instance = Klass.callback( 'newInstance' )( moduleName, modulePath, pkg );

    modules[ moduleName ] = instance;

    return instance;
}<commit_msg>fix(backgroundTasks): Only load tasks if clever-background-tasks is installed<commit_after>var injector    = require( 'injector' )
  , Class       = injector.getInstance( 'Class' )
  , path        = require( 'path' )
  , async       = require( 'async' )
  , fs          = require( 'fs' )
  , i           = require( 'i' )()
  , moduleDebug = require('debug')( 'Modules' )
  , config      = injector.getInstance( 'config' )
  , modules     = {}
  , Module;

Module = exports.Class = Class.extend(
{
    moduleFolders: [
        'exceptions',
        'classes',
        'models',
        'services',
        'controllers'
    ],

    injectableFolders: [
        'models',
        'controllers',
        'services'
    ],

    excludedFiles: [
        'index.js',
        'module.js',
        'Gruntfile.js',
        'package.json'
    ]
},
{
    name: null,

    config: null,

    path: null,

    pkg: null,

    paths: null,

    setup: function( _name, _path, _pkg ) {
        // Set our module name
        this.name = _name;

        // Set our config if there is any
        this.config = typeof config[ _name ] === 'object'
            ? config[ _name ]
            : {};

        // Set the modules location
        this.path = _path;

        // Set the modules package.json
        this.pkg = _pkg;

        // Allow some code to be executed before the main setup
        this.hook( 'preSetup' );

        // Add the modules path to our list of paths
        this.paths = [ _path ];

        // Check to see if clever-background-tasks is installed
        if ( config.bundledDependencies.indexOf( 'clever-background-tasks' ) ) {
            this.Class.moduleFolders.push( 'tasks' );
        }

        // Add our moduleFolders to the list of paths, and our injector paths
        this.Class.moduleFolders.forEach( this.proxy( 'addFolderToPath', injector ) );

        // Fire the preInit hook
        this.hook( 'preInit' );

        // Return no arguments to init
        return [];
    },

    hook: function( hookName ) {
        if ( typeof this[ hookName ] === 'function' ) {
            this.debug( 'calling ' + hookName + '() hook...' );

            // @TODO implement injector.injectSync() for use cases like this
            this[ hookName ]();
        }
    },

    addFolderToPath: function( injector, folder ) {
        var folderPath      = path.join( this.path, folder )
          , folders         = folder.split( '/' )
          , currentFolder   = null
          , rootFolder      = null
          , obj             = {}
          , lastFolder      = obj;

        while ( folders.length > 0 ) {
            currentFolder = folders.shift();
            if ( rootFolder === null ) {
                rootFolder = currentFolder;
                if ( this[ rootFolder ] !== undefined  ) {
                    lastFolder = obj = this[ rootFolder ];
                }
            } else {
                if ( lastFolder[ currentFolder ] === undefined ) {
                    lastFolder[ currentFolder ] = {};
                }
                lastFolder = lastFolder[ currentFolder ];
            }
        }

        this[ rootFolder ] = obj;
        this.paths.push( folderPath );
        injector._inherited.factoriesDirs.push( folderPath );
    },

    loadResources: function() {
        async.forEach(
            this.paths,
            this.proxy( 'inspectPathForResources' ),
            this.proxy( 'resourcesLoaded' )
        );
    },

    resourcesLoaded: function( err ) {
        this.debug( 'Resources Loaded' );
        this.emit( 'resourcesLoaded', err || null );
    },

    inspectPathForResources: function( pathToInspect, callback ) {
        var that = this;

        if ( fs.existsSync( pathToInspect + path.sep ) ) {
            fs.readdir( pathToInspect + path.sep, function( err, files ) {
                async.forEach( files, that.proxy( 'addResource', pathToInspect ), callback );
            });
        } else {
            callback( null );
        }
    },

    addResource: function( pathToInspect, file, callback ) {
        if ( file.match(/.+\.js$/g) !== null && this.Class.excludedFiles.indexOf( file ) === -1 ) {
            var folders         = pathToInspect.split( path.sep )
              , name            = file.replace( '.js', '' )
              , currentFolder   = null
              , insideModule    = false
              , rootFolder      = null
              , lastFolder      = this
              , that            = this
              , traceError      = new Error( 'Load Timeout for ' + file )
              , loadTimeout     = setTimeout( function() {
                    that.debug( traceError );
                    process.exit( 1 );
                }, 10000 )
              , resource;

            while ( folders.length > 0 ) {
                currentFolder = folders.shift();
                if ( insideModule === false && currentFolder === this.name ) {
                    // Make sure that this is the LAST instance of the name
                    if ( folders.indexOf( this.name ) === -1 ) {
                        insideModule = true;
                    }
                } else if ( insideModule === true ) {
                    if ( rootFolder === null ) {
                        rootFolder = currentFolder;
                        if ( this[ rootFolder ] !== undefined  ) {
                            lastFolder = this[ rootFolder ];
                        }
                    } else {
                        lastFolder = lastFolder[ currentFolder ];
                    }
                }
            }

            // Load the resource
            resource = require( [ pathToInspect, path.sep, file ].join( '' ) );

            // Do not load dependencies that can be injected
            if ( this.Class.injectableFolders.indexOf( rootFolder ) === -1 ) {

                if ( this.Class.injectableFolders.indexOf( name ) === -1 )  {
                    // Add the resource to the injector
                    if ( name !== 'routes' ) {
                        this.debug( 'Adding ' + name + ' to the injector' );
                        injector.instance( name, resource );
                    }

                    // Add the resource to the last object we found
                    lastFolder[ name ] = resource;
                    clearTimeout( loadTimeout );
                    callback( null );
                } else {
                    clearTimeout( loadTimeout );
                    callback( null );
                }
            } else {
                this.debug( 'Loading ' + name + ' using the injector...' );
                injector.inject( resource, function( resource ) {
                    injector.instance( name, resource );
                    lastFolder[ name ] = resource;
                    clearTimeout( loadTimeout );
                    callback( null );
                });
            }
        } else {
            callback( null );
        }
    },

    initRoutes: function() {
        if ( typeof this.routes === 'function' ) {
            this.debug( 'calling initRoutes() hook...' );
            injector.inject( this.routes );
        }
    }
});

exports.extend = function() {
    var Reg             = new RegExp( '.*\\(([^\\)]+)\\:.*\\:.*\\)', 'ig' )
      , stack           = new Error().stack.split( '\n' )
      , extendingArgs   = [].slice.call( arguments )
      , Static          = ( extendingArgs.length === 2 ) ? extendingArgs.shift() : {}
      , Proto           = extendingArgs.shift()
      , modulePath
      , moduleName
      , pkg;

    // Get rid of the Error at the start
    stack.shift();

    if ( Reg.test( stack[ 1 ] ) ) {
        modulePath = RegExp.$1.split( path.sep );
        modulePath = modulePath.splice( 0, modulePath.length - 1 ).join( path.sep );
        pkg        = [ modulePath, 'package.json' ];
        moduleName = path.basename( modulePath );
    } else {
        throw new Error( 'Error loading module, unable to determine modules location and name.' );
    }

    if ( modules[ moduleName ] !== undefined ) {
        moduleDebug( 'Returning previously defined module ' + moduleName + '...' );
        return modules[ moduleName ];
    }

    moduleDebug( 'Setting up ' + moduleName + ' module from path ' + modulePath + '...' );
    if ( Static.extend ) {
        moduleDebug( 'You cannot override the extend() function provided by the CleverStack Module Class!' );
        delete Static.extend;
    }

    if ( fs.existsSync( pkg ) ) {
        moduleDebug( 'Loading ' + pkg + '...' );
        pkg = require( pkg );
    } else {
        pkg = false;
    }

    Proto._camelName = i.camelize( moduleName.replace( /\-/ig, '_' ), false );
    moduleDebug( 'Creating debugger with name ' + Proto._camelName + '...' );
    Proto.debug = require( 'debug' )( Proto._camelName );

    moduleDebug( 'Creating module class...' );
    var Klass = Module.callback( 'extend' )( Static, Proto )
      , instance = Klass.callback( 'newInstance' )( moduleName, modulePath, pkg );

    modules[ moduleName ] = instance;

    return instance;
}
<|endoftext|>


<commit_before>var dom = require('./dom'),
    exec = require('./client-exec').exec,
    rewriteStack = require('./client-exec').rewriteStack,
    fs = require('fs'),
    jQuery = require('./fruit-loops'),
    path = require('path'),
    vm = require('vm');

module.exports = exports = function(options) {
  var host = options.host || 'localhost',
      callback = options.callback;

  var window = vm.createContext({
    $server: true,
    nextTick: function(callback) {
      process.nextTick(function() { exec(callback); });
    },

    navigator: {
      userAgent: options.userAgent
    },

    loadInContext: function(href, callback) {
      if (href && window.lumbarLoadPrefix) {
        // TODO : Make this more generic (i.e. don't expect a sha in there)
        href = path.relative(path.dirname(window.lumbarLoadPrefix), href);
        href = path.resolve(path.dirname(options.index) + '/web', href);
      }

      exec(function() {
        vm.runInContext(fs.readFileSync(href), window, href);
      });

      // TODO : Make this generic, i.e. allow names other than `Phoenix`
      if (window.Phoenix && !changeRegistered) {
        changeRegistered = true;
        window.Phoenix.on('emit', function() {
          setTimeout(function() {
            emit();
          }, 10);
        });
      }

      if (callback) {
        window.nextTick(callback);
      }
    }
  });
  window.self = window.window = window;

  dom.console(window);
  dom.document(window);
  dom.location(window, 'http://' + host + options.url.path);
  dom.history(window);
  dom.performance(window);
  dom.storage(window, 'localStorage');
  dom.storage(window, 'sessionStorage');

  var $ = jQuery(window, fs.readFileSync(options.index));
  window.jQuery = window.Zepto = window.$ = $.$;

  var changeRegistered,
      viewSet = false;

  function emit(force) {
    // TODO : Figure put the best way to handle output after send... Error? Ignore? Log?
    if (!callback) {
      console.log(rewriteStack(new Error().stack));//$.root.html());
      return;
    }

    // Inline any script content that we may have received
    $.$('body').append('<script>var $serverCache = ' + $.ajax.toJSON() + ';</script>');

    // Ensure sure that we have all of our script content and that it it at the end of the document
    // this has two benefits: the body element may be rendered to directly and this will push
    // all of the scripts after the content elements
    $.$('body').append(files);

    console.log('emit time: ' + (Date.now() - window.performance.timing.navigationStart));
    // And output the thing
    callback(undefined, $.root.html());
    callback = undefined;
  }

  var files = $.$('script');
  files.each(function() {
    var el = $.$(this),
        text = el.text(),
        external = el.attr('src');

    if (external) {
      window.loadInContext(external.replace(/\.js$/, '-server.js'));
    } else {
      exec(function() {
        vm.runInContext(text, window, text);
      });
    }
  });
};
<commit_msg>Update path reference<commit_after>var dom = require('./dom'),
    exec = require('./client-exec').exec,
    rewriteStack = require('./client-exec').rewriteStack,
    fs = require('fs'),
    jQuery = require('./jquery'),
    path = require('path'),
    vm = require('vm');

module.exports = exports = function(options) {
  var host = options.host || 'localhost',
      callback = options.callback;

  var window = vm.createContext({
    $server: true,
    nextTick: function(callback) {
      process.nextTick(function() { exec(callback); });
    },

    navigator: {
      userAgent: options.userAgent
    },

    loadInContext: function(href, callback) {
      if (href && window.lumbarLoadPrefix) {
        // TODO : Make this more generic (i.e. don't expect a sha in there)
        href = path.relative(path.dirname(window.lumbarLoadPrefix), href);
        href = path.resolve(path.dirname(options.index) + '/web', href);
      }

      exec(function() {
        vm.runInContext(fs.readFileSync(href), window, href);
      });

      // TODO : Make this generic, i.e. allow names other than `Phoenix`
      if (window.Phoenix && !changeRegistered) {
        changeRegistered = true;
        window.Phoenix.on('emit', function() {
          setTimeout(function() {
            emit();
          }, 10);
        });
      }

      if (callback) {
        window.nextTick(callback);
      }
    }
  });
  window.self = window.window = window;

  dom.console(window);
  dom.document(window);
  dom.location(window, 'http://' + host + options.url.path);
  dom.history(window);
  dom.performance(window);
  dom.storage(window, 'localStorage');
  dom.storage(window, 'sessionStorage');

  var $ = jQuery(window, fs.readFileSync(options.index));
  window.jQuery = window.Zepto = window.$ = $.$;

  var changeRegistered,
      viewSet = false;

  function emit(force) {
    // TODO : Figure put the best way to handle output after send... Error? Ignore? Log?
    if (!callback) {
      console.log(rewriteStack(new Error().stack));//$.root.html());
      return;
    }

    // Inline any script content that we may have received
    $.$('body').append('<script>var $serverCache = ' + $.ajax.toJSON() + ';</script>');

    // Ensure sure that we have all of our script content and that it it at the end of the document
    // this has two benefits: the body element may be rendered to directly and this will push
    // all of the scripts after the content elements
    $.$('body').append(files);

    console.log('emit time: ' + (Date.now() - window.performance.timing.navigationStart));
    // And output the thing
    callback(undefined, $.root.html());
    callback = undefined;
  }

  var files = $.$('script');
  files.each(function() {
    var el = $.$(this),
        text = el.text(),
        external = el.attr('src');

    if (external) {
      window.loadInContext(external.replace(/\.js$/, '-server.js'));
    } else {
      exec(function() {
        vm.runInContext(text, window, text);
      });
    }
  });
};
<|endoftext|>


<commit_before>var CloudCmd, Util, DOM, olark;

(function(CloudCmd, Util, DOM) {
    'use strict';

    CloudCmd.Contact = ContactProto;

    function ContactProto(pCallBack) {
        var Contact = this,
            Images  = DOM.Images,
            Key     = CloudCmd.Key,
            Inited  = false,
            DIR     = CloudCmd.LIBDIRCLIENT;

        function init(pCallBack) {
            if (!Inited) {
                Contact.show = show;
                Contact.hide = hide;

                load(function() {
                    Inited = true;

                    olark('api.box.onExpand',   Contact.show);
                    olark('api.box.onShow',     Contact.show);
                    olark('api.box.onHide',     Contact.hide);
                    olark('api.box.onShrink',   Contact.hide);

                    DOM.Events.addKey(listener);
                    Util.exec(pCallBack);
                });
            }
        }

        function load(callback) {
            var path = DIR + 'contact/olark.js';

            Images.showLoad({top: true});

            DOM.jsload(path, function() {
                Util.exec(callback);
            });
        }

        function show() {
            Key.unsetBind();
            Images.hide();

            if (Inited)
                olark('api.box.expand');
            else
                init(Contact.show);
        }

        function hide() {
            Key.setBind();

            if (Inited)
                olark('api.box.hide');
            else
                init(Contact.hide);
        }

        function listener(pEvent) {
            var ESC     = Key.ESC,
                isBind  = Key.isBind(),
                key     = pEvent.keyCode;

            if (!isBind && key === ESC)
                Contact.hide();
        }

        init(pCallBack);
    }

})(CloudCmd, Util, DOM);
<commit_msg>refactor(contact) init: pCallback -> callback<commit_after>var CloudCmd, Util, DOM, olark;

(function(CloudCmd, Util, DOM) {
    'use strict';

    CloudCmd.Contact = ContactProto;

    function ContactProto(pCallBack) {
        var Contact = this,
            Images  = DOM.Images,
            Key     = CloudCmd.Key,
            Inited  = false,
            DIR     = CloudCmd.LIBDIRCLIENT;

        function init(callback) {
            if (!Inited) {
                Contact.show = show;
                Contact.hide = hide;

                load(function() {
                    Inited = true;

                    olark('api.box.onExpand',   Contact.show);
                    olark('api.box.onShow',     Contact.show);
                    olark('api.box.onHide',     Contact.hide);
                    olark('api.box.onShrink',   Contact.hide);

                    DOM.Events.addKey(listener);
                    Util.exec(callback);
                });
            }
        }

        function load(callback) {
            var path = DIR + 'contact/olark.js';

            Images.showLoad({top: true});

            DOM.jsload(path, function() {
                Util.exec(callback);
            });
        }

        function show() {
            Key.unsetBind();
            Images.hide();

            if (Inited)
                olark('api.box.expand');
            else
                init(Contact.show);
        }

        function hide() {
            Key.setBind();

            if (Inited)
                olark('api.box.hide');
            else
                init(Contact.hide);
        }

        function listener(pEvent) {
            var ESC     = Key.ESC,
                isBind  = Key.isBind(),
                key     = pEvent.keyCode;

            if (!isBind && key === ESC)
                Contact.hide();
        }

        init(pCallBack);
    }

})(CloudCmd, Util, DOM);
<|endoftext|>