<commit_before>/**
 * Created by chengfulin on 2015/4/13.
 */
var varDefFactory = require('./vardeffactory'),
    defFactory = require('./deffactory'),
    dupairFactory = require('./dupairfactory'),
    pairFactory = require('./pairfactory'),
    AnalyzedCFG = require('./analyzedcfg'),
    ScopeWrapper = require('./scopewrapper'),
    FlowNode = require('../esgraph').FlowNode,
    Set = require('../analyses').Set,
    walkes = require('walkes'),
    worklist = require('../analyses'),
    Map = require('core-js/es6/map');

function DefUseAnalyzer() {
    "use strict";
}

/**
 * Get DUPairs of the CFG
 * @param analysisItem
 * @returns Map of DUPairs of each definitions, (key: def name, value: DUPair)
 * @constructor
 */
DefUseAnalyzer.prototype.findDUPairs = function (analysisItem) {
    'use strict';
    var dupairs = new Map();
    if (AnalyzedCFG.isAnalyzedCFG(analysisItem)) {
        analysisItem.cfg[2].forEach(function (node) {
            if (node.type === FlowNode.ENTRY_NODE_TYPE || node.type === FlowNode.EXIT_NODE_TYPE) {
                return;
            }
            var nodeCUse = getUsedDefs(node.reachIns, node.cuse),
                nodePUse = getUsedDefs(node.reachIns, node.puse);
            /// Initialization
            node.reachIns.values().forEach(function (elem) {
                var pairs = dupairs.get(elem.variable) || new Set();
                dupairs.set(elem.variable, pairs);
            });
            /// add Def-Use pairs of c-use
            nodeCUse.values().forEach(function (elem) {
                var pairs = dupairs.get(elem.variable);
                /// Assume each id of CFG nodes will be different
                pairs.add(dupairFactory.create(elem.definition.fromCFGNode, node));
                dupairs.set(elem.variable, pairs);
            });
            /// add Def-Use pairs of p-use
            nodePUse.values().forEach(function (elem) {
                var pairs = dupairs.get(elem.variable);
                /// Assume each id of CFG nodes will be different
                pairs.add(dupairFactory.create(elem.definition.fromCFGNode, pairFactory.create(node, node.true)));
                pairs.add(dupairFactory.create(elem.definition.fromCFGNode, pairFactory.create(node, node.false)));
                dupairs.set(elem.variable, pairs);
            });
        });
    }
    analysisItem.dupairs = dupairs;
};

/**
 * Get used definitions by getting the intersection of RD and USE
 * @param defs reaching definitions
 * @param used used definition names
 * @returns used definitions
 */
function getUsedDefs(defs, used) {
    'use strict';
    var usedDefs = new Set();
    if (defs instanceof Set && used instanceof Set) {
        defs.forEach(function (vardef) {
            used.forEach(function (variable) {
                if (vardef.variable === variable) {
                    usedDefs.add(vardef);
                }
            });
        });
    }
    return usedDefs;
}

DefUseAnalyzer.prototype.doAnalysis = function (analysisItem) {
    "use strict";
    var thisAnalyzer = this;
    if (AnalyzedCFG.isAnalyzedCFG(analysisItem)) {
        var reachDefinitions = worklist(analysisItem.cfg, function (input) { /// input = ReachIn(n)
            var currentNode = this;
            var kill = currentNode.kill || thisAnalyzer.findKILLSet(currentNode);
            /// GEN(n)
            var generate = currentNode.generate || thisAnalyzer.findGENSet(currentNode);
            /// Find VarDef of redefined Vars = KILL(n)
            var killSet = new Set();
            kill.forEach(function (killed) {
                input.values().forEach(function (elem) {
                    if (elem.variable === killed) {
                        killSet.add(elem);
                    }
                });
            });
            /// find Use(n)
            thisAnalyzer.findUSESet(currentNode);
            /// Return ReachOut(n)
            return Set.union(Set.minus(input, killSet), generate);
        }, {direction: 'forward', start: null});
        /// records
        reachDefinitions.inputs.forEach(function (varDefSet, node) {
            node.reachIns = new Set(varDefSet);
        });
        reachDefinitions.outputs.forEach(function (varDefSet, node) {
            node.reachOuts = new Set(varDefSet);
        });
    }
};

/**
 * Find set of Vars who are redefined
 * @param {FlowNode} cfgNode
 * @returns Set of variable whose definition was redefined in this node
 * @function
 */
DefUseAnalyzer.prototype.findKILLSet = function (cfgNode) {
    'use strict';
    var redefinedVars = new Set();
    if (FlowNode.isFlowNode(cfgNode) && ScopeWrapper.isScopeWrapper(cfgNode.scope)) {
        var currentScope = cfgNode.scope;
        if (cfgNode.type === FlowNode.EXIT_NODE_TYPE) {
            /// Let the ReachOut(Exit Node) excludes the local variables
            currentScope.vars.forEach(function (variable) {
                redefinedVars.add(variable);
            });
        } else if (cfgNode.type !== FlowNode.ENTRY_NODE_TYPE && !!cfgNode.astNode) {
            walkes(cfgNode.astNode, {/// Find one AST node in a CFG node at a time
                AssignmentExpression: function (node, recurse) {
                    var killedVar = (node.left.type === 'MemberExpression') ? currentScope.getVarByName(node.left.object.name) : currentScope.getVarByName(node.left.name);
                    if (!!killedVar) {
                        redefinedVars.add(killedVar);
                    }
                    if (node.right.type === 'AssignmentExpression' || node.right.type === 'UpdateExpression') {/// Sequential assignment
                        recurse(node.right);
                    }
                },
                UpdateExpression: function (node) {
                    var killedVar = currentScope.getVarByName(node.argument.name);
                    if (!!killedVar) {
                        redefinedVars.add(killedVar);
                    }
                },
                SwitchCase: function () {/*ignore AST nodes inside SwitchCase node*/}
            });
        }
        if (redefinedVars.size > 0) {
            cfgNode.kill = redefinedVars;
        }
    }
    return redefinedVars;
};

/**
 * Find GEN set
 * @param {FlowNode} cfgNode
 * @returns {Set}
 * @function
 */
DefUseAnalyzer.prototype.findGENSet = function (cfgNode) {
    'use strict';
    var generatedVarDef = new Set();
    if (FlowNode.isFlowNode(cfgNode) && ScopeWrapper.isScopeWrapper(cfgNode.scope)) {
        var currentScope = cfgNode.scope;
        if (cfgNode.type !== FlowNode.ENTRY_NODE_TYPE && !!cfgNode.astNode) {
            walkes(cfgNode.astNode, {
                AssignmentExpression: function (node, recurse) {
                    var definedVar = (node.left.type === 'MemberExpression') ? currentScope.getVarByName(node.left.object.name) : currentScope.getVarByName(node.left.name);
                    if (!!definedVar) {
                        if (node.right.type === 'FunctionExpression') {
                            generatedVarDef.add(
                                varDefFactory.create(
                                    definedVar,
                                    defFactory.createFunctionDef(
                                        cfgNode,
                                        node.right.range,
                                        currentScope.scope
                                    )
                                )
                            );
                        } else {
                            generatedVarDef.add(
                                varDefFactory.create(
                                    definedVar,
                                    defFactory.createLiteralDef(
                                        cfgNode,
                                        node.right.range,
                                        currentScope.scope
                                    )
                                )
                            );
                            if (node.right.type === 'AssignmentExpression' || node.right.type === 'UpdateExpression') {
                                recurse(node.right);
                            }
                        }
                    }
                },
                UpdateExpression: function (node) {
                    var definedVar = currentScope.getVarByName(node.argument.name);
                    if (!!definedVar) {
                        generatedVarDef.add(
                            varDefFactory.create(
                                definedVar,
                                defFactory.createLiteralDef(
                                    cfgNode,
                                    node.range,
                                    currentScope.scope
                                )
                            )
                        );
                    }
                },
                VariableDeclaration: function (node, recurse) {
                    node.declarations.forEach(function (declarator) {
                        recurse(declarator);
                    });
                },
                VariableDeclarator: function (node, recurse) {
                    var definedVar = currentScope.getVarByName(node.id.name);
                    if (!!definedVar) {
                        if (!!node.init) {
                            if (node.init.type === 'FunctionExpression') {
                                generatedVarDef.add(
                                    varDefFactory.create(
                                        definedVar,
                                        defFactory.createFunctionDef(
                                            cfgNode,
                                            node.init.range,
                                            currentScope.scope
                                        )
                                    )
                                );
                            } else {
                                generatedVarDef.add(
                                    varDefFactory.create(
                                        definedVar,
                                        defFactory.createLiteralDef(
                                            cfgNode,
                                            node.init.range,
                                            currentScope.scope
                                        )
                                    )
                                );

                                if (node.init.type === 'AssignmentExpression') {
                                    recurse(node.init);
                                }
                            }
                        }
                    }
                },
                SwitchCase: function () {/* ignore the SwitchCase node of AST */
                }
            });
        }
        if (generatedVarDef.size > 0) {
            cfgNode.generate = generatedVarDef;
        }
    }
    return generatedVarDef;
};

/**
 * Find set of variables who are used at this node
 * @param {FlowNode} cfgNode a node of CFG
 * @returns {Object} Object of sets of variable names used at this node
 * @function
 */
DefUseAnalyzer.prototype.findUSESet = function (cfgNode) {
    'use strict';
    var cuseVars = new Set(),
        puseVars = new Set(),
        isPUse = false;
    if (FlowNode.isFlowNode(cfgNode) && ScopeWrapper.isScopeWrapper(cfgNode.scope)) {
        var currentScope = cfgNode.scope;
        if (cfgNode.type !== FlowNode.ENTRY_NODE_TYPE && !!cfgNode.astNode) {
            walkes(cfgNode.astNode, {
                AssignmentExpression: function (node, recurse) {
                    if (node.right.type === 'AssignmentExpression') {
                        /// handle sequential assignment
                        recurse(node.right.left);
                    } else {
                        var selfAssignmentOp = ['+=', '-=', '*=', '/=', '%='];
                        if (selfAssignmentOp.indexOf(node.operator) !== -1) {
                            recurse(node.left);
                        }
                    }
                    recurse(node.right);
                },
                BinaryExpression: function (node, recurse) {
                    /// Both operand are used
                    if (!!cfgNode.true && !!cfgNode.false) {
                        isPUse = true;
                    }
                    recurse(node.left);
                    recurse(node.right);
                    isPUse = false;
                },
                CallExpression: function (node, recurse) {
                    if (!!cfgNode.true && !!cfgNode.false) {
                        isPUse = true;
                    }
                    recurse(node.callee);
                    /// for the function arguments
                    node.arguments.forEach(recurse);
                    isPUse = false;
                },
                VariableDeclaration: function (node, recurse) {
                    node.declarations.forEach(recurse);
                },
                VariableDeclarator: function (node, recurse) {
                    if (!!node.init && node.init.type === 'AssignmentExpression') {
                        /// e.g., var answer = var1 = var2;
                        /// USE = {var1, var2}
                        recurse(node.init.left);
                    }
                    recurse(node.init);
                },
                UpdateExpression: function (node, recurse) {
                    recurse(node.argument);
                },
                NewExpression: function (node, recurse) {
                    recurse(node.callee);
                },
                UnaryExpression: function (node, recurse) {
                    if (!!cfgNode.true && !!cfgNode.false) {
                        isPUse = true;
                    }
                    recurse(node.argument);
                    isPUse = false;
                },
                SwitchCase: function (node, recurse) {
                    isPUse = true;
                    /// handle expression in switch statement
                    if (!!node.test && !!cfgNode.parent && cfgNode.parent.type === 'SwitchStatement') {
                        recurse(cfgNode.parent.discriminant);
                    }
                },
                ConditionalExpression: function (node, recurse) {
                    isPUse = true;
                    recurse(node.test);
                    isPUse = false;
                    recurse(node.consequent);
                    recurse(node.alternate);
                },
                MemberExpression: function (node, recurse) {
                    recurse(node.object);
                },
                Identifier: function (node) {
                    /// Ignore statement with identifier only
                    if (cfgNode.astNode.type !== 'Identifier') {
                        var usedVar = currentScope.getVarByName(node.name);
                        if (!!usedVar) {
                            if (!isPUse) {
                                cuseVars.add(usedVar);
                            } else {
                                puseVars.add(usedVar);
                            }
                        }
                    }
                }
            });
        }
        if (cuseVars.size > 0 || puseVars.size > 0) {
            cfgNode.cuse = cuseVars;
            cfgNode.puse = puseVars;
        }
    }
    return {cuse: cuseVars, puse: puseVars};
};

/**
 * Find definitions of a variable from a set of VarDef
 * @param {Set} varDefSet
 * @param {Var} variable
 * @returns {Set}
 * @function
 */
DefUseAnalyzer.prototype.findDefSetByVar = function (varDefSet, variable) {
    "use strict";
    var defSet = new Set();
    if (varDefSet instanceof Set) {
        varDefSet.forEach(function (varDef) {
            if (varDef.variable === variable) {
                defSet.add(varDef.definition);
            }
        });
    }
    return defSet;
};

var singleton = new DefUseAnalyzer();
module.exports = singleton;<commit_msg>Arguments of CallExpression should be c-use<commit_after>/**
 * Created by chengfulin on 2015/4/13.
 */
var varDefFactory = require('./vardeffactory'),
    defFactory = require('./deffactory'),
    dupairFactory = require('./dupairfactory'),
    pairFactory = require('./pairfactory'),
    AnalyzedCFG = require('./analyzedcfg'),
    ScopeWrapper = require('./scopewrapper'),
    FlowNode = require('../esgraph').FlowNode,
    Set = require('../analyses').Set,
    walkes = require('walkes'),
    worklist = require('../analyses'),
    Map = require('core-js/es6/map');

function DefUseAnalyzer() {
    "use strict";
}

/**
 * Get DUPairs of the CFG
 * @param analysisItem
 * @returns Map of DUPairs of each definitions, (key: def name, value: DUPair)
 * @constructor
 */
DefUseAnalyzer.prototype.findDUPairs = function (analysisItem) {
    'use strict';
    var dupairs = new Map();
    if (AnalyzedCFG.isAnalyzedCFG(analysisItem)) {
        analysisItem.cfg[2].forEach(function (node) {
            if (node.type === FlowNode.ENTRY_NODE_TYPE || node.type === FlowNode.EXIT_NODE_TYPE) {
                return;
            }
            var nodeCUse = getUsedDefs(node.reachIns, node.cuse),
                nodePUse = getUsedDefs(node.reachIns, node.puse);
            /// Initialization
            node.reachIns.values().forEach(function (elem) {
                var pairs = dupairs.get(elem.variable) || new Set();
                dupairs.set(elem.variable, pairs);
            });
            /// add Def-Use pairs of c-use
            nodeCUse.values().forEach(function (elem) {
                var pairs = dupairs.get(elem.variable);
                /// Assume each id of CFG nodes will be different
                pairs.add(dupairFactory.create(elem.definition.fromCFGNode, node));
                dupairs.set(elem.variable, pairs);
            });
            /// add Def-Use pairs of p-use
            nodePUse.values().forEach(function (elem) {
                var pairs = dupairs.get(elem.variable);
                /// Assume each id of CFG nodes will be different
                pairs.add(dupairFactory.create(elem.definition.fromCFGNode, pairFactory.create(node, node.true)));
                pairs.add(dupairFactory.create(elem.definition.fromCFGNode, pairFactory.create(node, node.false)));
                dupairs.set(elem.variable, pairs);
            });
        });
    }
    analysisItem.dupairs = dupairs;
};

/**
 * Get used definitions by getting the intersection of RD and USE
 * @param defs reaching definitions
 * @param used used definition names
 * @returns used definitions
 */
function getUsedDefs(defs, used) {
    'use strict';
    var usedDefs = new Set();
    if (defs instanceof Set && used instanceof Set) {
        defs.forEach(function (vardef) {
            used.forEach(function (variable) {
                if (vardef.variable === variable) {
                    usedDefs.add(vardef);
                }
            });
        });
    }
    return usedDefs;
}

DefUseAnalyzer.prototype.doAnalysis = function (analysisItem) {
    "use strict";
    var thisAnalyzer = this;
    if (AnalyzedCFG.isAnalyzedCFG(analysisItem)) {
        var reachDefinitions = worklist(analysisItem.cfg, function (input) { /// input = ReachIn(n)
            var currentNode = this;
            var kill = currentNode.kill || thisAnalyzer.findKILLSet(currentNode);
            /// GEN(n)
            var generate = currentNode.generate || thisAnalyzer.findGENSet(currentNode);
            /// Find VarDef of redefined Vars = KILL(n)
            var killSet = new Set();
            kill.forEach(function (killed) {
                input.values().forEach(function (elem) {
                    if (elem.variable === killed) {
                        killSet.add(elem);
                    }
                });
            });
            /// find Use(n)
            thisAnalyzer.findUSESet(currentNode);
            /// Return ReachOut(n)
            return Set.union(Set.minus(input, killSet), generate);
        }, {direction: 'forward', start: null});
        /// records
        reachDefinitions.inputs.forEach(function (varDefSet, node) {
            node.reachIns = new Set(varDefSet);
        });
        reachDefinitions.outputs.forEach(function (varDefSet, node) {
            node.reachOuts = new Set(varDefSet);
        });
    }
};

/**
 * Find set of Vars who are redefined
 * @param {FlowNode} cfgNode
 * @returns Set of variable whose definition was redefined in this node
 * @function
 */
DefUseAnalyzer.prototype.findKILLSet = function (cfgNode) {
    'use strict';
    var redefinedVars = new Set();
    if (FlowNode.isFlowNode(cfgNode) && ScopeWrapper.isScopeWrapper(cfgNode.scope)) {
        var currentScope = cfgNode.scope;
        if (cfgNode.type === FlowNode.EXIT_NODE_TYPE) {
            /// Let the ReachOut(Exit Node) excludes the local variables
            currentScope.vars.forEach(function (variable) {
                redefinedVars.add(variable);
            });
        } else if (cfgNode.type !== FlowNode.ENTRY_NODE_TYPE && !!cfgNode.astNode) {
            walkes(cfgNode.astNode, {/// Find one AST node in a CFG node at a time
                AssignmentExpression: function (node, recurse) {
                    var killedVar = (node.left.type === 'MemberExpression') ? currentScope.getVarByName(node.left.object.name) : currentScope.getVarByName(node.left.name);
                    if (!!killedVar) {
                        redefinedVars.add(killedVar);
                    }
                    if (node.right.type === 'AssignmentExpression' || node.right.type === 'UpdateExpression') {/// Sequential assignment
                        recurse(node.right);
                    }
                },
                UpdateExpression: function (node) {
                    var killedVar = currentScope.getVarByName(node.argument.name);
                    if (!!killedVar) {
                        redefinedVars.add(killedVar);
                    }
                },
                SwitchCase: function () {/*ignore AST nodes inside SwitchCase node*/}
            });
        }
        if (redefinedVars.size > 0) {
            cfgNode.kill = redefinedVars;
        }
    }
    return redefinedVars;
};

/**
 * Find GEN set
 * @param {FlowNode} cfgNode
 * @returns {Set}
 * @function
 */
DefUseAnalyzer.prototype.findGENSet = function (cfgNode) {
    'use strict';
    var generatedVarDef = new Set();
    if (FlowNode.isFlowNode(cfgNode) && ScopeWrapper.isScopeWrapper(cfgNode.scope)) {
        var currentScope = cfgNode.scope;
        if (cfgNode.type !== FlowNode.ENTRY_NODE_TYPE && !!cfgNode.astNode) {
            walkes(cfgNode.astNode, {
                AssignmentExpression: function (node, recurse) {
                    var definedVar = (node.left.type === 'MemberExpression') ? currentScope.getVarByName(node.left.object.name) : currentScope.getVarByName(node.left.name);
                    if (!!definedVar) {
                        if (node.right.type === 'FunctionExpression') {
                            generatedVarDef.add(
                                varDefFactory.create(
                                    definedVar,
                                    defFactory.createFunctionDef(
                                        cfgNode,
                                        node.right.range,
                                        currentScope.scope
                                    )
                                )
                            );
                        } else {
                            generatedVarDef.add(
                                varDefFactory.create(
                                    definedVar,
                                    defFactory.createLiteralDef(
                                        cfgNode,
                                        node.right.range,
                                        currentScope.scope
                                    )
                                )
                            );
                            if (node.right.type === 'AssignmentExpression' || node.right.type === 'UpdateExpression') {
                                recurse(node.right);
                            }
                        }
                    }
                },
                UpdateExpression: function (node) {
                    var definedVar = currentScope.getVarByName(node.argument.name);
                    if (!!definedVar) {
                        generatedVarDef.add(
                            varDefFactory.create(
                                definedVar,
                                defFactory.createLiteralDef(
                                    cfgNode,
                                    node.range,
                                    currentScope.scope
                                )
                            )
                        );
                    }
                },
                VariableDeclaration: function (node, recurse) {
                    node.declarations.forEach(function (declarator) {
                        recurse(declarator);
                    });
                },
                VariableDeclarator: function (node, recurse) {
                    var definedVar = currentScope.getVarByName(node.id.name);
                    if (!!definedVar) {
                        if (!!node.init) {
                            if (node.init.type === 'FunctionExpression') {
                                generatedVarDef.add(
                                    varDefFactory.create(
                                        definedVar,
                                        defFactory.createFunctionDef(
                                            cfgNode,
                                            node.init.range,
                                            currentScope.scope
                                        )
                                    )
                                );
                            } else {
                                generatedVarDef.add(
                                    varDefFactory.create(
                                        definedVar,
                                        defFactory.createLiteralDef(
                                            cfgNode,
                                            node.init.range,
                                            currentScope.scope
                                        )
                                    )
                                );

                                if (node.init.type === 'AssignmentExpression') {
                                    recurse(node.init);
                                }
                            }
                        }
                    }
                },
                SwitchCase: function () {/* ignore the SwitchCase node of AST */
                }
            });
        }
        if (generatedVarDef.size > 0) {
            cfgNode.generate = generatedVarDef;
        }
    }
    return generatedVarDef;
};

