<commit_before>var fs = require('fs'),
  path = require('path'),
  LineStream = require('byline').LineStream,
  util = require('util'),
  utile = require('utile'),
  _u = require('underscore'),
  kue = require('kue'),
  xml = require('libxslt').libxmljs,
  config = require('./config.js');

// job queue
var jobs = kue.createQueue(),
  Job = kue.Job,
  currentJob = null,
  log_file = null;

// workflow modules
var escidoc = require('./escidoc-workflow.js'),
  md = require('./cmdi-workflow.js'),
  pid = require('./pid-workflow.js');

//MD workflow events
var cmdiWorkflow = new md();

// eSciDoc workflow events
var escidocWorkflow = new escidoc();

escidocWorkflow.on('updated', function(escidocID, lastdatetime) {
  console.log('Releasing (version): ' + escidocID);
  escidocWorkflow.release(escidocID, lastdatetime);
});

escidocWorkflow.on('item-assigned-version-pid', function(escidocID) {
  // write completed item to file if log file exists
  if (log_file != null)
    fs.appendFile(log_file, escidocID + '\n', function(err) {
      if (err) console.error('Could not write to output file: ' + config.completed_file);
    });

  console.log('Item completed:' + escidocID);
});

escidocWorkflow.on('error', function(err) {
  if (currentJob != null) {
    currentJob.error(err).failed();
    console.log('Current job #' + currentJob.id + ' (' + currentJob.data.escidocID + ') marked as failed.');
  }

  console.error(err.message);
});

// PID workflow events
var pidWorkflow = new pid();

pidWorkflow.on('createdItemPID', function(escidocID, pid, url) { // fetch md-record TEI/CMD
  if (pid == null)
    throw new Error('Null PID returned');

  console.log('Created PID (version)::\n\tescidocID: ' + escidocID + '\n\tPID: ' + pid);

  var escidoc_job = jobs.create('escidoc workflow', {
    title: 'creating new CMDI md record for ' + escidocID,
    escidocID: escidocID,
    pid: pid,
    url: url
  });

  escidoc_job.on('complete', function() {
    console.log("Job complete");
  }).on('failed', function() {
    console.log("Job failed");
  }).on('progress', function(progress) {
    process.stdout.write('\r eSciDoc CMDI job #' + escidoc_job.id + ' ' + progress + '% complete\n');
  });

  escidoc_job.save();
});

pidWorkflow.on('createdContentPID', function(escidocID, componentID, pid, lastdatetime) {
  if (pid == null)
    throw new Error('Null PID returned');

  console.log('Created PID (content):: \n\tcomponentID: ' + componentID + '\n\tPID: ' + pid);
  escidocWorkflow.assignComponentPID(escidocID, componentID, pid, lastdatetime);
});

var createLoggingDir = function(callback) {
  var dir = path.join(config.log_dir, config.escidoc_handle); // create dir based on escidoc handle?
  fs.exists(dir, function(exists) {
    if (exists) callback(dir)
    else fs.mkdir(dir, 0755, function(err) {
      if (err) console.error('Error creating logging directory: ' + dir);
      else callback(dir);
    });
  });
};

var createLoggingFile = function(callback) {
  createLoggingDir(function(dir) {
    var filepath = path.join(dir, 'completed-jobs.log');
    console.log('Logging completed jobs here: ' + filepath);
    fs.exists(filepath, function(exists) {
      // create new file
      fs.readdir(dir, function(err, files) {
        var file_count = 0;
        files.forEach(function(name) {
          console.log('file found: ' + name);
          if (name.indexOf('completed-jobs.log') != -1) file_count++
        });
        if (exists) fs.renameSync(filepath, filepath + '.' + file_count);
        callback(filepath);
      });
    });
  });
};

// create PIDs for each component and add them to the CMDI md
var parseComponents = function(resources, itemDoc, cmdi, url, lastdatetime) {
  resources = _u.values(resources);
  resources = _u.sortBy(resources, function(component) { return component.componentID; }).reverse();

  _u.each(resources, function(val, key, list) {
    var url_r = url;
    var componentID = val.componentID,
      parentID = val.parentID,
      mimeType = val.mimeType;

    console.log('Creating PID for componentID: ' + componentID);

    cmdiWorkflow.once('add-resource-' + componentID, function(resource) {
      cmdiWorkflow.addResource(cmdi, resource, resources.length);
    });

    escidocWorkflow.once('content-assigned-pid-' + componentID, function(componentID, pid) {
      console.log('Adding CMDI Resource ref for componentID: ' + componentID);
      cmdiWorkflow.emit('add-resource-' + componentID, {
        parentID: parentID,
        componentID: componentID,
        pid: pid,
        mimeType: mimeType
      });
    });

    escidocWorkflow.once('completed-component-' + componentID, function(lastdatetime) {
      if (lastdatetime != null) itemDoc.root().attr({
        'last-modification-date': lastdatetime
      });

      var nextComponent = (list.length >= key + 1) ? list[key + 1] : null;
      if (nextComponent != null)
        createComponentPIDJob(nextComponent, url_r, lastdatetime);
    });
  });

  var firstComponent = resources[0];
  var url_r_1 = url.substring(0, url.lastIndexOf("?v=")).concat("/" + firstComponent.componentID.replace(/\D/g, ""));
  createComponentPIDJob(firstComponent, url_r_1, lastdatetime);
};

var createComponentPIDJob = function(component, url, lastdatetime) {
  var job = jobs.create('pid workflow', {
    title: 'creating component PID for ' + component.componentID,
    component: component,
    url: url,
    lastdatetime: lastdatetime
  });

  job.on('complete', function() {
    console.log("component PID job complete");
  }).on('failed', function() {
    console.log(" component PID job failed");
  });

  job.save();
};

// Parse member list through line stream
var inStream = fs.createReadStream(process.argv[2]);
var outStream = fs.createWriteStream(path.join(config.log_dir, 'processed.txt')); //TODO create log dir if does not exist

var members = new LineStream();

// MemberStream events
members.on('data', function(line) {
  if (line != null) {
    var data = line.split('%');
    // process one line at a time
    console.log('Processing Item: ' + data[1]);
    var job = jobs.create('pid workflow', {
      title: 'creating version PID for ' + data[1],
      escidocID: data[1],
      contentModelID: data[2],
      version: data[4]
    });

    job.on('complete', function() {
      console.log("PID job complete");
    }).on('failed', function() {
      console.log("PID job failed");
    });

    job.save();

    outStream.write(data[1] + '\n');
  }
});

members.on('end', function() {
  // create output log file
  createLoggingFile(function(filepath) {
    log_file = filepath;
  });

  jobs.on('job complete', function(id) {
    Job.get(id, function(err, job) {
      if (err) return;
      job.remove(function(err) {
        if (err) throw err;
        console.log('Removed completed job #%d', job.id);
      });
    });
  });

  jobs.process('pid workflow', function(job, ctx, done) {
    var taskId = (job.data.component != null) ? job.data.component.componentID : job.data.escidocID;
    console.log('processing pid workflow task... ' + taskId);
    if (job.data.component != null)
      pidWorkflow.generatePid(["component", job.data.component.componentID], job.data.url, job.data.component, job.data.lastdatetime, {
        id: job.id,
        done: done
      });
    else
      pidWorkflow.generatePid(['item', job.data.escidocID, job.data.contentModelID, '', job.data.version], null, null, null, {
        id: job.id,
        done: done
      });
  });

  jobs.process('escidoc workflow', function(job, ctx, done) {
    currentJob = job;
    console.log('processing escidoc workflow task... ' + job.data.escidocID);
    var current = 1,
      complete = 12;

    // listener: assigned Item PID (after CMDI md version is released)
    escidocWorkflow.once('assign-item-version-pid-' + job.data.escidocID, function(lastdatetime) {
      job.progress(current++, complete);
      escidocWorkflow.assignItemVersionPid(job.data.escidocID, job.data.pid, lastdatetime);
      setTimeout(done, 2000); // job complete
    });

    // load content refs and files
    // TODO reduce to content components fetch from Item record
    escidocWorkflow.getContentComponents(job.data.escidocID, function(resources, lastdatetime) {
      job.progress(current++, complete);
      job.log('Fetching contents...');
      // get original md record
      escidocWorkflow.retrieveItem(job.data.escidocID, function(itemDoc, mdrecord) {
        job.progress(current++, complete);

        cmdiWorkflow.once('validated-' + job.data.escidocID, function(escidocID, cmdi) {
          job.progress(current++, complete);
          job.log('Validated, adding new CMDI to eSciDoc.');
          console.log('Validated (CMDI record): ' + escidocID);
          escidocWorkflow.createMdRecord(escidocID, itemDoc, cmdi, job.data.pid);
        });

        cmdiWorkflow.getOriginalMD(job.data.escidocID, function(md) {
          job.progress(current++, complete);

          if (md.root().text().replace(/\s/g, "") == mdrecord.text().replace(/\s/g, ""))
            console.log("Optional check: Fetched md-records are equal");
          else
            console.log('Optional check: Fetched md-records are non-equal');

          //TODO xslt params
          if (mdrecord != null) {
            console.log('md:\n' + md.toString(false));
            //check MD has namespace and attr reqs
            if (md.root().namespace() == null) md.root().namespace("http://www.clarin.eu/cmd/");
            if (md.root().attr("CMDVersion") == null) md.root().attr({
              "CMDVersion": "1.1"
            });

            cmdiWorkflow.transform(md.toString(false), null, function(transformedMdRecord) {
              console.log('Transformed md-record: ' + transformedMdRecord);

              job.progress(current++, complete);

              // build CMDI Resources
              cmdiWorkflow.buildCMDIHeader(job.data.escidocID, transformedMdRecord, job.data.pid, function(cmdi) {
                job.progress(current++, complete);

                cmdiWorkflow.updateTEIFileDesc(itemDoc, cmdi, function(itemDoc, cmdi) {
                  job.progress(current++, complete);

                  // retrieve TEI keyword values (if exists) and assign content PIDs
                  cmdiWorkflow.createTEIKeywords(itemDoc, cmdi, function(itemDoc, cmdi) {
                    job.progress(current++, complete);

                    cmdiWorkflow.createTEIAnnotation(itemDoc, cmdi, function(itemDoc, cmdi) {
                      job.progress(current++, complete);

											cmdiWorkflow.createTEIRevisionDesc(itemDoc, cmdi, function(itemDoc, cmdi) {
												job.progress(current++, complete);
                        var url_j = utile.clone(job.data.url);
												parseComponents(resources, itemDoc, cmdi, url_j, lastdatetime);
											});
                    });
                  });
                });
              });
            }); // end XSLT transform
          }
        });
      });
    });
  });

  outStream.end();
});

kue.app.listen(3000);
kue.app.set('title', 'Clarin.dk PID/CMDI Workflow');
console.log('KUE ui started on port 3000');

module.exports = inStream.pipe(members);
<commit_msg>Fix for invalid url value in component (content) PIDs.<commit_after>var fs = require('fs'),
  path = require('path'),
  LineStream = require('byline').LineStream,
  util = require('util'),
  utile = require('utile'),
  _u = require('underscore'),
  kue = require('kue'),
  xml = require('libxslt').libxmljs,
  config = require('./config.js');

// job queue
var jobs = kue.createQueue(),
  Job = kue.Job,
  currentJob = null,
  log_file = null;

// workflow modules
var escidoc = require('./escidoc-workflow.js'),
  md = require('./cmdi-workflow.js'),
  pid = require('./pid-workflow.js');

//MD workflow events
var cmdiWorkflow = new md();

// eSciDoc workflow events
var escidocWorkflow = new escidoc();

escidocWorkflow.on('updated', function(escidocID, lastdatetime) {
  console.log('Releasing (version): ' + escidocID);
  escidocWorkflow.release(escidocID, lastdatetime);
});

escidocWorkflow.on('item-assigned-version-pid', function(escidocID) {
  // write completed item to file if log file exists
  if (log_file != null)
    fs.appendFile(log_file, escidocID + '\n', function(err) {
      if (err) console.error('Could not write to output file: ' + config.completed_file);
    });

  console.log('Item completed:' + escidocID);
});

escidocWorkflow.on('error', function(err) {
  if (currentJob != null) {
    currentJob.error(err).failed();
    console.log('Current job #' + currentJob.id + ' (' + currentJob.data.escidocID + ') marked as failed.');
  }

  console.error(err.message);
});

// PID workflow events
var pidWorkflow = new pid();

pidWorkflow.on('createdItemPID', function(escidocID, pid, url) { // fetch md-record TEI/CMD
  if (pid == null)
    throw new Error('Null PID returned');

  console.log('Created PID (version)::\n\tescidocID: ' + escidocID + '\n\tPID: ' + pid);

  var escidoc_job = jobs.create('escidoc workflow', {
    title: 'creating new CMDI md record for ' + escidocID,
    escidocID: escidocID,
    pid: pid,
    url: url
  });

  escidoc_job.on('complete', function() {
    console.log("Job complete");
  }).on('failed', function() {
    console.log("Job failed");
  }).on('progress', function(progress) {
    process.stdout.write('\r eSciDoc CMDI job #' + escidoc_job.id + ' ' + progress + '% complete\n');
  });

  escidoc_job.save();
});

pidWorkflow.on('createdContentPID', function(escidocID, componentID, pid, lastdatetime) {
  if (pid == null)
    throw new Error('Null PID returned');

  console.log('Created PID (content):: \n\tcomponentID: ' + componentID + '\n\tPID: ' + pid);
  escidocWorkflow.assignComponentPID(escidocID, componentID, pid, lastdatetime);
});

var createLoggingDir = function(callback) {
  var dir = path.join(config.log_dir, config.escidoc_handle); // create dir based on escidoc handle?
  fs.exists(dir, function(exists) {
    if (exists) callback(dir)
    else fs.mkdir(dir, 0755, function(err) {
      if (err) console.error('Error creating logging directory: ' + dir);
      else callback(dir);
    });
  });
};

var createLoggingFile = function(callback) {
  createLoggingDir(function(dir) {
    var filepath = path.join(dir, 'completed-jobs.log');
    console.log('Logging completed jobs here: ' + filepath);
    fs.exists(filepath, function(exists) {
      // create new file
      fs.readdir(dir, function(err, files) {
        var file_count = 0;
        files.forEach(function(name) {
          console.log('file found: ' + name);
          if (name.indexOf('completed-jobs.log') != -1) file_count++
        });
        if (exists) fs.renameSync(filepath, filepath + '.' + file_count);
        callback(filepath);
      });
    });
  });
};

// create PIDs for each component and add them to the CMDI md
var parseComponents = function(resources, itemDoc, cmdi, url, lastdatetime) {
  resources = _u.values(resources);
  resources = _u.sortBy(resources, function(component) { return component.componentID; }).reverse();

  _u.each(resources, function(val, key, list) {
    var url_r = url;
    var componentID = val.componentID,
      parentID = val.parentID,
      mimeType = val.mimeType;

    console.log('Creating PID for componentID: ' + componentID);

    cmdiWorkflow.once('add-resource-' + componentID, function(resource) {
      cmdiWorkflow.addResource(cmdi, resource, resources.length);
    });

    escidocWorkflow.once('content-assigned-pid-' + componentID, function(componentID, pid) {
      console.log('Adding CMDI Resource ref for componentID: ' + componentID);
      cmdiWorkflow.emit('add-resource-' + componentID, {
        parentID: parentID,
        componentID: componentID,
        pid: pid,
        mimeType: mimeType
      });
    });

    escidocWorkflow.once('completed-component-' + componentID, function(lastdatetime) {
      if (lastdatetime != null) itemDoc.root().attr({
        'last-modification-date': lastdatetime
      });

      var nextComponent = (list.length >= key + 1) ? list[key + 1] : null;
      if (nextComponent != null)
        createComponentPIDJob(nextComponent, url_r, lastdatetime);
    });
  });

  var firstComponent = resources[0];
  var url_r_1 = url.substring(0, url.lastIndexOf("?v=")).concat("/" + firstComponent.componentID.replace(/\D/g, ""));
  createComponentPIDJob(firstComponent, url_r_1, lastdatetime);
};

var createComponentPIDJob = function(component, url, lastdatetime) {
  var job = jobs.create('pid workflow', {
    title: 'creating component PID for ' + component.componentID,
    component: component,
    url: url,
    lastdatetime: lastdatetime
  });

  job.on('complete', function() {
    console.log("component PID job complete");
  }).on('failed', function() {
    console.log(" component PID job failed");
  });

  job.save();
};

// Parse member list through line stream
var inStream = fs.createReadStream(process.argv[2]);
var outStream = fs.createWriteStream(path.join(config.log_dir, 'processed.txt')); //TODO create log dir if does not exist

var members = new LineStream();

// MemberStream events
members.on('data', function(line) {
  if (line != null) {
    var data = line.toString('utf8').split('%');
    // process one line at a time
    console.log('Processing Item: ' + data[1]);
    var job = jobs.create('pid workflow', {
      title: 'creating version PID for ' + data[1],
      escidocID: data[1],
      contentModelID: data[2],
      version: data[4]
    });

    job.on('complete', function() {
      console.log("PID job complete");
    }).on('failed', function() {
      console.log("PID job failed");
    });

    job.save();

    outStream.write(data[1] + '\n');
  }
});

members.on('end', function() {
  // create output log file
  createLoggingFile(function(filepath) {
    log_file = filepath;
  });

  jobs.on('job complete', function(id) {
    Job.get(id, function(err, job) {
      if (err) return;
      job.remove(function(err) {
        if (err) throw err;
        console.log('Removed completed job #%d', job.id);
      });
    });
  });

  jobs.process('pid workflow', function(job, ctx, done) {
    var taskId = (job.data.component != null) ? job.data.component.componentID : job.data.escidocID;
    console.log('processing pid workflow task... ' + taskId);
    if (job.data.component != null)
      pidWorkflow.generatePid(["component", job.data.component.componentID], job.data.url, job.data.component, job.data.lastdatetime, {
        id: job.id,
        done: done
      });
    else
      pidWorkflow.generatePid(['item', job.data.escidocID, job.data.contentModelID, '', job.data.version], null, null, null, {
        id: job.id,
        done: done
      });
  });

  jobs.process('escidoc workflow', function(job, ctx, done) {
    currentJob = job;
    console.log('processing escidoc workflow task... ' + job.data.escidocID);
    var current = 1,
      complete = 12;

    // listener: assigned Item PID (after CMDI md version is released)
    escidocWorkflow.once('assign-item-version-pid-' + job.data.escidocID, function(lastdatetime) {
      job.progress(current++, complete);
      escidocWorkflow.assignItemVersionPid(job.data.escidocID, job.data.pid, lastdatetime);
      setTimeout(done, 2000); // job complete
    });

    // load content refs and files
    // TODO reduce to content components fetch from Item record
    escidocWorkflow.getContentComponents(job.data.escidocID, function(resources, lastdatetime) {
      job.progress(current++, complete);
      job.log('Fetching contents...');
      // get original md record
      escidocWorkflow.retrieveItem(job.data.escidocID, function(itemDoc, mdrecord) {
        job.progress(current++, complete);

        cmdiWorkflow.once('validated-' + job.data.escidocID, function(escidocID, cmdi) {
          job.progress(current++, complete);
          job.log('Validated, adding new CMDI to eSciDoc.');
          console.log('Validated (CMDI record): ' + escidocID);
          escidocWorkflow.createMdRecord(escidocID, itemDoc, cmdi, job.data.pid);
        });

        cmdiWorkflow.getOriginalMD(job.data.escidocID, function(md) {
          job.progress(current++, complete);

          if (md.root().text().replace(/\s/g, "") == mdrecord.text().replace(/\s/g, ""))
            console.log("Optional check: Fetched md-records are equal");
          else
            console.log('Optional check: Fetched md-records are non-equal');

          //TODO xslt params
          if (mdrecord != null) {
            console.log('md:\n' + md.toString(false));
            //check MD has namespace and attr reqs
            if (md.root().namespace() == null) md.root().namespace("http://www.clarin.eu/cmd/");
            if (md.root().attr("CMDVersion") == null) md.root().attr({
              "CMDVersion": "1.1"
            });

            cmdiWorkflow.transform(md.toString(false), null, function(transformedMdRecord) {
              console.log('Transformed md-record: ' + transformedMdRecord);

              job.progress(current++, complete);

              // build CMDI Resources
              cmdiWorkflow.buildCMDIHeader(job.data.escidocID, transformedMdRecord, job.data.pid, function(cmdi) {
                job.progress(current++, complete);

                cmdiWorkflow.updateTEIFileDesc(itemDoc, cmdi, function(itemDoc, cmdi) {
                  job.progress(current++, complete);

                  // retrieve TEI keyword values (if exists) and assign content PIDs
                  cmdiWorkflow.createTEIKeywords(itemDoc, cmdi, function(itemDoc, cmdi) {
                    job.progress(current++, complete);

                    cmdiWorkflow.createTEIAnnotation(itemDoc, cmdi, function(itemDoc, cmdi) {
                      job.progress(current++, complete);

											cmdiWorkflow.createTEIRevisionDesc(itemDoc, cmdi, function(itemDoc, cmdi) {
												job.progress(current++, complete);
                        var url_j = utile.clone(job.data.url);
												parseComponents(resources, itemDoc, cmdi, url_j, lastdatetime);
											});
                    });
                  });
                });
              });
            }); // end XSLT transform
          }
        });
      });
    });
  });

  outStream.end();
});

kue.app.listen(3000);
kue.app.set('title', 'Clarin.dk PID/CMDI Workflow');
console.log('KUE ui started on port 3000');

module.exports = inStream.pipe(members);
<|endoftext|>


<commit_before>// TODO: http://en.wikipedia.org/wiki/X_Window_authorization

var fs = require('fs');
var Buffer = require('buffer').Buffer;
// add 'unpack' method for buffer
require('./unpackbuffer').addUnpack(Buffer);

function parseXauth( buf )
{
    var offset = 0;
    var auth = [];

    while (offset < buf.length)
    {
        var cookie = {};
        var typeToName = {
            256: 'Local',
          65535: 'Wild',
            254: 'Netname',
            253: 'Krb5Principal',
            252: 'LocalHost',
              0: 'Internet',
              1: 'DECnet',
              2: 'Chaos',
 	     5: 'ServerInterpreted',
              6: 'InternetV6'
        };
        cookie.type = buf.unpack('n')[0];
        offset += 2;
        // TODO: rewrite following using loop (16bits length + string data)
        var addressLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.address = buf.unpackString(addressLen, offset);
        offset += addressLen;
        var displayNumLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.display = buf.unpackString(displayNumLen, offset);
        offset += displayNumLen;
        var authNameLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.authName = buf.unpackString(authNameLen, offset);
        offset += authNameLen;
        var authDataLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.authData = buf.unpackString(authDataLen, offset);
        offset += authDataLen;
        auth.push(cookie);
    }
    return auth;
}

module.exports = function( display, host, cb )
{
    var XAuthorityFile = process.env.XAUTHORITY;
    if (!XAuthorityFile)
    {
        if ( process.platform.match(/win/) ) {
            // http://www.straightrunning.com/XmingNotes/trouble.php
            //
            // The Xming magic cookie program, xauth (user-based), uses an
            // Xauthority file (not the traditional .Xauthority file) in
            // the %HOME% directory. To use xauth from Command Processor
            // e.g. on Windows machine 192.168.0.2 with user colin...
            XAuthorityFile = process.env.USERPROFILE + '\\Xauthority';
        } else {
            XAuthorityFile = process.env.HOME + '/.Xauthority';
        }
        fs.readFile(XAuthorityFile, function (err, data) {

            if (err) throw err;

            var auth = parseXauth(data);
            for (cookieNum in auth)
            {
                var cookie = auth[cookieNum];
                if (cookie.display == display && cookie.address == host)
                {
                    cb( cookie.authName, cookie.authData );
                    return;
                }
            }
            throw 'No auth cookie matching display=' + display + ' and  host=' + host;

        });
    }
}<commit_msg>try to connect with empty auth data if no Xauthority file<commit_after>// TODO: http://en.wikipedia.org/wiki/X_Window_authorization

var fs = require('fs');
var Buffer = require('buffer').Buffer;
// add 'unpack' method for buffer
require('./unpackbuffer').addUnpack(Buffer);

function parseXauth( buf )
{
    var offset = 0;
    var auth = [];

    while (offset < buf.length)
    {
        var cookie = {};
        var typeToName = {
            256: 'Local',
          65535: 'Wild',
            254: 'Netname',
            253: 'Krb5Principal',
            252: 'LocalHost',
              0: 'Internet',
              1: 'DECnet',
              2: 'Chaos',
 	     5: 'ServerInterpreted',
              6: 'InternetV6'
        };
        cookie.type = buf.unpack('n')[0];
        offset += 2;
        // TODO: rewrite following using loop (16bits length + string data)
        var addressLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.address = buf.unpackString(addressLen, offset);
        offset += addressLen;
        var displayNumLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.display = buf.unpackString(displayNumLen, offset);
        offset += displayNumLen;
        var authNameLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.authName = buf.unpackString(authNameLen, offset);
        offset += authNameLen;
        var authDataLen = buf.unpack('n', offset)[0];
        offset += 2;
        cookie.authData = buf.unpackString(authDataLen, offset);
        offset += authDataLen;
        auth.push(cookie);
    }
    return auth;
}

module.exports = function( display, host, cb )
{
    var XAuthorityFile = process.env.XAUTHORITY;
    if (!XAuthorityFile)
    {
        if ( process.platform.match(/win/) ) {
            // http://www.straightrunning.com/XmingNotes/trouble.php
            //
            // The Xming magic cookie program, xauth (user-based), uses an
            // Xauthority file (not the traditional .Xauthority file) in
            // the %HOME% directory. To use xauth from Command Processor
            // e.g. on Windows machine 192.168.0.2 with user colin...
            XAuthorityFile = process.env.USERPROFILE + '\\Xauthority';
        } else {
            XAuthorityFile = process.env.HOME + '/.Xauthority';
        }
        fs.readFile(XAuthorityFile, function (err, data) {

            if (err)
            {
                if (err.code == 'ENOENT')
                {
                    cb('','');
                    return;
                }
                throw err;
            }

            var auth = parseXauth(data);
            for (cookieNum in auth)
            {
                var cookie = auth[cookieNum];
                if (cookie.display == display && cookie.address == host)
                {
                    cb( cookie.authName, cookie.authData );
                    return;
                }
            }
            // throw 'No auth cookie matching display=' + display + ' and  host=' + host;
            cb( '', '' );
        });
    }
}<|endoftext|>


<commit_before>var dns = require('dns');
var EventEmitter = require('events').EventEmitter;

function compareNumbers(a, b) {
    a = parseInt(a, 10);
    b = parseInt(b, 10);
    if (a < b)
        return -1;
    if (a > b)
        return 1;
    return 0;
}

function groupSrvRecords(addrs) {
    var groups = {};  // by priority
    addrs.forEach(function(addr) {
                      if (!groups.hasOwnProperty(addr.priority))
                          groups[addr.priority] = [];

                      groups[addr.priority].push(addr);
                  });

    var result = [];
    Object.keys(groups).sort(compareNumbers).forEach(function(priority) {
        var group = groups[priority];
        var totalWeight = 0;
        group.forEach(function(addr) {
            totalWeight += addr.weight;
        });
        var w = Math.floor(Math.random() * totalWeight);
        totalWeight = 0;
        var candidate = group[0];
        group.forEach(function(addr) {
            totalWeight += addr.weight;
            if (w < totalWeight)
                candidate = addr;
        });
        if (candidate)
            result.push(candidate);
    });
    return result;
}

