<commit_before>//----------------------------------------------------------------------
//
// This source file is part of the Folktale project.
//
// Licensed under MIT. See LICENCE for full licence information.
// See CONTRIBUTORS for the list of contributors to the project.
//
//----------------------------------------------------------------------

const { property } = require('jsverify');
const fl = require('folktale/helpers/fantasy-land');
const defaultEquals = require('./equals');

// This file implements reusable property tests for a fantasy-land
// data structure. Each function takes two arguments:
//
//   - A function that takes one argument, and constructs a value
//     from some fantasy-land algebra;
//   - An equality function, that takes two algebras and compares them.

const Setoid = (type) => {
  describe('Setoid instance', _ => {
    const { equals } = fl;

    property('reflexivity', 'nat', (value) => {
      const a = type(value);
      return a[equals](a) === true;
    });

    property('symmetry', 'nat', 'nat', (a, b) => {
      const SA = type(a);
      const SB = type(b);
      return SA[equals](SB) === SB[equals](SA);
    });

    property('transitivity', 'nat', (a) => {
      const SA = type(a);
      const SB = type(a);
      const SC = type(a);

      return SA[equals](SB)
      &&     SB[equals](SC)
      &&     SA[equals](SC)
    });
  });
};

const Semigroup = (type, equals = defaultEquals) => {
  const { concat } = fl;

  describe('Semigroup instance', _ => {
    property('associativity', 'string', 'string', 'string', (a, b, c) =>
      equals(
        type(a)[concat](type(b))[concat](type(c)),
        type(a)[concat](type(b)[concat](type(c)))
      )
    );
  });
};

const Monoid = (type, equals = defaultEquals) => {
  const { concat, empty } = fl;

  describe('Monoid instance', _ => {
    property('right identity', 'string', (a) =>
      equals(type(a)[concat](type[empty]()), type(a))
    );

    property('left identity', 'string', (a) =>
      equals(type()[empty]()[concat](type(a)), type(a))
    );
  });
};

const Functor = (type, equals = defaultEquals) => {
  const { map } = fl;

  describe('Functor instance', _ => {
    property('identity', 'nat', (a) =>
      equals(type(a)[map](a => a), type(a))
    );

    property('composition', 'nat', 'nat -> nat', 'nat -> nat', (a, f, g) =>
      equals(
        type(a)[map](x => f(g(x))),
        type(a)[map](g)[map](f)
      )
    );
  });
};

const Apply = (type, equals = defaultEquals) => {
  const { ap, map } = fl;

  describe('Apply instance', _ => {
    property('composition', 'string', 'string -> string', 'string -> string', (a, f, g) =>
      equals(
        type(a)[ap](type(g)[ap](type(f)[map](f => g => x => f(g(x))))),
        type(a)[ap](type(g))[ap](type(f))
      )
    );
  });
};

const Applicative = (type, equals = defaultEquals) => {
  const { ap, of } = fl;

  describe('Applicative instance', _ => {
    property('identity', 'nat', (a) =>
      equals(
        type().of(x => x).ap(type(a)),    // ap's different signature matters
        type(a)
      )
    );

    property('homomorphism', 'nat', 'nat -> nat', (a, f) =>
      equals(
        type()[of](a)[ap](type()[of](f)),
        type()[of](f(a))
      )
    );

    property('interchange', 'nat', 'nat -> nat', (a, f) =>
      equals(
        type()[of](a)[ap](type(f)),
        type(f)[ap](type()[of](f => f(a)))
      )
    );
  });
};

const Chain = (type, equals = defaultEquals) => {
  const { chain } = fl;

  describe('Chain instance', _ => {
    property('associativity', 'nat', 'nat -> nat', 'nat -> nat', (a, rf, rg) => {
      const f = (x) => type(rf(x));
      const g = (x) => type(rg(x));

      return equals(
        type(a)[chain](f)[chain](g),
        type(a)[chain](x => f(x)[chain](g))
      )
    });
  });
};

const Monad = (type, equals = defaultEquals) => {
  const { chain, of } = fl;

  describe('Monad instance', _ => {
    property('left identity', 'nat', 'nat -> nat', (a, rf) => {
      const f = (x) => type(rf(x));

      return equals(
        type()[of](a)[chain](f),
        f(a)
      )
    });

    property('right identity', 'nat', (a) =>
      equals(
        type(a)[chain](x => type()[of](x)),
        type(a)
      )
    );
  });
};

const Bifunctor = (type, equals = defaultEquals) => {
  const { bimap } = fl;

  describe('Bifunctor instance', _ => {
    property('identity', 'nat', 'nat', (a, b) =>
      equals(
        type(a, b)[bimap](a => a, b => b),
        type(a, b)
      )
    );

    property('composition', 'nat', 'nat', 'nat -> nat', 'nat -> nat', 'nat -> nat', 'nat -> nat', (a, b, f, g, h, i) =>
      equals(
        type(a, b)[bimap](
          a => f(g(a)),
          b => h(i(b))
        ),
        type(a, b)[bimap](g, i)[bimap](f, h)
      )
    );
  });
};

module.exports = {
  Setoid,
  Semigroup,
  Monoid,
  Functor,
  Apply,
  Applicative,
  Chain,
  Monad,
  Bifunctor
};
<commit_msg>(fix test) Uses the prototypical empty method for Monoid's law<commit_after>//----------------------------------------------------------------------
//
// This source file is part of the Folktale project.
//
// Licensed under MIT. See LICENCE for full licence information.
// See CONTRIBUTORS for the list of contributors to the project.
//
//----------------------------------------------------------------------

const { property } = require('jsverify');
const fl = require('folktale/helpers/fantasy-land');
const defaultEquals = require('./equals');

// This file implements reusable property tests for a fantasy-land
// data structure. Each function takes two arguments:
//
//   - A function that takes one argument, and constructs a value
//     from some fantasy-land algebra;
//   - An equality function, that takes two algebras and compares them.

const Setoid = (type) => {
  describe('Setoid instance', _ => {
    const { equals } = fl;

    property('reflexivity', 'nat', (value) => {
      const a = type(value);
      return a[equals](a) === true;
    });

    property('symmetry', 'nat', 'nat', (a, b) => {
      const SA = type(a);
      const SB = type(b);
      return SA[equals](SB) === SB[equals](SA);
    });

    property('transitivity', 'nat', (a) => {
      const SA = type(a);
      const SB = type(a);
      const SC = type(a);

      return SA[equals](SB)
      &&     SB[equals](SC)
      &&     SA[equals](SC)
    });
  });
};

const Semigroup = (type, equals = defaultEquals) => {
  const { concat } = fl;

  describe('Semigroup instance', _ => {
    property('associativity', 'string', 'string', 'string', (a, b, c) =>
      equals(
        type(a)[concat](type(b))[concat](type(c)),
        type(a)[concat](type(b)[concat](type(c)))
      )
    );
  });
};

const Monoid = (type, equals = defaultEquals) => {
  const { concat, empty } = fl;

  describe('Monoid instance', _ => {
    property('right identity', 'string', (a) =>
      equals(type(a)[concat](type()[empty]()), type(a))
    );

    property('left identity', 'string', (a) =>
      equals(type()[empty]()[concat](type(a)), type(a))
    );
  });
};

const Functor = (type, equals = defaultEquals) => {
  const { map } = fl;

  describe('Functor instance', _ => {
    property('identity', 'nat', (a) =>
      equals(type(a)[map](a => a), type(a))
    );

    property('composition', 'nat', 'nat -> nat', 'nat -> nat', (a, f, g) =>
      equals(
        type(a)[map](x => f(g(x))),
        type(a)[map](g)[map](f)
      )
    );
  });
};

const Apply = (type, equals = defaultEquals) => {
  const { ap, map } = fl;

  describe('Apply instance', _ => {
    property('composition', 'string', 'string -> string', 'string -> string', (a, f, g) =>
      equals(
        type(a)[ap](type(g)[ap](type(f)[map](f => g => x => f(g(x))))),
        type(a)[ap](type(g))[ap](type(f))
      )
    );
  });
};

const Applicative = (type, equals = defaultEquals) => {
  const { ap, of } = fl;

  describe('Applicative instance', _ => {
    property('identity', 'nat', (a) =>
      equals(
        type().of(x => x).ap(type(a)),    // ap's different signature matters
        type(a)
      )
    );

    property('homomorphism', 'nat', 'nat -> nat', (a, f) =>
      equals(
        type()[of](a)[ap](type()[of](f)),
        type()[of](f(a))
      )
    );

    property('interchange', 'nat', 'nat -> nat', (a, f) =>
      equals(
        type()[of](a)[ap](type(f)),
        type(f)[ap](type()[of](f => f(a)))
      )
    );
  });
};

const Chain = (type, equals = defaultEquals) => {
  const { chain } = fl;

  describe('Chain instance', _ => {
    property('associativity', 'nat', 'nat -> nat', 'nat -> nat', (a, rf, rg) => {
      const f = (x) => type(rf(x));
      const g = (x) => type(rg(x));

      return equals(
        type(a)[chain](f)[chain](g),
        type(a)[chain](x => f(x)[chain](g))
      )
    });
  });
};

const Monad = (type, equals = defaultEquals) => {
  const { chain, of } = fl;

  describe('Monad instance', _ => {
    property('left identity', 'nat', 'nat -> nat', (a, rf) => {
      const f = (x) => type(rf(x));

      return equals(
        type()[of](a)[chain](f),
        f(a)
      )
    });

    property('right identity', 'nat', (a) =>
      equals(
        type(a)[chain](x => type()[of](x)),
        type(a)
      )
    );
  });
};

const Bifunctor = (type, equals = defaultEquals) => {
  const { bimap } = fl;

  describe('Bifunctor instance', _ => {
    property('identity', 'nat', 'nat', (a, b) =>
      equals(
        type(a, b)[bimap](a => a, b => b),
        type(a, b)
      )
    );

    property('composition', 'nat', 'nat', 'nat -> nat', 'nat -> nat', 'nat -> nat', 'nat -> nat', (a, b, f, g, h, i) =>
      equals(
        type(a, b)[bimap](
          a => f(g(a)),
          b => h(i(b))
        ),
        type(a, b)[bimap](g, i)[bimap](f, h)
      )
    );
  });
};

module.exports = {
  Setoid,
  Semigroup,
  Monoid,
  Functor,
  Apply,
  Applicative,
  Chain,
  Monad,
  Bifunctor
};
<|endoftext|>


<commit_before>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

import cockpit from "cockpit";
import $ from "jquery";
import { superuser } from "superuser";

import '../lib/patternfly/patternfly-cockpit.scss';

const _ = cockpit.gettext;

var sos_task;
var sos_archive_url;
var sos_archive_files;

function sos_init() {
    // Start right away
    sos_create();
}

