mirror of https://github.com/webpack/webpack.git
				
				
				
			Merge pull request #4291 from Tushkiz/refactor-ruleset-to-es6
migrate 'lib/RuleSet.js' to es6
This commit is contained in:
		
						commit
						8b0b7aa64c
					
				
							
								
								
									
										621
									
								
								lib/RuleSet.js
								
								
								
								
							
							
						
						
									
										621
									
								
								lib/RuleSet.js
								
								
								
								
							|  | @ -69,277 +69,338 @@ normalized: | |||
| } | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| function RuleSet(rules) { | ||||
| 	this.references = Object.create(null); | ||||
| 	this.rules = RuleSet.normalizeRules(rules, this.references, "ref-"); | ||||
| } | ||||
| module.exports = class RuleSet { | ||||
| 	constructor(rules) { | ||||
| 		this.references = Object.create(null); | ||||
| 		this.rules = RuleSet.normalizeRules(rules, this.references, "ref-"); | ||||
| 	} | ||||
| 
 | ||||
| module.exports = RuleSet; | ||||
| 	static normalizeRules(rules, refs, ident) { | ||||
| 		if(Array.isArray(rules)) { | ||||
| 			return rules.map((rule, idx) => { | ||||
| 				return RuleSet.normalizeRule(rule, refs, `${ident}-${idx}`); | ||||
| 			}); | ||||
| 		} else if(rules) { | ||||
| 			return [RuleSet.normalizeRule(rules, refs, ident)]; | ||||
| 		} else { | ||||
| 			return []; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| RuleSet.normalizeRules = function(rules, refs, ident) { | ||||
| 	if(Array.isArray(rules)) { | ||||
| 		return rules.map(function(rule, idx) { | ||||
| 			return RuleSet.normalizeRule(rule, refs, `${ident}-${idx}`); | ||||
| 	static normalizeRule(rule, refs, ident) { | ||||
| 		if(typeof rule === "string") | ||||
| 			return { | ||||
| 				use: [{ | ||||
| 					loader: rule | ||||
| 				}] | ||||
| 			}; | ||||
| 		if(!rule) | ||||
| 			throw new Error("Unexcepted null when object was expected as rule"); | ||||
| 		if(typeof rule !== "object") | ||||
| 			throw new Error("Unexcepted " + typeof rule + " when object was expected as rule (" + rule + ")"); | ||||
| 
 | ||||
| 		let newRule = {}; | ||||
| 		let useSource; | ||||
| 		let resourceSource; | ||||
| 		let condition; | ||||
| 
 | ||||
| 		if(rule.test || rule.include || rule.exclude) { | ||||
| 			checkResourceSource("test + include + exclude"); | ||||
| 			condition = { | ||||
| 				test: rule.test, | ||||
| 				include: rule.include, | ||||
| 				exclude: rule.exclude | ||||
| 			}; | ||||
| 			try { | ||||
| 				newRule.resource = RuleSet.normalizeCondition(condition); | ||||
| 			} catch(error) { | ||||
| 				throw new Error(RuleSet.buildErrorMessage(condition, error)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.resource) { | ||||
| 			checkResourceSource("resource"); | ||||
| 			try { | ||||
| 				newRule.resource = RuleSet.normalizeCondition(rule.resource); | ||||
| 			} catch(error) { | ||||
| 				throw new Error(RuleSet.buildErrorMessage(rule.resource, error)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.resourceQuery) { | ||||
| 			try { | ||||
| 				newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery); | ||||
| 			} catch(error) { | ||||
| 				throw new Error(RuleSet.buildErrorMessage(rule.resourceQuery, error)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.issuer) { | ||||
| 			try { | ||||
| 				newRule.issuer = RuleSet.normalizeCondition(rule.issuer); | ||||
| 			} catch(error) { | ||||
| 				throw new Error(RuleSet.buildErrorMessage(rule.issuer, error)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.loader && rule.loaders) | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule, new Error("Provided loader and loaders for rule (use only one of them)"))); | ||||
| 
 | ||||
| 		const loader = rule.loaders || rule.loader; | ||||
| 		if(typeof loader === "string" && !rule.options && !rule.query) { | ||||
| 			checkUseSource("loader"); | ||||
| 			newRule.use = RuleSet.normalizeUse(loader.split("!"), ident); | ||||
| 		} else if(typeof loader === "string" && (rule.options || rule.query)) { | ||||
| 			checkUseSource("loader + options/query"); | ||||
| 			newRule.use = RuleSet.normalizeUse({ | ||||
| 				loader: loader, | ||||
| 				options: rule.options, | ||||
| 				query: rule.query | ||||
| 			}, ident); | ||||
| 		} else if(loader && (rule.options || rule.query)) { | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query cannot be used with loaders (use options for each array item)"))); | ||||
| 		} else if(loader) { | ||||
| 			checkUseSource("loaders"); | ||||
| 			newRule.use = RuleSet.normalizeUse(loader, ident); | ||||
| 		} else if(rule.options || rule.query) { | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query provided without loader (use loader + options)"))); | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.use) { | ||||
| 			checkUseSource("use"); | ||||
| 			newRule.use = RuleSet.normalizeUse(rule.use, ident); | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.rules) | ||||
| 			newRule.rules = RuleSet.normalizeRules(rule.rules, refs, `${ident}-rules`); | ||||
| 
 | ||||
| 		if(rule.oneOf) | ||||
| 			newRule.oneOf = RuleSet.normalizeRules(rule.oneOf, refs, `${ident}-oneOf`); | ||||
| 
 | ||||
| 		const keys = Object.keys(rule).filter((key) => { | ||||
| 			return ["resource", "resourceQuery", "test", "include", "exclude", "issuer", "loader", "options", "query", "loaders", "use", "rules", "oneOf"].indexOf(key) < 0; | ||||
| 		}); | ||||
| 		keys.forEach((key) => { | ||||
| 			newRule[key] = rule[key]; | ||||
| 		}); | ||||
| 	} else if(rules) { | ||||
| 		return [RuleSet.normalizeRule(rules, refs, ident)]; | ||||
| 	} else { | ||||
| 		return []; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| RuleSet.normalizeRule = function(rule, refs, ident) { | ||||
| 	if(typeof rule === "string") | ||||
| 		function checkUseSource(newSource) { | ||||
| 			if(useSource && useSource !== newSource) | ||||
| 				throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one result source (provided " + newSource + " and " + useSource + ")"))); | ||||
| 			useSource = newSource; | ||||
| 		} | ||||
| 
 | ||||
| 		function checkResourceSource(newSource) { | ||||
| 			if(resourceSource && resourceSource !== newSource) | ||||
| 				throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one resource source (provided " + newSource + " and " + resourceSource + ")"))); | ||||
| 			resourceSource = newSource; | ||||
| 		} | ||||
| 
 | ||||
| 		if(Array.isArray(newRule.use)) { | ||||
| 			newRule.use.forEach((item) => { | ||||
| 				if(item.ident) { | ||||
| 					refs[item.ident] = item.options; | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		return newRule; | ||||
| 	} | ||||
| 
 | ||||
| 	static buildErrorMessage(condition, error) { | ||||
| 		const conditionAsText = JSON.stringify(condition, (key, value) => { | ||||
| 			return value === undefined ? "undefined" : value; | ||||
| 		}, 2); | ||||
| 		return error.message + " in " + conditionAsText; | ||||
| 	} | ||||
| 
 | ||||
| 	static normalizeUse(use, ident) { | ||||
| 		if(Array.isArray(use)) { | ||||
| 			return use | ||||
| 				.map((item, idx) => RuleSet.normalizeUse(item, `${ident}-${idx}`)) | ||||
| 				.reduce((arr, items) => arr.concat(items), []); | ||||
| 		} | ||||
| 		return [RuleSet.normalizeUseItem(use, ident)]; | ||||
| 	} | ||||
| 
 | ||||
| 	static normalizeUseItemFunction(use, data) { | ||||
| 		const result = use(data); | ||||
| 		if(typeof result === "string") { | ||||
| 			return RuleSet.normalizeUseItem(result); | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	static normalizeUseItemString(useItemString) { | ||||
| 		const idx = useItemString.indexOf("?"); | ||||
| 		if(idx >= 0) { | ||||
| 			return { | ||||
| 				loader: useItemString.substr(0, idx), | ||||
| 				options: useItemString.substr(idx + 1) | ||||
| 			}; | ||||
| 		} | ||||
| 		return { | ||||
| 			use: [{ | ||||
| 				loader: rule | ||||
| 			}] | ||||
| 			loader: useItemString | ||||
| 		}; | ||||
| 	if(!rule) | ||||
| 		throw new Error("Unexcepted null when object was expected as rule"); | ||||
| 	if(typeof rule !== "object") | ||||
| 		throw new Error("Unexcepted " + typeof rule + " when object was expected as rule (" + rule + ")"); | ||||
| 	} | ||||
| 
 | ||||
| 	var newRule = {}; | ||||
| 	var useSource; | ||||
| 	var resourceSource; | ||||
| 	var condition; | ||||
| 	static normalizeUseItem(item, ident) { | ||||
| 		if(typeof item === "function") | ||||
| 			return item; | ||||
| 
 | ||||
| 	if(rule.test || rule.include || rule.exclude) { | ||||
| 		checkResourceSource("test + include + exclude"); | ||||
| 		condition = { | ||||
| 			test: rule.test, | ||||
| 			include: rule.include, | ||||
| 			exclude: rule.exclude | ||||
| 		}; | ||||
| 		try { | ||||
| 			newRule.resource = RuleSet.normalizeCondition(condition); | ||||
| 		} catch(error) { | ||||
| 			throw new Error(RuleSet.buildErrorMessage(condition, error)); | ||||
| 		if(typeof item === "string") { | ||||
| 			return RuleSet.normalizeUseItemString(item); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if(rule.resource) { | ||||
| 		checkResourceSource("resource"); | ||||
| 		try { | ||||
| 			newRule.resource = RuleSet.normalizeCondition(rule.resource); | ||||
| 		} catch(error) { | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule.resource, error)); | ||||
| 		let newItem = {}; | ||||
| 
 | ||||
| 		if(item.options && item.query) | ||||
| 			throw new Error("Provided options and query in use"); | ||||
| 
 | ||||
| 		if(!item.loader) | ||||
| 			throw new Error("No loader specified"); | ||||
| 
 | ||||
| 		newItem.options = item.options || item.query; | ||||
| 
 | ||||
| 		if(typeof newItem.options === "object" && newItem.options) { | ||||
| 			if(newItem.options.ident) | ||||
| 				newItem.ident = newItem.options.ident; | ||||
| 			else | ||||
| 				newItem.ident = ident; | ||||
| 		} | ||||
| 
 | ||||
| 		const keys = Object.keys(item).filter(function(key) { | ||||
| 			return ["options", "query"].indexOf(key) < 0; | ||||
| 		}); | ||||
| 
 | ||||
| 		keys.forEach(function(key) { | ||||
| 			newItem[key] = item[key]; | ||||
| 		}); | ||||
| 
 | ||||
| 		return newItem; | ||||
| 	} | ||||
| 
 | ||||
| 	if(rule.resourceQuery) { | ||||
| 		try { | ||||
| 			newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery); | ||||
| 		} catch(error) { | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule.resourceQuery, error)); | ||||
| 	static normalizeCondition(condition) { | ||||
| 		if(!condition) | ||||
| 			throw new Error("Expected condition but got falsy value"); | ||||
| 		if(typeof condition === "string") { | ||||
| 			return str => str.indexOf(condition) === 0; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if(rule.issuer) { | ||||
| 		try { | ||||
| 			newRule.issuer = RuleSet.normalizeCondition(rule.issuer); | ||||
| 		} catch(error) { | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule.issuer, error)); | ||||
| 		if(typeof condition === "function") { | ||||
| 			return condition; | ||||
| 		} | ||||
| 	} | ||||
| 		if(condition instanceof RegExp) { | ||||
| 			return condition.test.bind(condition); | ||||
| 		} | ||||
| 		if(Array.isArray(condition)) { | ||||
| 			const items = condition.map(c => RuleSet.normalizeCondition(c)); | ||||
| 			return orMatcher(items); | ||||
| 		} | ||||
| 		if(typeof condition !== "object") | ||||
| 			throw Error("Unexcepted " + typeof condition + " when condition was expected (" + condition + ")"); | ||||
| 
 | ||||
| 	if(rule.loader && rule.loaders) | ||||
| 		throw new Error(RuleSet.buildErrorMessage(rule, new Error("Provided loader and loaders for rule (use only one of them)"))); | ||||
| 
 | ||||
| 	var loader = rule.loaders || rule.loader; | ||||
| 	if(typeof loader === "string" && !rule.options && !rule.query) { | ||||
| 		checkUseSource("loader"); | ||||
| 		newRule.use = RuleSet.normalizeUse(loader.split("!"), ident); | ||||
| 	} else if(typeof loader === "string" && (rule.options || rule.query)) { | ||||
| 		checkUseSource("loader + options/query"); | ||||
| 		newRule.use = RuleSet.normalizeUse({ | ||||
| 			loader: loader, | ||||
| 			options: rule.options, | ||||
| 			query: rule.query | ||||
| 		}, ident); | ||||
| 	} else if(loader && (rule.options || rule.query)) { | ||||
| 		throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query cannot be used with loaders (use options for each array item)"))); | ||||
| 	} else if(loader) { | ||||
| 		checkUseSource("loaders"); | ||||
| 		newRule.use = RuleSet.normalizeUse(loader, ident); | ||||
| 	} else if(rule.options || rule.query) { | ||||
| 		throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query provided without loader (use loader + options)"))); | ||||
| 	} | ||||
| 
 | ||||
| 	if(rule.use) { | ||||
| 		checkUseSource("use"); | ||||
| 		newRule.use = RuleSet.normalizeUse(rule.use, ident); | ||||
| 	} | ||||
| 
 | ||||
| 	if(rule.rules) | ||||
| 		newRule.rules = RuleSet.normalizeRules(rule.rules, refs, `${ident}-rules`); | ||||
| 
 | ||||
| 	if(rule.oneOf) | ||||
| 		newRule.oneOf = RuleSet.normalizeRules(rule.oneOf, refs, `${ident}-oneOf`); | ||||
| 
 | ||||
| 	var keys = Object.keys(rule).filter(function(key) { | ||||
| 		return ["resource", "resourceQuery", "test", "include", "exclude", "issuer", "loader", "options", "query", "loaders", "use", "rules", "oneOf"].indexOf(key) < 0; | ||||
| 	}); | ||||
| 	keys.forEach(function(key) { | ||||
| 		newRule[key] = rule[key]; | ||||
| 	}); | ||||
| 
 | ||||
| 	function checkUseSource(newSource) { | ||||
| 		if(useSource && useSource !== newSource) | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one result source (provided " + newSource + " and " + useSource + ")"))); | ||||
| 		useSource = newSource; | ||||
| 	} | ||||
| 
 | ||||
| 	function checkResourceSource(newSource) { | ||||
| 		if(resourceSource && resourceSource !== newSource) | ||||
| 			throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one resource source (provided " + newSource + " and " + resourceSource + ")"))); | ||||
| 		resourceSource = newSource; | ||||
| 	} | ||||
| 
 | ||||
| 	if(Array.isArray(newRule.use)) { | ||||
| 		newRule.use.forEach(function(item) { | ||||
| 			if(item.ident) { | ||||
| 				refs[item.ident] = item.options; | ||||
| 		let matchers = []; | ||||
| 		Object.keys(condition).forEach(key => { | ||||
| 			const value = condition[key]; | ||||
| 			switch(key) { | ||||
| 				case "or": | ||||
| 				case "include": | ||||
| 				case "test": | ||||
| 					if(value) | ||||
| 						matchers.push(RuleSet.normalizeCondition(value)); | ||||
| 					break; | ||||
| 				case "and": | ||||
| 					if(value) { | ||||
| 						const items = value.map(c => RuleSet.normalizeCondition(c)); | ||||
| 						matchers.push(andMatcher(items)); | ||||
| 					} | ||||
| 					break; | ||||
| 				case "not": | ||||
| 				case "exclude": | ||||
| 					if(value) { | ||||
| 						const matcher = RuleSet.normalizeCondition(value); | ||||
| 						matchers.push(notMatcher(matcher)); | ||||
| 					} | ||||
| 					break; | ||||
| 				default: | ||||
| 					throw new Error("Unexcepted property " + key + " in condition"); | ||||
| 			} | ||||
| 		}); | ||||
| 		if(matchers.length === 0) | ||||
| 			throw new Error("Excepted condition but got " + condition); | ||||
| 		if(matchers.length === 1) | ||||
| 			return matchers[0]; | ||||
| 		return andMatcher(matchers); | ||||
| 	} | ||||
| 
 | ||||
| 	return newRule; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.buildErrorMessage = function buildErrorMessage(condition, error) { | ||||
| 	var conditionAsText = JSON.stringify(condition, function(key, value) { | ||||
| 		return value === undefined ? "undefined" : value; | ||||
| 	}, 2); | ||||
| 	var message = error.message + " in " + conditionAsText; | ||||
| 	return message; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.normalizeUse = function normalizeUse(use, ident) { | ||||
| 	if(Array.isArray(use)) { | ||||
| 		return use.map((item, idx) => RuleSet.normalizeUse(item, `${ident}-${idx}`)).reduce(function(arr, items) { | ||||
| 			return arr.concat(items); | ||||
| 		}, []); | ||||
| 	} | ||||
| 	return [RuleSet.normalizeUseItem(use, ident)]; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.normalizeUseItemFunction = function normalizeUseItemFunction(use, data) { | ||||
| 	var result = use(data); | ||||
| 	if(typeof result === "string") { | ||||
| 		return RuleSet.normalizeUseItem(result); | ||||
| 	} | ||||
| 	return result; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.normalizeUseItemString = function normalizeUseItemString(useItemString) { | ||||
| 	var idx = useItemString.indexOf("?"); | ||||
| 	if(idx >= 0) { | ||||
| 		return { | ||||
| 			loader: useItemString.substr(0, idx), | ||||
| 			options: useItemString.substr(idx + 1) | ||||
| 		}; | ||||
| 	} | ||||
| 	return { | ||||
| 		loader: useItemString | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.normalizeUseItem = function normalizeUseItem(item, ident) { | ||||
| 	if(typeof item === "function") | ||||
| 		return item; | ||||
| 
 | ||||
| 	if(typeof item === "string") { | ||||
| 		return RuleSet.normalizeUseItemString(item); | ||||
| 	exec(data) { | ||||
| 		const result = []; | ||||
| 		this._run(data, { | ||||
| 			rules: this.rules | ||||
| 		}, result); | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	var newItem = {}; | ||||
| 	_run(data, rule, result) { | ||||
| 		// test conditions
 | ||||
| 		if(rule.resource && !data.resource) | ||||
| 			return false; | ||||
| 		if(rule.resourceQuery && !data.resourceQuery) | ||||
| 			return false; | ||||
| 		if(rule.issuer && !data.issuer) | ||||
| 			return false; | ||||
| 		if(rule.resource && !rule.resource(data.resource)) | ||||
| 			return false; | ||||
| 		if(data.issuer && rule.issuer && !rule.issuer(data.issuer)) | ||||
| 			return false; | ||||
| 		if(data.resourceQuery && rule.resourceQuery && !rule.resourceQuery(data.resourceQuery)) | ||||
| 			return false; | ||||
| 
 | ||||
| 	if(item.options && item.query) | ||||
| 		throw new Error("Provided options and query in use"); | ||||
| 
 | ||||
| 	if(!item.loader) | ||||
| 		throw new Error("No loader specified"); | ||||
| 
 | ||||
| 	newItem.options = item.options || item.query; | ||||
| 
 | ||||
| 	if(typeof newItem.options === "object" && newItem.options) { | ||||
| 		if(newItem.options.ident) | ||||
| 			newItem.ident = newItem.options.ident; | ||||
| 		else | ||||
| 			newItem.ident = ident; | ||||
| 	} | ||||
| 
 | ||||
| 	var keys = Object.keys(item).filter(function(key) { | ||||
| 		return ["options", "query"].indexOf(key) < 0; | ||||
| 	}); | ||||
| 
 | ||||
| 	keys.forEach(function(key) { | ||||
| 		newItem[key] = item[key]; | ||||
| 	}); | ||||
| 
 | ||||
| 	return newItem; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.normalizeCondition = function normalizeCondition(condition) { | ||||
| 	if(!condition) | ||||
| 		throw new Error("Expected condition but got falsy value"); | ||||
| 	if(typeof condition === "string") { | ||||
| 		return function(str) { | ||||
| 			return str.indexOf(condition) === 0; | ||||
| 		}; | ||||
| 	} | ||||
| 	if(typeof condition === "function") { | ||||
| 		return condition; | ||||
| 	} | ||||
| 	if(condition instanceof RegExp) { | ||||
| 		return condition.test.bind(condition); | ||||
| 	} | ||||
| 	if(Array.isArray(condition)) { | ||||
| 		var items = condition.map(function(c) { | ||||
| 			return RuleSet.normalizeCondition(c); | ||||
| 		// apply
 | ||||
| 		const keys = Object.keys(rule).filter((key) => { | ||||
| 			return ["resource", "resourceQuery", "issuer", "rules", "oneOf", "use", "enforce"].indexOf(key) < 0; | ||||
| 		}); | ||||
| 		return orMatcher(items); | ||||
| 	} | ||||
| 	if(typeof condition !== "object") | ||||
| 		throw Error("Unexcepted " + typeof condition + " when condition was expected (" + condition + ")"); | ||||
| 	var matchers = []; | ||||
| 	Object.keys(condition).forEach(function(key) { | ||||
| 		var value = condition[key]; | ||||
| 		switch(key) { | ||||
| 			case "or": | ||||
| 			case "include": | ||||
| 			case "test": | ||||
| 				if(value) | ||||
| 					matchers.push(RuleSet.normalizeCondition(value)); | ||||
| 				break; | ||||
| 			case "and": | ||||
| 				if(value) { | ||||
| 					var items = value.map(function(c) { | ||||
| 						return RuleSet.normalizeCondition(c); | ||||
| 					}); | ||||
| 					matchers.push(andMatcher(items)); | ||||
| 				} | ||||
| 				break; | ||||
| 			case "not": | ||||
| 			case "exclude": | ||||
| 				if(value) { | ||||
| 					var matcher = RuleSet.normalizeCondition(value); | ||||
| 					matchers.push(notMatcher(matcher)); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				throw new Error("Unexcepted property " + key + " in condition"); | ||||
| 		keys.forEach((key) => { | ||||
| 			result.push({ | ||||
| 				type: key, | ||||
| 				value: rule[key] | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		if(rule.use) { | ||||
| 			rule.use.forEach((use) => { | ||||
| 				result.push({ | ||||
| 					type: "use", | ||||
| 					value: typeof use === "function" ? RuleSet.normalizeUseItemFunction(use, data) : use, | ||||
| 					enforce: rule.enforce | ||||
| 				}); | ||||
| 			}); | ||||
| 		} | ||||
| 	}); | ||||
| 	if(matchers.length === 0) | ||||
| 		throw new Error("Excepted condition but got " + condition); | ||||
| 	if(matchers.length === 1) | ||||
| 		return matchers[0]; | ||||
| 	return andMatcher(matchers); | ||||
| 
 | ||||
| 		if(rule.rules) { | ||||
| 			for(let i = 0; i < rule.rules.length; i++) { | ||||
| 				this._run(data, rule.rules[i], result); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if(rule.oneOf) { | ||||
| 			for(let i = 0; i < rule.oneOf.length; i++) { | ||||
| 				if(this._run(data, rule.oneOf[i], result)) | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	findOptionsByIdent(ident) { | ||||
| 		const options = this.references[ident]; | ||||
| 		if(!options) throw new Error("Can't find options with ident '" + ident + "'"); | ||||
| 		return options; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| function notMatcher(matcher) { | ||||
|  | @ -350,7 +411,7 @@ function notMatcher(matcher) { | |||
| 
 | ||||
| function orMatcher(items) { | ||||
| 	return function(str) { | ||||
| 		for(var i = 0; i < items.length; i++) { | ||||
| 		for(let i = 0; i < items.length; i++) { | ||||
| 			if(items[i](str)) | ||||
| 				return true; | ||||
| 		} | ||||
|  | @ -360,78 +421,10 @@ function orMatcher(items) { | |||
| 
 | ||||
| function andMatcher(items) { | ||||
| 	return function(str) { | ||||
| 		for(var i = 0; i < items.length; i++) { | ||||
| 		for(let i = 0; i < items.length; i++) { | ||||
| 			if(!items[i](str)) | ||||
| 				return false; | ||||
| 		} | ||||
| 		return true; | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| RuleSet.prototype.exec = function(data) { | ||||
| 	var result = []; | ||||
| 	this._run(data, { | ||||
| 		rules: this.rules | ||||
| 	}, result); | ||||
| 	return result; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.prototype._run = function _run(data, rule, result) { | ||||
| 	// test conditions
 | ||||
| 	if(rule.resource && !data.resource) | ||||
| 		return false; | ||||
| 	if(rule.resourceQuery && !data.resourceQuery) | ||||
| 		return false; | ||||
| 	if(rule.issuer && !data.issuer) | ||||
| 		return false; | ||||
| 	if(rule.resource && !rule.resource(data.resource)) | ||||
| 		return false; | ||||
| 	if(data.issuer && rule.issuer && !rule.issuer(data.issuer)) | ||||
| 		return false; | ||||
| 	if(data.resourceQuery && rule.resourceQuery && !rule.resourceQuery(data.resourceQuery)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	// apply
 | ||||
| 	var keys = Object.keys(rule).filter(function(key) { | ||||
| 		return ["resource", "resourceQuery", "issuer", "rules", "oneOf", "use", "enforce"].indexOf(key) < 0; | ||||
| 	}); | ||||
| 	keys.forEach(function(key) { | ||||
| 		result.push({ | ||||
| 			type: key, | ||||
| 			value: rule[key] | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	if(rule.use) { | ||||
| 		rule.use.forEach(function(use) { | ||||
| 			result.push({ | ||||
| 				type: "use", | ||||
| 				value: typeof use === "function" ? RuleSet.normalizeUseItemFunction(use, data) : use, | ||||
| 				enforce: rule.enforce | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	var i; | ||||
| 
 | ||||
| 	if(rule.rules) { | ||||
| 		for(i = 0; i < rule.rules.length; i++) { | ||||
| 			this._run(data, rule.rules[i], result); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if(rule.oneOf) { | ||||
| 		for(i = 0; i < rule.oneOf.length; i++) { | ||||
| 			if(this._run(data, rule.oneOf[i], result)) | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return true; | ||||
| }; | ||||
| 
 | ||||
| RuleSet.prototype.findOptionsByIdent = function findOptionsByIdent(ident) { | ||||
| 	var options = this.references[ident]; | ||||
| 	if(!options) throw new Error("Can't find options with ident '" + ident + "'"); | ||||
| 	return options; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue