<commit_before>define([
	'utils/isArray',
	'utils/isEqual',
	'shared/registerDependant',
	'shared/unregisterDependant'
], function (
	isArray,
	isEqual,
	registerDependant,
	unregisterDependant
) {

	'use strict';

	var Binding = function ( ractive, keypath, otherInstance, otherKeypath, priority ) {
		this.root = ractive;
		this.keypath = keypath;
		this.priority = priority;

		this.otherInstance = otherInstance;
		this.otherKeypath = otherKeypath;

		registerDependant( this );
	};

	Binding.prototype = {
		init: function ( propagate ) {
			var value = this.root.get( this.keypath );

			// Data should propagate from child to parent
			if ( propagate && value !== undefined ) {
				this.update();
			} else {
				this.value = value;
			}
		},

		update: function () {
			var value;

			// Only *you* can prevent infinite loops
			if ( this.counterpart && this.counterpart.setting ) {
				return;
			}

			value = this.root.get( this.keypath );

			// Is this a smart array update? If so, it'll update on its
			// own, we shouldn't do anything
			if ( isArray( value ) && value._ractive && value._ractive.setting ) {
				return;
			}

			if ( !isEqual( value, this.value ) ) {
				this.setting = true;
				this.otherInstance.set( this.otherKeypath, value );
				this.value = value;
				this.setting = false;
			}
		},

		teardown: function () {
			unregisterDependant( this );
		}
	};


	return function createComponentBinding ( component, parentInstance, parentKeypath, childKeypath ) {
		var hash, childInstance, bindings, priority, parentToChildBinding, childToParentBinding;

		hash = parentKeypath + '=' + childKeypath;
		bindings = component.bindings;

		if ( bindings[ hash ] ) {
			// TODO does this ever happen?
			return;
		}

		bindings[ hash ] = true;

		childInstance = component.instance;
		priority = component.parentFragment.priority;

		parentToChildBinding = new Binding( parentInstance, parentKeypath, childInstance, childKeypath, priority );
		parentToChildBinding.init();
		bindings.push( parentToChildBinding );

		if ( childInstance.twoway ) {
			childToParentBinding = new Binding( childInstance, childKeypath, parentInstance, parentKeypath, 1 );
			bindings.push( childToParentBinding );

			parentToChildBinding.counterpart = childToParentBinding;
			childToParentBinding.counterpart = parentToChildBinding;

			// propagate child data upwards, if it exists already
			//childToParentBinding.init( true );
		}
	};

});<commit_msg>guard against component bindings causing infinite loops<commit_after>define([
	'utils/isArray',
	'utils/isEqual',
	'shared/registerDependant',
	'shared/unregisterDependant'
], function (
	isArray,
	isEqual,
	registerDependant,
	unregisterDependant
) {

	'use strict';

	var Binding = function ( ractive, keypath, otherInstance, otherKeypath, priority ) {
		this.root = ractive;
		this.keypath = keypath;
		this.priority = priority;

		this.otherInstance = otherInstance;
		this.otherKeypath = otherKeypath;

		registerDependant( this );

		this.value = this.root.get( this.keypath );
	};

	Binding.prototype = {
		update: function () {
			var value;

			// Only *you* can prevent infinite loops
			if ( this.updating || this.counterpart && this.counterpart.updating ) {
				return;
			}

			this.updating = true;

			value = this.root.get( this.keypath );

			// Is this a smart array update? If so, it'll update on its
			// own, we shouldn't do anything
			if ( isArray( value ) && value._ractive && value._ractive.updating ) {
				return;
			}

			if ( !isEqual( value, this.value ) ) {
				this.otherInstance.set( this.otherKeypath, value );
				this.value = value;
			}

			this.updating = false;
		},

		teardown: function () {
			unregisterDependant( this );
		}
	};


	return function createComponentBinding ( component, parentInstance, parentKeypath, childKeypath ) {
		var hash, childInstance, bindings, priority, parentToChildBinding, childToParentBinding;

		hash = parentKeypath + '=' + childKeypath;
		bindings = component.bindings;

		if ( bindings[ hash ] ) {
			// TODO does this ever happen?
			return;
		}

		bindings[ hash ] = true;

		childInstance = component.instance;
		priority = component.parentFragment.priority;

		parentToChildBinding = new Binding( parentInstance, parentKeypath, childInstance, childKeypath, priority );
		bindings.push( parentToChildBinding );

		if ( childInstance.twoway ) {
			childToParentBinding = new Binding( childInstance, childKeypath, parentInstance, parentKeypath, 1 );
			bindings.push( childToParentBinding );

			parentToChildBinding.counterpart = childToParentBinding;
			childToParentBinding.counterpart = parentToChildBinding;
		}
	};

});
{'fraction_non_alphanumeric': 0.11120634240411399, 'fraction_numerical': 0.00042854081851296334, 'mean_word_length': 3.7151515151515153, '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': '3207193', 'n_tokens_mistral': 1659, 'n_tokens_neox': 1394, 'n_words': 345}