function sos_error(message, extra) {
    $("#sos-alert, #sos-progress, #sos-download").hide();
    $("#sos-error .alert-message").text(message);
    if (extra) {
        $("#sos-error-extra").text(extra);
        $("#sos-error-extra").show();
    } else
        $("#sos-error-extra").hide();
    $("#sos-error").show();
    $("#sos-cancel").text(_("Close"));
}

function sos_create() {
    $("#sos-progress .progress-bar").css("width", "0%");
    $("#sos-download, #sos-error").hide();
    $("#sos-cancel").text(_("Cancel"));

    sos_archive_url = null;
    sos_archive_files = [];

    var task = cockpit.spawn(["sosreport", "--batch"],
                             { superuser: true, err: "out", pty: true });
    sos_task = task;

    // TODO - Use a real API instead of scraping stdout once such
    //        an API exists.

    var output = "";
    var plugins_count = 0;
    var progress_regex = /Running ([0-9]+)\/([0-9]+):/; // Only for sos < 3.6
    var finishing_regex = /Finishing plugins.*\[Running: (.*)\]/;
    var starting_regex = /Starting ([0-9]+)\/([0-9]+).*\[Running: (.*)\]/;
    var archive_regex = /Your sosreport has been generated and saved in:\s+(\/[^\r\n]+)/;

    task.stream(function (text) {
        if (sos_task == task) {
            var m, p;
            p = 0;

            output += text;
            var lines = output.split("\n");
            for (var i = lines.length - 1; i >= 0; i--) {
                if ((m = starting_regex.exec(lines[i]))) {
                    plugins_count = parseInt(m[2], 10);
                    p = ((parseInt(m[1], 10) - m[3].split(" ").length) / plugins_count) * 100;
                    break;
                } else if ((m = finishing_regex.exec(lines[i]))) {
                    if (!plugins_count)
                        p = 100;
                    else
                        p = ((plugins_count - m[1].split(" ").length) / plugins_count) * 100;
                    break;
                } else if ((m = progress_regex.exec(lines[i]))) {
                    p = (parseInt(m[1], 10) / parseInt(m[2], 10)) * 100;
                    break;
                }
            }
            $("#sos-alert, #sos-progress").show();
            $("#sos-progress .progress-bar").css("width", p.toString() + "%");
        }
    });
    task.done(function () {
        if (sos_task == task) {
            var m = archive_regex.exec(output);
            if (m) {
                var archive = m[1];
                var basename = archive.replace(/.*\//, "");

                // When running sosreport in a container on the
                // Atomics, the archive path needs to be adjusted.
                //
                if (archive.indexOf("/host") === 0)
                    archive = archive.substr(5);

                sos_archive_files = [archive, archive + ".md5"];

                var query = window.btoa(JSON.stringify({
                    payload: "fsread1",
                    binary: "raw",
                    path: archive,
                    superuser: true,
                    max_read_size: 150 * 1024 * 1024,
                    external: {
                        "content-disposition": 'attachment; filename="' + basename + '"',
                        "content-type": "application/x-xz, application/octet-stream"
                    }
                }));
                var prefix = (new URL(cockpit.transport.uri("channel/" + cockpit.transport.csrf_token))).pathname;
                sos_archive_url = prefix + '?' + query;
                $("#sos-progress, #sos-error").hide();
                $("#sos-alert, #sos-download").show();
                $("#sos-cancel").text(_("Close"));
            } else {
                sos_error(_("No archive has been created."), output);
            }
            sos_task = null;
        }
    });
    task.fail(function (error) {
        if (sos_task == task) {
            sos_error(error.toString(), output);
            sos_task = null;
        }
    });
}

function sos_cancel() {
    if (sos_task) {
        sos_task.close("cancelled");
        sos_task = null;
    }
    if (sos_archive_files.length > 0) {
        cockpit.spawn(["rm"].concat(sos_archive_files), { superuser: true, err: "message" })
                .fail(function (error) {
                    console.log("failed to remove", sos_archive_files, error);
                });
    }
    sos_archive_url = null;
    sos_archive_files = [];
    $("#sos").prop('hidden', true);
}

function sos_download() {
    // We download via a hidden iframe to get better control over
    // the error cases.
    var iframe = $('<iframe>').attr('src', sos_archive_url)
            .hide();
    iframe.on('load', function (event) {
        var title = iframe.get(0).contentDocument.title;
        if (title)
            sos_error(title);
    });
    $('body').append(iframe);
}

function init() {
    $(function () {
        $("#create-button").on("click", () => {
            $("#sos").prop('hidden', false);
            sos_init();
        });
        $("#sos-cancel").on("click", sos_cancel);
        $('#sos-download button').on('click', sos_download);

        cockpit.translate();
        $('body').prop("hidden", false);

        function update_admin_allowed() {
            $("#switch-instructions").toggle(superuser.allowed === false);
            $("#create-button").toggle(!!superuser.allowed);
        }

        $(superuser).on("changed", update_admin_allowed);
        update_admin_allowed();

        // Send a 'init' message.  This tells the tests that we
        // are ready to go.
        //
        cockpit.transport.wait(function () { });
    });
}

init();
<commit_msg>sosreport: Port from jQuery to DOM API<commit_after>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

import cockpit from "cockpit";
import { superuser } from "superuser";

import '../lib/patternfly/patternfly-cockpit.scss';

const _ = cockpit.gettext;

var sos_task;
var sos_archive_url;
var sos_archive_files;

function sos_init() {
    // Start right away
    sos_create();
}

function sos_error(message, extra) {
    document.getElementById("sos-alert").setAttribute("hidden", "hidden");
    document.getElementById("sos-progress").setAttribute("hidden", "hidden");
    document.getElementById("sos-download").setAttribute("hidden", "hidden");
    document.querySelector("#sos-error .alert-message").textContent = message;

    const e_extra = document.getElementById("sos-error-extra");
    if (extra) {
        e_extra.textContent = extra;
        e_extra.removeAttribute("hidden");
    } else
        e_extra.setAttribute("hidden", "hidden");
    document.getElementById("sos-cancel").textContent = _("Close");
    document.getElementById("sos-error").removeAttribute("hidden");
}

function sos_create() {
    document.querySelector("#sos-progress .progress-bar").style.width = "0%";
    document.getElementById("sos-download").setAttribute("hidden", "hidden");
    document.getElementById("sos-error").setAttribute("hidden", "hidden");
    document.getElementById("sos-cancel").textContent = _("Cancel");

    sos_archive_url = null;
    sos_archive_files = [];

    var task = cockpit.spawn(["sosreport", "--batch"],
                             { superuser: true, err: "out", pty: true });
    sos_task = task;

    // TODO - Use a real API instead of scraping stdout once such
    //        an API exists.

    var output = "";
    var plugins_count = 0;
    var progress_regex = /Running ([0-9]+)\/([0-9]+):/; // Only for sos < 3.6
    var finishing_regex = /Finishing plugins.*\[Running: (.*)\]/;
    var starting_regex = /Starting ([0-9]+)\/([0-9]+).*\[Running: (.*)\]/;
    var archive_regex = /Your sosreport has been generated and saved in:\s+(\/[^\r\n]+)/;

    task.stream(function (text) {
        if (sos_task == task) {
            var m, p;
            p = 0;

            output += text;
            var lines = output.split("\n");
            for (var i = lines.length - 1; i >= 0; i--) {
                if ((m = starting_regex.exec(lines[i]))) {
                    plugins_count = parseInt(m[2], 10);
                    p = ((parseInt(m[1], 10) - m[3].split(" ").length) / plugins_count) * 100;
                    break;
                } else if ((m = finishing_regex.exec(lines[i]))) {
                    if (!plugins_count)
                        p = 100;
                    else
                        p = ((plugins_count - m[1].split(" ").length) / plugins_count) * 100;
                    break;
                } else if ((m = progress_regex.exec(lines[i]))) {
                    p = (parseInt(m[1], 10) / parseInt(m[2], 10)) * 100;
                    break;
                }
            }
            document.getElementById("sos-alert").removeAttribute("hidden");
            document.getElementById("sos-progress").removeAttribute("hidden");
            document.querySelector("#sos-progress .progress-bar").style.width = p.toString() + "%";
        }
    });
    task.done(function () {
        if (sos_task == task) {
            var m = archive_regex.exec(output);
            if (m) {
                var archive = m[1];
                var basename = archive.replace(/.*\//, "");

                // When running sosreport in a container on the
                // Atomics, the archive path needs to be adjusted.
                //
                if (archive.indexOf("/host") === 0)
                    archive = archive.substr(5);

                sos_archive_files = [archive, archive + ".md5"];

                var query = window.btoa(JSON.stringify({
                    payload: "fsread1",
                    binary: "raw",
                    path: archive,
                    superuser: true,
                    max_read_size: 150 * 1024 * 1024,
                    external: {
                        "content-disposition": 'attachment; filename="' + basename + '"',
                        "content-type": "application/x-xz, application/octet-stream"
                    }
                }));
                var prefix = (new URL(cockpit.transport.uri("channel/" + cockpit.transport.csrf_token))).pathname;
                sos_archive_url = prefix + '?' + query;
                document.getElementById("sos-progress").setAttribute("hidden", "hidden");
                document.getElementById("sos-error").setAttribute("hidden", "hidden");
                document.getElementById("sos-alert").removeAttribute("hidden");
                document.getElementById("sos-download").removeAttribute("hidden");
                document.getElementById("sos-cancel").textContent = _("Close");
            } else {
                sos_error(_("No archive has been created."), output);
            }
            sos_task = null;
        }
    });
    task.fail(function (error) {
        if (sos_task == task) {
            sos_error(error.toString(), output);
            sos_task = null;
        }
    });
}

function sos_cancel() {
    if (sos_task) {
        sos_task.close("cancelled");
        sos_task = null;
    }
    if (sos_archive_files.length > 0) {
        cockpit.spawn(["rm"].concat(sos_archive_files), { superuser: true, err: "message" })
                .fail(function (error) {
                    console.log("failed to remove", sos_archive_files, error);
                });
    }
    sos_archive_url = null;
    sos_archive_files = [];
    document.getElementById("sos").setAttribute("hidden", "hidden");
}

function sos_download() {
    // We download via a hidden iframe to get better control over
    // the error cases.
    const iframe = document.createElement("iframe");
    iframe.setAttribute("src", sos_archive_url);
    iframe.setAttribute("hidden", "hidden");
    iframe.addEventListener("load", () => {
        const title = iframe.contentDocument.title;
        if (title)
            sos_error(title);
    });
    document.body.appendChild(iframe);
}

document.addEventListener("DOMContentLoaded", () => {
    document.getElementById("create-button").addEventListener("click", () => {
        document.getElementById("sos").removeAttribute("hidden");
        sos_init();
    });
    document.getElementById("sos-cancel").addEventListener("click", sos_cancel);
    document.querySelector("#sos-download button").addEventListener("click", sos_download);

    cockpit.translate();
    document.body.removeAttribute("hidden");

    function update_admin_allowed() {
        document.getElementById("switch-instructions").style.display = superuser.allowed === false ? "block" : "none";
        if (superuser.allowed)
            document.getElementById("create-button").removeAttribute("hidden");
        else
            document.getElementById("create-button").setAttribute("hidden", "hidden");
    }

    superuser.addEventListener("changed", update_admin_allowed);
    update_admin_allowed();

    // Send a 'init' message.  This tells the tests that we
    // are ready to go.
    //
    cockpit.transport.wait(() => { });
});
<|endoftext|>


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

  var L20n;

  if (typeof exports !== 'undefined') {
    L20n = exports;
    L20n.Parser = require('./parser.js');
    L20n.Compiler = require('./compiler.js');
  } else {
    L20n = this.L20n = {};
  }

  L20n.getContext = function L20n_getContext() {
    return new Context();
  };

  var globals = {
    get hour() {
      return new Date().getHours();
    },
    get os() {
      if (/^MacIntel/.test(navigator.platform)) {
        return 'mac';
      }
      if (/^Linux/.test(navigator.platform)) {
        return 'linux';
      }
      if (/^Win/.test(navigatgor.platform)) {
        return 'win';
      }
      return 'unknown';
    },
  };

  var Cache = {
    LOLCache: {},
    resCache: {},
    getLOLFile: function(uri) {
      if (!this.LOLCache[uri]) {
        this.LOLCache[uri] = new LOLFile(uri);
      }
      return this.LOLCache[uri];
    },
    getResource: function(uri) {
      if (!this.resCache[uri]) {
        this.resCache[uri] = new Resource(uri);
      }
      return this.resCache[uri];
    },
  }

  function _fire(callbacks, args) {
    callbacks.forEach(function(callback) {
      callback.apply(this, args);
    });
    callbacks = [];
  }

  function LOLFile(uri) {
    //var uri = uri;
    var ast = null;
    var imports = null;
    var callbacks = [];
    var isDownloading = false;

    function download(uri, callback) {
      var xhr = new XMLHttpRequest();
      xhr.overrideMimeType('text/plain');
      xhr.addEventListener("load", function() {
        callback(xhr.responseText)
      });
      xhr.open('GET', uri, true);
      xhr.send('');
    }

    function parse(data) {
      ast = L20n.Parser.parse(data).body;
      imports = ast.filter(function(elem) {
        return elem.type == 'ImportStatement';
      });
      _fire(callbacks, [ast, imports]);
    }

    this.get = function LOLFile_get(callback) {
      if (ast) {
        callback(ast, imports);
      } else {
        callbacks.push(callback);
        if (!isDownloading) {
          isDownloading = true;
          download(uri, parse);
        }
      }
    }

  }

  function Resource(uri) {

    //var uri = uri;
    var ast = [];
    var rawast = [];
    var resources = []; // resources
    var callbacks = [];

    var isPreprocessed = false;
    var isLoading = false;

    var lol = Cache.getLOLFile(uri);

    function flattenIfAllReady() {
      for (var i in resources) {
        if (!resources[i].isReady) {
          return;
        }
      }
      rawast.forEach(function(node) {
        if (node.type == 'ImportStatement') {
          var importedAST = resources.shift().getAST();
          ast = ast.concat(importedAST);
        } else {
          ast.push(node);
        }
      });
      isPreprocessed = true;
      _fire(callbacks, [ast]);
    }

    function preprocess(imports, nesting) {
      imports.forEach(function(node){
        var imported = Cache.getResource(node.uri.content);
        resources.push(imported);
        imported.load(flattenIfAllReady, nesting + 1);
      });
    }

    this.load = function Resource_load(callback, nesting) {
      nesting = nesting || 0;
      if (nesting > 7) {
        throw "Too many nested imports";
      }
      if (isPreprocessed) {
        callback(ast);
      } else {
        callbacks.push(callback);
        lol.get(function(lolast, imports) {
          rawast = lolast;
          if (imports.length) {
            preprocess(imports, nesting);
          } else {
            ast = rawast;
            isPreprocessed = true;
            _fire(callbacks, [ast]);
          }
        });
      }
    }

    this.__defineGetter__('isReady', function() {
      return isPreprocessed;
    });

    this.getAST = function Resource_getAST() {
      if (!isPreprocessed) {
        throw "Resource not ready";
      }
      return ast;
    }
  }

  function Context() {
    var resources= []; // resource files in order

    var ast = []; // the full AST
    var entries = {}; // resource entries
    var ctxdata = {}; // context variables

    var isFrozen = false;
    var isCompiled = false;

    var ASYNC_TIMEOUT = 500;
    var self = this;

    function getArgs(data) {
      var args = Object.create(ctxdata);
      if (data) {
        for (var i in data) {
          args[i] = data[i];
        }
      }
      return args;
    }

    function isReady() {
      if (!isFrozen) {
        return false;
      }
      for (var i in resources) {
        if (!resources[i].isReady) {
          return false;
        }
      }
      return true;
    }

    function compile() {
      // flatten the AST
      ast = resources.reduce(function(prev, curr) {
        return prev.concat(curr.getAST());
      }, []);
      L20n.Compiler.compile(ast, entries, globals);
      isCompiled = true;
      fireReadyEvent();
    }

    function fireReadyEvent() {
      console.log('fired', { ast:ast, entries:entries});
      var event = document.createEvent('Event');
      event.initEvent('LocalizationReady', false, false);
      event.ctx = self;
      document.dispatchEvent(event);
    }

    function compileIfCtxReady() {
      if (isReady()) {
        compile();
      }
    }

    function getSync(id, data) {
      if (!isCompiled) {
        throw "Error: not compiled";
      }
      var entity = entries[id];
      if (!entity || entity.local) {
        console.warn("No such entity: " + id);
        return null;
      }
      var args = getArgs(data);
      return entity.toString(args);
    };

    function getAsync(id, data, callback, fallback) {
      if (isCompiled) {
        callback(getSync(id, data));
      }
      var overdue = false;
      var ttl = window.setTimeout(function() {
        overdue = true;
        // fallback is just a string, can't interpolate context data
        callback(fallback);
      }, ASYNC_TIMEOUT);

      document.addEventListener('LocalizationReady', function(event) {
        if (overdue || event.ctx !== self) {
          return;
        }
        window.clearTimeout(ttl);
        callback(getSync(id, data));
      });
    };

    this.__defineSetter__('timeout', function(ms) {
      ASYNC_TIMEOUT = ms;
    });

    this.__defineGetter__('timeout', function() {
      return ASYNC_TIMEOUT;
    });

    this.__defineSetter__('data', function(data) {
      ctxdata = data;
    });

    this.__defineGetter__('data', function() {
      return ctxdata;
    });

    this.addResource = function(uri) {
      if (isFrozen) {
        throw "Context is frozen, can't add more resources";
      }
      var res = new Resource(uri);
      resources.push(res);
      res.load(compileIfCtxReady);
    };

    this.freeze = function() {
      isFrozen = true;
      compileIfCtxReady();
    };

    this.get = function(id, data, callback, fallback) {
      if (callback !== undefined) {
        getAsync(id, data, callback, fallback);
      } else {
        return getSync(id, data);
      }
    };

    this.getAttribute = function(id, attr, data) {
      if (!isCompiled) {
        throw "Error: not compiled";
      }
      var entity = entries[id];
      if (!entity || entity.local) {
        console.warn("No such entity: " + id);
        return null;
      }
      var attribute = entity.attributes[attr]
      if (!attribute || attribute.local) {
        console.warn("No such attribute: " + attr);
        return null;
      }
      var args = this._getArgs(data);
      return attribute.toString(args);
    };

    this.getAttributes = function(id, data) {
      if (!isCompiled) {
        throw "Error";
      }
      var entity = entries[id];
      if (!entity || entity.local) {
        console.warn("No such entity: " + id);
        return null;
      }
      var args = this._getArgs(data);
      var attributes = {};
      for (var attr in entity.attributes) {
        var attribute = entity.attributes[attr];
        if (!attribute.local) {
          attributes[attr] = attribute.toString(args);
        }
      }
      return attributes;
    }
  }
}).call(this);
<commit_msg>Context is a resource<commit_after>(function() {
  'use strict';

  var L20n;

  if (typeof exports !== 'undefined') {
    L20n = exports;
    L20n.Parser = require('./parser.js');
    L20n.Compiler = require('./compiler.js');
  } else {
    L20n = this.L20n = {};
  }

  L20n.getContext = function L20n_getContext() {
    return new Context();
  };

  var globals = {
    get hour() {
      return new Date().getHours();
    },
    get os() {
      if (/^MacIntel/.test(navigator.platform)) {
        return 'mac';
      }
      if (/^Linux/.test(navigator.platform)) {
        return 'linux';
      }
      if (/^Win/.test(navigatgor.platform)) {
        return 'win';
      }
      return 'unknown';
    },
  };

  var Cache = {
    LOLCache: {},
    resCache: {},
    getLOLFile: function(uri) {
      if (!this.LOLCache[uri]) {
        this.LOLCache[uri] = new LOLFile(uri);
      }
      return this.LOLCache[uri];
    },
    getResource: function(uri) {
      if (!this.resCache[uri]) {
        this.resCache[uri] = new Resource(uri);
      }
      return this.resCache[uri];
    },
  }

  function _ifReady(self, fn) {
    return function ifReady() {
      if (self.isReady()) {
        fn.apply(self, arguments);
      }
    }
  }

  function _fire(callbacks, args) {
    callbacks.forEach(function(callback) {
      callback.apply(this, args);
    });
    callbacks.length = 0;
  }

  function LOLFile(uri) {
    //var uri = uri;
    var ast = null;
    var imports = null;
    var callbacks = [];
    var isDownloading = false;

    function download(uri, callback) {
      var xhr = new XMLHttpRequest();
      xhr.overrideMimeType('text/plain');
      xhr.addEventListener("load", function() {
        callback(xhr.responseText)
      });
      xhr.open('GET', uri, true);
      xhr.send('');
    }

    function parse(data) {
      ast = L20n.Parser.parse(data).body;
      imports = ast.filter(function(elem) {
        return elem.type == 'ImportStatement';
      });
      _fire(callbacks, [ast, imports]);
    }

    this.get = function LOLFile_get(callback) {
      if (ast) {
        callback(ast, imports);
      } else {
        callbacks.push(callback);
        if (!isDownloading) {
          isDownloading = true;
          download(uri, parse);
        }
      }
    }
  }

  function Resource(uri) {

    //var uri = uri;
    var rawast = [];
    var callbacks = [];

    this.ast = [];
    this.resources = []; // imported resources in order
    this.isPreprocessed = false;

    var lol = Cache.getLOLFile(uri);
    var self = this;

    function preprocess() {
      if (this.isPreprocessed) {
        return;
      }
      rawast.forEach(function(node) {
        if (node.type == 'ImportStatement') {
          var importedAST = this.resources.shift().ast;
          this.ast = self.ast.concat(importedAST);
        } else {
          this.ast.push(node);
        }
      }, this);
      this.isPreprocessed = true;
      _fire(callbacks);
    }

    this.load = function load(callback, nesting) {
      if (this.isPreprocessed) {
        callback();
      } else {
        callbacks.push(callback);
        lol.get(function resolveImports(lolast, imports) {
          rawast = lolast;
          if (imports.length) {
            imports.forEach(function(node){
              self.loadResource(node.uri.content, _ifReady(self, preprocess),
                nesting + 1);
            });
          } else {
            self.ast = rawast;
            self.isPreprocessed = true;
            _fire(callbacks);
          }
        });
      }
    }

    this.loadResource = function loadResource(uri, callback, nesting) {
      nesting = nesting || 0;
      if (nesting > 7) {
        throw "Too many nested imports";
      }
      var imported = Cache.getResource(uri);
      this.resources.push(imported);
      imported.load(callback, nesting);
    }

    this.isReady = function() {
      for (var i in this.resources) {
        if (!this.resources[i].isPreprocessed) {
          return false;
        }
      }
      return true;
    }
  }

  function Context() {

    Resource.call(this);

    var entries = {}; // resource entries
    var ctxdata = {}; // context variables

    var isFrozen = false;
    var isCompiled = false;

    var ASYNC_TIMEOUT = 500;
    var self = this;

    this.isReady = function isReady() {
      if (!isFrozen) {
        return false;
      }
      for (var i in this.resources) {
        if (!this.resources[i].isPreprocessed) {
          return false;
        }
      }
      return true;
    }

    function compile() {
      if (isCompiled) {
        return;
      }
      // flatten the AST
      this.ast = this.resources.reduce(function(prev, curr) {
        return prev.concat(curr.ast);
      }, []);
      L20n.Compiler.compile(this.ast, entries, globals);
      isCompiled = true;
      fireReadyEvent();
    }

    function fireReadyEvent() {
      console.log('fired', { ast:self.ast, entries:entries});
      var event = document.createEvent('Event');
      event.initEvent('LocalizationReady', false, false);
      event.ctx = self;
      document.dispatchEvent(event);
    }

    function getArgs(data) {
      var args = Object.create(ctxdata);
      if (data) {
        for (var i in data) {
          args[i] = data[i];
        }
      }
      return args;
    }

    function getSync(id, data) {
      if (!isCompiled) {
        throw "Error: not compiled";
      }
      var entity = entries[id];
      if (!entity || entity.local) {
        console.warn("No such entity: " + id);
        return null;
      }
      var args = getArgs(data);
      return entity.toString(args);
    };

    function getAsync(id, data, callback, fallback) {
      if (isCompiled) {
        callback(getSync(id, data));
      }
      var overdue = false;
      var ttl = window.setTimeout(function() {
        overdue = true;
        // fallback is just a string, can't interpolate context data
        callback(fallback);
      }, ASYNC_TIMEOUT);

      document.addEventListener('LocalizationReady', function(event) {
        if (overdue || event.ctx !== self) {
          return;
        }
        window.clearTimeout(ttl);
        callback(getSync(id, data));
      });
    };

    this.__defineSetter__('timeout', function(ms) {
      ASYNC_TIMEOUT = ms;
    });

    this.__defineGetter__('timeout', function() {
      return ASYNC_TIMEOUT;
    });

    this.__defineSetter__('data', function(data) {
      ctxdata = data;
    });

    this.__defineGetter__('data', function() {
      return ctxdata;
    });

    this.addResource = function(uri) {
      if (isFrozen) {
        throw "Context is frozen, can't add more resources";
      }
      this.loadResource(uri, _ifReady(this, compile));
    };

    this.freeze = function() {
      isFrozen = true;
      _ifReady(this, compile);
    };

    this.get = function(id, data, callback, fallback) {
      if (callback !== undefined) {
        getAsync(id, data, callback, fallback);
      } else {
        return getSync(id, data);
      }
    };

    this.getAttribute = function(id, attr, data) {
      if (!isCompiled) {
        throw "Error: not compiled";
      }
      var entity = entries[id];
      if (!entity || entity.local) {
        console.warn("No such entity: " + id);
        return null;
      }
      var attribute = entity.attributes[attr]
      if (!attribute || attribute.local) {
        console.warn("No such attribute: " + attr);
        return null;
      }
      var args = this._getArgs(data);
      return attribute.toString(args);
    };

    this.getAttributes = function(id, data) {
      if (!isCompiled) {
        throw "Error";
      }
      var entity = entries[id];
      if (!entity || entity.local) {
        console.warn("No such entity: " + id);
        return null;
      }
      var args = this._getArgs(data);
      var attributes = {};
      for (var attr in entity.attributes) {
        var attribute = entity.attributes[attr];
        if (!attribute.local) {
          attributes[attr] = attribute.toString(args);
        }
      }
      return attributes;
    }
  }
}).call(this);
<|endoftext|>


<commit_before>import Vue from 'vue';
import Router from 'vue-router';
import Hello from '@/components/Hello';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello,
    },
  ],
});
<commit_msg>historical routing<commit_after>import Vue from 'vue';
import Router from 'vue-router';
import Hello from '@/components/Hello';
import Login from '@/components/Login';

Vue.use(Router);

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello,
    },
    {
      path: '/login',
      name: 'Login',
      component: Login,
    },
  ],
});

<|endoftext|>


<commit_before>const track = (value) => {
	if (window.location.hostname.indexOf('localhost') > -1) console.log(val)
	if (typeof s_gi === 'function') {
		const tracker = s_gi('nytbostonglobecom')
		s.linkTrackVars = 'eVar15,prop43'
		s.linkTrackEvents = 'none'
		tracker.tl(true, 'o', value)
	}
}

export default track
<commit_msg>update tracker<commit_after>const track = (value) => {
	if (window.location.hostname.indexOf('localhost') > -1) console.log(val)
	if (typeof s_gi === 'function') {
		const tracker = s_gi('nytbostonglobecom')
		s.linkTrackVars = 'eVar15,channel,prop1
		s.linkTrackEvents = 'none'
		tracker.tl(true, 'o', value)
	}
}

export default track
<|endoftext|>


<commit_before>const tape = require('tape')
const { handleMessages } = require('./utils')
const canvasApi = require('../../canvasApi')
const randomstring = require('randomstring')

async function createCourse(sisCourseId) {
  const ACCOUNT_ID = 14
  const course = {
    name: `Integration test ${sisCourseId}`,
    course_code: 'Integration test',
    sis_course_id: sisCourseId
  }

  const canvasCourse = await canvasApi.createCourse({course}, ACCOUNT_ID)
  await canvasApi.createDefaultSection(canvasCourse)

  return canvasCourse
}

async function createUser() {
  const kthId = `v${randomstring.generate(7)}`
  const email = `${kthId}@kth.se`
  await canvasApi.createUser({
    pseudonym: {
      unique_id: kthId,
      sis_user_id: kthId,
      skip_registration: true,
      send_confirmation: false
    }m
    user: {
      name: 'Integration test',
      sortable_name: 'Integration test'
    },
    communication_channel: {
      type: 'email',
      address: email,
      skip_confirmation: true
    },
    enable_sis_reactivation: false
  })

  return kthId
}

test('should enroll an assistant in an existing course in canvas', async t => {
  t.plan(1)

  // Create the "existing course" and the "assistant" in Canvas
  // Course code should be 6 characters long
  const courseCode = 'A' + randomstring.generate(5)
  const assistantId = await createUser()
  const canvasCourse = await createCourse(courseCode + 'VT171')

  const message = {
    ugClass: 'group',
    ug1Name: `edu.courses.SF.${courseCode}.20171.1.assistants`,
    member: [assistantId]
  }

  const [{resp}] = await handleMessages(message)
  await canvasApi.pollUntilSisComplete(resp.id)
  const enrollments = await canvasApi.getEnrollments(course.id)
  t.equal(enrollments[0].sis_user_id , userKthId)
})

test('should enroll an employee in Miljöutbildningen and Canvas at KTH', async t => {
  t.plan(2)
  const muId = 5014 // Miljöutbildningen
  const ckId = 85   // Canvas at KTH

  // Create the "employee" in Canvas
  const employeeId = await createUser()

  const message = {
    ugClass: 'group',
    ug1Name: 'app.katalog3.A',
    member: [employeeId]
  }

  const [{resp}] = await handleMessages(staffMessage)
  await canvasApi.pollUntilSisComplete(resp.id)

  const muEnrollments = await canvasApi.get(`courses/${muId}/enrollments?sis_section_id[]=app.katalog3.A.section1`)
  const ckEnrollments = await canvasApi.get(`courses/${ckId}/enrollments?sis_section_id[]=app.katalog3.A.section1`)

  t.ok(
    muEnrollments.find(e => e.user.sis_user_id === employeeId),
    `The user ${employeeId} is not correctly enrolled in Miljöutbildningen`
  )

  t.ok(
    ckEnrollments.find(e => e.user.sis_user_id === employeeId),
    `The user ${employeeId} is not correctly enrolled in Canvas at KTH`
  )
})
<commit_msg>Fix typos<commit_after>const test = require('tape')
const { handleMessages } = require('./utils')
const canvasApi = require('../../canvasApi')
const randomstring = require('randomstring')

async function createCourse(sisCourseId) {
  const ACCOUNT_ID = 14
  const course = {
    name: `Integration test ${sisCourseId}`,
    course_code: 'Integration test',
    sis_course_id: sisCourseId
  }

  const canvasCourse = await canvasApi.createCourse({course}, ACCOUNT_ID)
  await canvasApi.createDefaultSection(canvasCourse)

  return canvasCourse
}

async function createUser() {
  const kthId = `v${randomstring.generate(7)}`
  const email = `${kthId}@kth.se`
  await canvasApi.createUser({
    pseudonym: {
      unique_id: kthId,
      sis_user_id: kthId,
      skip_registration: true,
      send_confirmation: false
    },
    user: {
      name: 'Integration test',
      sortable_name: 'Integration test'
    },
    communication_channel: {
      type: 'email',
      address: email,
      skip_confirmation: true
    },
    enable_sis_reactivation: false
  })

  return kthId
}