/**
 * Find set of variables who are used at this node
 * @param {FlowNode} cfgNode a node of CFG
 * @returns {Object} Object of sets of variable names used at this node
 * @function
 */
DefUseAnalyzer.prototype.findUSESet = function (cfgNode) {
    'use strict';
    var cuseVars = new Set(),
        puseVars = new Set(),
        isPUse = false;
    if (FlowNode.isFlowNode(cfgNode) && ScopeWrapper.isScopeWrapper(cfgNode.scope)) {
        var currentScope = cfgNode.scope;
        if (cfgNode.type !== FlowNode.ENTRY_NODE_TYPE && !!cfgNode.astNode) {
            walkes(cfgNode.astNode, {
                AssignmentExpression: function (node, recurse) {
                    if (node.right.type === 'AssignmentExpression') {
                        /// handle sequential assignment
                        recurse(node.right.left);
                    } else {
                        var selfAssignmentOp = ['+=', '-=', '*=', '/=', '%='];
                        if (selfAssignmentOp.indexOf(node.operator) !== -1) {
                            recurse(node.left);
                        }
                    }
                    recurse(node.right);
                },
                BinaryExpression: function (node, recurse) {
                    /// Both operand are used
                    if (!!cfgNode.true && !!cfgNode.false) {
                        isPUse = true;
                    }
                    recurse(node.left);
                    recurse(node.right);
                    isPUse = false;
                },
                CallExpression: function (node, recurse) {
                    if (!!cfgNode.true && !!cfgNode.false) {
                        isPUse = true;
                    }
                    recurse(node.callee);
                    isPUse = false;
                    /// for the function arguments
                    node.arguments.forEach(recurse);
                },
                VariableDeclaration: function (node, recurse) {
                    node.declarations.forEach(recurse);
                },
                VariableDeclarator: function (node, recurse) {
                    if (!!node.init && node.init.type === 'AssignmentExpression') {
                        /// e.g., var answer = var1 = var2;
                        /// USE = {var1, var2}
                        recurse(node.init.left);
                    }
                    recurse(node.init);
                },
                UpdateExpression: function (node, recurse) {
                    recurse(node.argument);
                },
                NewExpression: function (node, recurse) {
                    recurse(node.callee);
                },
                UnaryExpression: function (node, recurse) {
                    if (!!cfgNode.true && !!cfgNode.false) {
                        isPUse = true;
                    }
                    recurse(node.argument);
                    isPUse = false;
                },
                SwitchCase: function (node, recurse) {
                    isPUse = true;
                    /// handle expression in switch statement
                    if (!!node.test && !!cfgNode.parent && cfgNode.parent.type === 'SwitchStatement') {
                        recurse(cfgNode.parent.discriminant);
                    }
                },
                ConditionalExpression: function (node, recurse) {
                    isPUse = true;
                    recurse(node.test);
                    isPUse = false;
                    recurse(node.consequent);
                    recurse(node.alternate);
                },
                MemberExpression: function (node, recurse) {
                    recurse(node.object);
                },
                Identifier: function (node) {
                    /// Ignore statement with identifier only
                    if (cfgNode.astNode.type !== 'Identifier') {
                        var usedVar = currentScope.getVarByName(node.name);
                        if (!!usedVar) {
                            if (!isPUse) {
                                cuseVars.add(usedVar);
                            } else {
                                puseVars.add(usedVar);
                            }
                        }
                    }
                }
            });
        }
        if (cuseVars.size > 0 || puseVars.size > 0) {
            cfgNode.cuse = cuseVars;
            cfgNode.puse = puseVars;
        }
    }
    return {cuse: cuseVars, puse: puseVars};
};

/**
 * Find definitions of a variable from a set of VarDef
 * @param {Set} varDefSet
 * @param {Var} variable
 * @returns {Set}
 * @function
 */
DefUseAnalyzer.prototype.findDefSetByVar = function (varDefSet, variable) {
    "use strict";
    var defSet = new Set();
    if (varDefSet instanceof Set) {
        varDefSet.forEach(function (varDef) {
            if (varDef.variable === variable) {
                defSet.add(varDef.definition);
            }
        });
    }
    return defSet;
};

var singleton = new DefUseAnalyzer();
module.exports = singleton;<|endoftext|>


<commit_before>/*! UIkit 2.24.3 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
!function(e){var t;window.UIkit&&(t=e(UIkit)),"function"==typeof define&&define.amd&&define("uikit-upload",["uikit"],function(){return t||e(UIkit)})}(function(e){"use strict";function t(o,a){function r(t,n){var o=new FormData,a=new XMLHttpRequest;if(n.before(n,t)!==!1){for(var r,i=0;r=t[i];i++)o.append(n.param,r);for(var l in n.params)o.append(l,n.params[l]);a.upload.addEventListener("progress",function(e){var t=e.loaded/e.total*100;n.progress(t,e)},!1),a.addEventListener("loadstart",function(e){n.loadstart(e)},!1),a.addEventListener("load",function(e){n.load(e)},!1),a.addEventListener("loadend",function(e){n.loadend(e)},!1),a.addEventListener("error",function(e){n.error(e)},!1),a.addEventListener("abort",function(e){n.abort(e)},!1),a.open(n.method,n.action,!0),"json"==n.type&&a.setRequestHeader("Accept","application/json"),a.onreadystatechange=function(){if(n.readystatechange(a),4==a.readyState){var t=a.responseText;if("json"==n.type)try{t=e.$.parseJSON(t)}catch(o){t=!1}n.complete(t,a)}},n.beforeSend(a),a.send(o)}}if(!e.support.ajaxupload)return this;if(a=e.$.extend({},t.defaults,a),o.length){if("*.*"!==a.allow)for(var i,l=0;i=o[l];l++)if(!n(a.allow,i.name))return"string"==typeof a.notallowed?alert(a.notallowed):a.notallowed(i,a),void 0;var s=a.complete;if(a.single){var d=o.length,f=0,p=!0;a.beforeAll(o),a.complete=function(e,t){f+=1,s(e,t),a.filelimit&&f>=a.filelimit&&(p=!1),p&&d>f?r([o[f]],a):a.allcomplete(e,t)},r([o[0]],a)}else a.complete=function(e,t){s(e,t),a.allcomplete(e,t)},r(o,a)}}function n(e,t){var n="^"+e.replace(/\//g,"\\/").replace(/\*\*/g,"(\\/[^\\/]+)*").replace(/\*/g,"[^\\/]+").replace(/((?!\\))\?/g,"$1.")+"$";return n="^"+n+"$",null!==t.match(new RegExp(n,"i"))}return e.component("uploadSelect",{init:function(){var e=this;this.on("change",function(){t(e.element[0].files,e.options);var n=e.element.clone(!0).data("uploadSelect",e);e.element.replaceWith(n),e.element=n})}}),e.component("uploadDrop",{defaults:{dragoverClass:"uk-dragover"},init:function(){var e=this,n=!1;this.on("drop",function(n){n.dataTransfer&&n.dataTransfer.files&&(n.stopPropagation(),n.preventDefault(),e.element.removeClass(e.options.dragoverClass),e.element.trigger("dropped.uk.upload",[n.dataTransfer.files]),t(n.dataTransfer.files,e.options))}).on("dragenter",function(e){e.stopPropagation(),e.preventDefault()}).on("dragover",function(t){t.stopPropagation(),t.preventDefault(),n||(e.element.addClass(e.options.dragoverClass),n=!0)}).on("dragleave",function(t){t.stopPropagation(),t.preventDefault(),e.element.removeClass(e.options.dragoverClass),n=!1})}}),e.support.ajaxupload=function(){function e(){var e=document.createElement("INPUT");return e.type="file","files"in e}function t(){var e=new XMLHttpRequest;return!!(e&&"upload"in e&&"onprogress"in e.upload)}function n(){return!!window.FormData}return e()&&t()&&n()}(),e.support.ajaxupload&&e.$.event.props.push("dataTransfer"),t.defaults={action:"",single:!0,method:"POST",param:"files[]",params:{},allow:"*.*",type:"text",filelimit:!1,before:function(){},beforeSend:function(){},beforeAll:function(){},loadstart:function(){},load:function(){},loadend:function(){},error:function(){},abort:function(){},progress:function(){},complete:function(){},allcomplete:function(){},readystatechange:function(){},notallowed:function(e,t){alert("Only the following file types are allowed: "+t.allow)}},e.Utils.xhrupload=t,t});<commit_msg>UIkit 2.26.2<commit_after>/*! UIkit 2.26.2 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
!function(e){var t;window.UIkit&&(t=e(UIkit)),"function"==typeof define&&define.amd&&define("uikit-upload",["uikit"],function(){return t||e(UIkit)})}(function(e){"use strict";function t(o,a){function r(t,n){var o=new FormData,a=new XMLHttpRequest;if(n.before(n,t)!==!1){for(var r,i=0;r=t[i];i++)o.append(n.param,r);for(var l in n.params)o.append(l,n.params[l]);a.upload.addEventListener("progress",function(e){var t=e.loaded/e.total*100;n.progress(t,e)},!1),a.addEventListener("loadstart",function(e){n.loadstart(e)},!1),a.addEventListener("load",function(e){n.load(e)},!1),a.addEventListener("loadend",function(e){n.loadend(e)},!1),a.addEventListener("error",function(e){n.error(e)},!1),a.addEventListener("abort",function(e){n.abort(e)},!1),a.open(n.method,n.action,!0),"json"==n.type&&a.setRequestHeader("Accept","application/json"),a.onreadystatechange=function(){if(n.readystatechange(a),4==a.readyState){var t=a.responseText;if("json"==n.type)try{t=e.$.parseJSON(t)}catch(o){t=!1}n.complete(t,a)}},n.beforeSend(a),a.send(o)}}if(!e.support.ajaxupload)return this;if(a=e.$.extend({},t.defaults,a),o.length){if("*.*"!==a.allow)for(var i,l=0;i=o[l];l++)if(!n(a.allow,i.name))return"string"==typeof a.notallowed?alert(a.notallowed):a.notallowed(i,a),void 0;var s=a.complete;if(a.single){var d=o.length,f=0,p=!0;a.beforeAll(o),a.complete=function(e,t){f+=1,s(e,t),a.filelimit&&f>=a.filelimit&&(p=!1),p&&d>f?r([o[f]],a):a.allcomplete(e,t)},r([o[0]],a)}else a.complete=function(e,t){s(e,t),a.allcomplete(e,t)},r(o,a)}}function n(e,t){var n="^"+e.replace(/\//g,"\\/").replace(/\*\*/g,"(\\/[^\\/]+)*").replace(/\*/g,"[^\\/]+").replace(/((?!\\))\?/g,"$1.")+"$";return n="^"+n+"$",null!==t.match(new RegExp(n,"i"))}return e.component("uploadSelect",{init:function(){var e=this;this.on("change",function(){t(e.element[0].files,e.options);var n=e.element.clone(!0).data("uploadSelect",e);e.element.replaceWith(n),e.element=n})}}),e.component("uploadDrop",{defaults:{dragoverClass:"uk-dragover"},init:function(){var e=this,n=!1;this.on("drop",function(n){n.dataTransfer&&n.dataTransfer.files&&(n.stopPropagation(),n.preventDefault(),e.element.removeClass(e.options.dragoverClass),e.element.trigger("dropped.uk.upload",[n.dataTransfer.files]),t(n.dataTransfer.files,e.options))}).on("dragenter",function(e){e.stopPropagation(),e.preventDefault()}).on("dragover",function(t){t.stopPropagation(),t.preventDefault(),n||(e.element.addClass(e.options.dragoverClass),n=!0)}).on("dragleave",function(t){t.stopPropagation(),t.preventDefault(),e.element.removeClass(e.options.dragoverClass),n=!1})}}),e.support.ajaxupload=function(){function e(){var e=document.createElement("INPUT");return e.type="file","files"in e}function t(){var e=new XMLHttpRequest;return!!(e&&"upload"in e&&"onprogress"in e.upload)}function n(){return!!window.FormData}return e()&&t()&&n()}(),e.support.ajaxupload&&e.$.event.props.push("dataTransfer"),t.defaults={action:"",single:!0,method:"POST",param:"files[]",params:{},allow:"*.*",type:"text",filelimit:!1,before:function(){},beforeSend:function(){},beforeAll:function(){},loadstart:function(){},load:function(){},loadend:function(){},error:function(){},abort:function(){},progress:function(){},complete:function(){},allcomplete:function(){},readystatechange:function(){},notallowed:function(e,t){alert("Only the following file types are allowed: "+t.allow)}},e.Utils.xhrupload=t,t});
<|endoftext|>


