<commit_before>var logger = require('debug');
var traverse = require('traverse');
var noop = function(){};

/**
 * @param {Object} socket
 * @param {Object} tree
 * @param {String} clientOrServer
 */
module.exports = function(socket, tree, clientOrServer) {
	var debug = logger('socket.io-rpc:' + clientOrServer);
	/**
	 * for external use, simple function is used rather than an event emitter, because we lack event emitter in the browser
	 * @type {{batchStarts: Function, batchEnds: Function, call: Function, response: Function}}
	 */
	var eventHandlers = {
		batchStarts: noop,
		batchEnds: noop,
		call: noop,
		response: noop
	};
	var socketId;
	var deferreds = [];

	var invocationCounter = 0;
	var endCounter = 0;
	var remoteCallEnded = function(Id) {
		if (deferreds[Id]) {
			delete deferreds[Id];
			endCounter++;
			eventHandlers.response(endCounter);

			if (endCounter == invocationCounter) {
				eventHandlers.batchEnds(endCounter);
				invocationCounter = 0;
				endCounter = 0;
			}
		} else {
			//the client can maliciously try and resolve/reject something more than once. We should not throw an error on this, just warn
			console.error("Deferred Id " + Id + " was resolved/rejected more than once, this should not occur.");
		}
	};

	/**
	 * @param {String} fnPath
	 * @returns {Function} which will call the backend/client when executed
	 */
	function prepareRemoteCall(fnPath) {
		return function remoteCall() {
			var args = Array.prototype.slice.call(arguments, 0);
			return new Promise(function (resolve, reject){
				if (rpc.reconnecting) {
					reject(new Error('socket ' + socketId + ' disconnected, call rejected'));
				}
				invocationCounter++;
				debug('calling ', fnPath, 'on ', socketId, ', invocation counter ', invocationCounter);
				socket.emit('call',
					{Id: invocationCounter, fnPath: fnPath, args: args}
				);
				if (invocationCounter == 1) {
					eventHandlers.batchStarts(invocationCounter);
				}
				deferreds[invocationCounter] = {resolve: resolve, reject: reject};
			});
		};
	}
	var rpc = prepareRemoteCall;
	socket.rpc = rpc;
	socket.rpc.events = eventHandlers;
	var remoteNodes = {};

	/**
	 * @type {boolean} indicates when client is reconnecting
	 */
	rpc.reconnecting = false;

	if (clientOrServer === 'client') {
		rpc.initializedP = new Promise(function (resolve, reject){
			socket.on('connect', function() {
				socketId = socket.id || socket.io.engine.id;
				debug('connected socket ', socketId);
				resolve();
			}).on('connect_error', function(err) {
				if (!socketId) {
					reject(err);
				}
			});
		});
	} else {
		socketId = socket.id;
	}

	socket.on('disconnect', function onDisconnect() {
		rpc.reconnecting = true;
	}).on('connect_error', function(err) {
		debug('unable to connect through socket.io');
		for (var nodePath in remoteNodes) {
			remoteNodes[nodePath].reject(err)
		}
	}).on('call', function(data) {
		debug('invocation with ', data);
		if (!(data && typeof data.Id === 'number')) {
			return socket.emit('rpcError', {
				reason: 'Id is a required property for a call data payload'
			});
		}
		var emitRes = function(type, resData) {
			resData.Id = data.Id;
			socket.emit(type, resData)
		};
		try {<commit_msg>socket.id is only on server<commit_after>var logger = require('debug');
var traverse = require('traverse');
var noop = function(){};

/**
 * @param {Object} socket
 * @param {Object} tree
 * @param {String} clientOrServer
 */
module.exports = function(socket, tree, clientOrServer) {
	var debug = logger('socket.io-rpc:' + clientOrServer);
	/**
	 * for external use, simple function is used rather than an event emitter, because we lack event emitter in the browser
	 * @type {{batchStarts: Function, batchEnds: Function, call: Function, response: Function}}
	 */
	var eventHandlers = {
		batchStarts: noop,
		batchEnds: noop,
		call: noop,
		response: noop
	};
	var socketId;
	var deferreds = [];

	var invocationCounter = 0;
	var endCounter = 0;
	var remoteCallEnded = function(Id) {
		if (deferreds[Id]) {
			delete deferreds[Id];
			endCounter++;
			eventHandlers.response(endCounter);

			if (endCounter == invocationCounter) {
				eventHandlers.batchEnds(endCounter);
				invocationCounter = 0;
				endCounter = 0;
			}
		} else {
			//the client can maliciously try and resolve/reject something more than once. We should not throw an error on this, just warn
			console.error("Deferred Id " + Id + " was resolved/rejected more than once, this should not occur.");
		}
	};

	/**
	 * @param {String} fnPath
	 * @returns {Function} which will call the backend/client when executed
	 */
	function prepareRemoteCall(fnPath) {
		return function remoteCall() {
			var args = Array.prototype.slice.call(arguments, 0);
			return new Promise(function (resolve, reject){
				if (rpc.reconnecting) {
					reject(new Error('socket ' + socketId + ' disconnected, call rejected'));
				}
				invocationCounter++;
				debug('calling ', fnPath, 'on ', socketId, ', invocation counter ', invocationCounter);
				socket.emit('call',
					{Id: invocationCounter, fnPath: fnPath, args: args}
				);
				if (invocationCounter == 1) {
					eventHandlers.batchStarts(invocationCounter);
				}
				deferreds[invocationCounter] = {resolve: resolve, reject: reject};
			});
		};
	}
	var rpc = prepareRemoteCall;
	socket.rpc = rpc;
	socket.rpc.events = eventHandlers;
	var remoteNodes = {};

	/**
	 * @type {boolean} indicates when client is reconnecting
	 */
	rpc.reconnecting = false;

	if (clientOrServer === 'client') {
		rpc.initializedP = new Promise(function (resolve, reject){
			socket.on('connect', function() {
				socketId = socket.io.engine.id;
				debug('connected socket ', socketId);
				resolve();
			}).on('connect_error', function(err) {
				if (!socketId) {
					reject(err);
				}
			});
		});
	} else {
		socketId = socket.id;
	}

	socket.on('disconnect', function onDisconnect() {
		rpc.reconnecting = true;
	}).on('connect_error', function(err) {
		debug('unable to connect through socket.io');
		for (var nodePath in remoteNodes) {
			remoteNodes[nodePath].reject(err)
		}
	}).on('call', function(data) {
		debug('invocation with ', data);
		if (!(data && typeof data.Id === 'number')) {
			return socket.emit('rpcError', {
				reason: 'Id is a required property for a call data payload'
			});
		}
		var emitRes = function(type, resData) {
			resData.Id = data.Id;
			socket.emit(type, resData)
		};
		try {
{'fraction_non_alphanumeric': 0.13949867663085785, 'fraction_numerical': 0.0018682858477347033, 'mean_word_length': 3.747967479674797, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1274743', 'n_tokens_mistral': 2301, 'n_tokens_neox': 1982, 'n_words': 557}