<commit_before>var _ = require('lodash'),
	EventEmitter2 = require('eventemitter2');

// this module provides a different export depending on the module loader...
EventEmitter2.EventEmitter2 && (EventEmitter2 = EventEmitter2.EventEmitter2);

var StateService = module.exports = Object.create(null, {
	_cache: { writable: true, configurable: true, value: Object.create(null) },
	_locals: { writable: true, configurable: true, value: Object.create(null) },
	bus: { writable: true, configurable: true, value: new EventEmitter2() }
});


StateService.locals = function(locals) {
	// this usually only gets set by express-engine.js
	if (locals) {
		this._locals = locals;
		return;
	}

	// if we're in the browser
	if (typeof window !== 'undefined') {
		return window.__EXACT_PROPS__ || {};
	}

	// probably on the server... #lgtm
	return this._locals;
};

// the cache is used for sharing the same state-services across multiple
// components (coordinated based on some cache key). Client-side we never have
// to worry about clearing the cache, but server-side it needs to be reset
// before each render (see boot-client.js).
StateService.cache = function(key, val) {
	if (arguments.length === 1) {
		return this._cache[key];
	}
	this._cache[key] = val;
};

StateService.clearCache = function(key) {
	if (arguments.length === 1) {
		delete this._cache[key];
	} else {
		this._cache = Object.create(null);
	}
};

StateService.reset = function() {
	this.clearCache();
	this._locals = Object.create(null);
	this.bus.removeAllListeners();
};

StateService.createFactory = function(definition) {
	// capture and cache these now
	var defaultProps = definition.getDefaultProps ?
			definition.getDefaultProps() : Object.create(null);

	return Object.create({
		create: function(props) {
			return createServiceInstance(this, props);
		},
		mixin: function(opts) {
			return createServiceMixin(this, opts);
		}
	}, {
		factoryId: { value: 'factory-' + largeRandomNumber() },
		definition: { value: definition },
		defaultProps: { value: defaultProps }
	});
};

function createServiceInstance(factory, props) {
	var definition = factory.definition;

	// before we create a new one, check if we need to return a cached instance
	props = _.assign({}, factory.defaultProps, props);

	var uniqueKey = definition.getUniqueKey ? definition.getUniqueKey(props) : null;

	// scope it to the factory
	if (uniqueKey) {
		uniqueKey = factory.factoryId + '::' + uniqueKey;
	}

	var serviceInstance;

	// return a cached instance, if appropriate
	if (uniqueKey) {
		serviceInstance = StateService.cache(uniqueKey);
		if (serviceInstance) {
			return serviceInstance;
		}
	}

	// we need to create a new one
	var proto = _.assign(
		// create a new prototype object
		{},
		// ...that includes all of our default prototype methods
		defaultServiceInstanceProto,
		// ...and all provided methods (other than the lifecycle hooks)
		_.omit(definition, [
			'getDefaultProps',
			'getUniqueKey',
			'getInitialState',
			'registeredComponentWillMount',
			'registeredComponentDidMount',
			'registeredComponentWillUnmount'
		])
	);

	serviceInstance = Object.create(proto, {
		props: { writable: true, configurable: true, value: props },
		state: { writable: true, configurable: true },
		_uuid: { value: 'state-service-' + largeRandomNumber() },
		_registeredComponents: { value: Object.create(null) },
		_registeredComponentsCount: { writable: true, configurable: true, value: 0 },
		_uniqueKey: { value: uniqueKey }
	});

	serviceInstance.state = _.assign(
		Object.create(null),
		definition.getInitialState ? definition.getInitialState.apply(serviceInstance) : {}
	);

	if (uniqueKey) {
		StateService.cache(uniqueKey, serviceInstance)
	}

	return serviceInstance;
}