test('should enroll an assistant in an existing course in canvas', async t => {
  t.plan(1)

  // Create the "existing course" and the "assistant" in Canvas
  // Course code should be 6 characters long
  const courseCode = 'A' + randomstring.generate(5)
  const assistantId = await createUser()
  const canvasCourse = await createCourse(courseCode + 'VT171')

  const message = {
    ugClass: 'group',
    ug1Name: `edu.courses.SF.${courseCode}.20171.1.assistants`,
    member: [assistantId]
  }

  const [{resp}] = await handleMessages(message)
  await canvasApi.pollUntilSisComplete(resp.id)
  const enrollments = await canvasApi.getEnrollments(course.id)
  t.equal(enrollments[0].sis_user_id , userKthId)
})

test('should enroll an employee in Miljöutbildningen and Canvas at KTH', async t => {
  t.plan(2)
  const muId = 5014 // Miljöutbildningen
  const ckId = 85   // Canvas at KTH

  // Create the "employee" in Canvas
  const employeeId = await createUser()

  const message = {
    ugClass: 'group',
    ug1Name: 'app.katalog3.A',
    member: [employeeId]
  }

  const [{resp}] = await handleMessages(staffMessage)
  await canvasApi.pollUntilSisComplete(resp.id)

  const muEnrollments = await canvasApi.get(`courses/${muId}/enrollments?sis_section_id[]=app.katalog3.A.section1`)
  const ckEnrollments = await canvasApi.get(`courses/${ckId}/enrollments?sis_section_id[]=app.katalog3.A.section1`)

  t.ok(
    muEnrollments.find(e => e.user.sis_user_id === employeeId),
    `The user ${employeeId} is not correctly enrolled in Miljöutbildningen`
  )

  t.ok(
    ckEnrollments.find(e => e.user.sis_user_id === employeeId),
    `The user ${employeeId} is not correctly enrolled in Canvas at KTH`
  )
})
<|endoftext|>


<commit_before>// ## twig.expression.operator.js
//
// This file handles operator lookups and parsing.
module.exports = function (Twig) {
    "use strict";

    /**
     * Operator associativity constants.
     */
    Twig.expression.operator = {
        leftToRight: 'leftToRight',
        rightToLeft: 'rightToLeft'
    };

    var containment = function (a, b) {
        if (b === undefined || b === null) {
            return null;
        } else if (b.indexOf !== undefined) {
            // String
            return a === b || a !== '' && b.indexOf(a) > -1;
        } else {
            var el;
            for (el in b) {
                if (b.hasOwnProperty(el) && b[el] === a) {
                    return true;
                }
            }
            return false;
        }
    };

    /**
     * Get the precidence and associativity of an operator. These follow the order that C/C++ use.
     * See http://en.wikipedia.org/wiki/Operators_in_C_and_C++ for the table of values.
     */
    Twig.expression.operator.lookup = function (operator, token) {
        switch (operator) {
            case "..":
                token.precidence = 20;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case ',':
                token.precidence = 18;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            // Ternary
            case '?:':
            case '?':
            case ':':
                token.precidence = 16;
                token.associativity = Twig.expression.operator.rightToLeft;
                break;

            // Null-coalescing operator
            case '??':
                token.precidence = 15;
                token.associativity = Twig.expression.operator.rightToLeft;
                break;

            case 'or':
                token.precidence = 14;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'and':
                token.precidence = 13;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'b-or':
                token.precidence = 12;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'b-xor':
                token.precidence = 11;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'b-and':
                token.precidence = 10;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '==':
            case '!=':
                token.precidence = 9;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '<':
            case '<=':
            case '>':
            case '>=':
            case 'not in':
            case 'in':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '~': // String concatination
            case '+':
            case '-':
                token.precidence = 6;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '//':
            case '**':
            case '*':
            case '/':
            case '%':
                token.precidence = 5;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'not':
                token.precidence = 3;
                token.associativity = Twig.expression.operator.rightToLeft;
                break;

            case 'matches':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'starts with':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'ends with':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            default:
                throw new Twig.Error("Failed to lookup operator: " + operator + " is an unknown operator.");
        }
        token.operator = operator;
        return token;
    };

    /**
     * Handle operations on the RPN stack.
     *
     * Returns the updated stack.
     */
    Twig.expression.operator.parse = function (operator, stack) {
        Twig.log.trace("Twig.expression.operator.parse: ", "Handling ", operator);
        var a, b, c;

        if (operator === '?') {
            c = stack.pop();
        }

        b = stack.pop();
        if (operator !== 'not') {
            a = stack.pop();
        }

        if (operator !== 'in' && operator !== 'not in') {
            if (a && Array.isArray(a)) {
                a = a.length;
            }

            if (b && Array.isArray(b)) {
                b = b.length;
            }
        }

        if (operator === 'matches') {
            if (b && typeof b === 'string') {
                var reParts = b.match(/^\/(.*)\/([gims]?)$/);
                var reBody = reParts[1];
                var reFlags = reParts[2];
                b = new RegExp(reBody, reFlags);
            }
        }

        switch (operator) {
            case ':':
                // Ignore
                break;

            case '??':
                if (a === undefined) {
                    a = b;
                    b = c;
                    c = undefined;
                }

                if (a !== undefined && a !== null) {
                    stack.push(a);
                } else {
                    stack.push(b);
                }
                break;
            case '?:':
                if (Twig.lib.boolval(a)) {
                    stack.push(a);
                } else {
                    stack.push(b);
                }
                break;
            case '?':
                if (a === undefined) {
                    //An extended ternary.
                    a = b;
                    b = c;
                    c = undefined;
                }

                if (Twig.lib.boolval(a)) {
                    stack.push(b);
                } else {
                    stack.push(c);
                }
                break;

            case '+':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a + b);
                break;

            case '-':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a - b);
                break;

            case '*':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a * b);
                break;

            case '/':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a / b);
                break;

            case '//':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(Math.floor(a / b));
                break;

            case '%':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a % b);
                break;

            case '~':
                stack.push( (a != null ? a.toString() : "")
                          + (b != null ? b.toString() : "") );
                break;

            case 'not':
            case '!':
                stack.push(!Twig.lib.boolval(b));
                break;

            case '<':
                stack.push(a < b);
                break;

            case '<=':
                stack.push(a <= b);
                break;

            case '>':
                stack.push(a > b);
                break;

            case '>=':
                stack.push(a >= b);
                break;

            case '===':
                stack.push(a === b);
                break;

            case '==':
                stack.push(a == b);
                break;

            case '!==':
                stack.push(a !== b);
                break;

            case '!=':
                stack.push(a != b);
                break;

            case 'or':
                stack.push(Twig.lib.boolval(a) || Twig.lib.boolval(b));
                break;

            case 'b-or':
                stack.push(a | b);
                break;

            case 'b-xor':
                stack.push(a ^ b);
                break;

            case 'and':
                stack.push(Twig.lib.boolval(a) && Twig.lib.boolval(b));
                break;

            case 'b-and':
                stack.push(a & b);
                break;

            case '**':
                stack.push(Math.pow(a, b));
                break;

            case 'not in':
                stack.push( !containment(a, b) );
                break;

            case 'in':
                stack.push( containment(a, b) );
                break;

            case 'matches':
                stack.push( b.test(a) );
                break;

            case 'starts with':
                stack.push( a.indexOf(b) === 0 );
                break;

            case 'ends with':
                stack.push( a.indexOf(b, a.length - b.length) !== -1 );
                break;

            case '..':
                stack.push( Twig.functions.range(a, b) );
                break;

            default:
                debugger;
                throw new Twig.Error("Failed to parse operator: " + operator + " is an unknown operator.");
        }
    };

    return Twig;

};
<commit_msg>Delint twig.expression.operator.js<commit_after>// ## twig.expression.operator.js
//
// This file handles operator lookups and parsing.
module.exports = function (Twig) {
    'use strict';

    /**
     * Operator associativity constants.
     */
    Twig.expression.operator = {
        leftToRight: 'leftToRight',
        rightToLeft: 'rightToLeft'
    };

    const containment = function (a, b) {
        if (b === undefined || b === null) {
            return null;
        }

        if (b.indexOf !== undefined) {
            // String
            return (a === b || a !== '') && b.indexOf(a) > -1;
        }

        let el;
        for (el in b) {
            if (Object.hasOwnProperty.call(b, el) && b[el] === a) {
                return true;
            }
        }

        return false;
    };

    /**
     * Get the precidence and associativity of an operator. These follow the order that C/C++ use.
     * See http://en.wikipedia.org/wiki/Operators_in_C_and_C++ for the table of values.
     */
    Twig.expression.operator.lookup = function (operator, token) {
        switch (operator) {
            case '..':
                token.precidence = 20;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case ',':
                token.precidence = 18;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            // Ternary
            case '?:':
            case '?':
            case ':':
                token.precidence = 16;
                token.associativity = Twig.expression.operator.rightToLeft;
                break;

            // Null-coalescing operator
            case '??':
                token.precidence = 15;
                token.associativity = Twig.expression.operator.rightToLeft;
                break;

            case 'or':
                token.precidence = 14;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'and':
                token.precidence = 13;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'b-or':
                token.precidence = 12;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'b-xor':
                token.precidence = 11;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'b-and':
                token.precidence = 10;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '==':
            case '!=':
                token.precidence = 9;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '<':
            case '<=':
            case '>':
            case '>=':
            case 'not in':
            case 'in':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '~': // String concatination
            case '+':
            case '-':
                token.precidence = 6;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case '//':
            case '**':
            case '*':
            case '/':
            case '%':
                token.precidence = 5;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'not':
                token.precidence = 3;
                token.associativity = Twig.expression.operator.rightToLeft;
                break;

            case 'matches':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'starts with':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            case 'ends with':
                token.precidence = 8;
                token.associativity = Twig.expression.operator.leftToRight;
                break;

            default:
                throw new Twig.Error('Failed to lookup operator: ' + operator + ' is an unknown operator.');
        }

        token.operator = operator;
        return token;
    };

    /**
     * Handle operations on the RPN stack.
     *
     * Returns the updated stack.
     */
    Twig.expression.operator.parse = function (operator, stack) {
        Twig.log.trace('Twig.expression.operator.parse: ', 'Handling ', operator);
        let a;
        let b;
        let c;

        if (operator === '?') {
            c = stack.pop();
        }

        b = stack.pop();
        if (operator !== 'not') {
            a = stack.pop();
        }

        if (operator !== 'in' && operator !== 'not in') {
            if (a && Array.isArray(a)) {
                a = a.length;
            }

            if (b && Array.isArray(b)) {
                b = b.length;
            }
        }

        if (operator === 'matches') {
            if (b && typeof b === 'string') {
                const reParts = b.match(/^\/(.*)\/([gims]?)$/);
                const reBody = reParts[1];
                const reFlags = reParts[2];
                b = new RegExp(reBody, reFlags);
            }
        }

        switch (operator) {
            case ':':
                // Ignore
                break;

            case '??':
                if (a === undefined) {
                    a = b;
                    b = c;
                    c = undefined;
                }

                if (a !== undefined && a !== null) {
                    stack.push(a);
                } else {
                    stack.push(b);
                }

                break;
            case '?:':
                if (Twig.lib.boolval(a)) {
                    stack.push(a);
                } else {
                    stack.push(b);
                }

                break;
            case '?':
                if (a === undefined) {
                    // An extended ternary.
                    a = b;
                    b = c;
                    c = undefined;
                }

                if (Twig.lib.boolval(a)) {
                    stack.push(b);
                } else {
                    stack.push(c);
                }

                break;

            case '+':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a + b);
                break;

            case '-':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a - b);
                break;

            case '*':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a * b);
                break;

            case '/':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a / b);
                break;

            case '//':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(Math.floor(a / b));
                break;

            case '%':
                b = parseFloat(b);
                a = parseFloat(a);
                stack.push(a % b);
                break;

            case '~':
                stack.push((typeof a !== 'undefined' && a !== null ? a.toString() : '') +
                          (typeof b !== 'undefined' && b !== null ? b.toString() : ''));
                break;

            case 'not':
            case '!':
                stack.push(!Twig.lib.boolval(b));
                break;

            case '<':
                stack.push(a < b);
                break;

            case '<=':
                stack.push(a <= b);
                break;

            case '>':
                stack.push(a > b);
                break;

            case '>=':
                stack.push(a >= b);
                break;

            case '===':
                stack.push(a === b);
                break;

            case '==':
                /* eslint-disable-next-line eqeqeq */
                stack.push(a == b);
                break;

            case '!==':
                stack.push(a !== b);
                break;

            case '!=':
                /* eslint-disable-next-line eqeqeq */
                stack.push(a != b);
                break;

            case 'or':
                stack.push(Twig.lib.boolval(a) || Twig.lib.boolval(b));
                break;

            case 'b-or':
                stack.push(a | b);
                break;

            case 'b-xor':
                stack.push(a ^ b);
                break;

            case 'and':
                stack.push(Twig.lib.boolval(a) && Twig.lib.boolval(b));
                break;

            case 'b-and':
                stack.push(a & b);
                break;

            case '**':
                stack.push(a ** b);
                break;

            case 'not in':
                stack.push(!containment(a, b));
                break;

            case 'in':
                stack.push(containment(a, b));
                break;

            case 'matches':
                stack.push(b.test(a));
                break;

            case 'starts with':
                stack.push(a.indexOf(b) === 0);
                break;

            case 'ends with':
                stack.push(a.indexOf(b, a.length - b.length) !== -1);
                break;

            case '..':
                stack.push(Twig.functions.range(a, b));
                break;

            default:
                throw new Twig.Error('Failed to parse operator: ' + operator + ' is an unknown operator.');
        }
    };

    return Twig;
};
<|endoftext|>


