<commit_before>var url = require('url');
var semver = require('semver');
var nijs = require('nijs');
var inherit = require('nijs/lib/ast/util/inherit.js').inherit;
var base64js = require('base64-js');

/**
 * Creates a new source instance. This function should never be used directly,
 * instead use: Source.constructSource to construct a source object.
 *
 * @class Source
 * @extends NixASTNode
 * @classdesc Represents a file that is obtained from an external source
 *
 * @constructor
 * @param {String} baseDir Directory in which the referrer's package.json configuration resides
 * @param {String} dependencyName Name of the dependency
 * @param {String} versionSpec Version specifier of the Node.js package to fetch
 */
function Source(baseDir, dependencyName, versionSpec) {
    this.baseDir = baseDir;
    this.dependencyName = dependencyName;
    this.versionSpec = versionSpec;
}

/* Source inherits from NixASTNode */
inherit(nijs.NixASTNode, Source);

/**
 * Constructs a specific kind of source by inspecting the version specifier.
 *
 * @param {String} registryURL URL of the NPM registry
 * @param {String} baseDir Directory in which the referrer's package.json configuration resides
 * @param {String} outputDir Directory in which the nix expression will be written
 * @param {String} dependencyName Name of the dependency
 * @param {String} versionSpec Version specifier of the Node.js package to fetch
 * @param {Boolean} stripOptionalDependencies When enabled, the optional
 *   dependencies are stripped from the regular dependencies in the NPM registry
 */