var defaultServiceInstanceProto = {
	registerComponent: function(component, keys) {
		var self = this;

		// note: the act of fetching the data bag for this component effectively
		// registers it.
		var data = this.getComponentData(component);

		// store a quick lookup map of all the keys that this component is tracking
		data.keyMap = Object.create(null);
		(keys || Object.keys(this.state)).forEach(function(key) {
			data.keyMap[key] = true;
		});<commit_msg>make StateService instance methods be pre-bound to the instance itself<commit_after>var _ = require('lodash'),
	EventEmitter2 = require('eventemitter2');

// this module provides a different export depending on the module loader...
EventEmitter2.EventEmitter2 && (EventEmitter2 = EventEmitter2.EventEmitter2);

var StateService = module.exports = Object.create(null, {
	_cache: { writable: true, configurable: true, value: Object.create(null) },
	_locals: { writable: true, configurable: true, value: Object.create(null) },
	bus: { writable: true, configurable: true, value: new EventEmitter2() }
});


StateService.locals = function(locals) {
	// this usually only gets set by express-engine.js
	if (locals) {
		this._locals = locals;
		return;
	}

	// if we're in the browser
	if (typeof window !== 'undefined') {
		return window.__EXACT_PROPS__ || {};
	}

	// probably on the server... #lgtm
	return this._locals;
};

// the cache is used for sharing the same state-services across multiple
// components (coordinated based on some cache key). Client-side we never have
// to worry about clearing the cache, but server-side it needs to be reset
// before each render (see boot-client.js).
StateService.cache = function(key, val) {
	if (arguments.length === 1) {
		return this._cache[key];
	}
	this._cache[key] = val;
};

StateService.clearCache = function(key) {
	if (arguments.length === 1) {
		delete this._cache[key];
	} else {
		this._cache = Object.create(null);
	}
};

StateService.reset = function() {
	this.clearCache();
	this._locals = Object.create(null);
	this.bus.removeAllListeners();
};

StateService.createFactory = function(definition) {
	// capture and cache these now
	var defaultProps = definition.getDefaultProps ?
			definition.getDefaultProps() : Object.create(null);

	return Object.create({
		create: function(props) {
			return createServiceInstance(this, props);
		},
		mixin: function(opts) {
			return createServiceMixin(this, opts);
		}
	}, {
		factoryId: { value: 'factory-' + largeRandomNumber() },
		definition: { value: definition },
		defaultProps: { value: defaultProps }
	});
};

function createServiceInstance(factory, props) {
	var definition = factory.definition;

	// before we create a new one, check if we need to return a cached instance
	props = _.assign({}, factory.defaultProps, props);

	var uniqueKey = definition.getUniqueKey ? definition.getUniqueKey(props) : null;

	// scope it to the factory
	if (uniqueKey) {
		uniqueKey = factory.factoryId + '::' + uniqueKey;
	}

	var serviceInstance;

	// return a cached instance, if appropriate
	if (uniqueKey) {
		serviceInstance = StateService.cache(uniqueKey);
		if (serviceInstance) {
			return serviceInstance;
		}
	}

	// we need to create a new one
	var proto = _.assign(
		// create a new prototype object
		{},
		// ...that includes all of our default prototype methods
		defaultServiceInstanceProto
	);

	serviceInstance = Object.create(proto, {
		props: { writable: true, configurable: true, value: props },
		state: { writable: true, configurable: true },
		_uuid: { value: 'state-service-' + largeRandomNumber() },
		_registeredComponents: { value: Object.create(null) },
		_registeredComponentsCount: { writable: true, configurable: true, value: 0 },
		_uniqueKey: { value: uniqueKey }
	});

	// all of the provided methods (other than our lifecycle hooks) need to be
	// assigned as already-bound methods to the instance (similar to how React
	// component methods are bound).
	_.difference(Object.keys(definition), [
		'getDefaultProps',
		'getUniqueKey',
		'getInitialState',
		'registeredComponentWillMount',
		'registeredComponentDidMount',
		'registeredComponentWillUnmount'
	]).forEach(function(key) {
		var val = definition[key];
		Object.defineProperty(serviceInstance, key, {
			writable: true,
			configurable: true,
			value: typeof val === 'function' ? val.bind(serviceInstance) : val
		});
	});

	serviceInstance.state = _.assign(
		Object.create(null),
		definition.getInitialState ? definition.getInitialState.apply(serviceInstance) : {}
	);

	if (uniqueKey) {
		StateService.cache(uniqueKey, serviceInstance)
	}

	return serviceInstance;
}

var defaultServiceInstanceProto = {
	registerComponent: function(component, keys) {
		var self = this;

		// note: the act of fetching the data bag for this component effectively
		// registers it.
		var data = this.getComponentData(component);

		// store a quick lookup map of all the keys that this component is tracking
		data.keyMap = Object.create(null);
		(keys || Object.keys(this.state)).forEach(function(key) {
			data.keyMap[key] = true;
		});
{'fraction_non_alphanumeric': 0.1233295583238958, 'fraction_numerical': 0.002491506228765572, 'mean_word_length': 4.2502972651605235, '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': '2047755', 'n_tokens_mistral': 2783, 'n_tokens_neox': 2622, 'n_words': 762}