<commit_before>/*! [replace-name] v[replace-version] */
/***************************************************************************************************************************************************************
 *
 * footer function
 *
 * Footers help users who reach the bottom of a page without finding what they want.
 *
 **************************************************************************************************************************************************************/

import React from 'react';
import PropTypes from 'prop-types';

// The following line will be replaced automatically with generic imports for the ES5 pipeline.
// You can safely ignore this bit if you use this module with pancake
//
// [replace-imports]

/**
 * DEFAULT
 * The label component
 *
 * @param  {string}  text            - Text of the label, required
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} inline           - Display the label inline, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUlabel = ({ text, dark, inline, className = '', ...attributeOptions }) => (
	<label
		className={ `au-label ${ className }` +
		`${ dark ? ' au-label--dark' : '' }` +
		`${ inline ? ' au-label--inline' : ''}`
		}
		{ ...attributeOptions }
	>
    { text }

);

AUlabel.propTypes = {
	title: PropTypes.string.isRequired,
	dark: PropTypes.bool,
	inline: PropTypes.bool,
	className: PropTypes.string,
};

/**
 * DEFAULT
 * The hint text component
 *
 * @param  {string}  text            - Text of the label, required
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUhintText = ({ text, dark,  className = '', ...attributeOptions }) => (
	<span className={ `au-hint-text ${ className }` + `${ dark ? ' au-hint-text--dark' : '' }`
		}
		{ ...attributeOptions }
	>
    { text }

);

AUhintText.propTypes = {
	title: PropTypes.string.isRequired,
	dark: PropTypes.bool,
	className: PropTypes.string,
};

/**
 * The error text component
 *
 * @param  {string}  title            - Title of the label, required
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUerrorText = ({ text, dark, inline, className = '', ...attributeOptions }) => (
	<span
		className={ `au-error-text ${ className }` +
		`${ dark ? ' au-error-text--dark' : '' }` +
		`${ inline ? ' au-error-text--inline' : '' }`
		}
		{ ...attributeOptions }
	>
	{ text }

);

AUerrorText.propTypes = {
	dark: PropTypes.bool,
	title: PropTypes.string.isRequired,
	className: PropTypes.string,
};

/**
 * The form group component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUformGroup = ({ status, dark, className = '', ...attributeOptions }) => (
	<div
		className={ `au-form-group ${ className }` +
		`${ dark ? ' au-form-group--dark' : '' }` +
		`${ status === 'invalid' ? 'au-form-group--invalid ' : ' '}`
		}
		{ ...attributeOptions }
	>

);

AUformGroup.propTypes = {
	status: PropTypes.oneOf(['valid', 'invalid']),
	dark: PropTypes.bool,
	className: PropTypes.string,
};

AUformGroup.defaultProps = {
	status: "valid"
}

/**
 * The fieldset component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUfieldset = ({ dark, className = '', ...attributeOptions }) => (
	<fieldset
		className={ `au-fieldset ${ className }` +
		`${ dark ? ' au-fieldset--dark' : '' }`
		}
		{ ...attributeOptions }
	>

	</fieldset>
);

AUfieldset.propTypes = {
	dark: PropTypes.bool,
	className: PropTypes.string,
};

/**
 * The form component wrapper
 *
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUForm = ({...attributeOptions }) => (
	<form { ...attributeOptions } ></form>
);
<commit_msg>change react prop from title to text<commit_after>/*! [replace-name] v[replace-version] */
/***************************************************************************************************************************************************************
 *
 * footer function
 *
 * Footers help users who reach the bottom of a page without finding what they want.
 *
 **************************************************************************************************************************************************************/

import React from 'react';
import PropTypes from 'prop-types';

// The following line will be replaced automatically with generic imports for the ES5 pipeline.
// You can safely ignore this bit if you use this module with pancake
//
// [replace-imports]

/**
 * DEFAULT
 * The label component
 *
 * @param  {string}  text            - Text of the label, required
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} inline           - Display the label inline, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUlabel = ({ text, dark, inline, className = '', ...attributeOptions }) => (
	<label
		className={ `au-label ${ className }` +
		`${ dark ? ' au-label--dark' : '' }` +
		`${ inline ? ' au-label--inline' : ''}`
		}
		{ ...attributeOptions }
	>
    { text }

);

AUlabel.propTypes = {
	text: PropTypes.string.isRequired,
	dark: PropTypes.bool,
	inline: PropTypes.bool,
	className: PropTypes.string,
};

/**
 * DEFAULT
 * The hint text component
 *
 * @param  {string}  text            - Text of the label, required
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUhintText = ({ text, dark,  className = '', ...attributeOptions }) => (
	<span className={ `au-hint-text ${ className }` + `${ dark ? ' au-hint-text--dark' : '' }`
		}
		{ ...attributeOptions }
	>
    { text }

);

AUhintText.propTypes = {
	text: PropTypes.string.isRequired,
	dark: PropTypes.bool,
	className: PropTypes.string,
};

/**
 * The error text component
 *
 * @param  {string}  text            - Text of the label, required
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUerrorText = ({ text, dark, inline, className = '', ...attributeOptions }) => (
	<span
		className={ `au-error-text ${ className }` +
		`${ dark ? ' au-error-text--dark' : '' }` +
		`${ inline ? ' au-error-text--inline' : '' }`
		}
		{ ...attributeOptions }
	>
	{ text }

);

AUerrorText.propTypes = {
	dark: PropTypes.bool,
	text: PropTypes.string.isRequired,
	className: PropTypes.string,
};

/**
 * The form group component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUformGroup = ({ status, dark, className = '', ...attributeOptions }) => (
	<div
		className={ `au-form-group ${ className }` +
		`${ dark ? ' au-form-group--dark' : '' }` +
		`${ status === 'invalid' ? 'au-form-group--invalid ' : ' '}`
		}
		{ ...attributeOptions }
	>

);

AUformGroup.propTypes = {
	status: PropTypes.oneOf(['valid', 'invalid']),
	dark: PropTypes.bool,
	className: PropTypes.string,
};

AUformGroup.defaultProps = {
	status: "valid"
}

/**
 * The fieldset component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUfieldset = ({ dark, className = '', ...attributeOptions }) => (
	<fieldset
		className={ `au-fieldset ${ className }` +
		`${ dark ? ' au-fieldset--dark' : '' }`
		}
		{ ...attributeOptions }
	>

	</fieldset>
);

AUfieldset.propTypes = {
	dark: PropTypes.bool,
	className: PropTypes.string,
};

/**
 * The form component wrapper
 *
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUForm = ({...attributeOptions }) => (
	<form { ...attributeOptions } ></form>
);
<|endoftext|>


<commit_before>(function() {
    'use strict';
    angular.module('mwCollection', []).run([
        '$http',
        function($http) {
            Backbone.ajax = Bikini.ajax = function(options) {
                // Ignore notifications for given response codes
				if (options.data) {
					var requestData = JSON.parse(options.data);
					options.ignoreHandleResponseCodes = requestData.ignoreHandleResponseCodes;
				}
                // Set HTTP Verb as 'method'
                options.method = options.type;

                // Set headers
                options.headers  = {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                };
                // Use angulars $http implementation for requests
                return $http.apply(angular, [options]).success(options.success).error(options.error);
            };
        }
    ]).factory('MwCollection', [
        'MwModel',
        function(MwModel) {
            return Bikini.Collection.extend({
                model: MwModel,
                parse: function(response) {
                    this.total = response.length;
                    return response;
                }
            });
        }
    ]).factory('MwModel', [
        '$rootScope',
        function($rootScope) {
            return Bikini.Model.extend({
                idAttribute: 'uuid',
                initialize: function() {
                    // When a model gets removed, make sure to decrement the total count on the collection
                    this.on('destroy', function() {
                        if (this.collection.total && this.collection.total > 0) {
                            this.collection.total--;
                        }
                    }, this);
                },
                set: function() {
                    var callSet = Backbone.Model.prototype.set.apply(this, arguments);
                    // Trigger digest cycle to make calls to set recognizable by angular
                    if (!$rootScope.$$phase) {
                        $rootScope.$apply();
                    }
                    return callSet;
                },
                selected: false,
                toggleSelect: function() {
                    if (!this.selectDisabled()) {
                        this.selected = !this.selected;
                    }
                },
                selectDisabled: function() {
                    return false;
                }
            });
        }
    ]);
}());
<commit_msg>remove unused functions<commit_after>(function() {
    'use strict';
    angular.module('mwCollection', []).run([
        '$http',
        function($http) {
            Backbone.ajax = Bikini.ajax = function(options) {
                // Ignore notifications for given response codes
				if (options.data) {
					var requestData = JSON.parse(options.data);
					options.ignoreHandleResponseCodes = requestData.ignoreHandleResponseCodes;
				}
                // Set HTTP Verb as 'method'
                options.method = options.type;

                // Set headers
                options.headers  = {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                };
                // Use angulars $http implementation for requests
                return $http.apply(angular, [options]).success(options.success).error(options.error);
            };
        }
    ]).factory('MwCollection', [
        'MwModel',
        function(MwModel) {
            return Bikini.Collection.extend({
                model: MwModel
            });
        }
    ]).factory('MwModel', [
        '$rootScope',
        function($rootScope) {
            return Bikini.Model.extend({
                idAttribute: '_id',
                set: function() {
                    var callSet = Backbone.Model.prototype.set.apply(this, arguments);
                    // Trigger digest cycle to make calls to set recognizable by angular
                    if (!$rootScope.$$phase) {
                        $rootScope.$apply();
                    }
                    return callSet;
                }
            });
        }
    ]);
}());
<|endoftext|>


<commit_before>import {parse} from 'acorn'
import {simple, base} from 'acorn/dist/walk'

import {pack, unpack} from '../packing'

/**
 * A Javascript context
 *
 * Implements the Stencila `Context` API. All methods return a Promise.
 */