Source.constructSource = function(registryURL, baseDir, outputDir, dependencyName, versionSpec, stripOptionalDependencies) {
    // Load modules here, to prevent cycles in the include process
    var GitSource = require('./GitSource.js').GitSource;
    var HTTPSource = require('./HTTPSource.js').HTTPSource;
    var LocalSource = require('./LocalSource.js').LocalSource;
    var NPMRegistrySource = require('./NPMRegistrySource.js').NPMRegistrySource;

    var parsedVersionSpec = semver.validRange(versionSpec, true);
    var parsedUrl = url.parse(versionSpec);

    if(parsedVersionSpec !== null) { // If the version is valid semver range, fetch the package from the NPM registry
        return new NPMRegistrySource(baseDir, dependencyName, parsedVersionSpec, registryURL, stripOptionalDependencies);
    } else if(parsedUrl.protocol == "github:") { // If the version is a GitHub repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("git://github.com", parsedUrl));
    } else if(parsedUrl.protocol == "gist:") { // If the version is a GitHub gist repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("https://gist.github.com", parsedUrl));
    } else if(parsedUrl.protocol == "bitbucket:") { // If the version is a Bitbucket repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("git://bitbucket.org", parsedUrl));
    } else if(parsedUrl.protocol == "gitlab:") { // If the version is a Gitlab repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("git://gitlab.com", parsedUrl));
    } else if(typeof parsedUrl.protocol == "string" && parsedUrl.protocol.substr(0, 3) == "git") { // If the version is a Git URL do a Git checkout
        return new GitSource(baseDir, dependencyName, versionSpec);
    } else if(parsedUrl.protocol == "http:" || parsedUrl.protocol == "https:") { // If the version is an HTTP URL do a download
        return new HTTPSource(baseDir, dependencyName, versionSpec);
    } else if(versionSpec.match(/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9\.]+[#[a-zA-Z0-9_\-]+]?$/)) { // If the version is a GitHub repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, "git://github.com/"+versionSpec);
    } else if(parsedUrl.protocol == "file:") { // If the version is a file URL, simply compose a Nix path
        return new LocalSource(baseDir, dependencyName, outputDir, parsedUrl.path);
    } else if(versionSpec.substr(0, 3) == "../" || versionSpec.substr(0, 2) == "~/" || versionSpec.substr(0, 2) == "./" || versionSpec.substr(0, 1) == "/") { // If the version is a path, simply compose a Nix path
        return new LocalSource(baseDir, dependencyName, outputDir, versionSpec);
    } else { // In all other cases, just try the registry. Sometimes invalid semver ranges are encountered or a tag has been provided (e.g. 'latest', 'unstable')
        return new NPMRegistrySource(baseDir, dependencyName, versionSpec, registryURL, stripOptionalDependencies);
    }
};

/**
 * Fetches the package metadata from the external source.
 *
 * @method
 * @param {function(String)} callback Callback that gets invoked when the work
 *     is done. In case of an error, it will set the first parameter to contain
 *     an error message.
 */
Source.prototype.fetch = function(callback) {
    callback("fetch() is not implemented, please use a prototype that inherits from Source");
};

/**
 * Takes a dependency object from a lock file and converts it into a source object.
 *
 * @param {Object} dependencyObj Dependency object from the lock file
 * @param {function(String)} callback Callback that gets invoked when the work
 *     is done. In case of an error, it will set the first parameter to contain
 *     an error message.
 */
Source.prototype.convertFromLockedDependency = function(dependencyObj, callback) {
    callback("convertFromLockedDependency() is not implemented, please use a prototype that inherits from Source");
};

/**
 * Converts NPM's integrity strings that have the following format:
 * <algorithm>-<base64 hash> to a hash representation that Nix understands.
 *
 * @method
 * @param {String} integrity NPM integrity string
 */
Source.prototype.convertIntegrityStringToNixHash = function(integrity) {
    if(integrity.substr(0, 5) === "sha1-") {
        var hash = base64js.toByteArray(integrity.substring(5));
        this.hashType = "sha1";
        this.sha1 = new Buffer(hash).toString('hex');
    } else if(integrity.substr(0, 7) === "sha512-") {
        this.hashType = "sha512";
        this.sha512 = integrity.substring(7);
    } else {
        throw "Unknown integrity string: "+integrity;
    }
};

/**
 * @see NixASTNode#toNixAST
 */
Source.prototype.toNixAST = function() {
    return {
        name: this.config.name.replace("@", "_at_").replace("/", "_slash_"), // Escape characters from scoped package names that aren't allowed
        packageName: this.config.name,
        version: this.config.version
    };
};

exports.Source = Source;
<commit_msg>Use HTTPS URL for GitLab<commit_after>var url = require('url');
var semver = require('semver');
var nijs = require('nijs');
var inherit = require('nijs/lib/ast/util/inherit.js').inherit;
var base64js = require('base64-js');

/**
 * Creates a new source instance. This function should never be used directly,
 * instead use: Source.constructSource to construct a source object.
 *
 * @class Source
 * @extends NixASTNode
 * @classdesc Represents a file that is obtained from an external source
 *
 * @constructor
 * @param {String} baseDir Directory in which the referrer's package.json configuration resides
 * @param {String} dependencyName Name of the dependency
 * @param {String} versionSpec Version specifier of the Node.js package to fetch
 */
function Source(baseDir, dependencyName, versionSpec) {
    this.baseDir = baseDir;
    this.dependencyName = dependencyName;
    this.versionSpec = versionSpec;
}

/* Source inherits from NixASTNode */
inherit(nijs.NixASTNode, Source);

/**
 * Constructs a specific kind of source by inspecting the version specifier.
 *
 * @param {String} registryURL URL of the NPM registry
 * @param {String} baseDir Directory in which the referrer's package.json configuration resides
 * @param {String} outputDir Directory in which the nix expression will be written
 * @param {String} dependencyName Name of the dependency
 * @param {String} versionSpec Version specifier of the Node.js package to fetch
 * @param {Boolean} stripOptionalDependencies When enabled, the optional
 *   dependencies are stripped from the regular dependencies in the NPM registry
 */
Source.constructSource = function(registryURL, baseDir, outputDir, dependencyName, versionSpec, stripOptionalDependencies) {
    // Load modules here, to prevent cycles in the include process
    var GitSource = require('./GitSource.js').GitSource;
    var HTTPSource = require('./HTTPSource.js').HTTPSource;
    var LocalSource = require('./LocalSource.js').LocalSource;
    var NPMRegistrySource = require('./NPMRegistrySource.js').NPMRegistrySource;

    var parsedVersionSpec = semver.validRange(versionSpec, true);
    var parsedUrl = url.parse(versionSpec);

    if(parsedVersionSpec !== null) { // If the version is valid semver range, fetch the package from the NPM registry
        return new NPMRegistrySource(baseDir, dependencyName, parsedVersionSpec, registryURL, stripOptionalDependencies);
    } else if(parsedUrl.protocol == "github:") { // If the version is a GitHub repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("git://github.com", parsedUrl));
    } else if(parsedUrl.protocol == "gist:") { // If the version is a GitHub gist repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("https://gist.github.com", parsedUrl));
    } else if(parsedUrl.protocol == "bitbucket:") { // If the version is a Bitbucket repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("git://bitbucket.org", parsedUrl));
    } else if(parsedUrl.protocol == "gitlab:") { // If the version is a Gitlab repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, GitSource.composeGitURL("https://gitlab.com", parsedUrl));
    } else if(typeof parsedUrl.protocol == "string" && parsedUrl.protocol.substr(0, 3) == "git") { // If the version is a Git URL do a Git checkout
        return new GitSource(baseDir, dependencyName, versionSpec);
    } else if(parsedUrl.protocol == "http:" || parsedUrl.protocol == "https:") { // If the version is an HTTP URL do a download
        return new HTTPSource(baseDir, dependencyName, versionSpec);
    } else if(versionSpec.match(/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9\.]+[#[a-zA-Z0-9_\-]+]?$/)) { // If the version is a GitHub repository, compose the corresponding Git URL and do a Git checkout
        return new GitSource(baseDir, dependencyName, "git://github.com/"+versionSpec);
    } else if(parsedUrl.protocol == "file:") { // If the version is a file URL, simply compose a Nix path
        return new LocalSource(baseDir, dependencyName, outputDir, parsedUrl.path);
    } else if(versionSpec.substr(0, 3) == "../" || versionSpec.substr(0, 2) == "~/" || versionSpec.substr(0, 2) == "./" || versionSpec.substr(0, 1) == "/") { // If the version is a path, simply compose a Nix path
        return new LocalSource(baseDir, dependencyName, outputDir, versionSpec);
    } else { // In all other cases, just try the registry. Sometimes invalid semver ranges are encountered or a tag has been provided (e.g. 'latest', 'unstable')
        return new NPMRegistrySource(baseDir, dependencyName, versionSpec, registryURL, stripOptionalDependencies);
    }
};

/**
 * Fetches the package metadata from the external source.
 *
 * @method
 * @param {function(String)} callback Callback that gets invoked when the work
 *     is done. In case of an error, it will set the first parameter to contain
 *     an error message.
 */
Source.prototype.fetch = function(callback) {
    callback("fetch() is not implemented, please use a prototype that inherits from Source");
};

/**
 * Takes a dependency object from a lock file and converts it into a source object.
 *
 * @param {Object} dependencyObj Dependency object from the lock file
 * @param {function(String)} callback Callback that gets invoked when the work
 *     is done. In case of an error, it will set the first parameter to contain
 *     an error message.
 */
Source.prototype.convertFromLockedDependency = function(dependencyObj, callback) {
    callback("convertFromLockedDependency() is not implemented, please use a prototype that inherits from Source");
};

/**
 * Converts NPM's integrity strings that have the following format:
 * <algorithm>-<base64 hash> to a hash representation that Nix understands.
 *
 * @method
 * @param {String} integrity NPM integrity string
 */
Source.prototype.convertIntegrityStringToNixHash = function(integrity) {
    if(integrity.substr(0, 5) === "sha1-") {
        var hash = base64js.toByteArray(integrity.substring(5));
        this.hashType = "sha1";
        this.sha1 = new Buffer(hash).toString('hex');
    } else if(integrity.substr(0, 7) === "sha512-") {
        this.hashType = "sha512";
        this.sha512 = integrity.substring(7);
    } else {
        throw "Unknown integrity string: "+integrity;
    }
};

/**
 * @see NixASTNode#toNixAST
 */
Source.prototype.toNixAST = function() {
    return {
        name: this.config.name.replace("@", "_at_").replace("/", "_slash_"), // Escape characters from scoped package names that aren't allowed
        packageName: this.config.name,
        version: this.config.version
    };
};

exports.Source = Source;
<|endoftext|>


<commit_before>// iframe.js

(function($) {

    function checkWindowSize() {
        var innerHeight = window.innerHeight || document.documentElement.clientHeight;
        if (innerHeight < document.height) {
            parent.postMessage('PUT height\n\n' + document.height, '*');
        } else {
            var scrollHeight = document.height;
            $('#content').add($('#content').parents()).each(function(){
                scrollHeight += this.scrollHeight - this.clientHeight;
            });
            if (scrollHeight > innerHeight) {
                parent.postMessage('PUT height\n\n' + scrollHeight, '*');
            }
        }
        var clientWidth = document.documentElement.clientWidth;
        if (clientWidth < document.documentElement.scrollWidth) {
            parent.postMessage('PUT width\n\n' + document.documentElement.scrollWidth, '*');
        } else {
            var scrollWidth = document.documentElement.scrollWidth;
            $('#content').add($('#content').parents()).each(function(){
                scrollWidth += this.scrollWidth - this.clientWidth;
            });
            if (scrollWidth > clientWidth) {
                parent.postMessage('PUT height\n\n' + scrollWidth, '*');
            }
        }
    }

    if (window.parent != window) {
        document.documentElement.className += " iframe";
        var src = null;
        var postSource = function() {
            if (window.location.search == '?view' && parent.postMessage) {
                var url = calli.getPageUrl();
                if (url != src) {
                    src = url;
                    parent.postMessage('PUT src\n\n' + url, '*');
                }
            }
        }
        $(window).bind('popstate', postSource);
        $(window).bind('load', postSource);
        var checkNumber = 0;
        $(window).bind('load resize DOMNodeInserted', function() {
            var lastCheck = ++checkNumber;
            setTimeout(function() {
                if (checkNumber == lastCheck) {
                    checkWindowSize();
                }
            }, 0);
        });
    }
})(jQuery);
<commit_msg>Don't advertise iframe content size anymore (isn't used)<commit_after>// iframe.js

(function($) {
    if (window.parent != window) {
        document.documentElement.className += " iframe";
        var src = null;
        var postSource = function() {
            if (window.location.search == '?view' && parent.postMessage) {
                var url = calli.getPageUrl();
                if (url != src) {
                    src = url;
                    parent.postMessage('PUT src\n\n' + url, '*');
                }
            }
        }
        $(window).bind('popstate', postSource);
        $(window).bind('load', postSource);
    }
})(jQuery);
<|endoftext|>


<commit_before>var toggle_grading_container = function(target) {
    var target = $(target.target);
    var container = target.parent();
    var grading_container = container.find(".grading-container");
    if(grading_container.is(":visible")) {
        grading_container.hide();
    } else {
        grading_container.show();
    }

}

var render_essay_wrapper = function(prompt, problem_id) {
    var render_essay = function(data) {
        var model_data = $("#essay-container");
        model_data.empty();
        data = $.parseJSON(data);
        var item_template = $( "#essay-item-template" ).html();
        var container_template = $( "#essay-list-template" ).html();
        var rubric_list_template = $('#rubric-list-template').html();
        var essaygrades_template = $('#essay-grades-template').html();
        var essaygrade_tab_template = $('#essay-grade-tab-template').html();
        var essaygrade_detail_template = $('#essay-grade-detail-template').html();

        var essays = new Array();

        for (var i = 0; i < data.length; i++) {
            var essaygrade_tabs = new Array();
            var essaygrade_details = new Array();
            var elem = data[i];
            var essay_name = "Essay with id " + elem.id.toString();
            var mod_essay_name = essay_name.replace(/ /g, "_");
            var essaygrade_data = elem.essaygrades_full
            for (var z = 0; z < essaygrade_data.length; z++) {
                essaygrade_rubric = essaygrade_data[z]['rubric']
                essaygrade_href = "Essaygrade with id" + essaygrade_data[z]['id']
                essaygrade_href = essaygrade_href.replace(/ /g, "_");
                essaygrade_type = essaygrade_data[z].grader_type;
                var essaygrade_dict = {
                    href : essaygrade_href,
                    rubrics : essaygrade_rubric,
                    type : essaygrade_type
                }
                var essaygrade_tab = _.template(essaygrade_tab_template,essaygrade_dict);
                var essaygrade_detail = _.template(essaygrade_detail_template,essaygrade_dict);
                essaygrade_tabs.push(essaygrade_tab);
                essaygrade_details.push(essaygrade_detail);
            }
            var essaygrades_html = _.template(essaygrades_template,{tabs : essaygrade_tabs, details : essaygrade_details});
            var elem_dict = {
                name : essay_name,
                prompt : prompt,
                href : mod_essay_name,
                modified : new Date(Date.parse(elem.modified)),
                created: new Date(Date.parse(elem.created)),
                id : elem.id,
                essay_text : elem.essay_text,
                rubric : _.template(rubric_list_template,{rubrics : elem.rubric}),
                essaygrades : essaygrades_html
            }
            var problem = elem.problem
            var problem_split=problem.split("/");
            if(parseInt(problem_split[5])==problem_id){
                essays.push(_.template(item_template,elem_dict));
            }
        }
        var template_data = {
            essays: essays
        };
        model_data.append(_.template(container_template,template_data));
        var grading_container = $('.grading-container');
        grading_container.hide();
        $('.grade-essay').click(toggle_grading_container);
        $('.create-essaygrade').click(save_essaygrade);
    }
    return render_essay
}

var get_essay_template = function(data) {
    var target = $(data.target).parent();
    var problem_id = parseInt(target.data('problem_id'));
    var prompt = target.data('prompt');

    var api_base = $('#model_name').attr("url");
    $.ajax({
        type: "GET",
        url: api_base,
        data: { action: "get", model: "essay" }
    }).done(render_essay_wrapper(prompt, problem_id));
}

var save_essaygrade = function(data) {
    var target_btn = $(data.target);
    var grading_container = target_btn.parent().parent();
    var feedback = grading_container.find('.essay-feedback').val()
    var rubric_scores = new Array();
    var rubric_item_selects = grading_container.find('.rubric-item-select')
    var essay_id = grading_container.parent().parent().parent().find('.accordion-toggle').data('elem_id')
    for(var i=0;i < rubric_item_selects.length ; i++) {
        var item_score = 0
        if($(rubric_item_selects[i]).is(':checked')) {
            item_score = 1
        }
        rubric_scores.push(item_score)
    }
    var api_url = $('#model_name').attr("url") + "/";
    post_data = {
        target_scores: JSON.stringify(rubric_scores),
        essay : essay_id,
        confidence : 1,
        feedback: feedback,
        success: true,
        grader_type: "IN",
        premium_feedback_scores: JSON.stringify("[]"),
        annotated_text: ""
    }
    $.ajax({
        type: "POST",
        url: api_url,
        data: { action: "post", model: 'essaygrade', data : JSON.stringify(post_data)}
    }).done(get_courses);
}

$(function(){
    var tokenValue = $.cookie('problemgradercsrftoken');

    $.ajaxSetup({
        data: {csrfmiddlewaretoken: tokenValue },
        headers: {'X-CSRF-Token': tokenValue}
    });
    get_courses()
})<commit_msg>Finish docs for example<commit_after>var toggle_grading_container = function(target) {
    /*
    Shows or hides the grading container based on user click
     */
    var target = $(target.target);
    var container = target.parent();
    var grading_container = container.find(".grading-container");
    if(grading_container.is(":visible")) {
        grading_container.hide();
    } else {
        grading_container.show();
    }

}

var render_essay_wrapper = function(prompt, problem_id) {
    /*
    Wraps the render_essay function so that prompt and problem_id can be passed in
     */
    var render_essay = function(data) {
        /*
        Renders an essay and allows it to be graded, and for past grades to be viewed
         */
        //empty out the container
        var model_data = $("#essay-container");
        model_data.empty();
        //parse the json data
        data = $.parseJSON(data);

        //get the needed templates
        var item_template = $( "#essay-item-template" ).html();
        var container_template = $( "#essay-list-template" ).html();
        var rubric_list_template = $('#rubric-list-template').html();
        var essaygrades_template = $('#essay-grades-template').html();
        var essaygrade_tab_template = $('#essay-grade-tab-template').html();
        var essaygrade_detail_template = $('#essay-grade-detail-template').html();

        var essays = new Array();

        //loop through each essay that was retrieved from the api
        for (var i = 0; i < data.length; i++) {
            var essaygrade_tabs = new Array();
            var essaygrade_details = new Array();
            var elem = data[i];
            var essay_name = "Essay with id " + elem.id.toString();
            var mod_essay_name = essay_name.replace(/ /g, "_");
            var essaygrade_data = elem.essaygrades_full
            //loop through each essaygrade attached to the essay
            for (var z = 0; z < essaygrade_data.length; z++) {

                //extract needed values from the data
                essaygrade_rubric = essaygrade_data[z]['rubric']
                essaygrade_href = "Essaygrade with id" + essaygrade_data[z]['id']
                essaygrade_href = essaygrade_href.replace(/ /g, "_");
                essaygrade_type = essaygrade_data[z].grader_type;
                var essaygrade_dict = {
                    href : essaygrade_href,
                    rubrics : essaygrade_rubric,
                    type : essaygrade_type
                }
                //render the tab and the detail view for each essaygrade
                var essaygrade_tab = _.template(essaygrade_tab_template,essaygrade_dict);
                var essaygrade_detail = _.template(essaygrade_detail_template,essaygrade_dict);

                //add the tabs and details to the list
                essaygrade_tabs.push(essaygrade_tab);
                essaygrade_details.push(essaygrade_detail);
            }
            //render the full essaygrade html using the pieces
            var essaygrades_html = _.template(essaygrades_template,{tabs : essaygrade_tabs, details : essaygrade_details});

            //render the essay using this data
            var elem_dict = {
                name : essay_name,
                prompt : prompt,
                href : mod_essay_name,
                modified : new Date(Date.parse(elem.modified)),
                created: new Date(Date.parse(elem.created)),
                id : elem.id,
                essay_text : elem.essay_text,
                rubric : _.template(rubric_list_template,{rubrics : elem.rubric}),
                essaygrades : essaygrades_html
            }
            var problem = elem.problem
            var problem_split=problem.split("/");
            //if the problem id matches the user selected problem, add the problem to the essay list
            if(parseInt(problem_split[5])==problem_id){
                essays.push(_.template(item_template,elem_dict));
            }
        }
        var template_data = {
            essays: essays
        };
        //render the full template for all the essays
        model_data.append(_.template(container_template,template_data));

        //hide the grading container initially
        var grading_container = $('.grading-container');
        grading_container.hide();

        //register click events
        $('.grade-essay').click(toggle_grading_container);
        $('.create-essaygrade').click(save_essaygrade);
    }
    return render_essay
}

var get_essay_template = function(data) {
    /*
    Get a list of essays.  Function naming needs to be consistent with essay.js for essay_nav.js to work.
     */
    var target = $(data.target).parent();
    var problem_id = parseInt(target.data('problem_id'));
    var prompt = target.data('prompt');

    var api_base = $('#model_name').attr("url");
    $.ajax({
        type: "GET",
        url: api_base,
        data: { action: "get", model: "essay" }
    }).done(render_essay_wrapper(prompt, problem_id));
}

var save_essaygrade = function(data) {
    /*
    Save the grade for a given essay.
     */
    var target_btn = $(data.target);
    var grading_container = target_btn.parent().parent();
    //extract feedback
    var feedback = grading_container.find('.essay-feedback').val()
    var rubric_scores = new Array();
    var rubric_item_selects = grading_container.find('.rubric-item-select')
    var essay_id = grading_container.parent().parent().parent().find('.accordion-toggle').data('elem_id')
    //for each rubric item, pick 1 if it was checked, and 0 if it was not
    for(var i=0;i < rubric_item_selects.length ; i++) {
        var item_score = 0
        if($(rubric_item_selects[i]).is(':checked')) {
            item_score = 1
        }
        rubric_scores.push(item_score)
    }
    var api_url = $('#model_name').attr("url") + "/";
    //construct the post data dictionary.  Manually add in several values that are required by the API, but don't need to be user surfaced.
    post_data = {
        target_scores: JSON.stringify(rubric_scores),
        essay : essay_id,
        confidence : 1,
        feedback: feedback,
        success: true,
        grader_type: "IN",
        premium_feedback_scores: JSON.stringify("[]"),
        annotated_text: ""
    }
    $.ajax({
        type: "POST",
        url: api_url,
        data: { action: "post", model: 'essaygrade', data : JSON.stringify(post_data)}
    }).done(get_courses);
}

$(function(){
    var tokenValue = $.cookie('problemgradercsrftoken');

    $.ajaxSetup({
        data: {csrfmiddlewaretoken: tokenValue },
        headers: {'X-CSRF-Token': tokenValue}
    });
    get_courses()
})<|endoftext|>


<commit_before>'use strict'

const { readFileSync } = require('fs')
const { resolve } = require('path')
const { Server } = require('@hapi/hapi')
const hapiPluginWebsocket = require('hapi-plugin-websocket')
const authFunctionNameExtractor = require('./authFunctionNameExtractor.js')
const debugLog = require('./debugLog.js')
const LambdaFunctionPool = require('./LambdaFunctionPool.js')
const serverlessLog = require('./serverlessLog.js')
const {
  createUniqueId,
  parseQueryStringParameters,
} = require('./utils/index.js')
const {
  createConnectEvent,
  createDisconnectEvent,
  createEvent,
} = require('./websocketHelpers.js')

const { stringify } = JSON

module.exports = class ApiGatewayWebSocket {
  constructor(service, options, config) {
    this._actions = {}
    this._clients = new Map()
    this._config = config
    this._lambdaFunctionPool = new LambdaFunctionPool()
    this._options = options
    this._provider = service.provider
    this._server = null
    this._service = service
    this._websocketsApiRouteSelectionExpression =
      this._provider.websocketsApiRouteSelectionExpression ||
      '$request.body.action'

    this._init()
  }

  _printBlankLine() {
    if (process.env.NODE_ENV !== 'test') {
      console.log()
    }
  }

  _init() {
    // start COPY PASTE FROM HTTP SERVER CODE
    const {
      enforceSecureCookies,
      host,
      httpsProtocol,
      preserveTrailingSlash,
      websocketPort,
    } = this._options

    const serverOptions = {
      host,
      port: websocketPort,
      router: {
        // removes trailing slashes on incoming paths
        stripTrailingSlash: !preserveTrailingSlash,
      },
      state: enforceSecureCookies
        ? {
            isHttpOnly: true,
            isSameSite: false,
            isSecure: true,
          }
        : {
            isHttpOnly: false,
            isSameSite: false,
            isSecure: false,
          },
    }

    // HTTPS support
    if (typeof httpsProtocol === 'string' && httpsProtocol.length > 0) {
      serverOptions.tls = {
        cert: readFileSync(resolve(httpsProtocol, 'cert.pem'), 'ascii'),
        key: readFileSync(resolve(httpsProtocol, 'key.pem'), 'ascii'),
      }
    }

    // Hapijs server
    this._server = new Server(serverOptions)

    // Enable CORS preflight response
    this._server.ext('onPreResponse', (request, h) => {
      if (request.headers.origin) {
        const response = request.response.isBoom
          ? request.response.output
          : request.response

        response.headers['access-control-allow-origin'] = request.headers.origin
        response.headers['access-control-allow-credentials'] = 'true'

        if (request.method === 'options') {
          response.statusCode = 200
          response.headers['access-control-expose-headers'] =
            'content-type, content-length, etag'
          response.headers['access-control-max-age'] = 60 * 10

          if (request.headers['access-control-request-headers']) {
            response.headers['access-control-allow-headers'] =
              request.headers['access-control-request-headers']
          }

          if (request.headers['access-control-request-method']) {
            response.headers['access-control-allow-methods'] =
              request.headers['access-control-request-method']
          }
        }
      }

      return h.continue
    })
    // end COPY PASTE FROM HTTP SERVER CODE
  }

  async createServer() {
    const doAction = async (ws, connectionId, name, event, doDefaultAction) => {
      let action = this._actions[name]

      if (!action && doDefaultAction) action = this._actions.$default
      if (!action) return

      const sendError = (err) => {
        if (ws.readyState === /* OPEN */ 1) {
          ws.send(
            stringify({
              connectionId,
              message: 'Internal server error',
              requestId: '1234567890',
            }),
          )
        }

        // mimic AWS behaviour (close connection) when the $connect action handler throws
        if (name === '$connect') {
          ws.close()
        }

        debugLog(`Error in handler of action ${action}`, err)
      }

      const { functionName, functionObj } = action

      const lambdaFunction = this._lambdaFunctionPool.get(
        functionName,
        functionObj,
        this._provider,
        this._config,
        this._options,
      )

      const requestId = createUniqueId()

      lambdaFunction.setEvent(event)
      lambdaFunction.setRequestId(requestId)

      // let result

      try {
        /* result = */ await lambdaFunction.runHandler()

        const {
          billedExecutionTimeInMillis,
          executionTimeInMillis,
        } = lambdaFunction

        serverlessLog(
          `(λ: ${functionName}) RequestId: ${requestId}  Duration: ${executionTimeInMillis.toFixed(
            2,
          )} ms  Billed Duration: ${billedExecutionTimeInMillis} ms`,
        )

        // TODO what to do with "result"?
      } catch (err) {
        sendError(err)
      }
    }

    this._server.route({
      method: 'POST',
      path: '/',
      options: {
        payload: {
          allow: 'application/json',
          output: 'data',
          parse: true,
        },
        plugins: {
          websocket: {
            initially: false,
            only: true,
            connect: ({ ws, req }) => {
              const queryStringParameters = parseQueryStringParameters(req.url)
              const connection = {
                connectionId: createUniqueId(),
                connectionTime: Date.now(),
              }

              debugLog(`connect:${connection.connectionId}`)

              this._clients.set(ws, connection)

              let event = createConnectEvent(
                '$connect',
                'CONNECT',
                connection,
                this._options,
              )

              if (Object.keys(queryStringParameters || {}).length > 0) {
                event = { queryStringParameters, ...event }
              }

              doAction(ws, connection.connectionId, '$connect', event, false)
            },
            disconnect: ({ ws }) => {
              const connection = this._clients.get(ws)

              debugLog(`disconnect:${connection.connectionId}`)

              this._clients.delete(ws)

              const event = createDisconnectEvent(
                '$disconnect',
                'DISCONNECT',
                connection,
              )

              doAction(ws, connection.connectionId, '$disconnect', event, false)
            },
          },
        },
      },
      handler: (request, h) => {
        const { initially, ws } = request.websocket()

        if (!request.payload || initially) {
          return h.response().code(204)
        }

        const connection = this._clients.get(ws)
        let actionName = null

        if (
          this._websocketsApiRouteSelectionExpression.startsWith(
            '$request.body.',
          )
        ) {
          actionName = request.payload

          if (typeof actionName === 'object') {
            this._websocketsApiRouteSelectionExpression
              .replace('$request.body.', '')
              .split('.')
              .forEach((key) => {
                if (actionName) {
                  actionName = actionName[key]
                }
              })
          } else actionName = null
        }

        if (typeof actionName !== 'string') {
          actionName = null
        }

        const action = actionName || '$default'

        debugLog(`action:${action} on connection=${connection.connectionId}`)

        const event = createEvent(
          action,
          'MESSAGE',
          connection,
          request.payload,
        )

        doAction(ws, connection.connectionId, action, event, true)

        return h.response().code(204)
      },
    })

    this._server.route({
      handler: (request, h) => h.response().code(426),
      method: 'GET',
      path: '/{path*}',
    })

    this._server.route({
      method: 'POST',
      path: '/@connections/{connectionId}',
      options: {
        payload: {
          parse: false,
        },
      },
      handler: (request, h) => {
        debugLog(`got POST to ${request.url}`)

        const ws = this._getByConnectionId(
          this._clients,
          request.params.connectionId,
        )

        if (!ws) return h.response().code(410)
        if (!request.payload) return ''

        ws.send(request.payload.toString())

        debugLog(`sent data to connection:${request.params.connectionId}`)

        return ''
      },
    })

    this._server.route({
      options: {
        payload: {
          parse: false,
        },
      },
      method: 'DELETE',
      path: '/@connections/{connectionId}',
      handler: (request, h) => {
        debugLog(`got DELETE to ${request.url}`)

        const ws = this._getByConnectionId(
          this._clients,
          request.params.connectionId,
        )

        if (!ws) return h.response().code(410)

        ws.close()

        debugLog(`closed connection:${request.params.connectionId}`)

        return ''
      },
    })
  }

  _getByConnectionId(map, searchValue) {
    for (const [key, connection] of map.entries()) {
      if (connection.connectionId === searchValue) return key
    }

    return undefined
  }

  createWsAction(functionName, functionObj, websocket) {
    this._printBlankLine()

    const actionName = websocket.route
    const action = {
      functionName,
      functionObj,
    }

    this._actions[actionName] = action
    serverlessLog(`Action '${websocket.route}'`)
  }

  _extractAuthFunctionName(endpoint) {
    const result = authFunctionNameExtractor(endpoint, serverlessLog)

    return result.unsupportedAuth ? null : result.authorizerName
  }

  async registerPlugins() {
    try {
      await this._server.register(hapiPluginWebsocket)
    } catch (e) {
      serverlessLog(e)
    }
  }

  async start() {
    const { host, httpsProtocol, websocketPort } = this._options

    try {
      await this._server.start()
    } catch (error) {
      console.error(
        `Unexpected error while starting serverless-offline websocket server on port ${websocketPort}:`,
        error,
      )
      process.exit(1)
    }

    this._printBlankLine()
    serverlessLog(
      `Offline [websocket] listening on ws${
        httpsProtocol ? 's' : ''
      }://${host}:${websocketPort}`,
    )
  }

  // stops the hapi server
  stop(timeout) {
    return this._server.stop({
      timeout,
    })
  }
}
<commit_msg>Simplify, re-use instance field<commit_after>'use strict'

const { readFileSync } = require('fs')
const { resolve } = require('path')
const { Server } = require('@hapi/hapi')
const hapiPluginWebsocket = require('hapi-plugin-websocket')
const authFunctionNameExtractor = require('./authFunctionNameExtractor.js')
const debugLog = require('./debugLog.js')
const LambdaFunctionPool = require('./LambdaFunctionPool.js')
const serverlessLog = require('./serverlessLog.js')
const {
  createUniqueId,
  parseQueryStringParameters,
} = require('./utils/index.js')
const {
  createConnectEvent,
  createDisconnectEvent,
  createEvent,
} = require('./websocketHelpers.js')

const { stringify } = JSON

module.exports = class ApiGatewayWebSocket {
  constructor(service, options, config) {
    this._actions = {}
    this._clients = new Map()
    this._config = config
    this._lambdaFunctionPool = new LambdaFunctionPool()
    this._options = options
    this._provider = service.provider
    this._server = null
    this._service = service
    this._websocketsApiRouteSelectionExpression =
      this._provider.websocketsApiRouteSelectionExpression ||
      '$request.body.action'

    this._init()
  }

  _printBlankLine() {
    if (process.env.NODE_ENV !== 'test') {
      console.log()
    }
  }

  _init() {
    // start COPY PASTE FROM HTTP SERVER CODE
    const {
      enforceSecureCookies,
      host,
      httpsProtocol,
      preserveTrailingSlash,
      websocketPort,
    } = this._options

    const serverOptions = {
      host,
      port: websocketPort,
      router: {
        // removes trailing slashes on incoming paths
        stripTrailingSlash: !preserveTrailingSlash,
      },
      state: enforceSecureCookies
        ? {
            isHttpOnly: true,
            isSameSite: false,
            isSecure: true,
          }
        : {
            isHttpOnly: false,
            isSameSite: false,
            isSecure: false,
          },
    }

    // HTTPS support
    if (typeof httpsProtocol === 'string' && httpsProtocol.length > 0) {
      serverOptions.tls = {
        cert: readFileSync(resolve(httpsProtocol, 'cert.pem'), 'ascii'),
        key: readFileSync(resolve(httpsProtocol, 'key.pem'), 'ascii'),
      }
    }

    // Hapijs server
    this._server = new Server(serverOptions)

    // Enable CORS preflight response
    this._server.ext('onPreResponse', (request, h) => {
      if (request.headers.origin) {
        const response = request.response.isBoom
          ? request.response.output
          : request.response

        response.headers['access-control-allow-origin'] = request.headers.origin
        response.headers['access-control-allow-credentials'] = 'true'

        if (request.method === 'options') {
          response.statusCode = 200
          response.headers['access-control-expose-headers'] =
            'content-type, content-length, etag'
          response.headers['access-control-max-age'] = 60 * 10

          if (request.headers['access-control-request-headers']) {
            response.headers['access-control-allow-headers'] =
              request.headers['access-control-request-headers']
          }

          if (request.headers['access-control-request-method']) {
            response.headers['access-control-allow-methods'] =
              request.headers['access-control-request-method']
          }
        }
      }

      return h.continue
    })
    // end COPY PASTE FROM HTTP SERVER CODE
  }

  async createServer() {
    const doAction = async (ws, connectionId, name, event, doDefaultAction) => {
      let action = this._actions[name]

      if (!action && doDefaultAction) action = this._actions.$default
      if (!action) return

      const sendError = (err) => {
        if (ws.readyState === /* OPEN */ 1) {
          ws.send(
            stringify({
              connectionId,
              message: 'Internal server error',
              requestId: '1234567890',
            }),
          )
        }

        // mimic AWS behaviour (close connection) when the $connect action handler throws
        if (name === '$connect') {
          ws.close()
        }

        debugLog(`Error in handler of action ${action}`, err)
      }

      const { functionName, functionObj } = action

      const lambdaFunction = this._lambdaFunctionPool.get(
        functionName,
        functionObj,
        this._provider,
        this._config,
        this._options,
      )

      const requestId = createUniqueId()

      lambdaFunction.setEvent(event)
      lambdaFunction.setRequestId(requestId)

      // let result

      try {
        /* result = */ await lambdaFunction.runHandler()

        const {
          billedExecutionTimeInMillis,
          executionTimeInMillis,
        } = lambdaFunction

        serverlessLog(
          `(λ: ${functionName}) RequestId: ${requestId}  Duration: ${executionTimeInMillis.toFixed(
            2,
          )} ms  Billed Duration: ${billedExecutionTimeInMillis} ms`,
        )

        // TODO what to do with "result"?
      } catch (err) {
        sendError(err)
      }
    }

    this._server.route({
      method: 'POST',
      path: '/',
      options: {
        payload: {
          allow: 'application/json',
          output: 'data',
          parse: true,
        },
        plugins: {
          websocket: {
            initially: false,
            only: true,
            connect: ({ ws, req }) => {
              const queryStringParameters = parseQueryStringParameters(req.url)
              const connection = {
                connectionId: createUniqueId(),
                connectionTime: Date.now(),
              }

              debugLog(`connect:${connection.connectionId}`)

              this._clients.set(ws, connection)

              let event = createConnectEvent(
                '$connect',
                'CONNECT',
                connection,
                this._options,
              )

              if (Object.keys(queryStringParameters || {}).length > 0) {
                event = { queryStringParameters, ...event }
              }

              doAction(ws, connection.connectionId, '$connect', event, false)
            },
            disconnect: ({ ws }) => {
              const connection = this._clients.get(ws)

              debugLog(`disconnect:${connection.connectionId}`)

              this._clients.delete(ws)

              const event = createDisconnectEvent(
                '$disconnect',
                'DISCONNECT',
                connection,
              )

              doAction(ws, connection.connectionId, '$disconnect', event, false)
            },
          },
        },
      },
      handler: (request, h) => {
        const { initially, ws } = request.websocket()

        if (!request.payload || initially) {
          return h.response().code(204)
        }

        const connection = this._clients.get(ws)
        let actionName = null

        if (
          this._websocketsApiRouteSelectionExpression.startsWith(
            '$request.body.',
          )
        ) {
          actionName = request.payload

          if (typeof actionName === 'object') {
            this._websocketsApiRouteSelectionExpression
              .replace('$request.body.', '')
              .split('.')
              .forEach((key) => {
                if (actionName) {
                  actionName = actionName[key]
                }
              })
          } else actionName = null
        }

        if (typeof actionName !== 'string') {
          actionName = null
        }

        const action = actionName || '$default'

        debugLog(`action:${action} on connection=${connection.connectionId}`)

        const event = createEvent(
          action,
          'MESSAGE',
          connection,
          request.payload,
        )

        doAction(ws, connection.connectionId, action, event, true)

        return h.response().code(204)
      },
    })

    this._server.route({
      handler: (request, h) => h.response().code(426),
      method: 'GET',
      path: '/{path*}',
    })

    this._server.route({
      method: 'POST',
      path: '/@connections/{connectionId}',
      options: {
        payload: {
          parse: false,
        },
      },
      handler: (request, h) => {
        debugLog(`got POST to ${request.url}`)

        const ws = this._getByConnectionId(request.params.connectionId)

        if (!ws) return h.response().code(410)
        if (!request.payload) return ''

        ws.send(request.payload.toString())

        debugLog(`sent data to connection:${request.params.connectionId}`)

        return ''
      },
    })

    this._server.route({
      options: {
        payload: {
          parse: false,
        },
      },
      method: 'DELETE',
      path: '/@connections/{connectionId}',
      handler: (request, h) => {
        debugLog(`got DELETE to ${request.url}`)

        const ws = this._getByConnectionId(request.params.connectionId)

        if (!ws) return h.response().code(410)

        ws.close()

        debugLog(`closed connection:${request.params.connectionId}`)

        return ''
      },
    })
  }

  _getByConnectionId(connectionId) {
    for (const [key, connection] of this._clients.entries()) {
      if (connection.connectionId === connectionId) return key
    }

    return undefined
  }

  createWsAction(functionName, functionObj, websocket) {
    this._printBlankLine()

    const actionName = websocket.route
    const action = {
      functionName,
      functionObj,
    }

    this._actions[actionName] = action
    serverlessLog(`Action '${websocket.route}'`)
  }

  _extractAuthFunctionName(endpoint) {
    const result = authFunctionNameExtractor(endpoint, serverlessLog)

    return result.unsupportedAuth ? null : result.authorizerName
  }

  async registerPlugins() {
    try {
      await this._server.register(hapiPluginWebsocket)
    } catch (e) {
      serverlessLog(e)
    }
  }

  async start() {
    const { host, httpsProtocol, websocketPort } = this._options

    try {
      await this._server.start()
    } catch (error) {
      console.error(
        `Unexpected error while starting serverless-offline websocket server on port ${websocketPort}:`,
        error,
      )
      process.exit(1)
    }

    this._printBlankLine()
    serverlessLog(
      `Offline [websocket] listening on ws${
        httpsProtocol ? 's' : ''
      }://${host}:${websocketPort}`,
    )
  }

  // stops the hapi server
  stop(timeout) {
    return this._server.stop({
      timeout,
    })
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 by Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";

try {

Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("messages", {
    exports: ["Messages", "messages", "_"],
    require: ["services", "util"]
}, this);

// TODO: Lazy instantiation
var Messages = Module("messages", {

    init: function init() {
        let self = this;

        this.bundle = services.stringBundle.createBundle(JSMLoader.getTarget("dactyl://locale/messages.properties"));

        this._ = Class("_", String, {
            init: function _(message) {
                this.args = arguments;
            },
            message: Class.memoize(function () {
                let message = this.args[0];

                if (this.args.length > 1) {
                    let args = Array.slice(this.args, 1);
                    return self.format(message + "-" + args.length, args, null) || self.format(message, args);
                }
                return self.get(message);
            }),
            valueOf: function valueOf() this.message,
            toString: function toString() this.message
        });

        let seen = {};
        for (let { key } in this.iterate()) {
            if (!set.add(seen, key))
                this._[key] = this[key] = {
                    __noSuchMethod__: function __(prop, args) self._.apply(self, [prop].concat(args))
                };
        }
    },

    iterate: function () let (bundle = this.bundle)
        iter(prop.QueryInterface(Ci.nsIPropertyElement) for (prop in iter(bundle.getSimpleEnumeration()))),

    cleanup: function cleanup() {
        services.stringBundle.flushBundles();
    },

    get: function get(value, default_) {
        try {
            return this.bundle.GetStringFromName(value);
        }
        catch (e) {
            // Report error so tests fail, but don't throw
            if (arguments.length < 2)
                util.reportError(Error("Invalid locale string: " + value + ": " + e));
            return arguments.length > 1 ? default_ : value;
        }
    },

    format: function format(value, args, default_) {
        try {
            return this.bundle.formatStringFromName(value, args, args.length);
        }
        catch (e) {
            // Report error so tests fail, but don't throw
            if (arguments.length < 3)
                util.reportError(Error("Invalid locale string: " + value + ": " + e));
            return arguments.length > 2 ? default_ : value;
        }
    }

}, {
    Localized: Class("Localized", Class.Property, {
        init: function init(prop, obj) {
            let _prop = "localized_" + prop;
            if (this.initialized) {
                /*
                if (config.locale === "en-US")
                    return { configurable: true, enumerable: true, value: null, writable: true };
                */

                obj[_prop] = this.default;
                return {
                    get: function get() {
                        let self = this;
                        let value = this[_prop];

                        function getter(key, default_) function getter() messages.get([name, key].join("."), default_);

                        let name = [this.constructor.className.toLowerCase(), this.identifier || this.name, prop].join(".");
                        if (!isObject(value))
                            value = messages.get(name, value)
                        else if (isArray(value))
                            // Deprecated
                            iter(value).forEach(function ([k, v]) {
                                if (isArray(v))
                                    memoize(v, 1, getter(v[0], v[1]));
                                else
                                    memoize(value, k, getter(k, v));
                            });
                        else
                            iter(value).forEach(function ([k, v]) {
                                memoize(value, k, function () messages.get([name, k].join("."), v));
                            });

                        return Class.replaceProperty(this, prop, value);
                    },
                    set: function set(val) this[_prop] = val
                }
            }
            this.default = prop;
            this.initialized = true;
        }
    })
}, {
    javascript: function initJavascript(dactyl, modules, window) {
        modules.JavaScript.setCompleter([this._, this.get, this.format], [
            function (context) {
                context.keys = { text: "key", description: "value" };
                return messages.iterate();
            }
        ]);
    }
});

var { _ } = messages;

endModule();

} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }

// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
<commit_msg>Implement string bundle cascading.<commit_after>// Copyright (c) 2011 by Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";

try {

Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("messages", {
    exports: ["Messages", "messages", "_"],
    require: ["services", "util"]
}, this);

// TODO: Lazy instantiation
var Messages = Module("messages", {

    init: function init(name) {
        let self = this;
        name = name || "messages";

        this.bundles = array.uniq([JSMLoader.getTarget("dactyl://locale/" + name + ".properties"),
                                   JSMLoader.getTarget("dactyl://locale-local/" + name + ".properties"),
                                   "resource://dactyl-locale/en-US/" + name + ".properties",
                                   "resource://dactyl-locale-local/en-US/" + name + ".properties"])
                            .map(services.stringBundle.createBundle)
                            .filter(function (bundle) { try { bundle.getSimpleEnumeration(); return true; } catch (e) { return false; } });

        this._ = Class("_", String, {
            init: function _(message) {
                this.args = arguments;
            },
            message: Class.memoize(function () {
                let message = this.args[0];

                if (this.args.length > 1) {
                    let args = Array.slice(this.args, 1);
                    return self.format(message + "-" + args.length, args, null) || self.format(message, args);
                }
                return self.get(message);
            }),
            valueOf: function valueOf() this.message,
            toString: function toString() this.message
        });

        let seen = {};
        for (let { key } in this.iterate()) {
            if (!set.add(seen, key))
                this._[key] = this[key] = {
                    __noSuchMethod__: function __(prop, args) self._.apply(self, [prop].concat(args))
                };
        }
    },

    iterate: function () let (bundle = this.bundles[0])
        iter(prop.QueryInterface(Ci.nsIPropertyElement) for (prop in iter(bundle.getSimpleEnumeration()))),

    cleanup: function cleanup() {
        services.stringBundle.flushBundles();
    },

    get: function get(value, default_) {
        for (let bundle in values(this.bundles))
            try {
                return bundle.GetStringFromName(value);
            }
            catch (e) {}

        // Report error so tests fail, but don't throw
        if (arguments.length < 2)
            util.reportError(Error("Invalid locale string: " + value));
        return arguments.length > 1 ? default_ : value;
    },

    format: function format(value, args, default_) {
        for (let bundle in values(this.bundles))
            try {
                return bundle.formatStringFromName(value, args, args.length);
            }
            catch (e) {}

        // Report error so tests fail, but don't throw
        if (arguments.length < 3)
            util.reportError(Error("Invalid locale string: " + value));
        return arguments.length > 2 ? default_ : value;
    }

}, {
    Localized: Class("Localized", Class.Property, {
        init: function init(prop, obj) {
            let _prop = "localized_" + prop;
            if (this.initialized) {
                /*
                if (config.locale === "en-US")
                    return { configurable: true, enumerable: true, value: null, writable: true };
                */

                obj[_prop] = this.default;
                return {
                    get: function get() {
                        let self = this;
                        let value = this[_prop];

                        function getter(key, default_) function getter() messages.get([name, key].join("."), default_);

                        let name = [this.constructor.className.toLowerCase(), this.identifier || this.name, prop].join(".");
                        if (!isObject(value))
                            value = messages.get(name, value)
                        else if (isArray(value))
                            // Deprecated
                            iter(value).forEach(function ([k, v]) {
                                if (isArray(v))
                                    memoize(v, 1, getter(v[0], v[1]));
                                else
                                    memoize(value, k, getter(k, v));
                            });
                        else
                            iter(value).forEach(function ([k, v]) {
                                memoize(value, k, function () messages.get([name, k].join("."), v));
                            });

                        return Class.replaceProperty(this, prop, value);
                    },
                    set: function set(val) this[_prop] = val
                }
            }
            this.default = prop;
            this.initialized = true;
        }
    })
}, {
    javascript: function initJavascript(dactyl, modules, window) {
        modules.JavaScript.setCompleter([this._, this.get, this.format], [
            function (context) {
                context.keys = { text: "key", description: "value" };
                return messages.iterate();
            }
        ]);
    }
});

var { _ } = messages;

endModule();

} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }

// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
<|endoftext|>


<commit_before>"use strict";

/*global nodeca*/

var Path = require('path');
var Fs = require('fs');
// nodeca
var NLib = require('nlib');

var Async = NLib.Vendor.Async;
var FsTools = NLib.Vendor.FsTools;

var SEEDS_DIR = 'db/seeds';

function get_app_path(app_name) {
  for (var i = 0; i < nodeca.runtime.apps.length; i++) {
    if (app_name === nodeca.runtime.apps[i].name) {
      return nodeca.runtime.apps[i].root;
    }
  }
  return null;
}

function seed_run(app_name, seed_path, callback) {
  console.log('Applying seed...\n');
  require(seed_path)(function (err) {
    var prefix = '  ' + app_name + ':' + Path.basename(seed_path) + ' -- ';

    if (err) {
      console.log(prefix + 'failed');
      callback(err);
      return;
    }

    console.log(prefix + 'success');
    process.exit(0);
  });
}

module.exports.parserParameters = {
  addHelp: true,
  description: 'That will run `.<app_name>/db/seeds/<seed_name>.js` if exists. ' +
    'Or, all seeds from `./db/seeds/seed-name/` folder. If <seed-name>' +
    'missed, then script will show all available seeds for given app. ' +
    'If `-a` missed, then all seed for all apps will be shown.',
  epilog : 'Note: Loading seeds is limited to development/test enviroment. ' +
    'If you really need to run seed  on production/stageing, use ' +
    'option -f.',
  help: 'show or run existing seeds'
};

module.exports.commandLineArguments = [
  {
    args: ['-f'],
    options: {
      help: 'run without env checking',
      action: 'storeTrue'
    }
  },
  {
    args: ['-a', '--app'],
    options: {
      help: 'application name',
      type: 'string'
    }
  },
  {
    args: ['-n'],
    options: {
      metavar: 'SEED_NUMBER',
      dest: 'number',
      help: 'run seed by number',
      type: 'int'
    }
  },
  {
    args: ['seed'],
    options: {
      metavar: 'SEED_NAME',
      help: 'seed name',
      nargs: '?',
      defaultValue: null
    }
  },
];

module.exports.run = function (args, callback) {
  var app_name = args.app;
  var seed_name = args.seed;
  var seed_pos =  args.number ? args.number - 1 : -1;

  Async.series([
    require('../lib/init/redis'),
    require('../lib/init/mongoose'),
    NLib.InitStages.loadModels
  ], function (err) {
    if (err) {
      callback(err);
      return;
    }

    // execute seed by name
    if (!!app_name && !!seed_name) {
      var env = nodeca.runtime.env;
      if ('development' !== env && 'testing' !== env && !args.force) {
        console.log('Error: Can\'t run seed from ' + env + ' enviroment. Please, use -f to force.');
        process.exit(1);
      }

      var seed_path = Path.join(get_app_path(app_name), SEEDS_DIR, seed_name);
      if (!Fs.existsSync(seed_path)) {
        console.log('Error: Application "' + app_name + '"does not have "' + seed_name);
        process.exit(1);
      }

      seed_run(app_name, seed_path, callback);
    }
    else {
      var apps;
      if (app_name) {
        apps = [{name: app_name, root: get_app_path(app_name)}];
      }
      else {
        apps = nodeca.runtime.apps;
      }

      // collect seeds
      var seed_list = [];
      Async.forEachSeries(apps, function (app, next_app) {
        var seed_dir = Path.join(app.root, SEEDS_DIR);
        FsTools.walk(seed_dir, /w*\.js$/, function (file, stats, next_file) {
          seed_list.push({
            name: app.name,
            seed_path: file
          });
          next_file();
        }, next_app);
      }, function (err) {
        if (err) {
          callback(err);
        }
        // execute seed by number
        if (!!args.number && seed_list[seed_pos]) {
          seed_run(seed_list[seed_pos].name, seed_list[seed_pos].seed_path, callback);
        }
        // display seed list
        else {
          if (!!args.number) {
            console.log(args.number + ' seed not found\n');
          }
          console.log('Available seeds:\n');
          for (var i = 0; i < seed_list.length; i++) {
            console.log('  ' + (i + 1) + '. ' + seed_list[i].name + ': ' + Path.basename(seed_list[i].seed_path));
          }

          console.log('\nSeeds are shown in `<APP>: <SEED_NAME>` form.');
          console.log('See `seed --help` for details');
          process.exit(0);
        }
      });
    }
  });
};
<commit_msg>Update seed CLI script<commit_after>"use strict";

/*global N*/

// stdlib
var path  = require('path');
var fs    = require('fs');

// 3rd-party
var async   = require("async");
var fstools = require("fs-tools");

////////////////////////////////////////////////////////////////////////////////

var SEEDS_DIR = 'db/seeds';

////////////////////////////////////////////////////////////////////////////////

function get_app_path(app_name) {
  for (var i = 0; i < N.runtime.apps.length; i++) {
    if (app_name === N.runtime.apps[i].name) {
      return N.runtime.apps[i].root;
    }
  }
  return null;
}

function seed_run(app_name, seed_path, callback) {
  console.log('Applying seed...\n');

  require(seed_path)(function (err) {
    var prefix = '  ' + app_name + ':' + path.basename(seed_path) + ' -- ';

    if (err) {
      console.log(prefix + 'failed');
      callback(err);
      return;
    }

    console.log(prefix + 'success');
    process.exit(0);
  });
}

module.exports.parserParameters = {
  addHelp: true,
  description: 'That will run `.<app_name>/db/seeds/<seed_name>.js` if exists. ' +
    'Or, all seeds from `./db/seeds/seed-name/` folder. If <seed-name>' +
    'missed, then script will show all available seeds for given app. ' +
    'If `-a` missed, then all seed for all apps will be shown.',
  epilog : 'Note: Loading seeds is limited to development/test enviroment. ' +
    'If you really need to run seed  on production/stageing, use ' +
    'option -f.',
  help: 'show or run existing seeds'
};

module.exports.commandLineArguments = [
  {
    args: ['-f'],
    options: {
      help: 'run without env checking',
      action: 'storeTrue'
    }
  },
  {
    args: ['-a', '--app'],
    options: {
      help: 'application name',
      type: 'string'
    }
  },
  {
    args: ['-n'],
    options: {
      metavar: 'SEED_NUMBER',
      dest: 'number',
      help: 'run seed by number',
      type: 'int'
    }
  },
  {
    args: ['seed'],
    options: {
      metavar: 'SEED_NAME',
      help: 'seed name',
      nargs: '?',
      defaultValue: null
    }
  },
];

module.exports.run = function (args, callback) {
  var app_name = args.app;
  var seed_name = args.seed;
  var seed_pos =  args.number ? args.number - 1 : -1;

  async.series([
    require('../lib/system/init/redis'),
    require('../lib/system/init/mongoose'),
    require('../lib/system/init/models'),
    require('../lib/system/init/stores'),
    require('../lib/system/init/check_migrations'),
  ], function (err) {
    if (err) {
      callback(err);
      return;
    }

    // execute seed by name
    if (!!app_name && !!seed_name) {
      var env = N.runtime.env;
      if ('development' !== env && 'testing' !== env && !args.force) {
        console.log('Error: Can\'t run seed from ' + env + ' enviroment. Please, use -f to force.');
        process.exit(1);
      }

      var seed_path = path.join(get_app_path(app_name), SEEDS_DIR, seed_name);
      if (!fs.existsSync(seed_path)) {
        console.log('Error: Application "' + app_name + '"does not have "' + seed_name);
        process.exit(1);
      }

      seed_run(app_name, seed_path, callback);
    }
    else {
      var apps;
      if (app_name) {
        apps = [{name: app_name, root: get_app_path(app_name)}];
      }
      else {
        apps = N.runtime.apps;
      }

      // collect seeds
      var seed_list = [];
      async.forEachSeries(apps, function (app, next_app) {
        var seed_dir = path.join(app.root, SEEDS_DIR);
        fstools.walk(seed_dir, /w*\.js$/, function (file, stats, next_file) {
          seed_list.push({
            name: app.name,
            seed_path: file
          });
          next_file();
        }, next_app);
      }, function (err) {
        if (err) {
          callback(err);
          return;
        }

        if (!!args.number && seed_list[seed_pos]) {
          // execute seed by number
          seed_run(seed_list[seed_pos].name, seed_list[seed_pos].seed_path, callback);
        } else {
          // display seed list
          if (!!args.number) {
            console.log(args.number + ' seed not found\n');
          }

          console.log('Available seeds:\n');

          for (var i = 0; i < seed_list.length; i++) {
            console.log('  ' + (i + 1) + '. ' + seed_list[i].name + ': ' + path.basename(seed_list[i].seed_path));
          }

          console.log('\nSeeds are shown in `<APP>: <SEED_NAME>` form.');
          console.log('See `seed --help` for details');
          process.exit(0);
        }
      });
    }
  });
};
<|endoftext|>


<commit_before>import * as messages from "../../../messages";
import * as t from "../../../types";

export var check = t.isPattern;

export function ForOfStatement(node, parent, scope, file) {
  var left = node.left;

  if (t.isPattern(left)) {
    // for ({ length: k } in { abc: 3 });

    var temp = scope.generateUidIdentifier("ref");

    node.left = t.variableDeclaration("var", [
      t.variableDeclarator(temp)
    ]);

    t.ensureBlock(node);

    node.body.body.unshift(t.variableDeclaration("var", [
      t.variableDeclarator(left, temp)
    ]));

    return;
  }

  if (!t.isVariableDeclaration(left)) return;

  var pattern = left.declarations[0].id;
  if (!t.isPattern(pattern)) return;

  var key = scope.generateUidIdentifier("ref");
  node.left = t.variableDeclaration(left.kind, [
    t.variableDeclarator(key, null)
  ]);

  var nodes = [];

  var destructuring = new DestructuringTransformer({
    kind: left.kind,
    file: file,
    scope: scope,
    nodes: nodes
  });

  destructuring.init(pattern, key);

  t.ensureBlock(node);

  var block = node.body;
  block.body = nodes.concat(block.body);
}

export { ForOfStatement as ForInStatement };

exports.Function = function (node, parent, scope, file) {
  var nodes = [];

  var hasDestructuring = false;

  node.params = node.params.map(function (pattern, i) {
    if (!t.isPattern(pattern)) return pattern;

    hasDestructuring = true;
    var ref = scope.generateUidIdentifier("ref");

    var destructuring = new DestructuringTransformer({
      blockHoist: node.params.length - i,
      nodes:      nodes,
      scope:      scope,
      file:       file,
      kind:       "let"
    });
    destructuring.init(pattern, ref);

    return ref;
  });

  if (!hasDestructuring) return;

  file.checkNode(nodes);
  t.ensureBlock(node);

  var block = node.body;
  block.body = nodes.concat(block.body);
};

export function CatchClause(node, parent, scope, file) {
  var pattern = node.param;
  if (!t.isPattern(pattern)) return;

  var ref = scope.generateUidIdentifier("ref");
  node.param = ref;

  var nodes = [];

  var destructuring = new DestructuringTransformer({
    kind: "let",
    file: file,
    scope: scope,
    nodes: nodes
  });
  destructuring.init(pattern, ref);

  node.body.body = nodes.concat(node.body.body);

  return node;
}

export function ExpressionStatement(node, parent, scope, file) {
  var expr = node.expression;
  if (expr.type !== "AssignmentExpression") return;
  if (!t.isPattern(expr.left)) return;
  if (file.isConsequenceExpressionStatement(node)) return;

  var destructuring = new DestructuringTransformer({
    operator: expr.operator,
    scope:    scope,
    file:     file,
  });

  return destructuring.init(expr.left, expr.right);
}

export function AssignmentExpression(node, parent, scope, file) {
  if (!t.isPattern(node.left)) return;

  var ref = scope.generateUidIdentifier("temp");
  scope.push({ id: ref });

  var nodes = [];
  nodes.push(t.expressionStatement(t.assignmentExpression("=", ref, node.right)));

  var destructuring = new DestructuringTransformer({
    operator: node.operator,
    file: file,
    scope: scope,
    nodes: nodes
  });
  destructuring.init(node.left, ref);

  nodes.push(t.expressionStatement(ref));

  return nodes;
}

function variableDeclarationHasPattern(node) {
  for (var i = 0; i < node.declarations.length; i++) {
    if (t.isPattern(node.declarations[i].id)) {
      return true;
    }
  }
  return false;
}

export function VariableDeclaration(node, parent, scope, file) {
  if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;
  if (!variableDeclarationHasPattern(node)) return;

  var nodes = [];
  var declar;

  for (var i = 0; i < node.declarations.length; i++) {
    declar = node.declarations[i];

    var patternId = declar.init;
    var pattern   = declar.id;

    var destructuring = new DestructuringTransformer({
      nodes: nodes,
      scope: scope,
      kind:  node.kind,
      file:  file
    });

    if (t.isPattern(pattern) && patternId) {
      destructuring.init(pattern, patternId);

      if (+i !== node.declarations.length - 1) {
        // we aren't the last declarator so let's just make the
        // last transformed node inherit from us
        t.inherits(nodes[nodes.length - 1], declar);
      }
    } else {
      nodes.push(t.inherits(destructuring.buildVariableAssignment(declar.id, declar.init), declar));
    }
  }

  if (!t.isProgram(parent) && !t.isBlockStatement(parent)) {
    // https://github.com/babel/babel/issues/113
    // for (let [x] = [0]; false;) {}

    declar = null;

    for (i = 0; i < nodes.length; i++) {
      node = nodes[i];
      declar ||= t.variableDeclaration(node.kind, []);

      if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
        throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
      }

      declar.declarations = declar.declarations.concat(node.declarations);
    }

    return declar;
  }

  return nodes;
}