function resolveSrv(name, cb) {
    dns.resolveSrv(name, function(err, addrs) {
        if (err) {
            /* no SRV record, try domain as A */
            cb(err);
        } else {
            var pending = 0, error, results = [];
            var cb1 = function(e, addrs1) {
                error = error || e;
                results = results.concat(addrs1);
                pending--;
                if (pending < 1) {
                    cb(results ? null : error, results);
                }
            };
            groupSrvRecords(addrs).forEach(function(addr) {
                resolveHost(addr.name, function(e, a) {
                    if (a)
                        a = a.map(function(a1) {
                                      return { name: a1,
                                               port: addr.port };
                                  });
                    cb1(e, a);
                });
                pending++;
            });
        }
    });
}

// one of both A & AAAA, in case of broken tunnels
function resolveHost(name, cb) {
    var error, results = [], pending = 2;
    var cb1 = function(e, addrs) {
        error = error || e;
        var addr = addrs && addrs[Math.floor(Math.random() * addrs.length)];
        if (addr)
            results.push(addr);

        pending--;
        if (pending < 1)
            cb((results.length > 0) ? null : error, results);
    };

    dns.resolve4(name, cb1);
    dns.resolve6(name, cb1);
}

// connection attempts to multiple addresses in a row
function tryConnect(socket, addrs, listener) {
    var onConnect = function() {
        socket.removeListener('connect', onConnect);
        socket.removeListener('error', onError);
        // done!
        listener.emit('connect');
    };
    var error;
    var onError = function(e) {
        error = e;
        connectNext();
    };
    var connectNext = function() {
        var addr = addrs.shift();
        if (addr)
            socket.connect(addr.port, addr.name);
        else
            listener.emit('error', error);
    };
    socket.addListener('connect', onConnect);
    socket.addListener('error', onError);
    connectNext();
}

// returns EventEmitter with 'connect' & 'error'
exports.connect = function(socket, services, domain, defaultPort) {
    var listener = new EventEmitter();

    var tryServices = function() {
        var service = services.shift();
        if (service) {
            resolveSrv(service + '.' + domain, function(error, addrs) {
                if (addrs)
                    tryConnect(socket, addrs, listener);
                else
                    tryServices();
            });
        } else {
            resolveHost(domain, function(error, addrs) {
                if (addrs && addrs.length > 0) {
                    addrs = addrs.map(function(addr) {
                        return { name: addr,
                                 port: defaultPort };
                    });
                    tryConnect(socket, addrs, listener);
                } else
                    listener.emit('error', error);
            });
        }

    };
    tryServices();

    return listener;
};
<commit_msg>Use dns.lookup() rather than dns.resolve4/6(). Abandons parallelism but finds localhost.<commit_after>var dns = require('dns');
var EventEmitter = require('events').EventEmitter;

function compareNumbers(a, b) {
    a = parseInt(a, 10);
    b = parseInt(b, 10);
    if (a < b)
        return -1;
    if (a > b)
        return 1;
    return 0;
}

function groupSrvRecords(addrs) {
    var groups = {};  // by priority
    addrs.forEach(function(addr) {
                      if (!groups.hasOwnProperty(addr.priority))
                          groups[addr.priority] = [];

                      groups[addr.priority].push(addr);
                  });

    var result = [];
    Object.keys(groups).sort(compareNumbers).forEach(function(priority) {
        var group = groups[priority];
        var totalWeight = 0;
        group.forEach(function(addr) {
            totalWeight += addr.weight;
        });
        var w = Math.floor(Math.random() * totalWeight);
        totalWeight = 0;
        var candidate = group[0];
        group.forEach(function(addr) {
            totalWeight += addr.weight;
            if (w < totalWeight)
                candidate = addr;
        });
        if (candidate)
            result.push(candidate);
    });
    return result;
}

function resolveSrv(name, cb) {
    dns.resolveSrv(name, function(err, addrs) {
        if (err) {
            /* no SRV record, try domain as A */
            cb(err);
        } else {
            var pending = 0, error, results = [];
            var cb1 = function(e, addrs1) {
                error = error || e;
                results = results.concat(addrs1);
                pending--;
                if (pending < 1) {
                    cb(results ? null : error, results);
                }
            };
            groupSrvRecords(addrs).forEach(function(addr) {
                resolveHost(addr.name, function(e, a) {
                    if (a)
                        a = a.map(function(a1) {
                                      return { name: a1,
                                               port: addr.port };
                                  });
                    cb1(e, a);
                });
                pending++;
            });
        }
    });
}

// one of both A & AAAA, in case of broken tunnels
function resolveHost(name, cb) {
    var error, results = [];
    var cb1 = function(e, addr) {
        error = error || e;
        if (addr)
            results.push(addr);

        cb((results.length > 0) ? null : error, results);
    };

    dns.lookup(name, cb1);
}

// connection attempts to multiple addresses in a row
function tryConnect(socket, addrs, listener) {
    var onConnect = function() {
        socket.removeListener('connect', onConnect);
        socket.removeListener('error', onError);
        // done!
        listener.emit('connect');
    };
    var error;
    var onError = function(e) {
        error = e;
        connectNext();
    };
    var connectNext = function() {
        var addr = addrs.shift();
        if (addr)
            socket.connect(addr.port, addr.name);
        else
            listener.emit('error', error);
    };
    socket.addListener('connect', onConnect);
    socket.addListener('error', onError);
    connectNext();
}

// returns EventEmitter with 'connect' & 'error'
exports.connect = function(socket, services, domain, defaultPort) {
    var listener = new EventEmitter();

    var tryServices = function() {
        var service = services.shift();
        if (service) {
            resolveSrv(service + '.' + domain, function(error, addrs) {
                if (addrs)
                    tryConnect(socket, addrs, listener);
                else
                    tryServices();
            });
        } else {
            resolveHost(domain, function(error, addrs) {
                if (addrs && addrs.length > 0) {
                    addrs = addrs.map(function(addr) {
                        return { name: addr,
                                 port: defaultPort };
                    });
                    tryConnect(socket, addrs, listener);
                } else
                    listener.emit('error', error);
            });
        }

    };
    tryServices();

    return listener;
};
<|endoftext|>


<commit_before>/**
* Module loads jsdom & htmlparser support into YUI. Should be autoloaded once DOM is needed.
* @module nodejs-dom
*/
YUI.add('nodejs-dom', function(Y) {
    var jsdom = null,
        browser = {}, dom;

    if (!YUI._jsdom) {
        YUI._jsdom = YUI.require('jsdom');
    }

    jsdom = YUI._jsdom;
    dom = jsdom.defaultLevel;
    dom.Element.prototype.blur = function() {};
    dom.Element.prototype.focus = function() {};

    var features = {
        FetchExternalResources: [],
        ProcessExternalResources : false
    }
    browser.window = jsdom.jsdom('', null, {features: features}).createWindow();
    browser.document = browser.window.document;

    // Setup an html doctype
    var doctype = new dom.DocumentType(browser.document, 'html');
    browser.document.doctype = doctype;

    browser.document.getElementsByTagName('head').item(0).appendChild(browser.document.createElement('title'));

    browser.document.scrollTop = browser.document.documentElement.scrollTop = browser.document.body.scrollTop = 0;
    browser.document.scrollLeft = browser.document.documentElement.scrollLeft = browser.document.body.scrollLeft = 0;

    browser.window.eval = eval;

    browser.self = browser.window;
    browser.navigator = browser.window.navigator;
    browser.location = browser.window.navigator;

    if (Y.config.UA) {
        browser.window.navigator.userAgent = Y.config.UA;
    }

    browser.window.focus = function() {};
    browser.window.blur = function() {};
    browser.window.scrollTo = function() {};

    Y.config.doc = browser.window.document;
    Y.config.win = browser.window;

    if (Y.config.UA) {
        Y.UA = YUI.Env.parseUA();
    }

    Y.Browser = browser;

    Y.processCSS();

}, 'NODE', { requires: ['oop'], after: ['oop'] } );

<commit_msg>Skipping the Y.Browser creation for env-js-rhino environment.<commit_after>/**
* Module loads jsdom & htmlparser support into YUI. Should be autoloaded once DOM is needed.
* @module nodejs-dom
*/
YUI.add('nodejs-dom', function(Y) {
    // detect nodejs
    if (!process.versions.node) return;

    var jsdom = null,
        browser = {}, dom;

    if (!YUI._jsdom) {
        YUI._jsdom = YUI.require('jsdom');
    }

    jsdom = YUI._jsdom;
    dom = jsdom.defaultLevel;
    dom.Element.prototype.blur = function() {};
    dom.Element.prototype.focus = function() {};

    var features = {
        FetchExternalResources: [],
        ProcessExternalResources : false
    }
    browser.window = jsdom.jsdom('', null, {features: features}).createWindow();
    browser.document = browser.window.document;

    // Setup an html doctype
    var doctype = new dom.DocumentType(browser.document, 'html');
    browser.document.doctype = doctype;

    browser.document.getElementsByTagName('head').item(0).appendChild(browser.document.createElement('title'));

    browser.document.scrollTop = browser.document.documentElement.scrollTop = browser.document.body.scrollTop = 0;
    browser.document.scrollLeft = browser.document.documentElement.scrollLeft = browser.document.body.scrollLeft = 0;

    browser.window.eval = eval;

    browser.self = browser.window;
    browser.navigator = browser.window.navigator;
    browser.location = browser.window.navigator;

    if (Y.config.UA) {
        browser.window.navigator.userAgent = Y.config.UA;
    }

    browser.window.focus = function() {};
    browser.window.blur = function() {};
    browser.window.scrollTo = function() {};

    Y.config.doc = browser.window.document;
    Y.config.win = browser.window;

    if (Y.config.UA) {
        Y.UA = YUI.Env.parseUA();
    }

    Y.Browser = browser;

    Y.processCSS();

}, 'NODE', { requires: ['oop'], after: ['oop'] } );

<|endoftext|>


<commit_before>import React from 'react';
import renderer from 'react-test-renderer';
import { shallow } from 'enzyme';
import _inputFields from './index';
import { forEach } from 'lodash';
import { Provider } from 'react-redux';
import { reduxForm, reducer as formReducer } from 'redux-form';
import { createStore, combineReducers } from 'redux';

const { SelectInputField, ...inputFields } = _inputFields;

const testShallowInputFieldSnapshot = (options, InputComponent) => () => {
  const wrapper = shallow(<InputComponent {...options} />);

  expect(wrapper.getNodes()).toMatchSnapshot();
};

const testInputFieldSnapshot = (options, InputComponent) => () => {
  const rootReducers = combineReducers({ form: formReducer });
  const store = createStore(rootReducers);
  const WrappedComponent = reduxForm({ form: 'MyForm' })(InputComponent);
  const tree = renderer
    .create(
      <Provider store={store}>
        <WrappedComponent {...options} />
      </Provider>
    )
    .toJSON();
  expect(tree).toMatchSnapshot();
};

describe('Render InputFields', () => {
  forEach(inputFields, (InputComponent, name, idx) => {
    const schema = {
      id: name,
      title: name,
      type: 'string',
      meta: {
        vis: {
          ordinal: idx,
          editable: true,
          component: name
        }
      }
    };
    it(
      `Should render ${name}`,
      testInputFieldSnapshot({ schema, name }, InputComponent)
    );
  });

  it(
    'Should render SelectInputField',
    testInputFieldSnapshot(
      {
        schema: {
          id: 'SelectInputField',
          title: 'SelectInputField',
          type: 'number',
          oneOf: [
            { title: 'foo', const: 1, description: 'foo description' },
            { title: 'bar', const: 2, description: 'bar description' }
          ]
        },
        name: 'SelectInputField'
      },
      SelectInputField
    )
  );
});
<commit_msg>removed unused test function<commit_after>import React from 'react';
import renderer from 'react-test-renderer';
import _inputFields from './index';
import { forEach } from 'lodash';
import { Provider } from 'react-redux';
import { reduxForm, reducer as formReducer } from 'redux-form';
import { createStore, combineReducers } from 'redux';

const { SelectInputField, ...inputFields } = _inputFields;

const testInputFieldSnapshot = (options, InputComponent) => () => {
  const rootReducers = combineReducers({ form: formReducer });
  const store = createStore(rootReducers);
  const WrappedComponent = reduxForm({ form: 'MyForm' })(InputComponent);
  const tree = renderer
    .create(
      <Provider store={store}>
        <WrappedComponent {...options} />
      </Provider>
    )
    .toJSON();
  expect(tree).toMatchSnapshot();
};

describe('Render InputFields', () => {
  forEach(inputFields, (InputComponent, name, idx) => {
    const schema = {
      id: name,
      title: name,
      type: 'string',
      meta: {
        vis: {
          ordinal: idx,
          editable: true,
          component: name
        }
      }
    };
    it(
      `Should render ${name}`,
      testInputFieldSnapshot({ schema, name }, InputComponent)
    );
  });

  it(
    'Should render SelectInputField',
    testInputFieldSnapshot(
      {
        schema: {
          id: 'SelectInputField',
          title: 'SelectInputField',
          type: 'number',
          oneOf: [
            { title: 'foo', const: 1, description: 'foo description' },
            { title: 'bar', const: 2, description: 'bar description' }
          ]
        },
        name: 'SelectInputField'
      },
      SelectInputField
    )
  );
});
<|endoftext|>


<commit_before>// VENDOR LIBS
const _ = require('lodash');
const path = require('path');

module.exports.injectServiceTo = (mod) => {
    mod.service('API', [
        '$q',
        '$http',
        'Storage',
        function ($q, $http, Storage) {

            this.defaultConfig = {
                apiRoot: 'api',
                contentType: "application/json",
                dataType: 'json',
                host: 'https://iisidro-server.herokuapp.com',
                authToken: null
            };

            this.initialize = () => {
                let storedConfig = Storage.get('API');

                if (!this.config) {
                    this.config = storedConfig || this.defaultConfig;

                    if (!storedConfig) {
                        this.saveInStorage(this.defaultConfig);
                    }
                }
            };

            this.setAuthToken = (authToken) => {
                this.config.authToken = authToken;
                this.saveInStorage();
            };

            this.getAuthToken = () => {
                return this.config.authToken;
            };

            this.post = (config) => {
                return $http(this.addHeaders({
                    url: path.join(this.config.host, this.config.apiRoot, config.url),
                    method: 'POST',
                    contentType: this.config.contentType,
                    data: JSON.stringify(config.data),
                    params: config.params,
                    dataType: this.config.dataType
                }));
            };

            this.put = (config) => {
                return $http(this.addHeaders({
                    url: path.join(this.config.host, this.config.apiRoot, config.url),
                    method: 'PUT',
                    contentType: this.config.contentType,
                    data: JSON.stringify(config.data),
                    params: config.params,
                    dataType: this.config.dataType
                }));
            };

            this.get = (config) => {
                return $http(this.addHeaders({
                    url: path.join(this.config.host, this.config.apiRoot, config.url),
                    method: 'GET',
                    contentType: this.config.contentType,
                    data: JSON.stringify(config.data),
                    params: config.params,
                    dataType: this.config.dataType
                }));
            };

            this.delete = (config) => {
                return $http(this.addHeaders({
                    url: path.join(this.config.host, this.config.apiRoot, config.url),
                    method: 'DELETE',
                    contentType: this.config.contentType,
                    data: JSON.stringify(config.data),
                    params: config.params,
                    dataType: this.config.dataType
                }));
            };

            this.saveInStorage = (config) => {
                Storage.set('API', config || this.config);
            };

            this.addHeaders = (config) => {
                if (this.config.authToken) {
                    config.headers = {
                        'Authority': this.config.authToken,
                        'x-auth-token': this.config.authToken,
                        'X-CSRF-Token': this.config.authToken
                    };
                }

                return config;
            };

            this.initialize();
        }
    ]);
};<commit_msg>Delete api.js en minúsculas<commit_after><|endoftext|>


<commit_before>(function( $ ) {

module( "selectmenu: core" );

test("accessibility", function () {
	var links,
		element = $( "#speed" ).selectmenu(),
		button = element.selectmenu( "widget" ),
		menu = element.selectmenu( "menuWidget" );

	button.simulate( "focus" );
	links = menu.find( "li.ui-menu-item a" );

	expect(12 + links.length * 2);

	equal( button.attr( "role" ), "combobox", "button link role" );
	equal( button.attr( "aria-haspopup" ), "true", "button link aria-haspopup" );
	equal( button.attr( "aria-expanded" ), "false", "button link aria-expanded" );
	equal( button.attr( "aria-autocomplete" ), "list", "button link aria-autocomplete" );
	equal( button.attr( "aria-owns" ), menu.attr("id"), "button link aria-owns" );
	equal(
		button.attr( "aria-labelledby" ),
		links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
		"button link aria-labelledby"
	);
	equal( button.attr( "tabindex" ), 0, "button link tabindex" );

	equal( menu.attr( "role" ), "listbox", "menu role" );
	equal( menu.attr( "aria-labelledby" ), button.attr( "id" ), "menu aria-labelledby" );
	equal( menu.attr( "aria-hidden" ), "true", "menu aria-hidden" );
	equal( menu.attr( "tabindex" ), 0, "menu tabindex" );
	equal(
		menu.attr( "aria-activedescendant" ),
		links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
		"menu aria-activedescendant"
	);
	$.each( links, function( index ){
		equal( $( this ).attr( "role" ), "option", "menu link #" + index +" role" );
		equal( $( this ).attr( "tabindex" ), -1, "menu link #" + index +" tabindex" );
	});
});

$.each([
	{
		type: "default",
		selector: "#speed"
	},
	{
		type: "optgroups",
		selector: "#files"
	}
], function( i, settings ) {
	test( "state synchronization - after keydown on button - " + settings.type, function () {
		expect( 4 );

		var links,
			element = $( settings.selector ).selectmenu(),
			button = element.selectmenu( "widget" ),
			menu = element.selectmenu( "menuWidget" ),
			selected = element.find( "option:selected" );

		button.simulate( "focus" );
		links = menu.find("li.ui-menu-item a");

		button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
		equal(
			menu.attr( "aria-activedescendant" ),
			links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
			"menu aria-activedescendant"
		);
		equal(
			button.attr( "aria-activedescendant" ),
			links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
			"button aria-activedescendant"
		);
		equal(
			element.find( "option:selected" ).val(),
			selected.next( "option" ).val() ,
			"original select state"
		);
		equal( button.text(), selected.next( "option" ).text(), "button text" );
	});

	test("state synchronization - after click on item - " + settings.type, function () {
		expect(4);

		var links,
			element = $( settings.selector ).selectmenu(),
			button = element.selectmenu( "widget" ),
			menu = element.selectmenu( "menuWidget" );

		button.simulate( "focus" );
		links = menu.find("li.ui-menu-item a");

		button.simulate( "click" );
		menu.find( "a" ).last().simulate( "mouseover" ).trigger( "click" );
		equal(
			menu.attr( "aria-activedescendant" ),
			links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
			"menu aria-activedescendant"
		);
		equal(
			button.attr( "aria-activedescendant" ),
			links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
			"button aria-activedescendant"
		);
		equal(
			element.find( "option:selected" ).val(),
			element.find( "option" ).last().val(),
			"original select state"
		);
		equal( button.text(), element.find( "option" ).last().text(), "button text" );
	});

	test( "state synchronization - after focus item and keydown on button - " + settings.type, function () {
		expect(4);

		var links,
			element = $( settings.selector ).selectmenu(),
			button = element.selectmenu( "widget" ),
			menu = element.selectmenu( "menuWidget" ),
			options = element.find( "option" );

		// init menu
		button.simulate( "focus" );
		links = menu.find( "li.ui-menu-item a" );
		// open menu and click first item
		button.simulate( "click" );
		links.first().simulate( "mouseover" ).trigger( "click" );
		// open menu again and hover item
		button.simulate( "click" );
		links.eq(3).simulate( "mouseover" );
		// close and use keyboard control on button
		button.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
		button.simulate( "focus" );
		button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );

		equal( menu.attr( "aria-activedescendant" ), links.eq( 1 ).attr( "id" ), "menu aria-activedescendant" );
		equal( button.attr( "aria-activedescendant" ), links.eq( 1 ).attr( "id" ), "button aria-activedescendant" );
		equal( element.find( "option:selected" ).val(), options.eq( 1 ).val() , "original select state" );
		equal( button.text(), options.eq( 1 ).text(), "button text" );
	});
});

})( jQuery );
<commit_msg>Selectmenu Tests: use asyncTest when working with focus events<commit_after>(function( $ ) {

module( "selectmenu: core" );

asyncTest("accessibility", function () {
	var links,
		element = $( "#speed" ).selectmenu(),
		button = element.selectmenu( "widget" ),
		menu = element.selectmenu( "menuWidget" );

	button.simulate( "focus" );
	links = menu.find( "li.ui-menu-item a" );

	expect(12 + links.length * 2);

	setTimeout(function() {
		equal( button.attr( "role" ), "combobox", "button link role" );
		equal( button.attr( "aria-haspopup" ), "true", "button link aria-haspopup" );
		equal( button.attr( "aria-expanded" ), "false", "button link aria-expanded" );
		equal( button.attr( "aria-autocomplete" ), "list", "button link aria-autocomplete" );
		equal( button.attr( "aria-owns" ), menu.attr("id"), "button link aria-owns" );
		equal(
			button.attr( "aria-labelledby" ),
			links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
			"button link aria-labelledby"
		);
		equal( button.attr( "tabindex" ), 0, "button link tabindex" );

		equal( menu.attr( "role" ), "listbox", "menu role" );
		equal( menu.attr( "aria-labelledby" ), button.attr( "id" ), "menu aria-labelledby" );
		equal( menu.attr( "aria-hidden" ), "true", "menu aria-hidden" );
		equal( menu.attr( "tabindex" ), 0, "menu tabindex" );
		equal(
			menu.attr( "aria-activedescendant" ),
			links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
			"menu aria-activedescendant"
		);
		$.each( links, function( index ){
			equal( $( this ).attr( "role" ), "option", "menu link #" + index +" role" );
			equal( $( this ).attr( "tabindex" ), -1, "menu link #" + index +" tabindex" );
		});
		start();
	}, 1 );
});

$.each([
	{
		type: "default",
		selector: "#speed"
	},
	{
		type: "optgroups",
		selector: "#files"
	}
], function( i, settings ) {
	asyncTest( "state synchronization - after keydown on button - " + settings.type, function () {
		expect( 4 );

		var links,
			element = $( settings.selector ).selectmenu(),
			button = element.selectmenu( "widget" ),
			menu = element.selectmenu( "menuWidget" ),
			selected = element.find( "option:selected" );

		button.simulate( "focus" );
		setTimeout(function() {
			links = menu.find("li.ui-menu-item a");

			button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
			equal(
				menu.attr( "aria-activedescendant" ),
				links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
				"menu aria-activedescendant"
			);
			equal(
				button.attr( "aria-activedescendant" ),
				links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
				"button aria-activedescendant"
			);
			equal(
				element.find( "option:selected" ).val(),
				selected.next( "option" ).val() ,
				"original select state"
			);
			equal( button.text(), selected.next( "option" ).text(), "button text" );
			start();
		}, 1 );
	});

	asyncTest("state synchronization - after click on item - " + settings.type, function () {
		expect(4);

		var links,
			element = $( settings.selector ).selectmenu(),
			button = element.selectmenu( "widget" ),
			menu = element.selectmenu( "menuWidget" );

		button.simulate( "focus" );
		setTimeout(function() {
			links = menu.find("li.ui-menu-item a");

			button.simulate( "click" );
			menu.find( "a" ).last().simulate( "mouseover" ).trigger( "click" );
			equal(
				menu.attr( "aria-activedescendant" ),
				links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
				"menu aria-activedescendant"
			);
			equal(
				button.attr( "aria-activedescendant" ),
				links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
				"button aria-activedescendant"
			);
			equal(
				element.find( "option:selected" ).val(),
				element.find( "option" ).last().val(),
				"original select state"
			);
			equal( button.text(), element.find( "option" ).last().text(), "button text" );
			start();
		}, 1 );
	});

	asyncTest( "state synchronization - after focus item and keydown on button - " + settings.type, function () {
		expect(4);

		var links,
			element = $( settings.selector ).selectmenu(),
			button = element.selectmenu( "widget" ),
			menu = element.selectmenu( "menuWidget" ),
			options = element.find( "option" );

		// init menu
		button.simulate( "focus" );

		setTimeout(function() {
			links = menu.find( "li.ui-menu-item a" );
			// open menu and click first item
			button.simulate( "click" );
			links.first().simulate( "mouseover" ).trigger( "click" );
			// open menu again and hover item
			button.simulate( "click" );
			links.eq(3).simulate( "mouseover" );
			// close and use keyboard control on button
			button.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
			button.simulate( "focus" );
			setTimeout(function() {
				button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );

				equal( menu.attr( "aria-activedescendant" ), links.eq( 1 ).attr( "id" ), "menu aria-activedescendant" );
				equal( button.attr( "aria-activedescendant" ), links.eq( 1 ).attr( "id" ), "button aria-activedescendant" );
				equal( element.find( "option:selected" ).val(), options.eq( 1 ).val() , "original select state" );
				equal( button.text(), options.eq( 1 ).text(), "button text" );
				start();
			}, 1 );
		}, 1 );
	});
});

})( jQuery );
<|endoftext|>


<commit_before>import config  from '../config';
import request from 'request';

/**
 * Request
 *
 * A wrapper of npm 'request' to allow for
 * genericizing request and response manipulations.
 */
export default {

    get(url, options, callback) {
        handleRequest(url, options, (req) => {
            request.get(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    },

    /**
     * GET PROXY
     *
     * Functions the same as a get request but takes a
     * response object instead of a callback and pipes
     * the request response to the response object.
     */
    getProxy(url, options, res) {
        handleRequest(url, options, (req) => {
            request.get(req).pipe(res);
        });
    },

    post(url, options, callback) {
        handleRequest(url, options, (req) => {
            request.post(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    },

    put (url, options, callback) {
        handleRequest(url, options, (req) => {
            request.put(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    },

    del(url, options, callback) {
        handleRequest(url, options, (req) => {
            request.del(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    }

};

/**
 * Handle Request
 *
 * Processes all requests before they fire.
 */
function handleRequest(url, options, callback) {
    let req = {
        url: url,
        headers: {},
        qs: {},
        json: {}
    };

    req = parseOptions(req, options);
    callback(req);
}

/**
 * Handle Response
 *
 * Process all responses before they return
 * to the callback.
 */
function handleResponse(err, res, callback) {
    callback(err, res);
}

/**
 * Parse Options
 *
 * Normalizes request options.
 */
function parseOptions(req, options) {
    if (options.query)  {req.qs = options.query;}
    if (options.body)   {req.json = options.body;}
    if (req.url && req.url.indexOf(config.scitran.url) > -1) {
        req.headers = {
            'X-SciTran-Auth': config.scitran.secret,
            'User-Agent': 'SciTran Drone CRN Server'
        };
    }
    if (options.headers) {
        for (let key in options.headers) {
            req.headers[key] = options.headers[key];
        }
    }
    return req;
}
<commit_msg>Allow overriding statuses when proxying requests<commit_after>import config  from '../config';
import request from 'request';

/**
 * Request
 *
 * A wrapper of npm 'request' to allow for
 * genericizing request and response manipulations.
 */
export default {

    get(url, options, callback) {
        handleRequest(url, options, (req) => {
            request.get(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    },

    /**
     * GET PROXY
     *
     * Functions the same as a get request but takes a
     * response object instead of a callback and pipes
     * the request response to the response object.
     */
    getProxy(url, options, res) {
        handleRequest(url, options, (req) => {
            request.get(req).on('response', (resp) => {
                if (options.status) {resp.statusCode = options.status;}
            }).pipe(res);
        });
    },

    post(url, options, callback) {
        handleRequest(url, options, (req) => {
            request.post(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    },

    put (url, options, callback) {
        handleRequest(url, options, (req) => {
            request.put(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    },

    del(url, options, callback) {
        handleRequest(url, options, (req) => {
            request.del(req, (err, res) => {
                handleResponse(err, res, callback);
            });
        });
    }

};

/**
 * Handle Request
 *
 * Processes all requests before they fire.
 */
function handleRequest(url, options, callback) {
    let req = {
        url: url,
        headers: {},
        qs: {},
        json: {}
    };

    req = parseOptions(req, options);
    callback(req);
}

/**
 * Handle Response
 *
 * Process all responses before they return
 * to the callback.
 */
function handleResponse(err, res, callback) {
    callback(err, res);
}

/**
 * Parse Options
 *
 * Normalizes request options.
 */
function parseOptions(req, options) {
    if (options.query)  {req.qs = options.query;}
    if (options.body)   {req.json = options.body;}
    if (req.url && req.url.indexOf(config.scitran.url) > -1) {
        req.headers = {
            'X-SciTran-Auth': config.scitran.secret,
            'User-Agent': 'SciTran Drone CRN Server'
        };
    }
    if (options.headers) {
        for (let key in options.headers) {
            req.headers[key] = options.headers[key];
        }
    }
    return req;
}
<|endoftext|>


<commit_before>/* @flow */
import warning from 'warning'
import type StyleSheet from './StyleSheet'
import type {Plugin, Rule, RuleOptions, JssStyle} from './types'
import RegularRule from './plugins/RegularRule'

export default class PluginsRegistry {
  hooks: {[key: string]: Array<Function>} = {
    onCreateRule: [],
    onProcessRule: [],
    onProcessStyle: [],
    onProcessSheet: [],
    onChangeValue: []
  }

  /**
   * Call `onCreateRule` hooks and return an object if returned by a hook.
   */
  onCreateRule(name?: string, decl: JssStyle, options: RuleOptions): Rule|null {
    for (let i = 0; i < this.hooks.onCreateRule.length; i++) {
      const rule = this.hooks.onCreateRule[i](name, decl, options)
      if (rule) return rule
    }
    return null
  }

  /**
   * Call `onProcessRule` hooks.
   */
  onProcessRule(rule: Rule): void {
    if (rule.isProcessed) return
    const {sheet} = rule.options
    for (let i = 0; i < this.hooks.onProcessRule.length; i++) {
      this.hooks.onProcessRule[i](rule, sheet)
    }

    // TODO
    // Find a way to use rule.type with flow
    if (rule instanceof RegularRule) this.onProcessStyle(rule.style, rule, sheet)
    rule.isProcessed = true
  }

  /**
   * Call `onProcessStyle` hooks.
   */
  onProcessStyle(style: JssStyle, rule: Rule, sheet?: StyleSheet): void {
    // TODO
    // Only added because of flow.
    if (!(rule instanceof RegularRule)) return
    for (let i = 0; i < this.hooks.onProcessStyle.length; i++) {
      rule.style = style = this.hooks.onProcessStyle[i](style, rule, sheet)
    }
  }

  /**
   * Call `onProcessSheet` hooks.
   */
  onProcessSheet(sheet: StyleSheet): void {
    for (let i = 0; i < this.hooks.onProcessSheet.length; i++) {
      this.hooks.onProcessSheet[i](sheet)
    }
  }

  /**
   * Call `onChangeValue` hooks.
   */
  onChangeValue(value: string, prop: string, rule: Rule): string {
    let processedValue = value
    for (let i = 0; i < this.hooks.onChangeValue.length; i++) {
      processedValue = this.hooks.onChangeValue[i](processedValue, prop, rule)
    }
    return processedValue
  }

  /**
   * Register a plugin.
   * If function is passed, it is a shortcut for `{onProcessRule}`.
   */
  use(plugin: Plugin): void {
    for (const name in plugin) {
      if (this.hooks[name]) this.hooks[name].push(plugin[name])
      else warning(false, '[JSS] Unknown hook "%s".', name)
    }
  }
}
<commit_msg>use $FlowFixMe<commit_after>/* @flow */
import warning from 'warning'
import type StyleSheet from './StyleSheet'
import type {Plugin, Rule, RuleOptions, JssStyle} from './types'
import RegularRule from './plugins/RegularRule'

export default class PluginsRegistry {
  hooks: {[key: string]: Array<Function>} = {
    onCreateRule: [],
    onProcessRule: [],
    onProcessStyle: [],
    onProcessSheet: [],
    onChangeValue: []
  }

  /**
   * Call `onCreateRule` hooks and return an object if returned by a hook.
   */
  onCreateRule(name?: string, decl: JssStyle, options: RuleOptions): Rule|null {
    for (let i = 0; i < this.hooks.onCreateRule.length; i++) {
      const rule = this.hooks.onCreateRule[i](name, decl, options)
      if (rule) return rule
    }
    return null
  }

  /**
   * Call `onProcessRule` hooks.
   */
  onProcessRule(rule: Rule): void {
    if (rule.isProcessed) return
    const {sheet} = rule.options
    for (let i = 0; i < this.hooks.onProcessRule.length; i++) {
      this.hooks.onProcessRule[i](rule, sheet)
    }

    // $FlowFixMe
    if (rule.style) this.onProcessStyle(rule.style, rule, sheet)

    rule.isProcessed = true
  }

  /**
   * Call `onProcessStyle` hooks.
   */
  onProcessStyle(style: JssStyle, rule: Rule, sheet?: StyleSheet): void {
    let nextStyle = style

    for (let i = 0; i < this.hooks.onProcessStyle.length; i++) {
      nextStyle = this.hooks.onProcessStyle[i](nextStyle, rule, sheet)
      // $FlowFixMe
      rule.style = nextStyle
    }
  }

  /**
   * Call `onProcessSheet` hooks.
   */
  onProcessSheet(sheet: StyleSheet): void {
    for (let i = 0; i < this.hooks.onProcessSheet.length; i++) {
      this.hooks.onProcessSheet[i](sheet)
    }
  }

  /**
   * Call `onChangeValue` hooks.
   */
  onChangeValue(value: string, prop: string, rule: Rule): string {
    let processedValue = value
    for (let i = 0; i < this.hooks.onChangeValue.length; i++) {
      processedValue = this.hooks.onChangeValue[i](processedValue, prop, rule)
    }
    return processedValue
  }

  /**
   * Register a plugin.
   * If function is passed, it is a shortcut for `{onProcessRule}`.
   */
  use(plugin: Plugin): void {
    for (const name in plugin) {
      if (this.hooks[name]) this.hooks[name].push(plugin[name])
      else warning(false, '[JSS] Unknown hook "%s".', name)
    }
  }
}
<|endoftext|>


<commit_before>var _ = require("lodash");

module.exports = function(){

    var rulesets = {};
    var salience_graph = {};
    var keys_module_data = {};

    return Object.freeze({
        get: function(rid){
            return rulesets[rid];
        },
        put: function(rs){
            if(true
                && _.has(rs, "meta.keys")
                && _.has(rs, "meta.provides_keys")
            ){
                _.each(rs.meta.provides_keys, function(p, key){
                    _.each(p.to, function(to_rid){
                        _.set(keys_module_data, [
                            "provided",
                            rs.rid,
                            to_rid,
                            key
                        ], _.cloneDeep(rs.meta.keys[key]));
                    });
                });
            }

            if(_.has(rs, "meta.keys")){
                //"remove" keys so they don't leak out
                //don't use delete b/c it mutates the loaded rs
                rs = _.assign({}, rs, {
                    meta: _.omit(rs.meta, "keys")
                });
            }

            //now setup `salience_graph` and `rulesets`
            _.each(salience_graph, function(data_d, domain){
                _.each(data_d, function(data_t, type){
                    //clear out any old versions graph
                    _.unset(salience_graph, [domain, type, rs.rid]);
                });
            });
            _.each(rs.rules, function(rule){
                rule.rid = rs.rid;
                _.each(rule.select && rule.select.graph, function(g, domain){
                    _.each(g, function(exprs, type){
                        _.set(salience_graph, [domain, type, rule.rid, rule.name], true);
                    });
                });
            });
            rulesets[rs.rid] = rs;
        },
        del: function(rid){
            if(_.has(rulesets, rid)){
                _.each(rulesets[rid].rules, function(rule){
                    _.each(rule.select && rule.select.graph, function(g, domain){
                        _.each(g, function(exprs, type){
                            _.unset(salience_graph, [domain, type, rid]);
                        });
                    });
                });
                delete rulesets[rid];
            }
        },
        provideKey: function(rid, use_rid){
            if(_.has(keys_module_data, ["provided", use_rid, rid])){
                _.set(keys_module_data, [
                    "used_keys",
                    rid,
                ], keys_module_data.provided[use_rid][rid]);
            }
        },
        getKey: function(rid, key_id){
            return _.get(keys_module_data, ["used_keys", rid, key_id]);
        },
        salientRules: function(domain, type, ridFilter){
            var to_run = _.get(salience_graph, [domain, type], {});

            var rules_to_select = [];
            _.each(to_run, function(rules, rid){
                if(!ridFilter(rid)){
                    return;
                }
                _.each(rules, function(is_on, rule_name){
                    if(is_on){
                        var rule = _.get(rulesets, [rid, "rules", rule_name]);
                        if(rule){
                            //shallow clone with it's own scope for this run
                            rules_to_select.push(_.assign({}, rule, {
                                scope: rulesets[rid].scope.push()
                            }));
                        }
                    }
                });
            });
            return rules_to_select;
        },
        assertNoDependants: function(rid){
            _.each(rulesets, function(rs){
                _.each(rs.modules_used, function(info){
                    if(info.rid === rid){
                        throw new Error("\"" + rid + "\" is depended on by \"" + rs.rid + "\"");
                    }
                });
            });
        },
    });
};
<commit_msg>SalienceGraph<commit_after>var _ = require("lodash");

var SalienceGraph = function(){
    var graph = {};
    var put = function(rs){
        del(rs.rid);//clear out the old one, if pressent
        _.each(rs.rules, function(rule){
            rule.rid = rs.rid;
            _.each(rule.select && rule.select.graph, function(g, domain){
                _.each(g, function(exprs, type){
                    _.set(graph, [domain, type, rule.rid, rule.name], true);
                });
            });
        });
    };
    var get = function(domain, type){
        return _.get(graph, [domain, type], {});
    };
    var del = function(rid){
        _.each(graph, function(data_d, domain){
            _.each(data_d, function(data_t, type){
                //clear out any old versions graph
                _.unset(graph, [domain, type, rid]);
            });
        });
    };
    return Object.freeze({
        put: put,
        get: get,
        del: del,
    });
};

module.exports = function(){

    var rulesets = {};
    var salience_graph = SalienceGraph();
    var keys_module_data = {};

    return Object.freeze({
        get: function(rid){
            return rulesets[rid];
        },
        put: function(rs){
            if(true
                && _.has(rs, "meta.keys")
                && _.has(rs, "meta.provides_keys")
            ){
                _.each(rs.meta.provides_keys, function(p, key){
                    _.each(p.to, function(to_rid){
                        _.set(keys_module_data, [
                            "provided",
                            rs.rid,
                            to_rid,
                            key
                        ], _.cloneDeep(rs.meta.keys[key]));
                    });
                });
            }

            if(_.has(rs, "meta.keys")){
                //"remove" keys so they don't leak out
                //don't use delete b/c it mutates the loaded rs
                rs = _.assign({}, rs, {
                    meta: _.omit(rs.meta, "keys")
                });
            }

            salience_graph.put(rs);
            rulesets[rs.rid] = rs;
        },
        del: function(rid){
            salience_graph.del(rid);
            delete rulesets[rid];
        },
        provideKey: function(rid, use_rid){
            if(_.has(keys_module_data, ["provided", use_rid, rid])){
                _.set(keys_module_data, [
                    "used_keys",
                    rid,
                ], keys_module_data.provided[use_rid][rid]);
            }
        },
        getKey: function(rid, key_id){
            return _.get(keys_module_data, ["used_keys", rid, key_id]);
        },
        salientRules: function(domain, type, ridFilter){
            var to_run = salience_graph.get(domain, type);
            var rules_to_select = [];
            _.each(to_run, function(rules, rid){
                if(!ridFilter(rid)){
                    return;
                }
                _.each(rules, function(is_on, rule_name){
                    if(!is_on){
                        return;
                    }
                    var rule = _.get(rulesets, [rid, "rules", rule_name]);
                    if(!rule){
                        return;
                    }
                    //shallow clone with it's own scope for this run
                    rules_to_select.push(_.assign({}, rule, {
                        scope: rulesets[rid].scope.push()
                    }));
                });
            });
            return rules_to_select;
        },
        assertNoDependants: function(rid){
            _.each(rulesets, function(rs){
                _.each(rs.modules_used, function(info){
                    if(info.rid === rid){
                        throw new Error("\"" + rid + "\" is depended on by \"" + rs.rid + "\"");
                    }
                });
            });
        },
    });
};
<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { pure, props, skinnable, t, stateClassUtil } from '../utils';
import Popover from '../popover/Popover';

@pure
@skinnable()
@props({
  children: t.ReactChildren,
  popover: t.refinement(t.Object, p => t.String.is(p.content) && t.Nil.is(p.event)),
  type: t.enums.of(['light', 'dark']),
  size: t.enums.of(['small', 'big']),
  className: t.maybe(t.String),
  id: t.maybe(t.String),
  style: t.maybe(t.Object)
})
export default class Tooltip extends React.Component {

  static defaultProps = {
    type: 'dark',
    size: 'small'
  }

  getLocals() {
    const { children, type, size, ...props } = this.props;
    const popover = {
      ...props.popover,
      event: 'hover',
      className: cx('tooltip', stateClassUtil([type, size]), props.popover.className)
    };
    return {
      children,
      type, size,
      popoverProps: { ...props, popover }
    };
  }

  template({ popoverProps, children }) {
    return (
      <Popover { ...popoverProps }>
        {children}
      </Popover>
    );
  }

}
<commit_msg>add Tooltip comments<commit_after>import React from 'react';
import cx from 'classnames';
import { pure, props, skinnable, t, stateClassUtil } from '../utils';
import Popover from '../popover/Popover';

/** Tooltip that appears when the mouse is over an element
 * @param children - the element over which the tooltip is shown
 * @param popover - popover props
 * @param type - light | dark
 * @param size - small | big
 */
@pure
@skinnable()
@props({
  children: t.ReactChildren,
  popover: t.refinement(t.Object, p => t.String.is(p.content) && t.Nil.is(p.event)),
  type: t.enums.of(['light', 'dark']),
  size: t.enums.of(['small', 'big']),
  className: t.maybe(t.String),
  id: t.maybe(t.String),
  style: t.maybe(t.Object)
})
export default class Tooltip extends React.Component {

  static defaultProps = {
    type: 'dark',
    size: 'small'
  }

  getLocals() {
    const { children, type, size, ...props } = this.props;
    const popover = {
      ...props.popover,
      event: 'hover',
      className: cx('tooltip', stateClassUtil([type, size]), props.popover.className)
    };
    return {
      children,
      type, size,
      popoverProps: { ...props, popover }
    };
  }

  template({ popoverProps, children }) {
    return (
      <Popover { ...popoverProps }>
        {children}
      </Popover>
    );
  }

}
<|endoftext|>


<commit_before>
////////////////////////////////////////////////////////////////////////////////

var JSHC = new Object();
JSHC.Parser = new Object();
JSHC.Simplify = new Object();

modules = new Object();

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

JSHC.getKeys = function(obj){
   var key,keys = [];
   for(key in obj){
      keys.push(key);
   }
   return keys;
};

JSHC.getValues = function(obj){
   var key,values = [];
   for(key in obj){
      values.push(obj[key]);
   }
   return values;
};

JSHC.showKeys = function(obj){
    var key,strs=[];
    for(k in obj){
       strs.push(k);
       strs.push("
");
    }
    strs.pop();
    return strs.join("");
};

JSHC.numberOfKeys = function(obj){
   var key,keys = 0;
   for(key in obj){
      keys = keys + 1;
   }
   return keys;
};

JSHC.alert = function(){
   var res = "";
   for(var arg=0 ; arg<arguments.length ; arg++){
       if (typeof arguments[arg] !== "string")
          res += "\n" + JSHC.showAST(arguments[arg]) + "\n";
       else
          res += arguments[arg];
   };
   alert(res);
};

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

JSHC.deepCopy = function(obj){
    switch( typeof obj ){

    // immutable
    case "number":
    case "boolean":
    case "string":
    case "function":
        return obj;

    case "object":
        var clone = new Object;
        for(var key in obj){
            clone[key] = JSHC.deepCopy(obj[key]);
        }
        return clone;

    default:
        throw new Error("JSHC.deepCopy: missing case: "+typeof obj);
    }
};

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

JSHC.showPos = function(pos){
    if( pos === undefined ){
        return "unknown position";
    }

    return "line "+pos.first_line+"-"+pos.last_line+", "+
           "column "+pos.first_column+"-"+pos.last_column;
};

////////////////////////////////////////////////////////////////////////////////
<commit_msg>single line/column number when no range<commit_after>
////////////////////////////////////////////////////////////////////////////////

var JSHC = new Object();
JSHC.Parser = new Object();
JSHC.Simplify = new Object();

modules = new Object();

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

JSHC.getKeys = function(obj){
   var key,keys = [];
   for(key in obj){
      keys.push(key);
   }
   return keys;
};

JSHC.getValues = function(obj){
   var key,values = [];
   for(key in obj){
      values.push(obj[key]);
   }
   return values;
};

JSHC.showKeys = function(obj){
    var key,strs=[];
    for(k in obj){
       strs.push(k);
       strs.push("
");
    }
    strs.pop();
    return strs.join("");
};

JSHC.numberOfKeys = function(obj){
   var key,keys = 0;
   for(key in obj){
      keys = keys + 1;
   }
   return keys;
};

JSHC.alert = function(){
   var res = "";
   for(var arg=0 ; arg<arguments.length ; arg++){
       if (typeof arguments[arg] !== "string")
          res += "\n" + JSHC.showAST(arguments[arg]) + "\n";
       else
          res += arguments[arg];
   };
   alert(res);
};

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

JSHC.deepCopy = function(obj){
    switch( typeof obj ){

    // immutable
    case "number":
    case "boolean":
    case "string":
    case "function":
        return obj;

    case "object":
        var clone = new Object;
        for(var key in obj){
            clone[key] = JSHC.deepCopy(obj[key]);
        }
        return clone;

    default:
        throw new Error("JSHC.deepCopy: missing case: "+typeof obj);
    }
};

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

JSHC.showPos = function(pos){
    if( pos === undefined ){
        return "unknown position";
    }

    var line = (pos.last_line - pos.first_line > 0) ?
                (pos.first_line + "-" + pos.last_line) :
                pos.first_line;
    var column = (pos.last_column - pos.first_column > 0) ?
                (pos.first_column + "-" + pos.last_column) :
                pos.first_column;
    return "line " + line + ", column " + column;
};

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>