class JsContext {

  /**
   * Run JavaScript code within the global context scope (execute a code "chunk")
   *
   * In languages like R and Python it it straight forward to assign global variables
   *
   * @param {string} code Javascript code
   * @param {object} options - Any execution options
   * @return {object} - A Promise resolving to object with any `errors` (an object with line numbers as keys) and `outputs` (
   *                         a data package)
   *
   * @example
   *
   * // You can also assign global variables which are available in subsequent calls,
   * context.call('foo = "bar"\n\n') // { errors: {}, output: null }
   * context.call('foo') // { errors: {}, output: { type: 'str', format: 'text', value: 'bar' } }
   */
  run (code, options) {
    code = code || ''
    options = options || {}
    if (options.pack !== false) options.pack = true

    let error = null

    // Create a function and execute it
    try {
      (new Function(code))() // eslint-disable-line no-new-func
    } catch (e) {
      // Catch any error
      error = e
    }

    let value
    if (!error) {
      // Evaluate the last line, and if any error then undefined result
      // This is inefficient in the sense that the last line is evaluated twice
      // but it anything else would appear to require some code parsing
      let lines = code.split('\n')
      let last = lines[lines.length - 1]
      try {
        value = (new Function('return ' + last))() // eslint-disable-line no-new-func
      } catch (error) {
        value = undefined
      }
    }

    return this._result(error, 0, value, options.pack)
  }

  /**
   * Execute JavaScript code within a local function scope (execute a code "cell")
   *
   * @param {string} code - Javascript code
   * @param {object} inputs - An object with a data pack for each input variable
   * @param {object} options - Any execution options
   * @return {object} - A Promise resolving to an object with any `errors` (an object with line numbers as keys) and `outputs` (
   *                         a data package)
   *
   * @example
   *
   * // Return statement must be used to return a value
   * context.call('return 6*7') // { errors: {}, output: { type: 'int', format: 'text', value: '42' } }
   * context.call('let x = 6\nreturn x*7') // { errors: {}, output: { type: 'int', format: 'text', value: '42' } }
   *
   * // You can specify input variables (that are local to that call),
   * context.call('return Math.PI*radius', {radius:{type:'flt', format:'text', value: '21.4'}}) // { errors: {}, output: { type: 'flt', format: 'text', value: '67.23008278682157' } }
   * context.call('return radius') // { errors: { '1': 'ReferenceError: radius is not defined' }, output: null }
   */
  call (code, inputs, options) {
    code = code || ''
    inputs = inputs || {}
    options = options || {}
    if (options.pack !== false) options.pack = true

    let error = null

    // Add inputs to `locals` i.e. the execution's local scope
    let locals = {}
    for (let name in inputs) {
      locals[name] = unpack(inputs[name])
    }

    // Generate a function body. The [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
    // prevents errors during `buble.transform` associated with any return statements (which must be within a func)
    let body = '(function(){\n' + code + '\n})()'

    // Create a function to be executed with locals
    let value
    try {
      value = (new Function('locals', 'with(locals){ return ' + body + '}'))(locals) // eslint-disable-line no-new-func
    } catch (e) {
      // Catch any error
      error = e
    }

    return this._result(error, 2, value, options.pack)
  }

  /**
   * Determine the dependencies for a piece of Javascript code
   *
   * Returns an array of all variable names not declared within
   * the piece of code. This might include global functions.
   *
   * @param  {string} code - JavaScript code
   * @return {array<string>} - A Promise resolving to a list of dependencies
   */
  depends (code) {
    let names = {}
    let ast = parse(code)
    simple(ast, {
      Identifier: node => {
        let name = node.name
        names[name] = Object.assign(names[name] || {}, {used: true})
      },
      VariableDeclarator: node => {
        let name = node.id.name
        names[name] = Object.assign(names[name] || {}, {declared: true})
      }
    }, base)
    let depends = []
    for (let name in names) {
      let usage = names[name]
      if (usage.used && !usage.declared) depends.push(name)
    }
    return Promise.resolve(depends)
  }

  /**
   * Return a result promise
   *
   * @param {object} error - Error object, if any
   * @param {int} offset - Line number offset
   * @param {object} value - The value to be packed
   * @param {boolean} packed - Should the output be packed (or left unpacked for calls withing Javascript)
   * @return {null|object} - A set of errors by line number
   */
  _result (error, offset, value, packed) {
    if (packed !== false) packed = true

    let errors = null
    if (error) {
      // Parse the error stack to get message and line number
      let lines = error.stack.split('\n')
      let message = lines[0]
      let match = lines[1].match(/<anonymous>:(\d+):\d+/)
      let line = 0
      if (match) line = parseInt(match[1]) - 1 - offset
      errors = {}
      errors[line] = message
    }

    if (value === undefined) {
      return Promise.resolve({
        errors: errors,
        output: null
      })
    } else if (packed) {
      return Promise.resolve(pack(value)).then(pack => {
        return {
          errors: errors,
          output: pack
        }
      })
    } else {
      return Promise.resolve({
        errors: errors,
        output: value
      })
    }
  }

}

export default JsContext
<commit_msg>Simplify because pack function is no longer async<commit_after>import {parse} from 'acorn'
import {simple, base} from 'acorn/dist/walk'

import {pack, unpack} from '../packing'

/**
 * A Javascript context
 *
 * Implements the Stencila `Context` API. All methods return a Promise.
 */
export default class JsContext {

  /**
   * Run JavaScript code within the global context scope (execute a code "chunk")
   *
   * In languages like R and Python it it straight forward to assign global variables
   *
   * @param {string} code Javascript code
   * @param {object} options - Any execution options
   * @return {object} - A Promise resolving to object with any `errors` (an object with line numbers as keys) and `outputs` (
   *                         a data package)
   *
   * @example
   *
   * // You can also assign global variables which are available in subsequent calls,
   * context.call('foo = "bar"\n\n') // { errors: {}, output: null }
   * context.call('foo') // { errors: {}, output: { type: 'str', format: 'text', value: 'bar' } }
   */
  run (code, options) {
    code = code || ''
    options = options || {}
    if (options.pack !== false) options.pack = true

    let error = null

    // Create a function and execute it
    try {
      (new Function(code))() // eslint-disable-line no-new-func
    } catch (e) {
      // Catch any error
      error = e
    }

    let value
    if (!error) {
      // Evaluate the last line, and if any error then undefined result
      // This is inefficient in the sense that the last line is evaluated twice
      // but it anything else would appear to require some code parsing
      let lines = code.split('\n')
      let last = lines[lines.length - 1]
      try {
        value = (new Function('return ' + last))() // eslint-disable-line no-new-func
      } catch (error) {
        value = undefined
      }
    }

    return Promise.resolve(
      this._result(error, 0, value, options.pack)
    )
  }

  /**
   * Execute JavaScript code within a local function scope (execute a code "cell")
   *
   * @param {string} code - Javascript code
   * @param {object} inputs - An object with a data pack for each input variable
   * @param {object} options - Any execution options
   * @return {object} - A Promise resolving to an object with any `errors` (an object with line numbers as keys) and `outputs` (
   *                         a data package)
   *
   * @example
   *
   * // Return statement must be used to return a value
   * context.call('return 6*7') // { errors: {}, output: { type: 'int', format: 'text', value: '42' } }
   * context.call('let x = 6\nreturn x*7') // { errors: {}, output: { type: 'int', format: 'text', value: '42' } }
   *
   * // You can specify input variables (that are local to that call),
   * context.call('return Math.PI*radius', {radius:{type:'flt', format:'text', value: '21.4'}}) // { errors: {}, output: { type: 'flt', format: 'text', value: '67.23008278682157' } }
   * context.call('return radius') // { errors: { '1': 'ReferenceError: radius is not defined' }, output: null }
   */
  call (code, inputs, options) {
    code = code || ''
    inputs = inputs || {}
    options = options || {}
    if (options.pack !== false) options.pack = true

    let error = null

    // Add inputs to `locals` i.e. the execution's local scope
    let locals = {}
    for (let name in inputs) {
      locals[name] = unpack(inputs[name])
    }

    // Generate a function body. The [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
    // prevents errors during `buble.transform` associated with any return statements (which must be within a func)
    let body = '(function(){\n' + code + '\n})()'

    // Create a function to be executed with locals
    let value
    try {
      value = (new Function('locals', 'with(locals){ return ' + body + '}'))(locals) // eslint-disable-line no-new-func
    } catch (e) {
      // Catch any error
      error = e
    }

    return Promise.resolve(
      this._result(error, 2, value, options.pack)
    )
  }