function hasRest(pattern) {
  for (var i = 0; i < pattern.elements.length; i++) {
    if (t.isRestElement(pattern.elements[i])) {
      return true;
    }
  }
  return false;
}

var arrayUnpackVisitor = {
  enter(node, parent, scope, state) {
    if (this.isReferencedIdentifier() && state.bindings[node.name]) {
      state.deopt = true;
      this.stop();
    }
  }
};

class DestructuringTransformer {
  constructor(opts) {
    this.blockHoist = opts.blockHoist;
    this.operator   = opts.operator;
    this.nodes      = opts.nodes || [];
    this.scope      = opts.scope;
    this.file       = opts.file;
    this.kind       = opts.kind;
  }

  buildVariableAssignment(id, init) {
    var op = this.operator;
    if (t.isMemberExpression(id)) op = "=";

    var node;

    if (op) {
      node = t.expressionStatement(t.assignmentExpression(op, id, init));
    } else {
      node = t.variableDeclaration(this.kind, [
        t.variableDeclarator(id, init)
      ]);
    }

    node._blockHoist = this.blockHoist;

    return node;
  }

  buildVariableDeclaration(id, init) {
    var declar = t.variableDeclaration("var", [
      t.variableDeclarator(id, init)
    ]);
    declar._blockHoist = this.blockHoist;
    return declar;
  }

  push(id, init) {
    if (t.isObjectPattern(id)) {
      this.pushObjectPattern(id, init);
    } else if (t.isArrayPattern(id)) {
      this.pushArrayPattern(id, init);
    } else if (t.isAssignmentPattern(id)) {
      this.pushAssignmentPattern(id, init);
    } else {
      this.nodes.push(this.buildVariableAssignment(id, init));
    }
  }

  pushAssignmentPattern(pattern, valueRef) {
    // we need to assign the current value of the assignment to avoid evaluating
    // it more than once

    var tempValueRef = this.scope.generateUidBasedOnNode(valueRef);

    var declar = t.variableDeclaration("var", [
      t.variableDeclarator(tempValueRef, valueRef)
    ]);
    declar._blockHoist = this.blockHoist;
    this.nodes.push(declar);

    //

    var tempConditional = t.conditionalExpression(
      t.binaryExpression("===", tempValueRef, t.identifier("undefined")),
      pattern.right,
      tempValueRef
    );

    var left = pattern.left;
    if (t.isPattern(left)) {
      this.nodes.push(t.expressionStatement(
        t.assignmentExpression("=", tempValueRef, tempConditional)
      ));
      this.push(left, tempValueRef);
    } else {
      this.nodes.push(this.buildVariableAssignment(left, tempConditional));
    }
  }

  pushObjectSpread(pattern, objRef, spreadProp, spreadPropIndex) {
    // get all the keys that appear in this object before the current spread

    var keys = [];

    for (var i = 0; i < pattern.properties.length; i++) {
      var prop = pattern.properties[i];

      // we've exceeded the index of the spread property to all properties to the
      // right need to be ignored
      if (i >= spreadPropIndex) break;

      // ignore other spread properties
      if (t.isSpreadProperty(prop)) continue;

      var key = prop.key;
      if (t.isIdentifier(key)) key = t.literal(prop.key.name);
      keys.push(key);
    }

    keys = t.arrayExpression(keys);

    //

    var value = t.callExpression(this.file.addHelper("object-without-properties"), [objRef, keys]);
    this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
  }

  pushObjectProperty(prop, propRef) {
    if (t.isLiteral(prop.key)) prop.computed = true;

    var pattern = prop.value;
    var objRef  = t.memberExpression(propRef, prop.key, prop.computed);

    if (t.isPattern(pattern)) {
      this.push(pattern, objRef);
    } else {
      this.nodes.push(this.buildVariableAssignment(pattern, objRef));
    }
  }

  pushObjectPattern(pattern, objRef) {
    // https://github.com/babel/babel/issues/681

    if (!pattern.properties.length) {
      this.nodes.push(t.expressionStatement(
        t.callExpression(this.file.addHelper("object-destructuring-empty"), [objRef])
      ));
    }

    // if we have more than one properties in this pattern and the objectRef is a
    // member expression then we need to assign it to a temporary variable so it's
    // only evaluated once

    if (pattern.properties.length > 1 && t.isMemberExpression(objRef)) {
      var temp = this.scope.generateUidBasedOnNode(objRef, this.file);
      this.nodes.push(this.buildVariableDeclaration(temp, objRef));
      objRef = temp;
    }

    //

    for (var i = 0; i < pattern.properties.length; i++) {
      var prop = pattern.properties[i];
      if (t.isSpreadProperty(prop)) {
        this.pushObjectSpread(pattern, objRef, prop, i);
      } else {
        this.pushObjectProperty(prop, objRef);
      }
    }
  }

