mirror of
				https://github.com/flynx/features.js.git
				synced 2025-10-30 19:00:10 +00:00 
			
		
		
		
	new algorithm done, not yet used...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									cad40b850e
								
							
						
					
					
						commit
						4c73da1043
					
				
							
								
								
									
										159
									
								
								features.js
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								features.js
									
									
									
									
									
								
							| @ -1008,18 +1008,18 @@ var FeatureSetProto = { | |||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// XXX this looks really promising...
 | 	// Build list of features in an appropriate order to load...
 | ||||||
| 	// XXX
 | 	//
 | ||||||
| 	// 		- build tree (a-la ._buildFeatureList(..))
 | 	// Algorithm:
 | ||||||
| 	// 		- order the features in .depends and .suggested by priority
 | 	// 	- expand features:
 | ||||||
| 	// 		- order the features by dependency (similar to .buildFeatureList(..))
 | 	// 		- handle dependencies (detect loops)
 | ||||||
| 	// 			each feature in list must be strictly after it's dependencies
 | 	// 		- handle suggestions
 | ||||||
| 	// 				- for each feature
 | 	// 		- handle explicitly disabled features (detect loops)
 | ||||||
| 	// 					- check if all dependencies are before
 | 	// 		- handle exclusive feature groups/aliases (handle conflicts)
 | ||||||
| 	// 					- if not ??? (XXX)
 | 	// 	- sort list of features:
 | ||||||
| 	// XXX should we report stuff here???
 | 	// 		- by priority
 | ||||||
| 	// XXX TODO:
 | 	// 		- by dependency (detect loops/errors)
 | ||||||
| 	// 		- wrapper to pass in applicability filter...
 | 	//
 | ||||||
| 	_buildFeatureListReorder: function(lst, filter){ | 	_buildFeatureListReorder: function(lst, filter){ | ||||||
| 		var all = this.features | 		var all = this.features | ||||||
| 		lst = (lst == null || lst == '*') ? all : lst | 		lst = (lst == null || lst == '*') ? all : lst | ||||||
| @ -1027,6 +1027,10 @@ var FeatureSetProto = { | |||||||
| 
 | 
 | ||||||
| 		var that = this | 		var that = this | ||||||
| 
 | 
 | ||||||
|  | 		// Expand feature references (recursive)...
 | ||||||
|  | 		//
 | ||||||
|  | 		// NOTE: closures are not used here as we need to pass different
 | ||||||
|  | 		// 		stuff into data in different situations...
 | ||||||
| 		var expand = function(target, lst, store, data, _seen){ | 		var expand = function(target, lst, store, data, _seen){ | ||||||
| 			data = data || {} | 			data = data || {} | ||||||
| 			_seen = _seen || [] | 			_seen = _seen || [] | ||||||
| @ -1036,7 +1040,6 @@ var FeatureSetProto = { | |||||||
| 			// 		feature before it is disabled in the same list...
 | 			// 		feature before it is disabled in the same list...
 | ||||||
| 			lst = data.disabled ? | 			lst = data.disabled ? | ||||||
| 				lst | 				lst | ||||||
| 					// XXX also skip features depending on disabled...
 |  | ||||||
| 					.filter(function(n){ | 					.filter(function(n){ | ||||||
| 						// feature disabled -> record and skip...
 | 						// feature disabled -> record and skip...
 | ||||||
| 						if(n[0] == '-'){ | 						if(n[0] == '-'){ | ||||||
| @ -1122,34 +1125,22 @@ var FeatureSetProto = { | |||||||
| 			return store | 			return store | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		var loops = [] | 		// Expand feature dependencies and suggestions recursively...
 | ||||||
| 		var disable_loops = [] | 		//
 | ||||||
| 		var disabled = [] | 		// NOTE: this relies on the following values being in the closure:
 | ||||||
| 		var missing = [] | 		// 		loops			- list of loop chains found
 | ||||||
| 
 | 		// 		disable_loops	- disable loops
 | ||||||
| 		// user filter...
 | 		// 							when a feature containing a disable 
 | ||||||
| 		// NOTE: we build this out of the full feature list...
 | 		// 							directive gets disabled as a result
 | ||||||
| 		var filtered_out = filter ? | 		// 		disabled		- list of disabled features
 | ||||||
| 			all.filter(function(n){ return !filter.call(that, n) }) | 		// 		missing			- list of missing features
 | ||||||
| 			: []  | 		// 		exclusive		- exclusive feature index
 | ||||||
| 		disabled = disabled.concat(filtered_out) | 		// NOTE: the above containers will get updated as a side-effect.
 | ||||||
| 
 | 		// NOTE: all of the above values are defined near the location 
 | ||||||
| 		// build exclusive groups...
 | 		// 		they are first used/initiated...
 | ||||||
| 		// XXX use these as aliases...
 | 		// NOTE: closures are used here purely for simplicity and conciseness
 | ||||||
| 		// 		...we need to do this on the build stage to include correct
 | 		// 		as threading data would not add any flexibility but make 
 | ||||||
| 		// 		deps and suggesntions...
 | 		// 		the code more complex...
 | ||||||
| 		var exclusive = {} |  | ||||||
| 		var rev_exclusive = {} |  | ||||||
| 		all |  | ||||||
| 			.filter(function(f){ return !!that[f].exclusive }) |  | ||||||
| 			.forEach(function(k){ |  | ||||||
| 				(that[k].exclusive || []) |  | ||||||
| 					.forEach(function(e){ |  | ||||||
| 						exclusive[e] = (exclusive[e] || []).concat([k])  |  | ||||||
| 						rev_exclusive[k] = (rev_exclusive[k] || []).concat([e]) }) }) |  | ||||||
| 
 |  | ||||||
| 		// XXX revise:
 |  | ||||||
| 		// 		- should this be this depending on closure so much???
 |  | ||||||
| 		var expandFeatures = function(lst, features){ | 		var expandFeatures = function(lst, features){ | ||||||
| 			features = features || {} | 			features = features || {} | ||||||
| 
 | 
 | ||||||
| @ -1194,14 +1185,44 @@ var FeatureSetProto = { | |||||||
| 						features[f] = s[f] | 						features[f] = s[f] | ||||||
| 					} | 					} | ||||||
| 				}) | 				}) | ||||||
|  | 
 | ||||||
|  | 			return features | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 		var features = {} | 		//--------------------- Globals: filtering / exclusive tags ---
 | ||||||
| 		expandFeatures(lst, features) | 
 | ||||||
|  | 		var loops = [] | ||||||
|  | 		var disable_loops = [] | ||||||
|  | 		var disabled = [] | ||||||
|  | 		var missing = [] | ||||||
|  | 
 | ||||||
|  | 		// user filter...
 | ||||||
|  | 		// NOTE: we build this out of the full feature list...
 | ||||||
|  | 		var filtered_out = filter ? | ||||||
|  | 			all.filter(function(n){ return !filter.call(that, n) }) | ||||||
|  | 			: []  | ||||||
|  | 		disabled = disabled.concat(filtered_out) | ||||||
|  | 
 | ||||||
|  | 		// build exclusive groups...
 | ||||||
|  | 		var exclusive = {} | ||||||
|  | 		var rev_exclusive = {} | ||||||
|  | 		all | ||||||
|  | 			.filter(function(f){ return !!that[f].exclusive }) | ||||||
|  | 			.forEach(function(k){ | ||||||
|  | 				(that[k].exclusive || []) | ||||||
|  | 					.forEach(function(e){ | ||||||
|  | 						exclusive[e] = (exclusive[e] || []).concat([k])  | ||||||
|  | 						rev_exclusive[k] = (rev_exclusive[k] || []).concat([e]) }) }) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 		// check for exclusivity conflicts and aliases...
 | 		//-------------------------------- Stage 1: expand features ---
 | ||||||
|  | 		var features = expandFeatures(lst) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		//-------------------------------- Exclusive groups/aliases ---
 | ||||||
|  | 		// Handle exclusive feature groups and aliases...
 | ||||||
|  | 		//
 | ||||||
| 		var conflicts = {} | 		var conflicts = {} | ||||||
| 		Object.keys(features) | 		Object.keys(features) | ||||||
| 			.forEach(function(f){ | 			.forEach(function(f){ | ||||||
| @ -1214,7 +1235,7 @@ var FeatureSetProto = { | |||||||
| 					if(candidates.length == 0){ | 					if(candidates.length == 0){ | ||||||
| 						var target = exclusive[f][0] | 						var target = exclusive[f][0] | ||||||
| 
 | 
 | ||||||
| 						// expand target...
 | 						// expand target to features...
 | ||||||
| 						expandFeatures([target], features) | 						expandFeatures([target], features) | ||||||
| 
 | 
 | ||||||
| 					// link alias to existing feature...
 | 					// link alias to existing feature...
 | ||||||
| @ -1246,13 +1267,18 @@ var FeatureSetProto = { | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| 		// resolve any conflicts found...
 | 		// resolve any exclusivity conflicts found...
 | ||||||
|  | 		var excluded = [] | ||||||
| 		Object.keys(conflicts) | 		Object.keys(conflicts) | ||||||
| 			.forEach(function(group){ | 			.forEach(function(group){ | ||||||
| 				// XXX is this how we decide which feature to keep???
 | 				// XXX is this how we decide which feature to keep???
 | ||||||
| 				disabled = disabled.concat(conflicts[group].slice(1))}) | 				excluded = excluded.concat(conflicts[group].slice(1))}) | ||||||
|  | 		disabled = disabled.concat(excluded) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 		//--------------------------------------- Disabled features ---
 | ||||||
|  | 		// Handle disabled features and cleanup...
 | ||||||
|  | 
 | ||||||
| 		// reverse dependency index...
 | 		// reverse dependency index...
 | ||||||
| 		// 	...this is used to clear out orphaned features later and for
 | 		// 	...this is used to clear out orphaned features later and for
 | ||||||
| 		// 	introspection...
 | 		// 	introspection...
 | ||||||
| @ -1299,8 +1325,10 @@ var FeatureSetProto = { | |||||||
| 				delete features[f] | 				delete features[f] | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 		// expand dependency list... (index)
 | 
 | ||||||
| 		// 	...this is used for feature sorting by dependency...
 | 		//---------------------------------- Stage 2: sort features ---
 | ||||||
|  | 
 | ||||||
|  | 		// Prepare for sort: expand dependency list in features... 
 | ||||||
| 		//
 | 		//
 | ||||||
| 		// NOTE: this will expand lst in-place...
 | 		// NOTE: this will expand lst in-place...
 | ||||||
| 		// NOTE: we are not checking for loops here -- mainly because
 | 		// NOTE: we are not checking for loops here -- mainly because
 | ||||||
| @ -1331,7 +1359,12 @@ var FeatureSetProto = { | |||||||
| 		var list = Object.keys(features) | 		var list = Object.keys(features) | ||||||
| 		list.forEach(function(f){ expanddeps(list, f) }) | 		list.forEach(function(f){ expanddeps(list, f) }) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 		// sort by priority...
 | 		// sort by priority...
 | ||||||
|  | 		//
 | ||||||
|  | 		// NOTE: this will attempt to only move features with explicitly 
 | ||||||
|  | 		// 		defined priorities and keep the rest in the same order 
 | ||||||
|  | 		// 		when possible...
 | ||||||
| 		list = list | 		list = list | ||||||
| 			// format: 
 | 			// format: 
 | ||||||
| 			// 	[ <feature>, <index>, <priority> ]
 | 			// 	[ <feature>, <index>, <priority> ]
 | ||||||
| @ -1380,6 +1413,8 @@ var FeatureSetProto = { | |||||||
| 		} while(moves > 0 && loop_limit > 0) | 		} while(moves > 0 && loop_limit > 0) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 		//-------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
| 		// XXX should we report stuff here???
 | 		// XXX should we report stuff here???
 | ||||||
| 		// report dependency loops...
 | 		// report dependency loops...
 | ||||||
| 		//
 | 		//
 | ||||||
| @ -1391,26 +1426,34 @@ var FeatureSetProto = { | |||||||
| 			&& loops | 			&& loops | ||||||
| 				.forEach(function(loop){ | 				.forEach(function(loop){ | ||||||
| 					console.warn('feature loop detected:\n\t' + loop.join('\n\t\t-> ')) }) | 					console.warn('feature loop detected:\n\t' + loop.join('\n\t\t-> ')) }) | ||||||
| 		// report loop limit...
 |  | ||||||
| 		loop_limit <= 0 |  | ||||||
| 			&& console.error('Hit loop limit while sorting dependencies!') |  | ||||||
| 		// report conflicts...
 | 		// report conflicts...
 | ||||||
| 		Object.keys(conflicts) | 		Object.keys(conflicts) | ||||||
| 			.forEach(function(group){ | 			.forEach(function(group){ | ||||||
| 				console.error('Exclusive "'+ group +'" conflict at:', conflicts[group]) }) | 				console.error('Exclusive "'+ group +'" conflict at:', conflicts[group]) }) | ||||||
|  | 		// report loop limit...
 | ||||||
|  | 		// XXX store this to data...
 | ||||||
|  | 		loop_limit <= 0 | ||||||
|  | 			&& console.error('Hit loop limit while sorting dependencies!') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
|  | 			input: lst, | ||||||
|  | 
 | ||||||
| 			list: list, | 			list: list, | ||||||
| 
 | 
 | ||||||
| 			features: features, | 			disabled: disabled, | ||||||
| 			rev_features: rev_features, | 			excluded: excluded, | ||||||
| 			exclusive: exclusive, | 			filtered_out: filtered_out, | ||||||
| 			conflicts: conflicts, | 
 | ||||||
|  | 			// XXX should these be in a error block???
 | ||||||
| 			missing: missing, | 			missing: missing, | ||||||
| 			loops: loops, | 			loops: loops, | ||||||
| 			filtered_out: filtered_out, | 			conflicts: conflicts, | ||||||
| 			disabled: disabled, | 			sort_loop_error: loop_limit <= 0, | ||||||
|  | 
 | ||||||
|  | 			//features: features,
 | ||||||
|  | 			//rev_features: rev_features,
 | ||||||
|  | 			//exclusive: exclusive,
 | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user