  /**
   * Determine the dependencies for a piece of Javascript code
   *
   * Returns an array of all variable names not declared within
   * the piece of code. This might include global functions.
   *
   * @param  {string} code - JavaScript code
   * @return {array<string>} - A Promise resolving to a list of dependencies
   */
  depends (code) {
    let names = {}
    let ast = parse(code)
    simple(ast, {
      Identifier: node => {
        let name = node.name
        names[name] = Object.assign(names[name] || {}, {used: true})
      },
      VariableDeclarator: node => {
        let name = node.id.name
        names[name] = Object.assign(names[name] || {}, {declared: true})
      }
    }, base)
    let depends = []
    for (let name in names) {
      let usage = names[name]
      if (usage.used && !usage.declared) depends.push(name)
    }
    return Promise.resolve(depends)
  }

  /**
   * Return a result promise
   *
   * @param {object} error - Error object, if any
   * @param {int} offset - Line number offset
   * @param {object} value - The value to be packed
   * @param {boolean} packed - Should the output be packed (or left unpacked for calls withing Javascript)
   * @return {null|object} - A set of errors by line number
   */
  _result (error, offset, value, packed) {
    if (packed !== false) packed = true

    let errors = null
    if (error) {
      // Parse the error stack to get message and line number
      let lines = error.stack.split('\n')
      let message = lines[0]
      let match = lines[1].match(/<anonymous>:(\d+):\d+/)
      let line = 0
      if (match) line = parseInt(match[1]) - 1 - offset
      errors = {}
      errors[line] = message
    }

    let output
    if (value === undefined) output = null
    else if (packed) output = pack(value)
    else output = value

    return {
      errors: errors,
      output: output
    }
  }

}
<|endoftext|>


<commit_before>import keyMirror from 'keymirror';

module.exports = keyMirror({
  ANSWERS_LOAD: null,
  ANSWERS_LOAD_FOR_TYPE: null,
  MISSIONS_LOAD: null,
  TASKS_LOAD: null,
  USER_LOAD: null,
  USER_BADGES: null,
  USER_LOGOUT: null,
  USER_UPDATE: null,
  USER_VERIFY: null,
  VALIDATIONS_LOAD: null,
});
<commit_msg>structurize ActionTypes<commit_after>import keyMirror from 'keymirror';

module.exports = keyMirror({
  // Answer
  ANSWERS_LOAD: null,
  ANSWERS_LOAD_FOR_TYPE: null,
  // Mission
  MISSIONS_LOAD: null,
  // Task
  TASKS_LOAD: null,
  // User
  USER_LOAD: null,
  USER_BADGES: null,
  USER_LOGOUT: null,
  USER_UPDATE: null,
  USER_VERIFY: null,
  // Validation
  VALIDATIONS_LOAD: null,
});
<|endoftext|>


<commit_before>/** @fileoverview
  * This tool deletes a config from a PostgreSQL
  * database.
  *
 */

var fs=require('fs');
var pg=require('pg.js');
var Promise = require('es6-promise').Promise;
var filename = '';

/** @constructor
  * Deferred encapsulates a promise that gets fulfilled by outside code. */
var Deferred=function() {
	var self=this;

	this.promise=new Promise(function(resolve,reject) {
		self.resolve=resolve;
		self.reject=function(err, arg ) {
            console.log(err);
            if(arg) console.log(arg[0]);

        }
	});
};

/** Return a new function that calls fn making it see the desired scope
  * through its "this" variable.
  * @param {Object} scope Variable fn should see as "this".
  * @param {function()} fn Function to call. */
function bindToScope(scope, fn) {
	return function() {
		fn.apply(scope, arguments);
	};
}

/** @constructor
  * PostgreSQL database interface.
  * Simple wrapper to use promises with pg.js. */
var PgDatabase=function() {
	this.client=null;
};

/** @param {Object} client:
  * host, port, database, user and password. */
PgDatabase.prototype.connect=function(client) {
	console.log("pg connect");
	var defer=new Deferred();

	this.client=client;

    defer.resolve();
    console.log("db connect defer resolve");
	return(defer.promise);
};

PgDatabase.prototype.close=function(conf) {
	return(Promise.resolve(this.client.end()));
};

/** Execute query without reading any results. */
PgDatabase.prototype.exec=function() {
	console.log("pg exec");
	var query=this.client.query.apply(this.client,arguments);
	var defer=new Deferred();

	query.on('error',function(err) {
		defer.reject(err);
	});

	query.on('end',function(state) {
		defer.resolve(state);
	});

	return(defer.promise);
};

/** Send query to database and read a single result row. */
PgDatabase.prototype.querySingle=function() {
	var query=this.client.query.apply(this.client,arguments);
	var defer=new Deferred();
	var result;

	query.on('row',function(row) {
		result=row;
	});

	query.on('error',function(err) {
		defer.reject(err);
	});

	query.on('end',function(state) {
		if(!result) return(defer.reject('Not found: ',arguments));
		defer.resolve(result);
	});

	return(defer.promise);
};

/** Send query to database and read a single result row. */
PgDatabase.prototype.queryResult=function() {
	console.log("queryResult, this.client", this.client);
	var query=this.client.query.apply(this.client,arguments);

	var defer=new Deferred();
	var result = [];

	query.on('row',function(row) {
		result.push(row);
	});

	query.on('error',function(err) {
		defer.reject(err);
	});

	query.on('end',function(state) {
		if(!result) return(defer.reject('Not found'));
		defer.resolve(result);
	});

	return(defer.promise);
}

PgDatabase.prototype.begin=function() {
	console.log("db.begin");
	return(this.exec('BEGIN TRANSACTION'));
};

PgDatabase.prototype.commit=function() {
	return(this.exec('COMMIT'));
};

PgDatabase.prototype.rollback=function() {
	return(this.exec('ROLLBACK'));
};

/** @constructor
  * SldInserter stores a parsed SLD template and field configuration
  * into an SQL database. */
var SldDeleter=function() {
	console.log(" SLD deleter constructor");
	this.db=null;
	this.dbConf=null;
	console.log("/SLD deleter constructor");
}

/** @param {string} dbPath Name of JSON file with database address and credentials. */
SldDeleter.prototype.connect=function(client) {
	console.log("connecting to db");

	var defer=new Deferred();

	this.db=new PgDatabase();

	console.log("got connection");

	return(this.db.connect(client)).then(this.db.begin());
};

/** Roll back current transaction and close connection. */
SldDeleter.prototype.abort=function() {
	return(this.db.rollback());

	//.then(bindToScope(this.db,this.db.close)));
};

/** Commit current transaction and close connection. */
SldDeleter.prototype.finish=function() {
	return(this.db.commit());

	//.then(bindToScope(this.db,this.db.close)));
};

/** Select templates with all data
 * @param {string/number} id  template id
 *                        if  < 1  --> select all templates
 * @param {string/number} uuid  user id
 *                        if   == -1  -> admin user, always allow delete
 * @return {Promise} */
SldDeleter.prototype.deleteConfig=function(id, uuid) {
    var self=this;
    var sql = 'delete from sld_config where id='+id;
    if (uuid && uuid != -1) {
    	sql += " AND uuid = \'"+uuid+"\'";
    }
    console.log("deleteConfig: sql "+sql)
    return(self.db.queryResult(sql));

//    return(self.db.queryResult('delete from sld_config where id='+id ));
};

/** Main function, read template and store data to sld_styles db
 * @param id  templates id to be deleted
 * @param cb {function} status cb
 * */
exports.delete_config = function(client, id, uuid, cb) {

	console.log("IN DELETE CONFIG....");
	var deletes=new SldDeleter(),
        cb = cb;
    console.log("client", client);
	var connected=deletes.connect(client);

    var ready=connected.then(function() {
        return(deletes.deleteConfig(id, uuid));
    });
    console.log("READY: " , ready);

	ready.catch(function(err) {
		deletes.abort();
		console.error(err);
		console.log(err);
		return;
	});

	ready.then(function() {
		return(deletes.finish());
	}).then(function() {
		console.log('Success!');
        cb(false);
	});

	console.log("DONE delete_config main function");
}
<commit_msg>delete confix fixed, deleted extra console.logs<commit_after>/** @fileoverview
  * This tool deletes a config from a PostgreSQL
  * database.
  *
 */

var fs=require('fs');
var pg=require('pg.js');
var Promise = require('es6-promise').Promise;
var filename = '';

/** @constructor
  * Deferred encapsulates a promise that gets fulfilled by outside code. */
var Deferred=function() {
	var self=this;

	this.promise=new Promise(function(resolve,reject) {
		self.resolve=resolve;
		self.reject=function(err, arg ) {
            console.log(err);
            if(arg) console.log(arg[0]);

        }
	});
};

/** Return a new function that calls fn making it see the desired scope
  * through its "this" variable.
  * @param {Object} scope Variable fn should see as "this".
  * @param {function()} fn Function to call. */
function bindToScope(scope, fn) {
	return function() {
		fn.apply(scope, arguments);
	};
}

/** @constructor
  * PostgreSQL database interface.
  * Simple wrapper to use promises with pg.js. */
var PgDatabase=function() {
	this.client=null;
};

/** @param {Object} client:
  * host, port, database, user and password. */
PgDatabase.prototype.connect=function(client) {
	var defer=new Deferred();

	this.client=client;

    defer.resolve();

	return(defer.promise);
};

PgDatabase.prototype.close=function(conf) {
	return(Promise.resolve(this.client.end()));
};

/** Execute query without reading any results. */
PgDatabase.prototype.exec=function() {
	var query=this.client.query.apply(this.client,arguments);
	var defer=new Deferred();

	query.on('error',function(err) {
		defer.reject(err);
	});

	query.on('end',function(state) {
		defer.resolve(state);
	});

	return(defer.promise);
};

/** Send query to database and read a single result row. */
PgDatabase.prototype.querySingle=function() {
	var query=this.client.query.apply(this.client,arguments);
	var defer=new Deferred();
	var result;

	query.on('row',function(row) {
		result=row;
	});

	query.on('error',function(err) {
		defer.reject(err);
	});

	query.on('end',function(state) {
		if(!result) return(defer.reject('Not found: ',arguments));
		defer.resolve(result);
	});

	return(defer.promise);
};

