<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('underscore');
var grpc = require('..');
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
var GoogleAuth = require('google-auth-library');

var assert = require('assert');

var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' +
    '@developer.gserviceaccount.com');
var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
    '@developer.gserviceaccount.com');

/**
 * Create a buffer filled with size zeroes
 * @param {number} size The length of the buffer
 * @return {Buffer} The new buffer
 */
function zeroBuffer(size) {
  var zeros = new Buffer(size);
  zeros.fill(0);
  return zeros;
}

/**
 * Run the empty_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyUnary(client, done) {
  var call = client.emptyCall({}, function(err, resp) {
    assert.ifError(err);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the large_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function largeUnary(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_size: 314159,
    payload: {
      body: zeroBuffer(271828)
    }
  };
  var call = client.unaryCall(arg, function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
    assert.strictEqual(resp.payload.body.length, 314159);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the client_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function clientStreaming(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.aggregated_payload_size, 74922);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var payload_sizes = [27182, 8, 1828, 45904];
  for (var i = 0; i < payload_sizes.length; i++) {
    call.write({payload: {body: zeroBuffer(payload_sizes[i])}});
  }
  call.end();
}

/**
 * Run the server_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function serverStreaming(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_parameters: [
      {size: 31415},
      {size: 9},
      {size: 2653},
      {size: 58979}
    ]
  };
  var call = client.streamingOutputCall(arg);
  var resp_index = 0;
  call.on('data', function(value) {
    assert(resp_index < 4);
    assert.strictEqual(value.payload.type, 'COMPRESSABLE');
    assert.strictEqual(value.payload.body.length,
                       arg.response_parameters[resp_index].size);
    resp_index += 1;
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    assert.strictEqual(resp_index, 4);
    if (done) {
      done();
    }
  });
}

/**
 * Run the ping_pong test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function pingPong(client, done) {
  var payload_sizes = [27182, 8, 1828, 45904];
  var response_sizes = [31415, 9, 2653, 58979];
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var index = 0;
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: response_sizes[index]}
      ],
      payload: {body: zeroBuffer(payload_sizes[index])}
  });
  call.on('data', function(response) {
    assert.strictEqual(response.payload.type, 'COMPRESSABLE');
    assert.equal(response.payload.body.length, response_sizes[index]);
    index += 1;
    if (index === 4) {
      call.end();
    } else {
      call.write({
        response_type: 'COMPRESSABLE',
        response_parameters: [
          {size: response_sizes[index]}
        ],
        payload: {body: zeroBuffer(payload_sizes[index])}
      });
    }
  });
}

/**
 * Run the empty_stream test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyStream(client, done) {
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  call.on('data', function(value) {
    assert.fail(value, null, 'No data should have been received', '!==');
  });
  call.end();
}

/**
 * Run the cancel_after_begin test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterBegin(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.strictEqual(err.code, grpc.status.CANCELLED);
    done();
  });
  call.cancel();
}

/**
 * Run the cancel_after_first_response test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterFirstResponse(client, done) {
  var call = client.fullDuplexCall();
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: 31415}
      ],
      payload: {body: zeroBuffer(27182)}
  });
  call.on('data', function(data) {
    call.cancel();
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.CANCELLED);
    done();
  });
}

function timeoutOnSleepingServer(client, done) {
  var deadline = new Date();
  deadline.setMilliseconds(deadline.getMilliseconds() + 1);
  var call = client.fullDuplexCall(null, deadline);
  call.write({
    response_type: 'COMPRESSABLE',
    payload: {body: zeroBuffer(27182)}
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED);
    done();
  });
}

/**
 * Run one of the authentication tests.
 * @param {string} expected_user The expected username in the response
 * @param {Client} client The client to test against
 * @param {?string} scope The scope to apply to the credentials
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function authTest(expected_user, client, scope, done) {
  (new GoogleAuth()).getApplicationDefault(function(err, credential) {
    assert.ifError(err);
    if (credential.createScopedRequired() && scope) {
      credential = credential.createScoped(scope);
    }
    client.updateMetadata = grpc.getGoogleAuthDelegate(credential);
    var arg = {
      response_type: 'COMPRESSABLE',
      response_size: 314159,
      payload: {
        body: zeroBuffer(271828)
      },
      fill_username: true,
      fill_oauth_scope: true
    };
    var call = client.unaryCall(arg, function(err, resp) {
      assert.ifError(err);
      assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
      assert.strictEqual(resp.payload.body.length, 314159);
      assert.strictEqual(resp.username, expected_user);
      assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
    });
    call.on('status', function(status) {
      assert.strictEqual(status.code, grpc.status.OK);
      if (done) {
        done();
      }
    });
  });
}

/**
 * Map from test case names to test functions
 */
var test_cases = {
  empty_unary: emptyUnary,
  large_unary: largeUnary,
  client_streaming: clientStreaming,
  server_streaming: serverStreaming,
  ping_pong: pingPong,
  empty_stream: emptyStream,
  cancel_after_begin: cancelAfterBegin,
  cancel_after_first_response: cancelAfterFirstResponse,
  timeout_on_sleeping_server: timeoutOnSleepingServer,
  compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER, null),
  service_account_creds: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
  jwt_token_creds: _.partial(authTest, AUTH_USER, null)
};

/**
 * Execute a single test case.
 * @param {string} address The address of the server to connect to, in the
 *     format 'hostname:port'
 * @param {string} host_overrirde The hostname of the server to use as an SSL
 *     override
 * @param {string} test_case The name of the test case to run
 * @param {bool} tls Indicates that a secure channel should be used
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function runTest(address, host_override, test_case, tls, test_ca, done) {
  // TODO(mlumish): enable TLS functionality
  var options = {};
  if (tls) {
    var ca_path;
    if (test_ca) {
      ca_path = path.join(__dirname, '../test/data/ca.pem');
    } else {
      ca_path = process.env.SSL_CERT_FILE;
    }
    var ca_data = fs.readFileSync(ca_path);
    var creds = grpc.Credentials.createSsl(ca_data);
    options.credentials = creds;
    if (host_override) {
      options['grpc.ssl_target_name_override'] = host_override;
    }
  }
  var client = new testProto.TestService(address, options);

  test_cases[test_case](client, done);
}

if (require.main === module) {
  var parseArgs = require('minimist');
  var argv = parseArgs(process.argv, {
    string: ['server_host', 'server_host_override', 'server_port', 'test_case',
             'use_tls', 'use_test_ca']
  });
  runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
          argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
          function () {
            console.log('OK:', argv.test_case);
          });
}

/**
 * See docs for runTest
 */
exports.runTest = runTest;
<commit_msg>Removed response type<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('underscore');
var grpc = require('..');
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
var GoogleAuth = require('google-auth-library');

var assert = require('assert');

var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' +
    '@developer.gserviceaccount.com');
var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
    '@developer.gserviceaccount.com');

/**
 * Create a buffer filled with size zeroes
 * @param {number} size The length of the buffer
 * @return {Buffer} The new buffer
 */
function zeroBuffer(size) {
  var zeros = new Buffer(size);
  zeros.fill(0);
  return zeros;
}

/**
 * Run the empty_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyUnary(client, done) {
  var call = client.emptyCall({}, function(err, resp) {
    assert.ifError(err);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the large_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function largeUnary(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_size: 314159,
    payload: {
      body: zeroBuffer(271828)
    }
  };
  var call = client.unaryCall(arg, function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
    assert.strictEqual(resp.payload.body.length, 314159);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the client_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function clientStreaming(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.aggregated_payload_size, 74922);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var payload_sizes = [27182, 8, 1828, 45904];
  for (var i = 0; i < payload_sizes.length; i++) {
    call.write({payload: {body: zeroBuffer(payload_sizes[i])}});
  }
  call.end();
}

/**
 * Run the server_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function serverStreaming(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_parameters: [
      {size: 31415},
      {size: 9},
      {size: 2653},
      {size: 58979}
    ]
  };
  var call = client.streamingOutputCall(arg);
  var resp_index = 0;
  call.on('data', function(value) {
    assert(resp_index < 4);
    assert.strictEqual(value.payload.type, 'COMPRESSABLE');
    assert.strictEqual(value.payload.body.length,
                       arg.response_parameters[resp_index].size);
    resp_index += 1;
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    assert.strictEqual(resp_index, 4);
    if (done) {
      done();
    }
  });
}

/**
 * Run the ping_pong test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function pingPong(client, done) {
  var payload_sizes = [27182, 8, 1828, 45904];
  var response_sizes = [31415, 9, 2653, 58979];
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var index = 0;
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: response_sizes[index]}
      ],
      payload: {body: zeroBuffer(payload_sizes[index])}
  });
  call.on('data', function(response) {
    assert.strictEqual(response.payload.type, 'COMPRESSABLE');
    assert.equal(response.payload.body.length, response_sizes[index]);
    index += 1;
    if (index === 4) {
      call.end();
    } else {
      call.write({
        response_type: 'COMPRESSABLE',
        response_parameters: [
          {size: response_sizes[index]}
        ],
        payload: {body: zeroBuffer(payload_sizes[index])}
      });
    }
  });
}

/**
 * Run the empty_stream test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyStream(client, done) {
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  call.on('data', function(value) {
    assert.fail(value, null, 'No data should have been received', '!==');
  });
  call.end();
}

/**
 * Run the cancel_after_begin test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterBegin(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.strictEqual(err.code, grpc.status.CANCELLED);
    done();
  });
  call.cancel();
}

/**
 * Run the cancel_after_first_response test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterFirstResponse(client, done) {
  var call = client.fullDuplexCall();
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: 31415}
      ],
      payload: {body: zeroBuffer(27182)}
  });
  call.on('data', function(data) {
    call.cancel();
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.CANCELLED);
    done();
  });
}

function timeoutOnSleepingServer(client, done) {
  var deadline = new Date();
  deadline.setMilliseconds(deadline.getMilliseconds() + 1);
  var call = client.fullDuplexCall(null, deadline);
  call.write({
    payload: {body: zeroBuffer(27182)}
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED);
    done();
  });
}

/**
 * Run one of the authentication tests.
 * @param {string} expected_user The expected username in the response
 * @param {Client} client The client to test against
 * @param {?string} scope The scope to apply to the credentials
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function authTest(expected_user, client, scope, done) {
  (new GoogleAuth()).getApplicationDefault(function(err, credential) {
    assert.ifError(err);
    if (credential.createScopedRequired() && scope) {
      credential = credential.createScoped(scope);
    }
    client.updateMetadata = grpc.getGoogleAuthDelegate(credential);
    var arg = {
      response_type: 'COMPRESSABLE',
      response_size: 314159,
      payload: {
        body: zeroBuffer(271828)
      },
      fill_username: true,
      fill_oauth_scope: true
    };
    var call = client.unaryCall(arg, function(err, resp) {
      assert.ifError(err);
      assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
      assert.strictEqual(resp.payload.body.length, 314159);
      assert.strictEqual(resp.username, expected_user);
      assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
    });
    call.on('status', function(status) {
      assert.strictEqual(status.code, grpc.status.OK);
      if (done) {
        done();
      }
    });
  });
}

/**
 * Map from test case names to test functions
 */
