sort.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. }