/** Send query to database and read a single result row. */
PgDatabase.prototype.queryResult=function() {
	var query=this.client.query.apply(this.client,arguments);

	var defer=new Deferred();
	var result = [];

	query.on('row',function(row) {
		result.push(row);
	});

	query.on('error',function(err) {
		defer.reject(err);
	});

	query.on('end',function(state) {
		if(!result) return(defer.reject('Not found'));
		defer.resolve(result);
	});

	return(defer.promise);
}

PgDatabase.prototype.begin=function() {
	return(this.exec('BEGIN TRANSACTION'));
};

PgDatabase.prototype.commit=function() {
	return(this.exec('COMMIT'));
};

PgDatabase.prototype.rollback=function() {
	return(this.exec('ROLLBACK'));
};

/** @constructor
  * SldInserter stores a parsed SLD template and field configuration
  * into an SQL database. */
var SldDeleter=function() {
	console.log(" SLD deleter constructor");
	this.db=null;
	this.dbConf=null;
	console.log("/SLD deleter constructor");
}

/** @param {string} dbPath Name of JSON file with database address and credentials. */
SldDeleter.prototype.connect=function(client) {
	console.log("connecting to db");

	var defer=new Deferred();

	this.db=new PgDatabase();

	console.log("got connection");

	return(this.db.connect(client)).then(this.db.begin());
};

/** Roll back current transaction and close connection. */
SldDeleter.prototype.abort=function() {
	return(this.db.rollback());

	//.then(bindToScope(this.db,this.db.close)));
};

/** Commit current transaction and close connection. */
SldDeleter.prototype.finish=function() {
	return(this.db.commit());

	//.then(bindToScope(this.db,this.db.close)));
};

/** Select templates with all data
 * @param {string/number} id  template id
 *                        if  < 1  --> select all templates
 * @param {string/number} uuid  user id
 *                        if   == -1  -> admin user, always allow delete
 * @return {Promise} */
SldDeleter.prototype.deleteConfig=function(id, uuid) {
    var self=this;
    var sql = 'delete from sld_config where id='+id;
    if (uuid && uuid != -1) {
    	sql += " AND uuid = \'"+uuid+"\'";
    }
    console.log("deleteConfig: sql "+sql)
    return(self.db.queryResult(sql));

//    return(self.db.queryResult('delete from sld_config where id='+id ));
};

/** Main function, read template and store data to sld_styles db
 * @param id  templates id to be deleted
 * @param cb {function} status cb
 * */
exports.delete_config = function(client, id, uuid, cb) {

	console.log("IN DELETE CONFIG....");
	var deletes=new SldDeleter(),
        cb = cb;

	var connected=deletes.connect(client);

    var ready=connected.then(function() {
        return(deletes.deleteConfig(id, uuid));
    });
    console.log("READY: " , ready);

	ready.catch(function(err) {
		deletes.abort();
		console.error(err);
		console.log(err);
		return;
	});

	ready.then(function() {
		return(deletes.finish());
	}).then(function() {
		console.log('Success!');
        cb(false);
	});

	console.log("DONE delete_config main function");
}
<|endoftext|>


<commit_before>'use strict';

const constants = require('../constants');
const debug = require('./debug')('nano');
const hasOwnProperty = Object.prototype.hasOwnProperty;
const getConfig = require('../config/config').getConfig;

exports.authenticate = function (nano, user, password) {
    return new Promise((resolve, reject) => {
        debug.trace('auth ' + user);
        nano.auth(user, password, function (err, body, headers) {
            if (err) {
                debug.warn('auth failed');
                return reject(err);
            }
            if (headers && headers['set-cookie']) {
                debug.trace('auth success');
                return resolve(headers['set-cookie']);
            }
            reject(new Error('cookie auth not supported'));
        });
    });
};

exports.getDatabase = function (nano, database) {
    return new Promise((resolve, reject) => {
        debug.trace('getDatabase ' + database);
        nano.db.get(database, function (err) {
            if (err) {
                if (err.reason === 'no_db_file') {
                    debug.trace('database not found');
                    return resolve(false);
                }
                debug.warn('getDatabase failed');
                return reject(err);
            }
            debug.trace('database exists');
            resolve(true);
        });
    });
};

exports.createDatabase = function (nano, database) {
    return new Promise((resolve, reject) => {
        debug.trace('createDatabase ' + database);
        nano.db.create(database, function (err) {
            if (err) {
                debug.warn('create failed');
                return reject(err);
            }
            debug('database created');
            resolve();
        });
    });
};

exports.getDocument = function (db, docID, options = {}) {
    return new Promise((resolve, reject) => {
        debug.trace(`getDocument ${docID}`);
        cleanOptions(options);
        db.get(docID, options, function (err, result) {
            if (err) {
                if (err.statusCode === 404 && (err.reason === 'missing' || err.reason === 'deleted')) {
                    debug.trace('document missing');
                    return resolve(null);
                }
                debug.warn('getDocument failed');
                return reject(err);
            }
            debug.trace('found document');
            resolve(result);
        });
    });
};

exports.insertDocument = function (db, doc) {
    return new Promise((resolve, reject) => {
        debug.trace(`insertDocument with _id ${doc._id}`);
        db.insert(doc, function (err, body) {
            if (err) return reject(err);
            debug.trace(`document inserted (${body.id})`);
            resolve(body);
        });
    });
};

exports.queryView = function (db, view, params = {}, options = {}) {
    if (!hasOwnProperty.call(params, 'reduce')) {
        params.reduce = false;
    }
    return new Promise((resolve, reject) => {
        debug.trace(`queryView ${view}`);
        cleanOptions(params);
        var config = getConfig(db.config.db);
        var designDoc = config.designDocNames && config.designDocNames[view] || constants.DESIGN_DOC_NAME;
        db.view(designDoc, view, params, function (err, body) {
            if (err) return reject(err);
            if (options.onlyValue) {
                resolve(body.rows.map(row => row.value));
            } else if (options.onlyDoc) {
                resolve(body.rows.map(row => row.doc));
            } else {
                resolve(body.rows);
            }
        });
    });
};