<commit_before>var expect = require('chai').expect;
var log4jsSupport = require('../lib/log4js');
var log4js = require('log4js');
var runServer = require('../lib/testHelper').runServer;

log4js.restoreConsole();
describe("log4js", function(){
  describe('name', function(){
    it('should be "fluent"', function(done){
      expect(log4jsSupport.name).to.be.equal('fluent');
      done();
    });
  });

  describe('appender', function(){
    var appender = null;
    before(function(done){
      log4js.clearAppenders();
      done();
    });

    it('should send log records', function(done){
      runServer(function(server, finish){
        var appender = log4jsSupport.appender('debug', {port: server.port});
        log4js.addAppender(appender);
        var logger = log4js.getLogger('mycategory');
        logger.info('foo %s', 'bar');
        setTimeout(function(){
          finish(function(data){
            expect(data[0].tag).to.be.equal('debug.INFO');
            expect(data[0].data).exist;
            expect(data[0].data.data).to.be.equal('foo bar');
            expect(data[0].data.category).to.be.equal('mycategory');
            expect(data[0].data.timestamp).exist;
            expect(data[0].data.levelInt).exist;
            expect(data[0].data.levelStr).to.be.equal('INFO');
            done();
          });
        }, 1000);
      });
    });

    it('should not crash when fluentd is not running', function(done){
      runServer(function(server, finish){
        var appender = log4jsSupport.appender('debug', {port: server.port});
        log4js.addAppender(appender);
        var logger = log4js.getLogger('mycategory');
        logger.info('foo %s', 'bar');
        setTimeout(function(){
          finish(function(data){
            expect(data[0].tag).to.be.equal('debug.INFO');
            logger.info('foo %s', 'bar');
            done();
          });
        }, 1000);
      });
    });

    it('should listen error event when fluentd is down', function(done){
      runServer(function(server, finish){
        var appender = log4jsSupport.appender('debug', {port: server.port});
        appender.on('error', function(err) {
          expect(err.code).to.be.equal('ECONNREFUSED');
          done();
        });
        log4js.addAppender(appender);
        var logger = log4js.getLogger('mycategory');
        logger.info('foo %s', 'bar');
        setTimeout(function(){
          finish(function(data){
            expect(data[0].tag).to.be.equal('debug.INFO');
            logger.info('foo %s', 'bar');
          });
        }, 1000);
      });
    });

    it('should set max listeners', function(done) {
      var appender = log4jsSupport.appender('debug');
      log4js.addAppender(appender);
      var logger = log4js.getLogger('mycategory');
      expect(logger.getMaxListeners()).to.be.equal(10);
      logger.setMaxListeners(100);
      expect(logger.getMaxListeners()).to.be.equal(100);
      done();
    });
  });
});
<commit_msg>Test for appender<commit_after>var expect = require('chai').expect;
var log4jsSupport = require('../lib/log4js');
var log4js = require('log4js');
var runServer = require('../lib/testHelper').runServer;

log4js.restoreConsole();
describe("log4js", function(){
  describe('name', function(){
    it('should be "fluent"', function(done){
      expect(log4jsSupport.name).to.be.equal('fluent');
      done();
    });
  });

  describe('appender', function(){
    var appender = null;
    before(function(done){
      log4js.clearAppenders();
      done();
    });

    it('should send log records', function(done){
      runServer(function(server, finish){
        var appender = log4jsSupport.appender('debug', {port: server.port});
        log4js.addAppender(appender);
        var logger = log4js.getLogger('mycategory');
        logger.info('foo %s', 'bar');
        setTimeout(function(){
          finish(function(data){
            expect(data[0].tag).to.be.equal('debug.INFO');
            expect(data[0].data).exist;
            expect(data[0].data.data).to.be.equal('foo bar');
            expect(data[0].data.category).to.be.equal('mycategory');
            expect(data[0].data.timestamp).exist;
            expect(data[0].data.levelInt).exist;
            expect(data[0].data.levelStr).to.be.equal('INFO');
            done();
          });
        }, 1000);
      });
    });

    it('should not crash when fluentd is not running', function(done){
      runServer(function(server, finish){
        var appender = log4jsSupport.appender('debug', {port: server.port});
        log4js.addAppender(appender);
        var logger = log4js.getLogger('mycategory');
        logger.info('foo %s', 'bar');
        setTimeout(function(){
          finish(function(data){
            expect(data[0].tag).to.be.equal('debug.INFO');
            logger.info('foo %s', 'bar');
            done();
          });
        }, 1000);
      });
    });

    it('should listen error event when fluentd is down', function(done){
      runServer(function(server, finish){
        var appender = log4jsSupport.appender('debug', {port: server.port});
        appender.on('error', function(err) {
          expect(err.code).to.be.equal('ECONNREFUSED');
          done();
        });
        log4js.addAppender(appender);
        var logger = log4js.getLogger('mycategory');
        logger.info('foo %s', 'bar');
        setTimeout(function(){
          finish(function(data){
            expect(data[0].tag).to.be.equal('debug.INFO');
            logger.info('foo %s', 'bar');
          });
        }, 1000);
      });
    });

    it('should set max listeners', function(done) {
      var appender = log4jsSupport.appender('debug');
      expect(appender.getMaxListeners()).to.be.equal(10);
      appender.setMaxListeners(100);
      expect(appender.getMaxListeners()).to.be.equal(100);
      done();
    });
  });
});
<|endoftext|>


<commit_before>var logger = require("jitsi-meet-logger").getLogger(__filename);
var RTCBrowserType = require("./RTCBrowserType");
var JitsiTrackEvents = require("../../JitsiTrackEvents");
var EventEmitter = require("events");
var RTC = require("./RTCUtils");

/**
 * This implements 'onended' callback normally fired by WebRTC after the stream
 * is stopped. There is no such behaviour yet in FF, so we have to add it.
 * @param jitsiTrack our track object holding the original WebRTC stream object
 * to which 'onended' handling will be added.
 */
function implementOnEndedHandling(jitsiTrack) {
    var stream = jitsiTrack.getOriginalStream();

    if(!stream)
        return;

    var originalStop = stream.stop;
    stream.stop = function () {
        originalStop.apply(stream);
        if (jitsiTrack.isActive()) {
            stream.onended();
        }
    };
}

/**
 * Adds onended/oninactive handler to a MediaStream.
 * @param mediaStream a MediaStream to attach onended/oninactive handler
 * @param handler the handler
 */
function addMediaStreamInactiveHandler(mediaStream, handler) {
    if(RTCBrowserType.isTemasysPluginUsed()) {
        // themasys
        //FIXME: Seems that not working properly.
        if(mediaStream.onended) {
            mediaStream.onended = handler;
        } else if(mediaStream.addEventListener) {
            mediaStream.addEventListener('ended', function () {
                handler(mediaStream);
            });
        } else if(mediaStream.attachEvent) {
            mediaStream.attachEvent('ended', function () {
                handler(mediaStream);
            });
        }
    }
    else {
        if(typeof mediaStream.active !== "undefined")
            mediaStream.oninactive = handler;
        else
            mediaStream.onended = handler;
    }
}

/**
 * Represents a single media track (either audio or video).
 * @constructor
 * @param rtc the rtc instance
 * @param stream the stream
 * @param streamInactiveHandler the function that will handle
 *        onended/oninactive events of the stream.
 * @param jitsiTrackType optionally a type can be specified.
 *        This is the case where we are creating a dummy track with no stream
 *        Currently this happens when a remote side is starting with video muted
 */
function JitsiTrack(rtc, stream, streamInactiveHandler, jitsiTrackType)
{
    /**
     * Array with the HTML elements that are displaying the streams.
     * @type {Array}
     */
    this.containers = [];
    this.rtc = rtc;
    this.stream = stream;
    this.eventEmitter = new EventEmitter();
    this.audioLevel = -1;
    this.type = jitsiTrackType || (this.stream.getVideoTracks().length > 0)?
        JitsiTrack.VIDEO : JitsiTrack.AUDIO;
    if(this.type == JitsiTrack.AUDIO) {
        this._getTracks = function () {
            return this.stream.getAudioTracks();
        }.bind(this);
    } else {
        this._getTracks = function () {
            return this.stream.getVideoTracks();
        }.bind(this);
    }
    if (RTCBrowserType.isFirefox() && this.stream) {
        implementOnEndedHandling(this);
    }

    if(stream)
        addMediaStreamInactiveHandler(stream, streamInactiveHandler);
}

