1 | "use strict";
|
---|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
3 | var procedure_1 = require("./procedure");
|
---|
4 | var attributes = {
|
---|
5 | exists: 10,
|
---|
6 | equals: 8,
|
---|
7 | not: 7,
|
---|
8 | start: 6,
|
---|
9 | end: 6,
|
---|
10 | any: 5,
|
---|
11 | hyphen: 4,
|
---|
12 | element: 4,
|
---|
13 | };
|
---|
14 | /**
|
---|
15 | * Sort the parts of the passed selector,
|
---|
16 | * as there is potential for optimization
|
---|
17 | * (some types of selectors are faster than others)
|
---|
18 | *
|
---|
19 | * @param arr Selector to sort
|
---|
20 | */
|
---|
21 | function sortByProcedure(arr) {
|
---|
22 | var procs = arr.map(getProcedure);
|
---|
23 | for (var i = 1; i < arr.length; i++) {
|
---|
24 | var procNew = procs[i];
|
---|
25 | if (procNew < 0)
|
---|
26 | continue;
|
---|
27 | for (var j = i - 1; j >= 0 && procNew < procs[j]; j--) {
|
---|
28 | var token = arr[j + 1];
|
---|
29 | arr[j + 1] = arr[j];
|
---|
30 | arr[j] = token;
|
---|
31 | procs[j + 1] = procs[j];
|
---|
32 | procs[j] = procNew;
|
---|
33 | }
|
---|
34 | }
|
---|
35 | }
|
---|
36 | exports.default = sortByProcedure;
|
---|
37 | function getProcedure(token) {
|
---|
38 | var proc = procedure_1.procedure[token.type];
|
---|
39 | if (token.type === "attribute") {
|
---|
40 | proc = attributes[token.action];
|
---|
41 | if (proc === attributes.equals && token.name === "id") {
|
---|
42 | // Prefer ID selectors (eg. #ID)
|
---|
43 | proc = 9;
|
---|
44 | }
|
---|
45 | if (token.ignoreCase) {
|
---|
46 | /*
|
---|
47 | * IgnoreCase adds some overhead, prefer "normal" token
|
---|
48 | * this is a binary operation, to ensure it's still an int
|
---|
49 | */
|
---|
50 | proc >>= 1;
|
---|
51 | }
|
---|
52 | }
|
---|
53 | else if (token.type === "pseudo") {
|
---|
54 | if (!token.data) {
|
---|
55 | proc = 3;
|
---|
56 | }
|
---|
57 | else if (token.name === "has" || token.name === "contains") {
|
---|
58 | proc = 0; // Expensive in any case
|
---|
59 | }
|
---|
60 | else if (Array.isArray(token.data)) {
|
---|
61 | // "matches" and "not"
|
---|
62 | proc = 0;
|
---|
63 | for (var i = 0; i < token.data.length; i++) {
|
---|
64 | // TODO better handling of complex selectors
|
---|
65 | if (token.data[i].length !== 1)
|
---|
66 | continue;
|
---|
67 | var cur = getProcedure(token.data[i][0]);
|
---|
68 | // Avoid executing :has or :contains
|
---|
69 | if (cur === 0) {
|
---|
70 | proc = 0;
|
---|
71 | break;
|
---|
72 | }
|
---|
73 | if (cur > proc)
|
---|
74 | proc = cur;
|
---|
75 | }
|
---|
76 | if (token.data.length > 1 && proc > 0)
|
---|
77 | proc -= 1;
|
---|
78 | }
|
---|
79 | else {
|
---|
80 | proc = 1;
|
---|
81 | }
|
---|
82 | }
|
---|
83 | return proc;
|
---|
84 | }
|
---|