exports.destroyDatabase = function (nano, dbName) {
    return new Promise((resolve, reject) => {
        debug('destroy database ' + dbName);
        nano.db.destroy(dbName, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.destroyDocument = function (db, docId, revId) {
    debug.trace('destroy document');
    if (!revId) {
        return exports.getDocument(db, docId).then(doc => {
            if (!doc || !doc._rev) return null;
            return exports.destroyDocument(db, docId, doc._rev);
        });
    }
    return new Promise(function (resolve, reject) {
        db.destroy(docId, revId, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.updateWithHandler = function (db, update, docId, body) {
    return new Promise((resolve, reject) => {
        debug.trace(`update with handler ${JSON.stringify(body)}`);
        db.atomic(constants.DESIGN_DOC_NAME, update, docId, body, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.attachFiles = function (db, doc, files) {
    return new Promise((resolve, reject) => {
        debug.trace('attach files');
        db.multipart.insert(doc, files, doc._id, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.getAttachment = function (db, doc, name, asStream, options = {}) {
    return new Promise((resolve, reject) => {
        debug.trace(`get attachment ${doc}/${name}`);
        cleanOptions(options);
        if (asStream) {
            const stream = db.attachment.get(doc, name, options);
            resolve(stream);
        } else {
            db.attachment.get(doc, name, options, function (err, body) {
                if (err) return reject(err);
                resolve(body);
            });
        }
    });
};

exports.request = function (nano, options = {}) {
    return new Promise((resolve, reject) => {
        debug.trace('request');
        cleanOptions(options);
        nano.request(options, function (err, result) {
            if (err) return reject(err);
            resolve(result);
        });
    });
};

function cleanOptions(options) {
    if (options.token) {
        delete options.token;
    }
}
<commit_msg>fix(tests): use node v4 compatible syntax<commit_after>'use strict';

const constants = require('../constants');
const debug = require('./debug')('nano');
const hasOwnProperty = Object.prototype.hasOwnProperty;
const getConfig = require('../config/config').getConfig;

exports.authenticate = function (nano, user, password) {
    return new Promise((resolve, reject) => {
        debug.trace('auth ' + user);
        nano.auth(user, password, function (err, body, headers) {
            if (err) {
                debug.warn('auth failed');
                return reject(err);
            }
            if (headers && headers['set-cookie']) {
                debug.trace('auth success');
                return resolve(headers['set-cookie']);
            }
            reject(new Error('cookie auth not supported'));
        });
    });
};

exports.getDatabase = function (nano, database) {
    return new Promise((resolve, reject) => {
        debug.trace('getDatabase ' + database);
        nano.db.get(database, function (err) {
            if (err) {
                if (err.reason === 'no_db_file') {
                    debug.trace('database not found');
                    return resolve(false);
                }
                debug.warn('getDatabase failed');
                return reject(err);
            }
            debug.trace('database exists');
            resolve(true);
        });
    });
};

exports.createDatabase = function (nano, database) {
    return new Promise((resolve, reject) => {
        debug.trace('createDatabase ' + database);
        nano.db.create(database, function (err) {
            if (err) {
                debug.warn('create failed');
                return reject(err);
            }
            debug('database created');
            resolve();
        });
    });
};

exports.getDocument = function (db, docID, options) {
    options = options || {};
    return new Promise((resolve, reject) => {
        debug.trace(`getDocument ${docID}`);
        cleanOptions(options);
        db.get(docID, options, function (err, result) {
            if (err) {
                if (err.statusCode === 404 && (err.reason === 'missing' || err.reason === 'deleted')) {
                    debug.trace('document missing');
                    return resolve(null);
                }
                debug.warn('getDocument failed');
                return reject(err);
            }
            debug.trace('found document');
            resolve(result);
        });
    });
};

exports.insertDocument = function (db, doc) {
    return new Promise((resolve, reject) => {
        debug.trace(`insertDocument with _id ${doc._id}`);
        db.insert(doc, function (err, body) {
            if (err) return reject(err);
            debug.trace(`document inserted (${body.id})`);
            resolve(body);
        });
    });
};

exports.queryView = function (db, view, params = {}, options = {}) {
    if (!hasOwnProperty.call(params, 'reduce')) {
        params.reduce = false;
    }
    return new Promise((resolve, reject) => {
        debug.trace(`queryView ${view}`);
        cleanOptions(params);
        var config = getConfig(db.config.db);
        var designDoc = config.designDocNames && config.designDocNames[view] || constants.DESIGN_DOC_NAME;
        db.view(designDoc, view, params, function (err, body) {
            if (err) return reject(err);
            if (options.onlyValue) {
                resolve(body.rows.map(row => row.value));
            } else if (options.onlyDoc) {
                resolve(body.rows.map(row => row.doc));
            } else {
                resolve(body.rows);
            }
        });
    });
};

exports.destroyDatabase = function (nano, dbName) {
    return new Promise((resolve, reject) => {
        debug('destroy database ' + dbName);
        nano.db.destroy(dbName, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.destroyDocument = function (db, docId, revId) {
    debug.trace('destroy document');
    if (!revId) {
        return exports.getDocument(db, docId).then(doc => {
            if (!doc || !doc._rev) return null;
            return exports.destroyDocument(db, docId, doc._rev);
        });
    }
    return new Promise(function (resolve, reject) {
        db.destroy(docId, revId, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.updateWithHandler = function (db, update, docId, body) {
    return new Promise((resolve, reject) => {
        debug.trace(`update with handler ${JSON.stringify(body)}`);
        db.atomic(constants.DESIGN_DOC_NAME, update, docId, body, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.attachFiles = function (db, doc, files) {
    return new Promise((resolve, reject) => {
        debug.trace('attach files');
        db.multipart.insert(doc, files, doc._id, function (err, body) {
            if (err) return reject(err);
            resolve(body);
        });
    });
};

exports.getAttachment = function (db, doc, name, asStream, options = {}) {
    return new Promise((resolve, reject) => {
        debug.trace(`get attachment ${doc}/${name}`);
        cleanOptions(options);
        if (asStream) {
            const stream = db.attachment.get(doc, name, options);
            resolve(stream);
        } else {
            db.attachment.get(doc, name, options, function (err, body) {
                if (err) return reject(err);
                resolve(body);
            });
        }
    });
};

exports.request = function (nano, options = {}) {
    return new Promise((resolve, reject) => {
        debug.trace('request');
        cleanOptions(options);
        nano.request(options, function (err, result) {
            if (err) return reject(err);
            resolve(result);
        });
    });
};

function cleanOptions(options) {
    if (options.token) {
        delete options.token;
    }
}
<|endoftext|>


<commit_before>import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import streamutil from 'streamutil';

import * as sqlutil from '../lib/sqlutil';

chai.use(chaiAsPromised);
let expect = chai.expect;

describe('table with foreign keys', () => {
  let db;
  let table;
  let parentTable;
  let childTable;

  beforeEach(() => {
    db = new sqlutil.Db();

    parentTable = new sqlutil.Table(db, {
      name: 'parent',
      columns: {
        id: {type: sqlutil.DataType.INTEGER, primaryKey: true},
        name: {type: sqlutil.DataType.TEXT, unique: true}
      }
    });

    childTable = new sqlutil.Table(db, {
      name: 'child',
      columns: {
        id: {type: sqlutil.DataType.INTEGER, primaryKey: true},
        value: {type: sqlutil.DataType.TEXT, unique: true},
        parentId: {type: sqlutil.DataType.INTEGER}
      },
      foreignKeys: [
        {from: 'parentId', references: {parent: 'id'}}
      ]
    });

    return db.open(':memory:')
      .then(() => db.enableForeignKeys())
      .then(() => Promise.all([
        parentTable.createTable(),
        childTable.createTable()
      ]));
  });

  function insertSomeData() {
    return parentTable.insert({id: 1, name: 'Banan'})
      .then(() => childTable.insert({parentId: 1, value: 'Apa'}))
      .then(() => childTable.insert({parentId: 1, value: 'Ape'}));
  }

  it('should be possible to insert valid rows', () => {
    return insertSomeData();
  });

  it('should not be possible to insert foreign key validations', () => {
    return expect(childTable.insert({parentId: 42, value: 'Ape'})).to.eventually.be.rejectedWith(/FOREIGN KEY constraint failed/);
  });

  it('should be possible to remove foreign keys from a table', () => {
    return insertSomeData()
      .then(() => {
        let newChildTable = new sqlutil.Table(db, {
          name: 'child',
          columns: {
            id: {type: sqlutil.DataType.INTEGER, primaryKey: true},
            value: {type: sqlutil.DataType.TEXT, unique: true},
            parentId: {type: sqlutil.DataType.INTEGER}
          }
        });

        return newChildTable.createTable()
          .then(status => expect(status.wasRecreated).to.be.true)
          .then(() => newChildTable.insert({parentId: 42, value: 'Elephant'}));
      });
  });

  it('should be possible to add foreign keys to a table');
  it('table should only be recreated when needed');
});
<commit_msg>Add documentation for more foreign key test cases<commit_after>import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import streamutil from 'streamutil';

import * as sqlutil from '../lib/sqlutil';

chai.use(chaiAsPromised);
let expect = chai.expect;

describe('table with foreign keys', () => {
  let db;
  let table;
  let parentTable;
  let childTable;

  beforeEach(() => {
    db = new sqlutil.Db();

    parentTable = new sqlutil.Table(db, {
      name: 'parent',
      columns: {
        id: {type: sqlutil.DataType.INTEGER, primaryKey: true},
        name: {type: sqlutil.DataType.TEXT, unique: true}
      }
    });

    childTable = new sqlutil.Table(db, {
      name: 'child',
      columns: {
        id: {type: sqlutil.DataType.INTEGER, primaryKey: true},
        value: {type: sqlutil.DataType.TEXT, unique: true},
        parentId: {type: sqlutil.DataType.INTEGER}
      },
      foreignKeys: [
        {from: 'parentId', references: {parent: 'id'}}
      ]
    });

    return db.open(':memory:')
      .then(() => db.enableForeignKeys())
      .then(() => Promise.all([
        parentTable.createTable(),
        childTable.createTable()
      ]));
  });

  function insertSomeData() {
    return parentTable.insert({id: 1, name: 'Banan'})
      .then(() => childTable.insert({parentId: 1, value: 'Apa'}))
      .then(() => childTable.insert({parentId: 1, value: 'Ape'}));
  }

  it('should be possible to insert valid rows', () => {
    return insertSomeData();
  });

  it('should not be possible to insert foreign key validations', () => {
    return expect(childTable.insert({parentId: 42, value: 'Ape'})).to.eventually.be.rejectedWith(/FOREIGN KEY constraint failed/);
  });

  it('should be possible to remove foreign keys from a table', () => {
    return insertSomeData()
      .then(() => {
        let newChildTable = new sqlutil.Table(db, {
          name: 'child',
          columns: {
            id: {type: sqlutil.DataType.INTEGER, primaryKey: true},
            value: {type: sqlutil.DataType.TEXT, unique: true},
            parentId: {type: sqlutil.DataType.INTEGER}
          }
        });

        return newChildTable.createTable()
          .then(status => expect(status.wasRecreated).to.be.true)
          .then(() => newChildTable.insert({parentId: 42, value: 'Elephant'}));
      });
  });

  it('should be possible to add foreign keys to a table');
  it('table should only be recreated when needed');
  it('should be possible to update table with foreign key target');
});
<|endoftext|>


<commit_before>var TransformFeedback = {};

/**
 * @param {WebGLRenderingContext} gl
 * @param {Surface} surface
 * @param {Array<WebGLTexture>} textures
 */
TransformFeedback.toTextures = function(gl, surface, textures) {
    var stride = 4 + 2 * GLSL.N;
    var size = stride * surface.numIndices;
    var output = new Float32Array(size);
    gl["bindTransformFeedback"](gl["TRANSFORM_FEEDBACK"], surface.transformFeedback);
    gl["bindBufferBase"](gl["TRANSFORM_FEEDBACK_BUFFER"], 0, surface.transformFeedbackBuffer);
    gl["getBufferSubData"](gl["TRANSFORM_FEEDBACK_BUFFER"], 0, output);
    gl["bindBufferBase"](gl["TRANSFORM_FEEDBACK_BUFFER"], 0, null);
    gl["bindTransformFeedback"](gl["TRANSFORM_FEEDBACK"], null);
    var texData = new Float32Array(4 * 2048 * 2048);
    for (var i = 0; i <= GLSL.N / 2; i++) {
        gl.bindTexture(gl.TEXTURE_2D, textures[i]);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        for (var l = 0; l < surface.numIndices; l++) {
            for (var k = 0; k < 4; k++)
                texData[4 * l + k] = output[stride * l + 4 * i + k];
        }
        gl.texImage2D(gl.TEXTURE_2D, 0, gl["RGBA16F"], 2048, 2048, 0, gl.RGBA,
            gl.FLOAT, texData);
    }
};
<commit_msg>Factor out TransformFeedback.toFloat32Array from TransformFeedback.toTextures<commit_after>var TransformFeedback = {};

/**
 * @param {WebGLRenderingContext} gl
 * @param {Surface} surface
 * @return {Float32Array}
 */
TransformFeedback.toFloat32Array = function(gl, surface) {
    var stride = 4 + 2 * GLSL.N;
    var size = stride * surface.numIndices;
    var output = new Float32Array(size);
    gl["bindTransformFeedback"](gl["TRANSFORM_FEEDBACK"], surface.transformFeedback);
    gl["bindBufferBase"](gl["TRANSFORM_FEEDBACK_BUFFER"], 0, surface.transformFeedbackBuffer);
    gl["getBufferSubData"](gl["TRANSFORM_FEEDBACK_BUFFER"], 0, output);
    gl["bindBufferBase"](gl["TRANSFORM_FEEDBACK_BUFFER"], 0, null);
    gl["bindTransformFeedback"](gl["TRANSFORM_FEEDBACK"], null);
    return output;
};

/**
 * @param {WebGLRenderingContext} gl
 * @param {Surface} surface
 * @param {Array<WebGLTexture>} textures
 */
TransformFeedback.toTextures = function(gl, surface, textures) {
    var stride = 4 + 2 * GLSL.N;
    var output = TransformFeedback.toFloat32Array(gl, surface);
    var texData = new Float32Array(4 * 2048 * 2048);
    for (var i = 0; i <= GLSL.N / 2; i++) {
        gl.bindTexture(gl.TEXTURE_2D, textures[i]);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        for (var l = 0; l < surface.numIndices; l++) {
            for (var k = 0; k < 4; k++)
                texData[4 * l + k] = output[stride * l + 4 * i + k];
        }
        gl.texImage2D(gl.TEXTURE_2D, 0, gl["RGBA16F"], 2048, 2048, 0, gl.RGBA,
            gl.FLOAT, texData);
    }
};
<|endoftext|>