var test_cases = {
  empty_unary: emptyUnary,
  large_unary: largeUnary,
  client_streaming: clientStreaming,
  server_streaming: serverStreaming,
  ping_pong: pingPong,
  empty_stream: emptyStream,
  cancel_after_begin: cancelAfterBegin,
  cancel_after_first_response: cancelAfterFirstResponse,
  timeout_on_sleeping_server: timeoutOnSleepingServer,
  compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER, null),
  service_account_creds: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
  jwt_token_creds: _.partial(authTest, AUTH_USER, null)
};

/**
 * Execute a single test case.
 * @param {string} address The address of the server to connect to, in the
 *     format 'hostname:port'
 * @param {string} host_overrirde The hostname of the server to use as an SSL
 *     override
 * @param {string} test_case The name of the test case to run
 * @param {bool} tls Indicates that a secure channel should be used
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function runTest(address, host_override, test_case, tls, test_ca, done) {
  // TODO(mlumish): enable TLS functionality
  var options = {};
  if (tls) {
    var ca_path;
    if (test_ca) {
      ca_path = path.join(__dirname, '../test/data/ca.pem');
    } else {
      ca_path = process.env.SSL_CERT_FILE;
    }
    var ca_data = fs.readFileSync(ca_path);
    var creds = grpc.Credentials.createSsl(ca_data);
    options.credentials = creds;
    if (host_override) {
      options['grpc.ssl_target_name_override'] = host_override;
    }
  }
  var client = new testProto.TestService(address, options);

  test_cases[test_case](client, done);
}

if (require.main === module) {
  var parseArgs = require('minimist');
  var argv = parseArgs(process.argv, {
    string: ['server_host', 'server_host_override', 'server_port', 'test_case',
             'use_tls', 'use_test_ca']
  });
  runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
          argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
          function () {
            console.log('OK:', argv.test_case);
          });
}

/**
 * See docs for runTest
 */
exports.runTest = runTest;
<|endoftext|>


<commit_before>  /**
  "mep_country": "PT",
    "mep_emailAddress": "ines.zuber@europarl.europa.eu",
    "mep_epFotoUrl": "http://www.europarl.europa.eu/mepphoto/111589.jpg",
    "mep_epPageUrl": "",
    "mep_facebookId": "",
    "mep_facebookPageUrl": "",
    "mep_faction": "UL",
    "mep_firstName": "Inês Cristina",
    "mep_lastName": "Zuber",
    "mep_localParty": "Partido Comunista Português",
    "mep_personalWebsite": "",
    "mep_twitterUrl": "",
    "mep_userId": "23132",
    "mep_additionalProperties": "[{\"Member\":\"European Parliament\"},{\"Vice-Chair\":\"Committee on Employment and Social Affairs\"},{\"Substitute\":\"Committee on Industry, Research and Energy\"}]",
    "mep_itemCount": 0
  */