  canUnpackArrayPattern(pattern, arr) {
    // not an array so there's no way we can deal with this
    if (!t.isArrayExpression(arr)) return false;

    // pattern has less elements than the array and doesn't have a rest so some
    // elements wont be evaluated
    if (pattern.elements.length > arr.elements.length) return;
    if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) return false;

    // deopt on holes
    for (var i = 0; i < pattern.elements.length; i++) {
      if (!pattern.elements[i]) return false;
    }

    // deopt on reference to left side identifiers
    var bindings = t.getBindingIdentifiers(pattern);
    var state = { deopt: false, bindings };
    this.scope.traverse(arr, arrayUnpackVisitor, state);
    return !state.deopt;
  }

  pushUnpackedArrayPattern(pattern, arr) {
    for (var i = 0; i < pattern.elements.length; i++) {
      var elem = pattern.elements[i];
      if (t.isRestElement(elem)) {
        this.push(elem.argument, t.arrayExpression(arr.elements.slice(i)));
      } else {
        this.push(elem, arr.elements[i]);
      }
    }
  }

  pushArrayPattern(pattern, arrayRef) {
    if (!pattern.elements) return;

    // optimise basic array destructuring of an array expression
    //
    // we can't do this to a pattern of unequal size to it's right hand
    // array expression as then there will be values that wont be evaluated
    //
    // eg: var [a, b] = [1, 2];

    if (this.canUnpackArrayPattern(pattern, arrayRef)) {
      return this.pushUnpackedArrayPattern(pattern, arrayRef);
    }

    // if we have a rest then we need all the elements so don't tell
    // `scope.toArray` to only get a certain amount

    var count = !hasRest(pattern) && pattern.elements.length;

    // so we need to ensure that the `arrayRef` is an array, `scope.toArray` will
    // return a locally bound identifier if it's been inferred to be an array,
    // otherwise it'll be a call to a helper that will ensure it's one

    var toArray = arrayRef;

    if (!this.file.isLoose("es6.destructuring")) {
      toArray = this.scope.toArray(arrayRef, count);
    }

    if (t.isIdentifier(toArray)) {
      // we've been given an identifier so it must have been inferred to be an
      // array
      arrayRef = toArray;
    } else {
      arrayRef = this.scope.generateUidBasedOnNode(arrayRef);
      this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
      //this.getBinding(arrayRef.name).assignTypeGeneric("Array");
    }

    //

    for (var i = 0; i < pattern.elements.length; i++) {
      var elem = pattern.elements[i];

      // hole
      if (!elem) continue;

      var elemRef;

      if (t.isRestElement(elem)) {
        elemRef = arrayRef;

        if (!this.file.isLoose("es6.destructuring")) {
          elemRef = this.scope.toArray(arrayRef);
        }

        if (i > 0) {
          elemRef = t.callExpression(t.memberExpression(elemRef, t.identifier("slice")), [t.literal(i)]);
        }

        // set the element to the rest element argument since we've dealt with it
        // being a rest already
        elem = elem.argument;
      } else {
        elemRef = t.memberExpression(arrayRef, t.literal(i), true);
      }

      this.push(elem, elemRef);
    }
  }

  init(pattern, ref) {
    // trying to destructure a value that we can't evaluate more than once so we
    // need to save it to a variable

    var shouldMemoise = true;
    if (!t.isArrayExpression(ref) && !t.isMemberExpression(ref)) {
      var memo = this.scope.generateMemoisedReference(ref, true);
      if (memo) {
        this.nodes.push(this.buildVariableDeclaration(memo, ref));
        ref = memo;
      }
    }

    //

    this.push(pattern, ref);

    return this.nodes;
  }
}
<commit_msg>add array cache to es6.destructuring to avoid running toArray multiple times<commit_after>import * as messages from "../../../messages";
import * as t from "../../../types";

