You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							80 lines
						
					
					
						
							2.1 KiB
						
					
					
				
			
		
		
	
	
							80 lines
						
					
					
						
							2.1 KiB
						
					
					
				module.exports = sortByProcedure; | 
						|
 | 
						|
/* | 
						|
	sort the parts of the passed selector, | 
						|
	as there is potential for optimization | 
						|
	(some types of selectors are faster than others) | 
						|
*/ | 
						|
 | 
						|
var procedure = require("./procedure.json"); | 
						|
 | 
						|
var attributes = { | 
						|
    __proto__: null, | 
						|
    exists: 10, | 
						|
    equals: 8, | 
						|
    not: 7, | 
						|
    start: 6, | 
						|
    end: 6, | 
						|
    any: 5, | 
						|
    hyphen: 4, | 
						|
    element: 4 | 
						|
}; | 
						|
 | 
						|
function sortByProcedure(arr) { | 
						|
    var procs = arr.map(getProcedure); | 
						|
    for (var i = 1; i < arr.length; i++) { | 
						|
        var procNew = procs[i]; | 
						|
 | 
						|
        if (procNew < 0) continue; | 
						|
 | 
						|
        for (var j = i - 1; j >= 0 && procNew < procs[j]; j--) { | 
						|
            var token = arr[j + 1]; | 
						|
            arr[j + 1] = arr[j]; | 
						|
            arr[j] = token; | 
						|
            procs[j + 1] = procs[j]; | 
						|
            procs[j] = procNew; | 
						|
        } | 
						|
    } | 
						|
} | 
						|
 | 
						|
function getProcedure(token) { | 
						|
    var proc = procedure[token.type]; | 
						|
 | 
						|
    if (proc === procedure.attribute) { | 
						|
        proc = attributes[token.action]; | 
						|
 | 
						|
        if (proc === attributes.equals && token.name === "id") { | 
						|
            //prefer ID selectors (eg. #ID) | 
						|
            proc = 9; | 
						|
        } | 
						|
 | 
						|
        if (token.ignoreCase) { | 
						|
            //ignoreCase adds some overhead, prefer "normal" token | 
						|
            //this is a binary operation, to ensure it's still an int | 
						|
            proc >>= 1; | 
						|
        } | 
						|
    } else if (proc === procedure.pseudo) { | 
						|
        if (!token.data) { | 
						|
            proc = 3; | 
						|
        } else if (token.name === "has" || token.name === "contains") { | 
						|
            proc = 0; //expensive in any case | 
						|
        } else if (token.name === "matches" || token.name === "not") { | 
						|
            proc = 0; | 
						|
            for (var i = 0; i < token.data.length; i++) { | 
						|
                //TODO better handling of complex selectors | 
						|
                if (token.data[i].length !== 1) continue; | 
						|
                var cur = getProcedure(token.data[i][0]); | 
						|
                //avoid executing :has or :contains | 
						|
                if (cur === 0) { | 
						|
                    proc = 0; | 
						|
                    break; | 
						|
                } | 
						|
                if (cur > proc) proc = cur; | 
						|
            } | 
						|
            if (token.data.length > 1 && proc > 0) proc -= 1; | 
						|
        } else { | 
						|
            proc = 1; | 
						|
        } | 
						|
    } | 
						|
    return proc; | 
						|
}
 | 
						|
 |