var mepModel = function() {
  var mongoose = require('mongoose');
  var config = require('../config.js');
  var schema = mongoose.Schema;

  // Define Mep model
  var mepSchema = config.schema;

  this.getModel = function() {
    // @todo handle errors
    var db = mongoose.createConnection(config.db_host, config.db_name);
    var mepModel = db.model(config.db_collection, mepSchema);
    return mepModel;
  }

  // fetch mep records
  this.getMeps = function(options, callback) {
    var Mongo = this.getModel();

    // sort (http://stackoverflow.com/questions/11043026/variable-as-the-property-name-in-a-javascript-object-literal)
    var sort = {};
    sort[options.sort_attrib] = options.sort_type;

    var q = Mongo.find({mep_twitterUrl: {$ne : ""}})
            .limit(options.limit)
            .sort(sort);

    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  this.search = function(op, callback) {
    var Mongo = this.getModel();
    var q = Mongo.find(op);
    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  this.save = function(data) {
    // just a stub function
    /*var Mep = this.getModel();
    Mep.save(function (err) {
      if (err) throw err;
      console.log('User saved, thanks');
    });
    */
  };

  this.findByCountry = function(iso2) {

  };

  this.findByName = function(name, callback) {
    var op = {mep_fullName:  { $regex: name, $options: 'i' }};
    this.search(op, callback);
  };

  this.findByParty = function (party) {};
}

module.exports = new mepModel();

<commit_msg>print just twitter users<commit_after>  /**
  "mep_country": "PT",
    "mep_emailAddress": "ines.zuber@europarl.europa.eu",
    "mep_epFotoUrl": "http://www.europarl.europa.eu/mepphoto/111589.jpg",
    "mep_epPageUrl": "",
    "mep_facebookId": "",
    "mep_facebookPageUrl": "",
    "mep_faction": "UL",
    "mep_firstName": "Inês Cristina",
    "mep_lastName": "Zuber",
    "mep_localParty": "Partido Comunista Português",
    "mep_personalWebsite": "",
    "mep_twitterUrl": "",
    "mep_userId": "23132",
    "mep_additionalProperties": "[{\"Member\":\"European Parliament\"},{\"Vice-Chair\":\"Committee on Employment and Social Affairs\"},{\"Substitute\":\"Committee on Industry, Research and Energy\"}]",
    "mep_itemCount": 0
  */

var mepModel = function() {
  var mongoose = require('mongoose');
  var config = require('../config.js');
  var schema = mongoose.Schema;

  // Define Mep model
  var mepSchema = config.schema;

  this.getModel = function() {
    // @todo handle errors
    var db = mongoose.createConnection(config.db_host, config.db_name);
    var mepModel = db.model(config.db_collection, mepSchema);
    return mepModel;
  }

  // fetch mep records
  this.getMeps = function(options, callback) {
    var Mongo = this.getModel();

    // sort (http://stackoverflow.com/questions/11043026/variable-as-the-property-name-in-a-javascript-object-literal)
    var sort = {};
    sort[options.sort_attrib] = options.sort_type;

    var q = Mongo.find({mep_twitterUrl: {$ne : ""}})
            .limit(options.limit)
            .sort(sort);

    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  this.search = function(op, callback) {
    var Mongo = this.getModel();
    var q = Mongo.find(op);
    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  this.save = function(data) {
    // just a stub function
    /*var Mep = this.getModel();
    Mep.save(function (err) {
      if (err) throw err;
      console.log('User saved, thanks');
    });
    */
  };

  this.findByCountry = function(iso2) {

  };

  this.findByName = function(name, callback) {
    var op = {mep_fullName:  { $regex: name, $options: 'i' }, mep_twitterUrl: {$ne : ""}};
    this.search(op, callback);
  };

  this.findByParty = function (party) {};
}

module.exports = new mepModel();

<|endoftext|>


<commit_before>  /**
  "mep_country": "PT",
    "mep_emailAddress": "ines.zuber@europarl.europa.eu",
    "mep_epFotoUrl": "http://www.europarl.europa.eu/mepphoto/111589.jpg",
    "mep_epPageUrl": "",
    "mep_facebookId": "",
    "mep_facebookPageUrl": "",
    "mep_faction": "UL",
    "mep_firstName": "Inês Cristina",
    "mep_lastName": "Zuber",
    "mep_localParty": "Partido Comunista Português",
    "mep_personalWebsite": "",
    "mep_twitterUrl": "",
    "mep_userId": "23132",
    "mep_additionalProperties": "[{\"Member\":\"European Parliament\"},{\"Vice-Chair\":\"Committee on Employment and Social Affairs\"},{\"Substitute\":\"Committee on Industry, Research and Energy\"}]",
    "mep_itemCount": 0
  */

var mepModel = function() {
  var mongoose = require('mongoose');
  var config = require('../config.js');
  var schema = mongoose.Schema;

  // Define Mep model
  var mepSchema = config.schema;

  // connect to db
  this.getModel = function() {
    // @todo handle errors
    var db = mongoose.createConnection(config.db_host, config.db_name);
    var mepModel = db.model(config.db_collection, mepSchema);
    return mepModel;
  }

  // fetch mep records
  // @todo Join this function using the global search method
  this.getMeps = function(options, callback) {

    var Mongo = this.getModel();

    // sort (http://stackoverflow.com/questions/11043026/variable-as-the-property-name-in-a-javascript-object-literal)
    var sort = {};
    sort[options.sort_attrib] = options.sort_type;

    var q = Mongo.find({mep_twitterUrl: {$ne : ""}})
            .limit(options.limit)
            .sort(sort);
    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  /* Execute search */
  this.search = function(op, options, callback) {
    var sort = {};
    sort[options.sort_attrib] = options.sort_type;

    var Mongo = this.getModel();
    var q = Mongo.find(op).sort(sort);

    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  this.save = function(data) {
    // just a stub function
    /*var Mep = this.getModel();
    Mep.save(function (err) {
      if (err) throw err;
      console.log('User saved, thanks');
    });
    */
  };

  /* ricerca in base a criteri multipli .
   * TODO: sostituire i parametri con un oggetto options modificato solo nei campi interessati...
   */
  this.findByCriteria = function(name, localParty, country, faction, limit, offset, options, callback) {
    var op = {
	    mep_fullName:  { $regex: name, $options: 'i' },
      mep_localParty: { $regex: localParty, $options: 'i' },
      mep_country:  { $regex: country, $options: 'i' }, // NOTA: per ora lasciamo l'uso di regex così da contemplare il caso di no-country... poi va trovata una soluzione più elegante
      mep_localParty: { $regex: localParty, $options: 'i' },
	    mep_twitterUrl: {$ne : ""}
    };
    this.search(op, options, callback);
  };
}

module.exports = new mepModel();

<commit_msg>fixes #21, search inside array<commit_after>  /**
  "mep_country": "PT",
    "mep_emailAddress": "ines.zuber@europarl.europa.eu",
    "mep_epFotoUrl": "http://www.europarl.europa.eu/mepphoto/111589.jpg",
    "mep_epPageUrl": "",
    "mep_facebookId": "",
    "mep_facebookPageUrl": "",
    "mep_faction": "UL",
    "mep_firstName": "Inês Cristina",
    "mep_lastName": "Zuber",
    "mep_localParty": "Partido Comunista Português",
    "mep_personalWebsite": "",
    "mep_twitterUrl": "",
    "mep_userId": "23132",
    "mep_additionalProperties": "[{\"Member\":\"European Parliament\"},{\"Vice-Chair\":\"Committee on Employment and Social Affairs\"},{\"Substitute\":\"Committee on Industry, Research and Energy\"}]",
    "mep_itemCount": 0
  */

var mepModel = function() {
  var mongoose = require('mongoose');
  var config = require('../config.js');
  var schema = mongoose.Schema;

  // Define Mep model
  var mepSchema = config.schema;

  // connect to db
  this.getModel = function() {
    // @todo handle errors
    var db = mongoose.createConnection(config.db_host, config.db_name);
    var mepModel = db.model(config.db_collection, mepSchema);
    return mepModel;
  }

  // fetch mep records
  // @todo Join this function using the global search method
  this.getMeps = function(options, callback) {

    var Mongo = this.getModel();

    // sort (http://stackoverflow.com/questions/11043026/variable-as-the-property-name-in-a-javascript-object-literal)
    var sort = {};
    sort[options.sort_attrib] = options.sort_type;

    var q = Mongo.find({mep_twitterUrl: {$ne : ""}})
            .limit(options.limit)
            .sort(sort);
    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  /* Execute search */
  this.search = function(op, options, callback) {
    var sort = {};
    sort[options.sort_attrib] = options.sort_type;

    var Mongo = this.getModel();
    var q = Mongo.find(op).sort(sort);

    q.execFind(function(err, mep) {
      if (err) {
        //@todo we urgently need a robust error handlers
        console.err('Fatal error, try again.').
        process.exit(0);
      }
      callback(mep);
    });
  }

  this.save = function(data) {
    // just a stub function
    /*var Mep = this.getModel();
    Mep.save(function (err) {
      if (err) throw err;
      console.log('User saved, thanks');
    });
    */
  };

  /* ricerca in base a criteri multipli .
   * TODO: sostituire i parametri con un oggetto options modificato solo nei campi interessati...
   */
  this.findByCriteria = function(name, localParty, country, faction, limit, offset, options, callback) {
    var op = {
	    mep_fullName:  { $regex: name, $options: 'i' },
      mep_localParty: { $regex: localParty, $options: 'i' },
      // thanks: http://stackoverflow.com/questions/10700921/case-insensitive-search-with-in
      mep_country: { $elemMatch :  { $regex : country, $options : 'i' } },
      mep_localParty: { $regex: localParty, $options: 'i' },
	    mep_twitterUrl: {$ne : ""}
    };
    this.search(op, options, callback);
  };
}

module.exports = new mepModel();

<|endoftext|>


<commit_before>var jsp  = require('uglify-js').parser,
    pro  = require('uglify-js').uglify,
    fs   = require('fs'),
    path = require('path'),
    util = require('util'),
    cssom = require('cssom'),
    mime = require('connect').utils.mime,
    url = require('url'),
    mod = require('module');

var REQUIRE = 'require';
var REQUIRE_TEXT = 'requireText';
var REQUIRE_CSS  = 'requireCss';
var TO_DATA_URI  = 'toDataUri';
var PREFIX  = '__module_';

function new_sate () {
    return {
        required: {},
        requiredCount: 0,
        requiredAsts: [],

        requiredCss: {},
        requiredCssFiles: [],
        requiredCssUsed: false,

        currentPath: '',
        searchPaths: [],
        options: {}
    };
}

var sate = exports.state = null;

var walker = pro.ast_walker(),
    walkers = {
       "call": function(expr, args) {
           if (expr[0] === 'name' && expr[1] === REQUIRE) {
               var file = resolvePath(args[0][1]);

               if (!state.required[file]) {
                   addFileToAstList(file, true);
               }
               return [this[0], expr, [['num', state.required[file]]] ];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_TEXT) {
               var file = resolvePath(args[0][1]);
               return ['string', fs.readFileSync(file, 'utf8')];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_CSS) {
               var file = resolvePath(args[0][1]);
               if (!state.requiredCss[file]) {
                   state.requiredCss[file] = true;
                   state.requiredCssFiles.push(file);
               }
               return ['num', 1];
           }
           return null;
       },
       "name": function(name) {
           if (name === "__dirname") {
               return ['string', path.dirname(state.currentPath)];
           } else if (name === '__filename') {
               return ['string', state.currentPath];
           } else if (name === '__requiredCss') {
               state.requiredCssUsed = true;
               return null;
           }
           return null;
       }
    };

function imagePathToDataUri (filePath) {
    var contentType = mime.type( path.extname(filePath) ),
        buffer = fs.readFileSync(filePath);
    return 'data:' + contentType + ';base64,' + buffer.toString('base64');
}

function absoluteImagePath (filePath) {
    return filePath.substring(state.options.serverRoot.length);
}

function dataUriCssImages (cssPath, string) {
    return string.replace(/url\(([^)]+)\)/, function(_, filePath) {
        var imagePath = path.join( path.dirname(cssPath), filePath );
        return 'url(' + imagePathToDataUri(imagePath) + ')';
    });
}

function addIEBackground (cssPath, style, sourceValue) {
    if (style['*background-image']) return;
    var filePath = sourceValue.match(/url\(([^)]+)\)/)[1],
        url = path.join( path.dirname(cssPath), filePath );

    style.setProperty('*background-image', 'url(' + absoluteImagePath(url) + ')');
}

function processCssIncludes (cssPath) {
    var code = fs.readFileSync(cssPath, 'utf8');
    var styleSheet = cssom.parse(code);
    styleSheet.cssRules.forEach(function(rule) {
        var style = rule.style;
        if (style.background) {
            var newBg = dataUriCssImages(cssPath, style.background);
            if (newBg != style.background) {
                addIEBackground(cssPath, style, style.background);
                style.background = newBg;
            }
        }
        if (style['background-image']) {
            var newBg = dataUriCssImages(cssPath, style['background-image']);
            if (newBg != style['background-image']) {
                addIEBackground(cssPath, stle, style['background-image']);
                style['background-image'] = newBg;
            };
        }
    });
    return styleSheet + '';
}

function resolvePath (filePath) {
    var resolvedPath = mod._findPath(filePath,
        [path.dirname(state.currentPath)].concat(state.options.searchPaths));
    if (!resolvedPath) throw new Error('Path ' + filePath + ' not found.');
    return fs.realpathSync(resolvedPath);
}

function addFileToAstList (filePath, wrap) {
    state.required[filePath] = state.requiredCount++;
    var oldPath = state.currentPath;
    state.currentPath = filePath;
    var text = fs.readFileSync(filePath, 'utf8');
    // remove shebang
    text = text.replace(/^\#\!.*/, '');
    if (wrap) {
        text = '(function(global, module) {var exports = this;' + text + '})';
    }
    var ast = jsp.parse(text);
    var newAst = walker.with_walkers(walkers, function() {
        return walker.walk(ast);
    });
    state.currentPath = oldPath;
    state.requiredAsts[state.required[filePath]] = newAst;
}

function staticRequire (filePath, options) {
    state = exports.state = new_sate();
    filePath = fs.realpathSync(filePath);
    state.currentPath = filePath;
    var newOptions = {};
    options = Object.create(options || {});

    options.searchPaths = options.searchPaths ? options.searchPaths : [];
    options.searchPaths = [path.dirname(state.currentPath)].concat(options.searchPaths);

    options.serverRoot = options.serverRoot ?
        fs.realpathSync(options.serverRoot) :
        path.dirname(currentPath);

    state.options = options;

    state.requiredAsts = [];

    addFileToAstList(filePath, true);

    var code = 'var global = this;';
    code    += 'function require(index) { if (!require.cache[index]) {var module = require.cache[index] = {exports: {}}; require.modules[index].call(module.exports, global, module);} return require.cache[index].exports; }\n';
    code    += 'require.modules = []; require.cache = [];';
    var body = jsp.parse(code)[1];

    if (state.requiredCssUsed) {
        var code = state.requiredCssFiles.map(function(filePath) {
            return processCssIncludes(filePath);
        }).join('\n');
        body.push( ['var', [['__requiredCss', ['string', code]]]] );
    }
    for (var i=0; i < state.requiredCount; i++) {
        body[body.length] =
            [ 'stat',
                ['assign',
                    true,
                    ['sub',
                        ['dot', ['name', 'require'], 'modules' ],
                        ['num', i]
                    ],
                    state.requiredAsts[i][1][0][1]
                ]
            ];
    };
    body.push(['stat', ['call', ['name', 'require'], [['num', '0']]]]);

    return [ 'toplevel',
      [ [ 'stat',
          [ 'call',
            [ 'function',
              null,
              [],
              body
            ],
            [] ] ] ] ];

}

exports.parse = staticRequire;

exports.getHandler = function(options) {
    return function(req, res) {
        exports.handle(req, res, options);
    };
};

exports.handle = function(req, res, options) {
    options = options || {};
    var filePath = options.filePath || (url.parse(req.url).pathname.substr(1));
    if (!options.serverRoot) options.serverRoot = process.cwd();
    try {
        var ast = staticRequire(filePath, options);
        if (req.param('squeeze')) {
            ast = pro.ast_mangle(ast);
            ast = pro.ast_squeeze(ast);
            ast = pro.ast_squeeze_more(ast);
        }

        var code = pro.gen_code(ast, !req.param('squeeze'));
    } catch (e) {
        require('util').error(e);
        var code = 'alert(' + JSON.stringify(e.message + '. Current file ' + exports.state.currentPath) + ')';
    }
    res.writeHead(200, {
        "Content-Type": 'application/javascript',
        "Content-Length": code.length
    });
    res.end(req.method === "HEAD" ? "" : code);
};<commit_msg>app handler, NO HTML!<commit_after>var jsp  = require('uglify-js').parser,
    pro  = require('uglify-js').uglify,
    fs   = require('fs'),
    path = require('path'),
    util = require('util'),
    cssom = require('cssom'),
    mime = require('connect').utils.mime,
    url = require('url'),
    mod = require('module');

var REQUIRE = 'require';
var REQUIRE_TEXT = 'requireText';
var REQUIRE_CSS  = 'requireCss';
var TO_DATA_URI  = 'toDataUri';
var PREFIX  = '__module_';

function new_sate () {
    return {
        required: {},
        requiredCount: 0,
        requiredAsts: [],

        requiredCss: {},
        requiredCssFiles: [],
        requiredCssUsed: false,

        currentPath: '',
        searchPaths: [],
        options: {}
    };
}

var sate = exports.state = null;

var walker = pro.ast_walker(),
    walkers = {
       "call": function(expr, args) {
           if (expr[0] === 'name' && expr[1] === REQUIRE) {
               var file = resolvePath(args[0][1]);

               if (!state.required[file]) {
                   addFileToAstList(file, true);
               }
               return [this[0], expr, [['num', state.required[file]]] ];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_TEXT) {
               var file = resolvePath(args[0][1]);
               return ['string', fs.readFileSync(file, 'utf8')];
           } else if (expr[0] === 'name' && expr[1] === REQUIRE_CSS) {
               var file = resolvePath(args[0][1]);
               if (!state.requiredCss[file]) {
                   state.requiredCss[file] = true;
                   state.requiredCssFiles.push(file);
               }
               return ['num', 1];
           }
           return null;
       },
       "name": function(name) {
           if (name === "__dirname") {
               return ['string', path.dirname(state.currentPath)];
           } else if (name === '__filename') {
               return ['string', state.currentPath];
           } else if (name === '__requiredCss') {
               state.requiredCssUsed = true;
               return null;
           }
           return null;
       }
    };

function imagePathToDataUri (filePath) {
    var contentType = mime.type( path.extname(filePath) ),
        buffer = fs.readFileSync(filePath);
    return 'data:' + contentType + ';base64,' + buffer.toString('base64');
}

function absoluteImagePath (filePath) {
    return filePath.substring(state.options.serverRoot.length);
}

function dataUriCssImages (cssPath, string) {
    return string.replace(/url\(([^)]+)\)/, function(_, filePath) {
        var imagePath = path.join( path.dirname(cssPath), filePath );
        return 'url(' + imagePathToDataUri(imagePath) + ')';
    });
}

function addIEBackground (cssPath, style, sourceValue) {
    if (style['*background-image']) return;
    var filePath = sourceValue.match(/url\(([^)]+)\)/)[1],
        url = path.join( path.dirname(cssPath), filePath );

    style.setProperty('*background-image', 'url(' + absoluteImagePath(url) + ')');
}

function processCssIncludes (cssPath) {
    var code = fs.readFileSync(cssPath, 'utf8');
    var styleSheet = cssom.parse(code);
    styleSheet.cssRules.forEach(function(rule) {
        var style = rule.style;
        if (style.background) {
            var newBg = dataUriCssImages(cssPath, style.background);
            if (newBg != style.background) {
                addIEBackground(cssPath, style, style.background);
                style.background = newBg;
            }
        }
        if (style['background-image']) {
            var newBg = dataUriCssImages(cssPath, style['background-image']);
            if (newBg != style['background-image']) {
                addIEBackground(cssPath, stle, style['background-image']);
                style['background-image'] = newBg;
            };
        }
    });
    return styleSheet + '';
}

function resolvePath (filePath) {
    var resolvedPath = mod._findPath(filePath,
        [path.dirname(state.currentPath)].concat(state.options.searchPaths));
    if (!resolvedPath) throw new Error('Path ' + filePath + ' not found.');
    return fs.realpathSync(resolvedPath);
}

function addFileToAstList (filePath, wrap) {
    state.required[filePath] = state.requiredCount++;
    var oldPath = state.currentPath;
    state.currentPath = filePath;
    var text = fs.readFileSync(filePath, 'utf8');
    // remove shebang
    text = text.replace(/^\#\!.*/, '');
    if (wrap) {
        text = '(function(global, module) {var exports = this;' + text + '})';
    }
    var ast = jsp.parse(text);
    var newAst = walker.with_walkers(walkers, function() {
        return walker.walk(ast);
    });
    state.currentPath = oldPath;
    state.requiredAsts[state.required[filePath]] = newAst;
}

function staticRequire (filePath, options) {
    state = exports.state = new_sate();
    filePath = fs.realpathSync(filePath);
    state.currentPath = filePath;
    var newOptions = {};
    options = Object.create(options || {});

    options.searchPaths = options.searchPaths ? options.searchPaths : [];
    options.searchPaths = [path.dirname(state.currentPath)].concat(options.searchPaths);

    options.serverRoot = options.serverRoot ?
        fs.realpathSync(options.serverRoot) :
        path.dirname(currentPath);

    state.options = options;

    state.requiredAsts = [];

    addFileToAstList(filePath, true);

    var code = 'var global = this;';
    code    += 'function require(index) { if (!require.cache[index]) {var module = require.cache[index] = {exports: {}}; require.modules[index].call(module.exports, global, module);} return require.cache[index].exports; }\n';
    code    += 'require.modules = []; require.cache = [];';
    var body = jsp.parse(code)[1];

    if (state.requiredCssUsed) {
        var code = state.requiredCssFiles.map(function(filePath) {
            return processCssIncludes(filePath);
        }).join('\n');
        body.push( ['var', [['__requiredCss', ['string', code]]]] );
    }
    for (var i=0; i < state.requiredCount; i++) {
        body[body.length] =
            [ 'stat',
                ['assign',
                    true,
                    ['sub',
                        ['dot', ['name', 'require'], 'modules' ],
                        ['num', i]
                    ],
                    state.requiredAsts[i][1][0][1]
                ]
            ];
    };
    body.push(['stat', ['call', ['name', 'require'], [['num', '0']]]]);

    return [ 'toplevel',
      [ [ 'stat',
          [ 'call',
            [ 'function',
              null,
              [],
              body
            ],
            [] ] ] ] ];

}

exports.parse = staticRequire;

exports.getAppHandler = function(title, src) {
    return function(req, res) {
        res.send('<!DOCTYPE html><title>' + title + '</title>' +
            '' +
            '' +
            '' +
        '');
    };
};

exports.getHandler = function(options) {
    return function(req, res) {
        exports.handle(req, res, options);
    };
};

exports.handle = function(req, res, options) {
    options = options || {};
    var filePath = options.filePath || (url.parse(req.url).pathname.substr(1));
    if (!options.serverRoot) options.serverRoot = process.cwd();
    try {
        var ast = staticRequire(filePath, options);
        if (req.param('squeeze')) {
            ast = pro.ast_mangle(ast);
            ast = pro.ast_squeeze(ast);
            ast = pro.ast_squeeze_more(ast);
        }

        var code = pro.gen_code(ast, !req.param('squeeze'));
    } catch (e) {
        require('util').error(e);
        var code = 'alert(' + JSON.stringify(e.message + '. Current file ' + exports.state.currentPath) + ')';
    }
    res.writeHead(200, {
        "Content-Type": 'application/javascript',
        "Content-Length": code.length
    });
    res.end(req.method === "HEAD" ? "" : code);
};<|endoftext|>


<commit_before>"use strict";

module.exports = function(sequelize, DataTypes) {
    var ref = sequelize.define('ref', {
        doi: {
            type: DataTypes.STRING,
            comment: "DOI of the attached publication"
        },
        jstor: {
          type: DataTypes.STRING,
          comment: "JSTOR of the attached publication"
        },
        pmid: {
            type: DataTypes.STRING,
            comment: "PMID of the attached publication"
        },
        bibtex: {
            type: DataTypes.TEXT,
            comment: "bibtex of the attached publication"
        },
        paper_url: {
            type: DataTypes.STRING,
            comment: "URL of the attached publication"
        },
        data_url: {
            type: DataTypes.STRING,
            comment: "URL of the attached data"
        }
    }, {
        underscored: true,
        classMethods: {
            associate: function(models) {
                ref.hasMany(models.network, {
                    onDelete: 'cascade'
                }),
                ref.hasMany(models.environment, {
                    onDelete: 'cascade'
                }),
                ref.hasMany(models.trait, {
                    onDelete: 'cascade'
                }),
                ref.hasMany(models.interaction, {
                    onDelete: 'cascade'
                }),
                ref.hasMany(models.dataset, {
                    onDelete: 'cascade'
                })
            }
        }
    });

    return ref
};
<commit_msg>refs relation + attribute changes<commit_after>"use strict";

module.exports = function(sequelize, DataTypes) {
    var ref = sequelize.define('ref', {
        doi: {
            type: DataTypes.STRING,
            comment: "DOI of the attached publication"
        },
        author: {
            type: DataTypes.STRING,
            comment: "firt author name"
        },
        year: {
            type: DataTypes.STRING,
            comment: "year of publication"
        },
        jstor: {
          type: DataTypes.STRING,
          comment: "JSTOR of the attached publication"
        },
        pmid: {
            type: DataTypes.STRING,
            comment: "PMID of the attached publication"
        },
        bibtex: {
            type: DataTypes.TEXT,
            comment: "bibtex of the attached publication"
        },
        paper_url: {
            type: DataTypes.STRING,
            comment: "URL of the attached publication"
        },
        data_url: {
            type: DataTypes.STRING,
            comment: "URL of the attached data"
        }
    }, {
        underscored: true,
        classMethods: {
            associate: function(models) {
                ref.hasMany(models.dataset, {
                    onDelete: 'cascade'
                })
            }
        }
    });

    return ref
};
<|endoftext|>


<commit_before>/**
 * @brief コミット
 */
module.exports = function(mongoModels) {
  var _ = require('lodash');

  /**
   * @brief タグ編集用情報を取得する
   *
   * @param fileName 対象のファイル名
   * @param resultCallback 結果を渡すコールバック
   */
  function getTagEditInfo(fileName, resultCallback) {
    mongoModels.util.findLatestFileVersion(fileName, function(lastVersion, lastDocumentId) {
      if(lastVersion === 0) {
        resultCallback({ errorMessage: '対象のファイルは見つかりませんでした' });
        return;
      }

      mongoModels
        .commitInfo
        .findOne({ _id: lastDocumentId }, function(error, doc) {
          findAllLatestTagNames(function(tagNames) {
            var info = {
              file_tags: doc.tag_names,
              stock_tags: _.difference(tagNames, doc.tag_names)
            };

            resultCallback(info);
          });
        });
    });
  }

  /**
   * @brief タグの編集結果を適用する
   *
   * @param fileName 対象のファイル名
   * @param tagNames 適用するタグ名の配列
   * @param resultCallback 結果を渡すコールバック
   */
  function applyTagEditInfo(fileName, tagNames, resultCallback) {
    mongoModels.util.findLatestFileVersion(fileName, function(lastVersion, lastDocumentId) {
      if(lastVersion === 0) {
        resultCallback({ errorMessage: '対象のファイルは見つかりませんでした' });
        return;
      }

      mongoModels
        .commitInfo
        .findOneAndUpdate({ _id: lastDocumentId },
                          { tag_names: tagNames },
                          function(error, docs) {
                            if(error) {
                              throw error;
                            }

                            resultCallback({});
                          });
    });
  }

  /**
   * @brief 最新のコミット情報のタグを全て取得する
   *
   * @param resultCallback 結果を渡すコールバック
   */
  function findAllLatestTagNames(resultCallback) {
    mongoModels.latestCommitId.find({}, function(error, docs) {
      var commitDocIds = _.pluck(docs, function(doc) { return doc.commit_doc_id; });
      var findInfo = { _id: { $in: commitDocIds } };

      mongoModels.commitInfo.find(findInfo, function(error, docs) {
        if(error) {
          throw error;
        }

        var tagNames = _(docs)
                        .pluck('tag_names')
                        .flatten()
                        .uniq()
                        .value();

        resultCallback(tagNames);
      });
    });
  }

  return {
    getTagEditInfo: getTagEditInfo,
    applyTagEditInfo: applyTagEditInfo,
    findAllLatestTagNames: findAllLatestTagNames
  };
};
<commit_msg>終了タグが最新のタグ情報に追加されるように対応<commit_after>/**
 * @brief コミット
 */
module.exports = function(mongoModels) {
  var _ = require('lodash');

  /**
   * @brief タグ編集用情報を取得する
   *
   * @param fileName 対象のファイル名
   * @param resultCallback 結果を渡すコールバック
   */
  function getTagEditInfo(fileName, resultCallback) {
    mongoModels.util.findLatestFileVersion(fileName, function(lastVersion, lastDocumentId) {
      if(lastVersion === 0) {
        resultCallback({ errorMessage: '対象のファイルは見つかりませんでした' });
        return;
      }

      mongoModels
        .commitInfo
        .findOne({ _id: lastDocumentId }, function(error, doc) {
          findAllLatestTagNames(function(tagNames) {
            var info = {
              file_tags: doc.tag_names,
              stock_tags: _.difference(tagNames, doc.tag_names)
            };

            resultCallback(info);
          });
        });
    });
  }

  /**
   * @brief タグの編集結果を適用する
   *
   * @param fileName 対象のファイル名
   * @param tagNames 適用するタグ名の配列
   * @param resultCallback 結果を渡すコールバック
   */
  function applyTagEditInfo(fileName, tagNames, resultCallback) {
    mongoModels.util.findLatestFileVersion(fileName, function(lastVersion, lastDocumentId) {
      if(lastVersion === 0) {
        resultCallback({ errorMessage: '対象のファイルは見つかりませんでした' });
        return;
      }

      mongoModels
        .commitInfo
        .findOneAndUpdate({ _id: lastDocumentId },
                          { tag_names: tagNames },
                          function(error, docs) {
                            if(error) {
                              throw error;
                            }

                            resultCallback({});
                          });
    });
  }

  /**
   * @brief 最新のコミット情報のタグを全て取得する
   *
   * @param resultCallback 結果を渡すコールバック
   */
  function findAllLatestTagNames(resultCallback) {
    mongoModels.latestCommitId.find({}, function(error, docs) {
      var commitDocIds = _.pluck(docs, function(doc) { return doc.commit_doc_id; });
      var findInfo = { _id: { $in: commitDocIds } };

      mongoModels.commitInfo.find(findInfo, function(error, docs) {
        if(error) {
          throw error;
        }

        var tagNames = _(docs)
                        .pluck('tag_names')
                        .flatten()
                        .uniq()
                        .value();

        // 終了タグがなければ追加する
        (function() {
          // @todo クライアント側と定義を共通化する
          function isClosed(name) {
            return name === 'system:closed';
          }

          if(!_.any(tagNames, isClosed)) {
            tagNames.push('system:closed');
          }
        })();

        resultCallback(tagNames);
      });
    });
  }

  return {
    getTagEditInfo: getTagEditInfo,
    applyTagEditInfo: applyTagEditInfo,
    findAllLatestTagNames: findAllLatestTagNames
  };
};
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var assert = require('assert');
var bufrw = require('bufrw');
var ReadMachine = require('bufrw/stream/read_machine');
var inherits = require('util').inherits;

var v2 = require('./v2');
var errors = require('./errors');
var States = require('./reqres_states');

var TChannelConnectionBase = require('./connection_base');

function TChannelConnection(channel, socket, direction, remoteAddr) {
    assert(remoteAddr !== channel.hostPort, 'refusing to create self connection');

    var self = this;
    TChannelConnectionBase.call(self, channel, direction, remoteAddr);
    self.identifiedEvent = self.defineEvent('identified');

    self.socket = socket;

    var opts = {
        logger: self.channel.logger,
        random: self.channel.random,
        timers: self.channel.timers,
        hostPort: self.channel.hostPort,
        tracer: self.tracer
    };
    // jshint forin:false
    for (var prop in self.options) {
        opts[prop] = self.options[prop];
    }
    // jshint forin:true
    self.handler = new v2.Handler(opts);

    self.mach = ReadMachine(bufrw.UInt16BE, v2.Frame.RW);

    self.setupSocket();
    self.setupHandler();
    self.start();
}
inherits(TChannelConnection, TChannelConnectionBase);

TChannelConnection.prototype.setupSocket = function setupSocket() {
    var self = this;

    self.socket.setNoDelay(true);
    self.socket.on('data', onSocketChunk);
    self.socket.on('close', onSocketClose);
    self.socket.on('error', onSocketError);

    function onSocketChunk(chunk) {
        self.mach.handleChunk(chunk, chunkHandled);
    }

    function chunkHandled(err) {
        if (err) {
            self.resetAll(errors.TChannelReadProtocolError(err, {
                remoteName: self.remoteName,
                localName: self.channel.hostPort
            }));
            self.socket.destroy();
        }
    }

    function onSocketClose() {
        self.resetAll(errors.SocketClosedError({reason: 'remote clossed'}));
        if (self.remoteName === '0.0.0.0:0') {
            self.channel.peers.delete(self.remoteAddr);
        }
    }

    function onSocketError(err) {
        self.onSocketError(err);
    }
};

TChannelConnection.prototype.setupHandler = function setupHandler() {
    var self = this;

    self.handler.write = function write(buf, done) {
        self.socket.write(buf, null, done);
    };

    self.mach.emit = handleReadFrame;

    self.handler.writeErrorEvent.on(onWriteError);
    self.handler.errorEvent.on(onHandlerError);
    self.handler.callIncomingRequestEvent.on(onCallRequest);
    self.handler.callIncomingResponseEvent.on(onCallResponse);
    self.handler.callIncomingErrorEvent.on(onCallError);
    self.timedOutEvent.on(self.onTimedOut);

    // TODO: restore dumping from old:
    // var stream = self.socket;
    // if (dumpEnabled) {
    //     stream = stream.pipe(Spy(process.stdout, {
    //         prefix: '>>> ' + self.remoteAddr + ' '
    //     }));
    // }
    // stream = stream
    //     .pipe(self.reader)
    //     .pipe(self.handler)
    //     ;
    // if (dumpEnabled) {
    //     stream = stream.pipe(Spy(process.stdout, {
    //         prefix: '<<< ' + self.remoteAddr + ' '
    //     }));
    // }
    // stream = stream
    //     .pipe(self.socket)
    //     ;

    function onWriteError(err) {
        self.onWriteError(err);
    }

    function onHandlerError(err) {
        self.onHandlerError(err);
    }

    function handleReadFrame(frame) {
        self.handleReadFrame(frame);
    }

    function onCallRequest(req) {
        self.handleCallRequest(req);
    }

    function onCallResponse(res) {
        self.onCallResponse(res);
    }

    function onCallError(err) {
        self.onCallError(err);
    }
};

TChannelConnection.prototype.onTimedOut = function onTimedOut(_arg, self) {
    self.logger.warn(self.channel.hostPort + ' destroying socket from timeouts');
    self.socket.destroy();
};

TChannelConnection.prototype.onWriteError = function onWriteError(err) {
    var self = this;
    self.resetAll(errors.TChannelWriteProtocolError(err, {
        remoteName: self.remoteName,
        localName: self.channel.hostPort
    }));
    self.socket.destroy();
};

TChannelConnection.prototype.onHandlerError = function onHandlerError(err) {
    var self = this;
    self.resetAll(err);
    // resetAll() does not close the socket
    self.socket.destroy();
};

TChannelConnection.prototype.handleReadFrame = function handleReadFrame(frame) {
    var self = this;
    if (!self.closing) {
        self.lastTimeoutTime = 0;
    }
    self.handler.handleFrame(frame, handledFrame);
    function handledFrame(err) {
        if (err) self.onHandlerError(err);
    }
};

TChannelConnection.prototype.onCallResponse = function onCallResponse(res) {
    var self = this;

    var req = self.requests.out[res.id];
    var called = false;

    if (res.state === States.Done || res.state === States.Error) {
        popOutReq();
    } else {
        res.errorEvent.on(popOutReq);
        res.finishEvent.on(popOutReq);
    }

    if (!req) {
        self.logger.info('call response received for unknown or lost operation', {
            responseId: res.id,
            code: res.code,
            arg1: Buffer.isBuffer(res.arg1) ?
                String(res.arg1) : 'streamed-arg1',
            remoteAddr: self.remoteAddr,
            direction: self.direction
        });
        return;
    }

    if (self.tracer) {
        // TODO: better annotations
        req.span.annotate('cr');
        self.tracer.report(req.span);
        res.span = req.span;
    }

    req.responseEvent.emit(req, res);

    function popOutReq() {
        if (called) {
            return;
        }

        called = true;

        req = self.popOutReq(res.id);
        if (!req) {
            self.logger.info('response received for unknown or lost operation', {
                responseId: res.id,
                code: res.code,
                arg1: Buffer.isBuffer(res.arg1) ?
                    String(res.arg1) : 'streamed-arg1',
                remoteAddr: self.remoteAddr,
                direction: self.direction
            });
            return;
        }
    }
};

TChannelConnection.prototype.onCallError = function onCallError(err) {
    var self = this;

    var req = self.requests.out[err.originalId];

    if (req && req.res) {
        req.res.errorEvent.emit(req.res, err);
    } else {
        // Only popOutReq if there is no call response object yet
        req = self.popOutReq(err.originalId);
        if (!req) {
            self.logger.info('error received for unknown or lost operation', err);
            return;
        }

        req.errorEvent.emit(req, err);
    }
};

TChannelConnection.prototype.start = function start() {
    var self = this;
    if (self.direction === 'out') {
        self.handler.sendInitRequest();
        self.handler.initResponseEvent.on(onOutIdentified);
    } else {
        self.handler.initRequestEvent.on(onInIdentified);
    }

    function onOutIdentified(init) {
        self.onOutIdentified(init);
    }

    function onInIdentified(init) {
        self.onInIdentified(init);
    }
};

TChannelConnection.prototype.onOutIdentified = function onOutIdentified(init) {
    var self = this;
    self.remoteName = init.hostPort;
    self.identifiedEvent.emit(self, {
        hostPort: init.hostPort,
        processName: init.processName
    });
};

TChannelConnection.prototype.onInIdentified = function onInIdentified(init) {
    var self = this;
    if (init.hostPort === '0.0.0.0:0') {
        self.remoteName = '' + self.socket.remoteAddress + ':' + self.socket.remotePort;
        assert(self.remoteName !== self.channel.hostPort,
              'should not be able to receive ephemeral connection from self');
    } else {
        self.remoteName = init.hostPort;
    }

    self.channel.peers.add(self.remoteName).addConnection(self);
    self.identifiedEvent.emit(self, {
        hostPort: self.remoteName,
        processName: init.processName
    });
};

TChannelConnection.prototype.close = function close(callback) {
    var self = this;
    if (self.socket.destroyed) {
        callback();
    } else {
        self.socket.once('close', callback);
        self.resetAll(errors.SocketClosedError({reason: 'local close'}));
        self.socket.destroy();
    }
};

TChannelConnection.prototype.onSocketError = function onSocketError(err) {
    var self = this;
    if (!self.closing) {
        self.resetAll(errors.SocketError(err, {
            hostPort: self.channel.hostPort,
            direction: self.direction,
            remoteAddr: self.remoteAddr
        }));
    }
};

TChannelConnection.prototype.buildOutRequest = function buildOutRequest(options) {
    var self = this;
    options.logger = self.logger;
    options.random = self.random;
    options.timers = self.timers;
    return self.handler.buildOutRequest(options);
};

TChannelConnection.prototype.buildOutResponse = function buildOutResponse(req, options) {
    var self = this;
    var opts = {
        logger: self.logger,
        random: self.random,
        timers: self.timers
    };
    if (options) {
        // jshint forin:false
        for (var prop in options) {
            opts[prop] = options[prop];
        }
        // jshint forin:true
    }
    return self.handler.buildOutResponse(req, opts);
};

module.exports = TChannelConnection;
<commit_msg>conn: rename unknown response log message<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var assert = require('assert');
var bufrw = require('bufrw');
var ReadMachine = require('bufrw/stream/read_machine');
var inherits = require('util').inherits;

var v2 = require('./v2');
var errors = require('./errors');
var States = require('./reqres_states');

var TChannelConnectionBase = require('./connection_base');

function TChannelConnection(channel, socket, direction, remoteAddr) {
    assert(remoteAddr !== channel.hostPort, 'refusing to create self connection');

    var self = this;
    TChannelConnectionBase.call(self, channel, direction, remoteAddr);
    self.identifiedEvent = self.defineEvent('identified');

    self.socket = socket;

    var opts = {
        logger: self.channel.logger,
        random: self.channel.random,
        timers: self.channel.timers,
        hostPort: self.channel.hostPort,
        tracer: self.tracer
    };
    // jshint forin:false
    for (var prop in self.options) {
        opts[prop] = self.options[prop];
    }
    // jshint forin:true
    self.handler = new v2.Handler(opts);

    self.mach = ReadMachine(bufrw.UInt16BE, v2.Frame.RW);

    self.setupSocket();
    self.setupHandler();
    self.start();
}
inherits(TChannelConnection, TChannelConnectionBase);

TChannelConnection.prototype.setupSocket = function setupSocket() {
    var self = this;

    self.socket.setNoDelay(true);
    self.socket.on('data', onSocketChunk);
    self.socket.on('close', onSocketClose);
    self.socket.on('error', onSocketError);

    function onSocketChunk(chunk) {
        self.mach.handleChunk(chunk, chunkHandled);
    }

    function chunkHandled(err) {
        if (err) {
            self.resetAll(errors.TChannelReadProtocolError(err, {
                remoteName: self.remoteName,
                localName: self.channel.hostPort
            }));
            self.socket.destroy();
        }
    }

    function onSocketClose() {
        self.resetAll(errors.SocketClosedError({reason: 'remote clossed'}));
        if (self.remoteName === '0.0.0.0:0') {
            self.channel.peers.delete(self.remoteAddr);
        }
    }

    function onSocketError(err) {
        self.onSocketError(err);
    }
};

TChannelConnection.prototype.setupHandler = function setupHandler() {
    var self = this;

    self.handler.write = function write(buf, done) {
        self.socket.write(buf, null, done);
    };

    self.mach.emit = handleReadFrame;

    self.handler.writeErrorEvent.on(onWriteError);
    self.handler.errorEvent.on(onHandlerError);
    self.handler.callIncomingRequestEvent.on(onCallRequest);
    self.handler.callIncomingResponseEvent.on(onCallResponse);
    self.handler.callIncomingErrorEvent.on(onCallError);
    self.timedOutEvent.on(self.onTimedOut);

    // TODO: restore dumping from old:
    // var stream = self.socket;
    // if (dumpEnabled) {
    //     stream = stream.pipe(Spy(process.stdout, {
    //         prefix: '>>> ' + self.remoteAddr + ' '
    //     }));
    // }
    // stream = stream
    //     .pipe(self.reader)
    //     .pipe(self.handler)
    //     ;
    // if (dumpEnabled) {
    //     stream = stream.pipe(Spy(process.stdout, {
    //         prefix: '<<< ' + self.remoteAddr + ' '
    //     }));
    // }
    // stream = stream
    //     .pipe(self.socket)
    //     ;

    function onWriteError(err) {
        self.onWriteError(err);
    }

    function onHandlerError(err) {
        self.onHandlerError(err);
    }

    function handleReadFrame(frame) {
        self.handleReadFrame(frame);
    }

    function onCallRequest(req) {
        self.handleCallRequest(req);
    }

    function onCallResponse(res) {
        self.onCallResponse(res);
    }

    function onCallError(err) {
        self.onCallError(err);
    }
};

TChannelConnection.prototype.onTimedOut = function onTimedOut(_arg, self) {
    self.logger.warn(self.channel.hostPort + ' destroying socket from timeouts');
    self.socket.destroy();
};

TChannelConnection.prototype.onWriteError = function onWriteError(err) {
    var self = this;
    self.resetAll(errors.TChannelWriteProtocolError(err, {
        remoteName: self.remoteName,
        localName: self.channel.hostPort
    }));
    self.socket.destroy();
};

TChannelConnection.prototype.onHandlerError = function onHandlerError(err) {
    var self = this;
    self.resetAll(err);
    // resetAll() does not close the socket
    self.socket.destroy();
};

TChannelConnection.prototype.handleReadFrame = function handleReadFrame(frame) {
    var self = this;
    if (!self.closing) {
        self.lastTimeoutTime = 0;
    }
    self.handler.handleFrame(frame, handledFrame);
    function handledFrame(err) {
        if (err) self.onHandlerError(err);
    }
};

TChannelConnection.prototype.onCallResponse = function onCallResponse(res) {
    var self = this;

    var req = self.requests.out[res.id];
    var called = false;

    if (res.state === States.Done || res.state === States.Error) {
        popOutReq();
    } else {
        res.errorEvent.on(popOutReq);
        res.finishEvent.on(popOutReq);
    }

    if (!req) {
        self.logger.info('call response received for unknown or lost operation', {
            responseId: res.id,
            code: res.code,
            arg1: Buffer.isBuffer(res.arg1) ?
                String(res.arg1) : 'streamed-arg1',
            remoteAddr: self.remoteAddr,
            direction: self.direction
        });
        return;
    }

    if (self.tracer) {
        // TODO: better annotations
        req.span.annotate('cr');
        self.tracer.report(req.span);
        res.span = req.span;
    }

    req.responseEvent.emit(req, res);

    function popOutReq() {
        if (called) {
            return;
        }

        called = true;

        req = self.popOutReq(res.id);
        if (!req) {
            self.logger.info('full response received for unknown or lost operation', {
                responseId: res.id,
                code: res.code,
                arg1: Buffer.isBuffer(res.arg1) ?
                    String(res.arg1) : 'streamed-arg1',
                remoteAddr: self.remoteAddr,
                direction: self.direction
            });
            return;
        }
    }
};

TChannelConnection.prototype.onCallError = function onCallError(err) {
    var self = this;

    var req = self.requests.out[err.originalId];

    if (req && req.res) {
        req.res.errorEvent.emit(req.res, err);
    } else {
        // Only popOutReq if there is no call response object yet
        req = self.popOutReq(err.originalId);
        if (!req) {
            self.logger.info('error received for unknown or lost operation', err);
            return;
        }

        req.errorEvent.emit(req, err);
    }
};

TChannelConnection.prototype.start = function start() {
    var self = this;
    if (self.direction === 'out') {
        self.handler.sendInitRequest();
        self.handler.initResponseEvent.on(onOutIdentified);
    } else {
        self.handler.initRequestEvent.on(onInIdentified);
    }

    function onOutIdentified(init) {
        self.onOutIdentified(init);
    }

    function onInIdentified(init) {
        self.onInIdentified(init);
    }
};

TChannelConnection.prototype.onOutIdentified = function onOutIdentified(init) {
    var self = this;
    self.remoteName = init.hostPort;
    self.identifiedEvent.emit(self, {
        hostPort: init.hostPort,
        processName: init.processName
    });
};

TChannelConnection.prototype.onInIdentified = function onInIdentified(init) {
    var self = this;
    if (init.hostPort === '0.0.0.0:0') {
        self.remoteName = '' + self.socket.remoteAddress + ':' + self.socket.remotePort;
        assert(self.remoteName !== self.channel.hostPort,
              'should not be able to receive ephemeral connection from self');
    } else {
        self.remoteName = init.hostPort;
    }

    self.channel.peers.add(self.remoteName).addConnection(self);
    self.identifiedEvent.emit(self, {
        hostPort: self.remoteName,
        processName: init.processName
    });
};

TChannelConnection.prototype.close = function close(callback) {
    var self = this;
    if (self.socket.destroyed) {
        callback();
    } else {
        self.socket.once('close', callback);
        self.resetAll(errors.SocketClosedError({reason: 'local close'}));
        self.socket.destroy();
    }
};

TChannelConnection.prototype.onSocketError = function onSocketError(err) {
    var self = this;
    if (!self.closing) {
        self.resetAll(errors.SocketError(err, {
            hostPort: self.channel.hostPort,
            direction: self.direction,
            remoteAddr: self.remoteAddr
        }));
    }
};

TChannelConnection.prototype.buildOutRequest = function buildOutRequest(options) {
    var self = this;
    options.logger = self.logger;
    options.random = self.random;
    options.timers = self.timers;
    return self.handler.buildOutRequest(options);
};

TChannelConnection.prototype.buildOutResponse = function buildOutResponse(req, options) {
    var self = this;
    var opts = {
        logger: self.logger,
        random: self.random,
        timers: self.timers
    };
    if (options) {
        // jshint forin:false
        for (var prop in options) {
            opts[prop] = options[prop];
        }
        // jshint forin:true
    }
    return self.handler.buildOutResponse(req, opts);
};

module.exports = TChannelConnection;
<|endoftext|>


<commit_before>/**
 * Copyright 2006 - 2012 Eric D. Hough (http://ehough.com)
 *
 * This file is part of TubePress (http://tubepress.org) and is released
 * under the General Public License (GPL) version 3
 *
 * Shrink your JS: http://developer.yahoo.com/yui/compressor/
 */

/*global jQuery, TubePressEvents */
/*jslint white: true, onevar: true, undef: true, newcap: true, nomen: true, regexp: true, plusplus: true, bitwise: true, continue: true, browser: true, maxerr: 50, indent: 4 */

var TubePressPopupPlayer = (function () {

	/* this stuff helps compression */
	var events	= TubePressEvents,
		name	= 'popup',
		doc		= jQuery(document),
		windows = {},

		invoke = function (e, videoId, galleryId, width, height) {

			var top		= (screen.height / 2) - (height / 2),
				left	= (screen.width / 2) - (width / 2);

			windows[galleryId + videoId] = window.open('', '', 'location=0,directories=0,menubar=0,scrollbars=0,status=0,toolbar=0,width=' + width + 'px,height=' + height + 'px,top=' + top + ',left=' + left);
		},

		populate = function (e, title, html, height, width, videoId, galleryId) {

			var preamble	= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>' + title + '</title>',
				postAmble	= '',
				wind		= windows[galleryId + videoId].document;

			wind.write(preamble + html + postAmble);
			wind.close();

		};

	doc.bind(events.PLAYER_INVOKE + name, invoke);
	doc.bind(events.PLAYER_POPULATE + name, populate);
}());<commit_msg>Fixing JS error in popup player<commit_after>/**
 * Copyright 2006 - 2012 Eric D. Hough (http://ehough.com)
 *
 * This file is part of TubePress (http://tubepress.org) and is released
 * under the General Public License (GPL) version 3
 *
 * Shrink your JS: http://developer.yahoo.com/yui/compressor/
 */

/*global jQuery, TubePressEvents */
/*jslint white: true, onevar: true, undef: true, newcap: true, nomen: true, regexp: true, plusplus: true, bitwise: true, continue: true, browser: true, maxerr: 50, indent: 4 */

var TubePressPopupPlayer = (function () {

	/* this stuff helps compression */
	var events	= TubePressEvents,
		name	= 'popup',
		doc		= jQuery(document),
		windows = {},

		invoke = function (e, videoId, galleryId, width, height) {

			var top		= (screen.height / 2) - (height / 2),
				left	= (screen.width / 2) - (width / 2);

			windows[galleryId + videoId] = window.open('', '', 'location=0,directories=0,menubar=0,scrollbars=0,status=0,toolbar=0,width=' + width + 'px,height=' + height + 'px,top=' + top + ',left=' + left);
		},

		populate = function (e, title, html, height, width, videoId, galleryId) {

			var preamble	= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>' + title + '</title>',
				js			= '',
				postAmble	= '',
				wind		= windows[galleryId + videoId].document;

			wind.write(preamble + js + html + postAmble);
			wind.close();

		};

	doc.bind(events.PLAYER_INVOKE + name, invoke);
	doc.bind(events.PLAYER_POPULATE + name, populate);
}());<|endoftext|>


<commit_before>"use strict";

// bitmasks
const NAMETABLE_BITMASK = 0xc00,
      NAMETABLE_RESET = ~NAMETABLE_BITMASK;

function Background( ppu ) {
	this.ppu = ppu;
	this.memory = ppu.memory;

	this.enabled = true;
	this.enabledLeft = true;
	this.enabledPixel = false;

	this.loopyV = 0;
	this.loopyT = 0;
	this.loopyW = 0;
	this.loopyX = 0;

	this.baseTable = 0;

	this.copyingVertical = false;
	this.fetchingTiles = false;
	this.fetchingTilesPhase = 0;

	this.x = 0;
	this.scanlineColors = new Uint8Array( 0x200 );
	this.palette = 0;
	this.tileLow = 0;
	this.tileHigh = 0;
	this.tileMask = 0;

	Object.preventExtensions( this );
}

Background.prototype = {
	toggle: function( flag ) {
		this.enabled = !!flag;
	},

	toggleLeft: function( flag ) {
		this.enabledLeft = !!flag;
	},

	writeAddress: function( value ) {
		if ( this.loopyW ) {
			value &= 0xff;
			this.loopyT = ( this.loopyT & 0xff00 ) | value;
			this.loopyV = this.loopyT;
		} else {
			value &= 0x3f; // only use lowest 6 bits
			value = value << 8;
			this.loopyT = ( this.loopyT & 0x00ff ) | value; // note, also resets bit 14 of loopy_t (for unknown reason)
		}

		this.loopyW = !this.loopyW;
	},

	writeScroll: function( value ) {
		if ( this.loopyW ) {
			// set vertical scroll
			this.loopyT = this.loopyT & ~0x73e0;
			this.loopyT = this.loopyT | ( (value & 0x7) << 12 );
			this.loopyT = this.loopyT | ( (value & 0xf8) << 2 );

			this.loopyW = 0;
		} else {
			// set horizontal scroll
			this.loopyT = this.loopyT & 0x7fe0;
			this.loopyT |= ( value >> 3 );

			this.loopyX = value & ( 0x7 );

			this.loopyW = 1;
		}
	},

	evaluate: function() {
		this.initLineCycle();

		if ( this.fetchingTiles ) {
			this.setColor();

			if ( this.ppu.enabled ) {
				this.fetchTileData();
			}
		}

		if ( this.ppu.lineCycle > 255 ) {
			switch( this.ppu.lineCycle ) {
			case 256:
				if ( this.ppu.enabled ) {
					// increment coarse X position every 8th cycle
					this.incrementVY();
				}
				break;
			case 257:
				if ( this.ppu.enabled ) {
					// reset horizontal at end of scanline
					// copy horizontal bits from loopy_t to loopy_v
					this.loopyV = ( this.loopyV & 0x7be0 ) | ( this.loopyT & 0x41f );
				}
				break;
			}

			// finish initialization of loopy_v from loopy_t at end of pre-render scanline
			if ( this.copyingVertical ) {
				if ( this.ppu.enabled ) {
					// copy vertical bits from loopy_t to loopy_v
					this.loopyV = ( this.loopyV & 0x41f ) | ( this.loopyT & 0x7be0 );
				}
			}
		}
	},

	initLineCycle: function() {
		const lineCycle = this.ppu.lineCycle;

		if ( lineCycle < 10 ) {
			switch( lineCycle ) {
			case 1:
				this.enabledPixel = this.enabledLeft && this.ppu.inLeft8px;
				this.fetchingTiles = true;
				this.fetchingTilesPhase = 1;
				break;
			case 9:
				this.enabledPixel = this.ppu.enabled;
				break;
			}
		} else if ( lineCycle > 256 ) {
			switch( lineCycle ) {
			case 321:
				this.x = -this.loopyX - 8;
				this.fetchingTiles = true;
				this.fetchingTilesPhase = 1;
				break;
			case 337:
				/* falls through */
			case 257:
				this.fetchingTiles = false;
				break;
			case 281:
				if ( this.ppu.scanline === -1 ) {
					this.copyingVertical = true;
				}
				break;
			case 304:
				if ( this.ppu.scanline === -1 ) {
					this.copyingVertical = false;
				}
				break;
			}
		}
	},

	/**
	 * Increment coarse X scroll in loopy_v.
	 */
	incrementVX: function() {
		if ((this.loopyV & 0x1f) === 31) {
			// coarse X is maxed out, wrap around to next nametable
			this.loopyV &= ( 0xffff & ~0x1f );
			this.loopyV ^= 0x0400;
		}
		else {
			// we can safely increment loopy_v (since X is in the lowest bits)
			this.loopyV += 1;
		}
	},

	/**
	 * Increment Y scroll in loopy_v.
	 * TODO optimizations
	 */
	incrementVY: function() {
		if ((this.loopyV & 0x7000) != 0x7000) {
			// fine Y < 7: increment
			this.loopyV += 0x1000;
		} else {
			// fine Y at maximum: reset fine Y, increment coarse Y
			this.loopyV &= ~0x7000;

			var coarseY = (this.loopyV & 0x03e0) >>> 5;
			if (coarseY == 29) {
				// switch vertical nametable
				coarseY = 0;
				this.loopyV ^= 0x0800;
			} else if (coarseY == 31) {
				// reset coarse Y without switching nametable
				coarseY = 0;
			} else {
				// simply increment coarse Y
				coarseY += 1;
			}

			// set coarse Y in loopy_v
			this.loopyV = (this.loopyV & ~0x03e0) | (coarseY << 5);
		}
	},

	setPixel: function() {
		var color = this.scanlineColors[ this.ppu.lineCycle - 1 ];

		if ( !this.enabledPixel ) {
			color = 0;
		}

		return color;
	},

	/**
	 * Fetch background tile data.
	 */
	fetchTileData: function() {
		if ( this.fetchingTilesPhase++ === 7 ) {
			const nametableAddress = 0x2000 | (this.loopyV & 0x0fff),
			      attrAddress = 0x23c0 | (this.loopyV & 0x0c00) | ((this.loopyV >> 4) & 0x38) | ((this.loopyV >> 2) & 0x07),
			      nameTableByte = this.memory.read( nametableAddress ),
			      attribute = this.memory.read( attrAddress ),

			      fineY = ( this.loopyV & 0x7000 ) >> 12,
			      tileAddress = ( nameTableByte << 4 ) + this.baseTable + fineY,

			      bitmapLow = this.memory.read( tileAddress ),
			      bitmapHigh = this.memory.read( tileAddress + 8 );

			var paletteMask = 3, // top left
			    paletteShift = 0,
			    palette = 0;

			if ( nametableAddress & 0x2 ) {
				// right
				paletteMask <<= 2;
				paletteShift = 2;
			}
			if ( nametableAddress & 0x40 ) {
				// bottom
				paletteMask <<= 4;
				paletteShift += 4;
			}

			palette = ( attribute & paletteMask ) >> paletteShift;

			// this.preloadTile( bitmapLow, bitmapHigh, palette );
			this.palette = palette << 2;
			this.tileLow = bitmapLow;
			this.tileHigh = bitmapHigh;
			this.tileMask = 0x80;

			this.incrementVX();

			this.fetchingTilesPhase = 0;
		}
	},

	setColor: function() {
		const low = !!( this.tileLow & this.tileMask ),
		      high = !!( this.tileHigh & this.tileMask ) << 1,
		      color = ( high | low );

		this.scanlineColors[ this.x++ & 0x1ff ] = color && ( this.palette | color );

		this.tileMask >>= 1;
	},

	setNameTable: function( index ) {
		this.loopyT = ( this.loopyT & NAMETABLE_RESET ) | ( index << 10 );
	}
};

module.exports = Background;<commit_msg>Calculate loopyV using a lookup table.<commit_after>"use strict";

// bitmasks
const NAMETABLE_BITMASK = 0xc00,
      NAMETABLE_RESET = ~NAMETABLE_BITMASK;

function Background( ppu ) {
	this.ppu = ppu;
	this.memory = ppu.memory;

	this.enabled = true;
	this.enabledLeft = true;
	this.enabledPixel = false;

	this.loopyV = 0;
	this.loopyT = 0;
	this.loopyW = 0;
	this.loopyX = 0;

	this.baseTable = 0;

	this.copyingVertical = false;
	this.fetchingTiles = false;
	this.fetchingTilesPhase = 0;

	this.x = 0;
	this.scanlineColors = new Uint8Array( 0x200 );
	this.palette = 0;
	this.tileLow = 0;
	this.tileHigh = 0;
	this.tileMask = 0;

	Object.preventExtensions( this );
}

Background.prototype = {
	toggle: function( flag ) {
		this.enabled = !!flag;
	},

	toggleLeft: function( flag ) {
		this.enabledLeft = !!flag;
	},

	writeAddress: function( value ) {
		if ( this.loopyW ) {
			value &= 0xff;
			this.loopyT = ( this.loopyT & 0xff00 ) | value;
			this.loopyV = this.loopyT;
		} else {
			value &= 0x3f; // only use lowest 6 bits
			value = value << 8;
			this.loopyT = ( this.loopyT & 0x00ff ) | value; // note, also resets bit 14 of loopy_t (for unknown reason)
		}

		this.loopyW = !this.loopyW;
	},

	writeScroll: function( value ) {
		if ( this.loopyW ) {
			// set vertical scroll
			this.loopyT = this.loopyT & ~0x73e0;
			this.loopyT = this.loopyT | ( (value & 0x7) << 12 );
			this.loopyT = this.loopyT | ( (value & 0xf8) << 2 );

			this.loopyW = 0;
		} else {
			// set horizontal scroll
			this.loopyT = this.loopyT & 0x7fe0;
			this.loopyT |= ( value >> 3 );

			this.loopyX = value & ( 0x7 );

			this.loopyW = 1;
		}
	},

	evaluate: function() {
		this.initLineCycle();

		if ( this.fetchingTiles ) {
			this.setColor();

			if ( this.ppu.enabled ) {
				this.fetchTileData();
			}
		}

		if ( this.ppu.lineCycle > 255 ) {
			switch( this.ppu.lineCycle ) {
			case 256:
				if ( this.ppu.enabled ) {
					// increment coarse X position every 8th cycle
					this.incrementVY();
				}
				break;
			case 257:
				if ( this.ppu.enabled ) {
					// reset horizontal at end of scanline
					// copy horizontal bits from loopy_t to loopy_v
					this.loopyV = ( this.loopyV & 0x7be0 ) | ( this.loopyT & 0x41f );
				}
				break;
			}

			// finish initialization of loopy_v from loopy_t at end of pre-render scanline
			if ( this.copyingVertical ) {
				if ( this.ppu.enabled ) {
					// copy vertical bits from loopy_t to loopy_v
					this.loopyV = ( this.loopyV & 0x41f ) | ( this.loopyT & 0x7be0 );
				}
			}
		}
	},

	initLineCycle: function() {
		const lineCycle = this.ppu.lineCycle;

		if ( lineCycle < 10 ) {
			switch( lineCycle ) {
			case 1:
				this.enabledPixel = this.enabledLeft && this.ppu.inLeft8px;
				this.fetchingTiles = true;
				this.fetchingTilesPhase = 1;
				break;
			case 9:
				this.enabledPixel = this.ppu.enabled;
				break;
			}
		} else if ( lineCycle > 256 ) {
			switch( lineCycle ) {
			case 321:
				this.x = -this.loopyX - 8;
				this.fetchingTiles = true;
				this.fetchingTilesPhase = 1;
				break;
			case 337:
				/* falls through */
			case 257:
				this.fetchingTiles = false;
				break;
			case 281:
				if ( this.ppu.scanline === -1 ) {
					this.copyingVertical = true;
				}
				break;
			case 304:
				if ( this.ppu.scanline === -1 ) {
					this.copyingVertical = false;
				}
				break;
			}
		}
	},

	/**
	 * Increment coarse X scroll in loopy_v.
	 */
	incrementVX: function() {
		if ((this.loopyV & 0x1f) === 31) {
			// coarse X is maxed out, wrap around to next nametable
			this.loopyV &= ( 0xffff & ~0x1f );
			this.loopyV ^= 0x0400;
		}
		else {
			// we can safely increment loopy_v (since X is in the lowest bits)
			this.loopyV += 1;
		}
	},

	/**
	 * Increment Y scroll in loopy_v.
	 * TODO optimizations
	 */
	incrementVY: function() {
		if ((this.loopyV & 0x7000) != 0x7000) {
			// fine Y < 7: increment
			this.loopyV += 0x1000;
		} else {
			// fine Y at maximum: reset fine Y, increment coarse Y
			this.loopyV &= ~0x7000;

			var coarseY = (this.loopyV & 0x03e0) >>> 5;
			if (coarseY == 29) {
				// switch vertical nametable
				coarseY = 0;
				this.loopyV ^= 0x0800;
			} else if (coarseY == 31) {
				// reset coarse Y without switching nametable
				coarseY = 0;
			} else {
				// simply increment coarse Y
				coarseY += 1;
			}

			// set coarse Y in loopy_v
			this.loopyV = (this.loopyV & ~0x03e0) | (coarseY << 5);
		}
	},

	setPixel: function() {
		var color = this.scanlineColors[ this.ppu.lineCycle - 1 ];

		if ( !this.enabledPixel ) {
			color = 0;
		}

		return color;
	},

	/**
	 * Fetch background tile data.
	 */
	fetchTileData: function() {
		if ( this.fetchingTilesPhase++ === 7 ) {
			const nametableAddress = 0x2000 | (this.loopyV & 0x0fff),
			      attrAddress = attrAddressLookup[ this.loopyV ],
			      nameTableByte = this.memory.read( nametableAddress ),
			      attribute = this.memory.read( attrAddress ),

			      fineY = ( this.loopyV & 0x7000 ) >> 12,
			      tileAddress = ( nameTableByte << 4 ) + this.baseTable + fineY,

			      bitmapLow = this.memory.read( tileAddress ),
			      bitmapHigh = this.memory.read( tileAddress + 8 );

			var paletteMask = 3, // top left
			    paletteShift = 0,
			    palette = 0;

			if ( nametableAddress & 0x2 ) {
				// right
				paletteMask <<= 2;
				paletteShift = 2;
			}
			if ( nametableAddress & 0x40 ) {
				// bottom
				paletteMask <<= 4;
				paletteShift += 4;
			}

			palette = ( attribute & paletteMask ) >> paletteShift;

			// this.preloadTile( bitmapLow, bitmapHigh, palette );
			this.palette = palette << 2;
			this.tileLow = bitmapLow;
			this.tileHigh = bitmapHigh;
			this.tileMask = 0x80;

			this.incrementVX();

			this.fetchingTilesPhase = 0;
		}
	},

	setColor: function() {
		const low = !!( this.tileLow & this.tileMask ),
		      high = !!( this.tileHigh & this.tileMask ) << 1,
		      color = ( high | low );

		this.scanlineColors[ this.x++ & 0x1ff ] = color && ( this.palette | color );

		this.tileMask >>= 1;
	},

	setNameTable: function( index ) {
		this.loopyT = ( this.loopyT & NAMETABLE_RESET ) | ( index << 10 );
	}
};

var i = 0;
var attrAddressLookup = new Uint16Array( 0x8000 );
for ( i = 0; i < 0x8000; i++ ) {
	attrAddressLookup[ i ] = 0x23c0 | (i & 0x0c00) | ((i >> 4) & 0x38) | ((i >> 2) & 0x07);
}

module.exports = Background;<|endoftext|>