/**
 * JitsiTrack video type.
 * @type {string}
 */
JitsiTrack.VIDEO = "video";

/**
 * JitsiTrack audio type.
 * @type {string}
 */
JitsiTrack.AUDIO = "audio";

/**
 * Returns the type (audio or video) of this track.
 */
JitsiTrack.prototype.getType = function() {
    return this.type;
};

/**
 * Check if this is audiotrack.
 */
JitsiTrack.prototype.isAudioTrack = function () {
    return this.getType() === JitsiTrack.AUDIO;
};

/**
 * Check if this is videotrack.
 */
JitsiTrack.prototype.isVideoTrack = function () {
    return this.getType() === JitsiTrack.VIDEO;
};

/**
 * Returns the RTCMediaStream from the browser (?).
 */
JitsiTrack.prototype.getOriginalStream = function() {
    return this.stream;
}

/**
 * Mutes the track.
 */
JitsiTrack.prototype.mute = function () {
    this._setMute(true);
}

/**
 * Unmutes the stream.
 */
JitsiTrack.prototype.unmute = function () {
    this._setMute(false);
}

/**
 * Attaches the MediaStream of this track to an HTML container.
 * Adds the container to the list of containers that are displaying the track.
 * Note that Temasys plugin will replace original audio/video element with
 * 'object' when stream is being attached to the container for the first time.
 *
 * * NOTE * if given container element is not visible when the stream is being
 * attached it will be shown back given that Temasys plugin is currently in use.
 *
 * @param container the HTML container which can be 'video' or 'audio' element.
 *        It can also be 'object' element if Temasys plugin is in use and this
 *        method has been called previously on video or audio HTML element.
 *
 * @returns potentially new instance of container if it was replaced by the
 *          library. That's the case when Temasys plugin is in use.
 */
JitsiTrack.prototype.attach = function (container) {
    if(this.stream) {
        // The container must be visible in order to play or attach the stream
        // when Temasys plugin is in use
        var containerSel = $(container);
        if (RTCBrowserType.isTemasysPluginUsed() &&
            !containerSel.is(':visible')) {
            containerSel.show();
        }
        container
            = require("./RTCUtils").attachMediaStream(container, this.stream);
    }
    this.containers.push(container);
    return container;
}

/**
 * Removes the track from the passed HTML container.
 * @param container the HTML container. If <tt>null</tt> all containers are removed.
 *        A container can be 'video', 'audio' or 'object' HTML element instance
 *        to which this JitsiTrack is currently attached to.
 */
JitsiTrack.prototype.detach = function (container) {
    for(var i = 0; i < this.containers.length; i++)
    {
        if(!container)
        {
            require("./RTCUtils").setVideoSrc(this.containers[i], null);
        }
        if(!container || $(this.containers[i]).is($(container)))
        {
            this.containers.splice(i,1);
        }
    }

    if(container) {
        require("./RTCUtils").setVideoSrc(container, null);
    }
}

/**
 * Stops sending the media track. And removes it from the HTML.
 * NOTE: Works for local tracks only.
 */
JitsiTrack.prototype.stop = function () {
}

/**
 * Returns true if this is a video track and the source of the video is a
 * screen capture as opposed to a camera.
 */
JitsiTrack.prototype.isScreenSharing = function(){

}

/**
 * Returns id of the track.
 * @returns {string} id of the track or null if this is fake track.
 */
JitsiTrack.prototype._getId = function () {
    var tracks = this.stream.getTracks();
    if(!tracks || tracks.length === 0)
        return null;
    return tracks[0].id;
};

/**
 * Returns id of the track.
 * @returns {string} id of the track or null if this is fake track.
 */
JitsiTrack.prototype.getId = function () {
    if(this.stream)
        return RTC.getStreamID(this.stream);
    else
        return null;
};

/**
 * Checks whether the MediaStream is avtive/not ended.
 * When there is no check for active we don't have information and so
 * will return that stream is active (in case of FF).
 * @returns {boolean} whether MediaStream is active.
 */
JitsiTrack.prototype.isActive = function () {
    if((typeof this.stream.active !== "undefined"))
        return this.stream.active;
    else
        return true;
};

/**
 * Attaches a handler for events(For example - "audio level changed".).
 * All possible event are defined in JitsiTrackEvents.
 * @param eventId the event ID.
 * @param handler handler for the event.
 */
JitsiTrack.prototype.on = function (eventId, handler) {
    if(this.eventEmitter)
        this.eventEmitter.on(eventId, handler);
}

/**
 * Removes event listener
 * @param eventId the event ID.
 * @param [handler] optional, the specific handler to unbind
 */
JitsiTrack.prototype.off = function (eventId, handler) {
    if(this.eventEmitter)
        this.eventEmitter.removeListener(eventId, handler);
}

// Common aliases for event emitter
JitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;
JitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;

/**
 * Sets the audio level for the stream
 * @param audioLevel the new audio level
 */
JitsiTrack.prototype.setAudioLevel = function (audioLevel) {
    if(this.audioLevel !== audioLevel) {
        this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
            audioLevel);
        this.audioLevel = audioLevel;
    }
 }

module.exports = JitsiTrack;
<commit_msg>fix(JitsiTrack): set video element src to empty string instead of null on #detach()<commit_after>var logger = require("jitsi-meet-logger").getLogger(__filename);
var RTCBrowserType = require("./RTCBrowserType");
var JitsiTrackEvents = require("../../JitsiTrackEvents");
var EventEmitter = require("events");
var RTC = require("./RTCUtils");

/**
 * This implements 'onended' callback normally fired by WebRTC after the stream
 * is stopped. There is no such behaviour yet in FF, so we have to add it.
 * @param jitsiTrack our track object holding the original WebRTC stream object
 * to which 'onended' handling will be added.
 */
function implementOnEndedHandling(jitsiTrack) {
    var stream = jitsiTrack.getOriginalStream();

    if(!stream)
        return;

    var originalStop = stream.stop;
    stream.stop = function () {
        originalStop.apply(stream);
        if (jitsiTrack.isActive()) {
            stream.onended();
        }
    };
}

/**
 * Adds onended/oninactive handler to a MediaStream.
 * @param mediaStream a MediaStream to attach onended/oninactive handler
 * @param handler the handler
 */
function addMediaStreamInactiveHandler(mediaStream, handler) {
    if(RTCBrowserType.isTemasysPluginUsed()) {
        // themasys
        //FIXME: Seems that not working properly.
        if(mediaStream.onended) {
            mediaStream.onended = handler;
        } else if(mediaStream.addEventListener) {
            mediaStream.addEventListener('ended', function () {
                handler(mediaStream);
            });
        } else if(mediaStream.attachEvent) {
            mediaStream.attachEvent('ended', function () {
                handler(mediaStream);
            });
        }
    }
    else {
        if(typeof mediaStream.active !== "undefined")
            mediaStream.oninactive = handler;
        else
            mediaStream.onended = handler;
    }
}

/**
 * Represents a single media track (either audio or video).
 * @constructor
 * @param rtc the rtc instance
 * @param stream the stream
 * @param streamInactiveHandler the function that will handle
 *        onended/oninactive events of the stream.
 * @param jitsiTrackType optionally a type can be specified.
 *        This is the case where we are creating a dummy track with no stream
 *        Currently this happens when a remote side is starting with video muted
 */
function JitsiTrack(rtc, stream, streamInactiveHandler, jitsiTrackType)
{
    /**
     * Array with the HTML elements that are displaying the streams.
     * @type {Array}
     */
    this.containers = [];
    this.rtc = rtc;
    this.stream = stream;
    this.eventEmitter = new EventEmitter();
    this.audioLevel = -1;
    this.type = jitsiTrackType || (this.stream.getVideoTracks().length > 0)?
        JitsiTrack.VIDEO : JitsiTrack.AUDIO;
    if(this.type == JitsiTrack.AUDIO) {
        this._getTracks = function () {
            return this.stream.getAudioTracks();
        }.bind(this);
    } else {
        this._getTracks = function () {
            return this.stream.getVideoTracks();
        }.bind(this);
    }
    if (RTCBrowserType.isFirefox() && this.stream) {
        implementOnEndedHandling(this);
    }

    if(stream)
        addMediaStreamInactiveHandler(stream, streamInactiveHandler);
}

/**
 * JitsiTrack video type.
 * @type {string}
 */
JitsiTrack.VIDEO = "video";

/**
 * JitsiTrack audio type.
 * @type {string}
 */
JitsiTrack.AUDIO = "audio";

/**
 * Returns the type (audio or video) of this track.
 */
JitsiTrack.prototype.getType = function() {
    return this.type;
};

/**
 * Check if this is audiotrack.
 */
JitsiTrack.prototype.isAudioTrack = function () {
    return this.getType() === JitsiTrack.AUDIO;
};

/**
 * Check if this is videotrack.
 */
JitsiTrack.prototype.isVideoTrack = function () {
    return this.getType() === JitsiTrack.VIDEO;
};

/**
 * Returns the RTCMediaStream from the browser (?).
 */
JitsiTrack.prototype.getOriginalStream = function() {
    return this.stream;
}

/**
 * Mutes the track.
 */
JitsiTrack.prototype.mute = function () {
    this._setMute(true);
}

/**
 * Unmutes the stream.
 */
JitsiTrack.prototype.unmute = function () {
    this._setMute(false);
}

/**
 * Attaches the MediaStream of this track to an HTML container.
 * Adds the container to the list of containers that are displaying the track.
 * Note that Temasys plugin will replace original audio/video element with
 * 'object' when stream is being attached to the container for the first time.
 *
 * * NOTE * if given container element is not visible when the stream is being
 * attached it will be shown back given that Temasys plugin is currently in use.
 *
 * @param container the HTML container which can be 'video' or 'audio' element.
 *        It can also be 'object' element if Temasys plugin is in use and this
 *        method has been called previously on video or audio HTML element.
 *
 * @returns potentially new instance of container if it was replaced by the
 *          library. That's the case when Temasys plugin is in use.
 */
JitsiTrack.prototype.attach = function (container) {
    if(this.stream) {
        // The container must be visible in order to play or attach the stream
        // when Temasys plugin is in use
        var containerSel = $(container);
        if (RTCBrowserType.isTemasysPluginUsed() &&
            !containerSel.is(':visible')) {
            containerSel.show();
        }
        container
            = require("./RTCUtils").attachMediaStream(container, this.stream);
    }
    this.containers.push(container);
    return container;
}