export var check = t.isPattern;

export function ForOfStatement(node, parent, scope, file) {
  var left = node.left;

  if (t.isPattern(left)) {
    // for ({ length: k } in { abc: 3 });

    var temp = scope.generateUidIdentifier("ref");

    node.left = t.variableDeclaration("var", [
      t.variableDeclarator(temp)
    ]);

    t.ensureBlock(node);

    node.body.body.unshift(t.variableDeclaration("var", [
      t.variableDeclarator(left, temp)
    ]));

    return;
  }

  if (!t.isVariableDeclaration(left)) return;

  var pattern = left.declarations[0].id;
  if (!t.isPattern(pattern)) return;

  var key = scope.generateUidIdentifier("ref");
  node.left = t.variableDeclaration(left.kind, [
    t.variableDeclarator(key, null)
  ]);

  var nodes = [];

  var destructuring = new DestructuringTransformer({
    kind: left.kind,
    file: file,
    scope: scope,
    nodes: nodes
  });

  destructuring.init(pattern, key);

  t.ensureBlock(node);

  var block = node.body;
  block.body = nodes.concat(block.body);
}

export { ForOfStatement as ForInStatement };

exports.Function = function (node, parent, scope, file) {
  var nodes = [];

  var hasDestructuring = false;

  node.params = node.params.map(function (pattern, i) {
    if (!t.isPattern(pattern)) return pattern;

    hasDestructuring = true;
    var ref = scope.generateUidIdentifier("ref");

    var destructuring = new DestructuringTransformer({
      blockHoist: node.params.length - i,
      nodes:      nodes,
      scope:      scope,
      file:       file,
      kind:       "let"
    });
    destructuring.init(pattern, ref);

    return ref;
  });

  if (!hasDestructuring) return;

  file.checkNode(nodes);
  t.ensureBlock(node);

  var block = node.body;
  block.body = nodes.concat(block.body);
};

export function CatchClause(node, parent, scope, file) {
  var pattern = node.param;
  if (!t.isPattern(pattern)) return;

  var ref = scope.generateUidIdentifier("ref");
  node.param = ref;

  var nodes = [];

  var destructuring = new DestructuringTransformer({
    kind: "let",
    file: file,
    scope: scope,
    nodes: nodes
  });
  destructuring.init(pattern, ref);

  node.body.body = nodes.concat(node.body.body);

  return node;
}

export function ExpressionStatement(node, parent, scope, file) {
  var expr = node.expression;
  if (expr.type !== "AssignmentExpression") return;
  if (!t.isPattern(expr.left)) return;
  if (file.isConsequenceExpressionStatement(node)) return;

  var destructuring = new DestructuringTransformer({
    operator: expr.operator,
    scope:    scope,
    file:     file,
  });

  return destructuring.init(expr.left, expr.right);
}

export function AssignmentExpression(node, parent, scope, file) {
  if (!t.isPattern(node.left)) return;

  var ref = scope.generateUidIdentifier("temp");
  scope.push({ id: ref });

  var nodes = [];
  nodes.push(t.expressionStatement(t.assignmentExpression("=", ref, node.right)));

  var destructuring = new DestructuringTransformer({
    operator: node.operator,
    file: file,
    scope: scope,
    nodes: nodes
  });
  destructuring.init(node.left, ref);

  nodes.push(t.expressionStatement(ref));

  return nodes;
}

function variableDeclarationHasPattern(node) {
  for (var i = 0; i < node.declarations.length; i++) {
    if (t.isPattern(node.declarations[i].id)) {
      return true;
    }
  }
  return false;
}

export function VariableDeclaration(node, parent, scope, file) {
  if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;
  if (!variableDeclarationHasPattern(node)) return;

  var nodes = [];
  var declar;

  for (var i = 0; i < node.declarations.length; i++) {
    declar = node.declarations[i];

    var patternId = declar.init;
    var pattern   = declar.id;

    var destructuring = new DestructuringTransformer({
      nodes: nodes,
      scope: scope,
      kind:  node.kind,
      file:  file
    });

    if (t.isPattern(pattern) && patternId) {
      destructuring.init(pattern, patternId);

      if (+i !== node.declarations.length - 1) {
        // we aren't the last declarator so let's just make the
        // last transformed node inherit from us
        t.inherits(nodes[nodes.length - 1], declar);
      }
    } else {
      nodes.push(t.inherits(destructuring.buildVariableAssignment(declar.id, declar.init), declar));
    }
  }

  if (!t.isProgram(parent) && !t.isBlockStatement(parent)) {
    // https://github.com/babel/babel/issues/113
    // for (let [x] = [0]; false;) {}

    declar = null;

    for (i = 0; i < nodes.length; i++) {
      node = nodes[i];
      declar ||= t.variableDeclaration(node.kind, []);

      if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
        throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
      }

      declar.declarations = declar.declarations.concat(node.declarations);
    }

    return declar;
  }

  return nodes;
}

function hasRest(pattern) {
  for (var i = 0; i < pattern.elements.length; i++) {
    if (t.isRestElement(pattern.elements[i])) {
      return true;
    }
  }
  return false;
}

var arrayUnpackVisitor = {
  enter(node, parent, scope, state) {
    if (this.isReferencedIdentifier() && state.bindings[node.name]) {
      state.deopt = true;
      this.stop();
    }
  }
};

class DestructuringTransformer {
  constructor(opts) {
    this.blockHoist = opts.blockHoist;
    this.operator   = opts.operator;
    this.arrays     = {};
    this.nodes      = opts.nodes || [];
    this.scope      = opts.scope;
    this.file       = opts.file;
    this.kind       = opts.kind;
  }

  buildVariableAssignment(id, init) {
    var op = this.operator;
    if (t.isMemberExpression(id)) op = "=";

    var node;

    if (op) {
      node = t.expressionStatement(t.assignmentExpression(op, id, init));
    } else {
      node = t.variableDeclaration(this.kind, [
        t.variableDeclarator(id, init)
      ]);
    }

    node._blockHoist = this.blockHoist;

    return node;
  }

  buildVariableDeclaration(id, init) {
    var declar = t.variableDeclaration("var", [
      t.variableDeclarator(id, init)
    ]);
    declar._blockHoist = this.blockHoist;
    return declar;
  }

  push(id, init) {
    if (t.isObjectPattern(id)) {
      this.pushObjectPattern(id, init);
    } else if (t.isArrayPattern(id)) {
      this.pushArrayPattern(id, init);
    } else if (t.isAssignmentPattern(id)) {
      this.pushAssignmentPattern(id, init);
    } else {
      this.nodes.push(this.buildVariableAssignment(id, init));
    }
  }

  toArray(node, count) {
    if (this.file.isLoose("es6.destructuring") || (t.isIdentifier(node) && this.arrays[node.name])) {
      return node;
    } else {
      return this.scope.toArray(node, count);
    }
  }

  pushAssignmentPattern(pattern, valueRef) {
    // we need to assign the current value of the assignment to avoid evaluating
    // it more than once

    var tempValueRef = this.scope.generateUidBasedOnNode(valueRef);

    var declar = t.variableDeclaration("var", [
      t.variableDeclarator(tempValueRef, valueRef)
    ]);
    declar._blockHoist = this.blockHoist;
    this.nodes.push(declar);

    //

    var tempConditional = t.conditionalExpression(
      t.binaryExpression("===", tempValueRef, t.identifier("undefined")),
      pattern.right,
      tempValueRef
    );

    var left = pattern.left;
    if (t.isPattern(left)) {
      this.nodes.push(t.expressionStatement(
        t.assignmentExpression("=", tempValueRef, tempConditional)
      ));
      this.push(left, tempValueRef);
    } else {
      this.nodes.push(this.buildVariableAssignment(left, tempConditional));
    }
  }

  pushObjectSpread(pattern, objRef, spreadProp, spreadPropIndex) {
    // get all the keys that appear in this object before the current spread

    var keys = [];

    for (var i = 0; i < pattern.properties.length; i++) {
      var prop = pattern.properties[i];

      // we've exceeded the index of the spread property to all properties to the
      // right need to be ignored
      if (i >= spreadPropIndex) break;

      // ignore other spread properties
      if (t.isSpreadProperty(prop)) continue;

      var key = prop.key;
      if (t.isIdentifier(key)) key = t.literal(prop.key.name);
      keys.push(key);
    }

    keys = t.arrayExpression(keys);

    //

    var value = t.callExpression(this.file.addHelper("object-without-properties"), [objRef, keys]);
    this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
  }

  pushObjectProperty(prop, propRef) {
    if (t.isLiteral(prop.key)) prop.computed = true;

    var pattern = prop.value;
    var objRef  = t.memberExpression(propRef, prop.key, prop.computed);

    if (t.isPattern(pattern)) {
      this.push(pattern, objRef);
    } else {
      this.nodes.push(this.buildVariableAssignment(pattern, objRef));
    }
  }

  pushObjectPattern(pattern, objRef) {
    // https://github.com/babel/babel/issues/681

    if (!pattern.properties.length) {
      this.nodes.push(t.expressionStatement(
        t.callExpression(this.file.addHelper("object-destructuring-empty"), [objRef])
      ));
    }

    // if we have more than one properties in this pattern and the objectRef is a
    // member expression then we need to assign it to a temporary variable so it's
    // only evaluated once

    if (pattern.properties.length > 1 && t.isMemberExpression(objRef)) {
      var temp = this.scope.generateUidBasedOnNode(objRef, this.file);
      this.nodes.push(this.buildVariableDeclaration(temp, objRef));
      objRef = temp;
    }

    //

    for (var i = 0; i < pattern.properties.length; i++) {
      var prop = pattern.properties[i];
      if (t.isSpreadProperty(prop)) {
        this.pushObjectSpread(pattern, objRef, prop, i);
      } else {
        this.pushObjectProperty(prop, objRef);
      }
    }
  }

  canUnpackArrayPattern(pattern, arr) {
    // not an array so there's no way we can deal with this
    if (!t.isArrayExpression(arr)) return false;

    // pattern has less elements than the array and doesn't have a rest so some
    // elements wont be evaluated
    if (pattern.elements.length > arr.elements.length) return;
    if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) return false;

    // deopt on holes
    for (var i = 0; i < pattern.elements.length; i++) {
      if (!pattern.elements[i]) return false;
    }

    // deopt on reference to left side identifiers
    var bindings = t.getBindingIdentifiers(pattern);
    var state = { deopt: false, bindings };
    this.scope.traverse(arr, arrayUnpackVisitor, state);
    return !state.deopt;
  }

  pushUnpackedArrayPattern(pattern, arr) {
    for (var i = 0; i < pattern.elements.length; i++) {
      var elem = pattern.elements[i];
      if (t.isRestElement(elem)) {
        this.push(elem.argument, t.arrayExpression(arr.elements.slice(i)));
      } else {
        this.push(elem, arr.elements[i]);
      }
    }
  }

  pushArrayPattern(pattern, arrayRef) {
    if (!pattern.elements) return;

    // optimise basic array destructuring of an array expression
    //
    // we can't do this to a pattern of unequal size to it's right hand
    // array expression as then there will be values that wont be evaluated
    //
    // eg: var [a, b] = [1, 2];

    if (this.canUnpackArrayPattern(pattern, arrayRef)) {
      return this.pushUnpackedArrayPattern(pattern, arrayRef);
    }

    // if we have a rest then we need all the elements so don't tell
    // `scope.toArray` to only get a certain amount

    var count = !hasRest(pattern) && pattern.elements.length;

    // so we need to ensure that the `arrayRef` is an array, `scope.toArray` will
    // return a locally bound identifier if it's been inferred to be an array,
    // otherwise it'll be a call to a helper that will ensure it's one

    var toArray = this.toArray(arrayRef, count);

    if (t.isIdentifier(toArray)) {
      // we've been given an identifier so it must have been inferred to be an
      // array
      arrayRef = toArray;
    } else {
      arrayRef = this.scope.generateUidBasedOnNode(arrayRef);
      this.arrays[arrayRef.name] = true;
      this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
    }

    //

    for (var i = 0; i < pattern.elements.length; i++) {
      var elem = pattern.elements[i];

      // hole
      if (!elem) continue;

      var elemRef;

      if (t.isRestElement(elem)) {
        elemRef = this.toArray(arrayRef);

        if (i > 0) {
          elemRef = t.callExpression(t.memberExpression(elemRef, t.identifier("slice")), [t.literal(i)]);
        }

        // set the element to the rest element argument since we've dealt with it
        // being a rest already
        elem = elem.argument;
      } else {
        elemRef = t.memberExpression(arrayRef, t.literal(i), true);
      }

      this.push(elem, elemRef);
    }
  }

  init(pattern, ref) {
    // trying to destructure a value that we can't evaluate more than once so we
    // need to save it to a variable

    var shouldMemoise = true;
    if (!t.isArrayExpression(ref) && !t.isMemberExpression(ref)) {
      var memo = this.scope.generateMemoisedReference(ref, true);
      if (memo) {
        this.nodes.push(this.buildVariableDeclaration(memo, ref));
        ref = memo;
      }
    }

    //

    this.push(pattern, ref);

    return this.nodes;
  }
}
<|endoftext|>