/**
 * Removes the track from the passed HTML container.
 * @param container the HTML container. If <tt>null</tt> all containers are removed.
 *        A container can be 'video', 'audio' or 'object' HTML element instance
 *        to which this JitsiTrack is currently attached to.
 */
JitsiTrack.prototype.detach = function (container) {
    for(var i = 0; i < this.containers.length; i++)
    {
        if(!container)
        {
            require("./RTCUtils").setVideoSrc(this.containers[i], '');
        }
        if(!container || $(this.containers[i]).is($(container)))
        {
            this.containers.splice(i,1);
        }
    }

    if(container) {
        require("./RTCUtils").setVideoSrc(container, '');
    }
}

/**
 * Stops sending the media track. And removes it from the HTML.
 * NOTE: Works for local tracks only.
 */
JitsiTrack.prototype.stop = function () {
}

/**
 * Returns true if this is a video track and the source of the video is a
 * screen capture as opposed to a camera.
 */
JitsiTrack.prototype.isScreenSharing = function(){

}

/**
 * Returns id of the track.
 * @returns {string} id of the track or null if this is fake track.
 */
JitsiTrack.prototype._getId = function () {
    var tracks = this.stream.getTracks();
    if(!tracks || tracks.length === 0)
        return null;
    return tracks[0].id;
};

/**
 * Returns id of the track.
 * @returns {string} id of the track or null if this is fake track.
 */
JitsiTrack.prototype.getId = function () {
    if(this.stream)
        return RTC.getStreamID(this.stream);
    else
        return null;
};

/**
 * Checks whether the MediaStream is avtive/not ended.
 * When there is no check for active we don't have information and so
 * will return that stream is active (in case of FF).
 * @returns {boolean} whether MediaStream is active.
 */
JitsiTrack.prototype.isActive = function () {
    if((typeof this.stream.active !== "undefined"))
        return this.stream.active;
    else
        return true;
};

/**
 * Attaches a handler for events(For example - "audio level changed".).
 * All possible event are defined in JitsiTrackEvents.
 * @param eventId the event ID.
 * @param handler handler for the event.
 */
JitsiTrack.prototype.on = function (eventId, handler) {
    if(this.eventEmitter)
        this.eventEmitter.on(eventId, handler);
}

/**
 * Removes event listener
 * @param eventId the event ID.
 * @param [handler] optional, the specific handler to unbind
 */
JitsiTrack.prototype.off = function (eventId, handler) {
    if(this.eventEmitter)
        this.eventEmitter.removeListener(eventId, handler);
}

// Common aliases for event emitter
JitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;
JitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;

/**
 * Sets the audio level for the stream
 * @param audioLevel the new audio level
 */
JitsiTrack.prototype.setAudioLevel = function (audioLevel) {
    if(this.audioLevel !== audioLevel) {
        this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
            audioLevel);
        this.audioLevel = audioLevel;
    }
 }

module.exports = JitsiTrack;
<|endoftext|>


<commit_before>var vr_count = 0;
var vr_totalRuns = 0;
var vr_alldone = true;

var vr_slow_checker;
var slow_check_flag = false;
var sid = "";

var times_to_check = 10;

function A_checkGenePatternStatus(jobId){

	//alert("A_checkGenePatternStatus(jobId) called " + jobId);
	if(sid=="") sid = jobId;
	showLoading(true);
	vr_totalRuns++;
	GenePatternHelper.checkGPStatus(sid, A_checkGenePatternStatus_cb);
	//alert("After GenePatternHelper.checkGPStatus... " + jobId);
	if(vr_totalRuns > times_to_check) 	{ //avoid infinte loops
		clearInterval(vr_checker);

		//lets slow the interval for checking...1 minute
		if(!slow_check_flag)	{
			slow_check_flag = true;
			//alert("slow it down");
			vr_slow_checker = setInterval("A_checkGenePatternStatus(sid)", 60000);
		}
	}
	//alert("A_checkGenePatternStatus(jobId) exisitng... " + jobId);
}

/*
function A_checkSingleFindingStatus(taskId, sessionId)	{
	Inbox.checkSingleStatus(sessionId, taskId, A_checkFindingStatus_cb);
}
*/

function A_checkGenePatternStatus_cb(message){
	//looking for an assoc array arr[taskId]=arr[status, time]
	//alert("A_checkGenePatternStatus_cb called " + message);
	var vr_alldone = true;

	var curEl = document.getElementById(sid+"_status");
	var curElImg = document.getElementById(sid+"_image");
	var curElLink = document.getElementById(sid+"_link");
	var curElJobSelect = document.getElementById(sid+"_jobId");
	var curElProcessSelect = document.getElementById(sid+"_process");
	var curElSubmit = document.getElementById(sid+"_submit");
	if(message == 'completed')	{
		//its done, see if the innerhtml already says done
		if(curEl.innerHTML != "completed")	{
			curEl.innerHTML = "completed";
			//alert("message == 'completed' " + message);
			curElImg.src = "images/check.png";
			curElLink.onclick = "";
			curElLink.removeAttribute("onclick");
			curElJobSelect.disabled = false;
			curElProcessSelect.disabled = false;
			curElSubmit.disabled = false;
		}
	}
	else if(message == 'error')	{
		//its done, see if the innerhtml already says done
		if(curEl.innerHTML.indexOf('error') == -1)	{
			var comments = "Unspecified Error";
			curEl.innerHTML = showErrorHelp(comments, "error");
			curElImg.src = "images/error.png";
			//curElLink.onclick = "";
			//curElLink.removeAttribute("onclick");
		}
	}
	else if(message == 'running' && curEl.innerHTML.indexOf('completed') != -1 )	{
		//handle overlapping AJAX calls...this ones already completed...dont reset to running
		//basically just ignore it
	}
	else{
		//its running, need to continue
		vr_alldone = false;
	}

	if(vr_alldone)	{
		//stop checking, theyre all done
		clearInterval(vr_checker);
	}
}

function showLoading(showit)	{
	var msg = document.getElementById("loadingMsg");
	if(showit)	{
		msg.innerHTML = " Checking status...";
		setTimeout("showLoading(false)", 1000);
	}
	else
		msg.innerHTML = " ";
}

function testMap(k)	{
	Inbox.mapTest(k, testMap_cb);
}

function showErrorHelp(txt, show)	{
	txt = txt.replace("\n", " ");
	txt = txt.replace("/n", " ");
	txt = txt.replace("\"", "\\\"");
	txt = txt.replace("\'", "\\\'");
	var html = ""+show+"";
	return html;
}

function overlibWrapper(txt)	{
	//just get the first sentence
	var err = "";
	err = txt.indexOf(".") != -1 ? txt.split(".")[0] : txt;
	var t = err != "" ? err +"." : "Unspecified Error.";
	t=unescape(t);
	return overlib(t, CAPTION, "Error Details");
}<commit_msg>Added new job option to the jobdown list box.<commit_after>var vr_count = 0;
var vr_totalRuns = 0;
var vr_alldone = true;

var vr_slow_checker;
var slow_check_flag = false;
var sid = "";

var times_to_check = 10;

function A_checkGenePatternStatus(jobId){

	//alert("A_checkGenePatternStatus(jobId) called " + jobId);
	if(sid=="") sid = jobId;
	showLoading(true);
	vr_totalRuns++;
	GenePatternHelper.checkGPStatus(sid, A_checkGenePatternStatus_cb);
	//alert("After GenePatternHelper.checkGPStatus... " + jobId);
	if(vr_totalRuns > times_to_check) 	{ //avoid infinte loops
		clearInterval(vr_checker);

		//lets slow the interval for checking...1 minute
		if(!slow_check_flag)	{
			slow_check_flag = true;
			//alert("slow it down");
			vr_slow_checker = setInterval("A_checkGenePatternStatus(sid)", 60000);
		}
	}
	//alert("A_checkGenePatternStatus(jobId) exisitng... " + jobId);
}

/*
function A_checkSingleFindingStatus(taskId, sessionId)	{
	Inbox.checkSingleStatus(sessionId, taskId, A_checkFindingStatus_cb);
}
*/

function A_checkGenePatternStatus_cb(message){
	//looking for an assoc array arr[taskId]=arr[status, time]
	//alert("A_checkGenePatternStatus_cb called " + message);
	var vr_alldone = true;

	var curEl = document.getElementById(sid+"_status");
	var curElImg = document.getElementById(sid+"_image");
	var curElLink = document.getElementById(sid+"_link");
	var curElJobSelect = document.getElementById(sid+"_jobId");
	var curElProcessSelect = document.getElementById(sid+"_process");
	var curElSubmit = document.getElementById(sid+"_submit");
	if(message == 'completed')	{
		//its done, see if the innerhtml already says done
		if(curEl.innerHTML != "completed")	{
			curEl.innerHTML = "completed";
			//alert("message == 'completed' " + message);
			curElImg.src = "images/check.png";
			curElLink.onclick = "";
			curElLink.removeAttribute("onclick");
			curElJobSelect.disabled = false;
			curElProcessSelect.disabled = false;
			curElSubmit.disabled = false;

			//Add the new job id to job list list box.
			var no = new Option();
			no.value = sid;
			no.text = sid;
			curElJobSelect.options[curElJobSelect.options.length] = no;
		}
	}
	else if(message == 'error')	{
		//its done, see if the innerhtml already says done
		if(curEl.innerHTML.indexOf('error') == -1)	{
			var comments = "Unspecified Error";
			curEl.innerHTML = showErrorHelp(comments, "error");
			curElImg.src = "images/error.png";
			//curElLink.onclick = "";
			//curElLink.removeAttribute("onclick");
		}
	}
	else if(message == 'running' && curEl.innerHTML.indexOf('completed') != -1 )	{
		//handle overlapping AJAX calls...this ones already completed...dont reset to running
		//basically just ignore it
	}
	else{
		//its running, need to continue
		vr_alldone = false;
	}

	if(vr_alldone)	{
		//stop checking, theyre all done
		clearInterval(vr_checker);
	}
}

function showLoading(showit)	{
	var msg = document.getElementById("loadingMsg");
	if(showit)	{
		msg.innerHTML = " Checking status...";
		setTimeout("showLoading(false)", 1000);
	}
	else
		msg.innerHTML = " ";
}

function testMap(k)	{
	Inbox.mapTest(k, testMap_cb);
}

function showErrorHelp(txt, show)	{
	txt = txt.replace("\n", " ");
	txt = txt.replace("/n", " ");
	txt = txt.replace("\"", "\\\"");
	txt = txt.replace("\'", "\\\'");
	var html = ""+show+"";
	return html;
}

function overlibWrapper(txt)	{
	//just get the first sentence
	var err = "";
	err = txt.indexOf(".") != -1 ? txt.split(".")[0] : txt;
	var t = err != "" ? err +"." : "Unspecified Error.";
	t=unescape(t);
	return overlib(t, CAPTION, "Error Details");
}<|endoftext|>