diff --git a/source/changelog.lisp b/source/changelog.lisp index d0b370e2347..a549dd5fd32 100644 --- a/source/changelog.lisp +++ b/source/changelog.lisp @@ -100,7 +100,9 @@ elements are scaled accordingly.") (:nsection :title "Bug fixes" (:ul (:li "Fix crash on " (:a :href (nyxt-url 'common-settings) ".")) - (:li "Fix warnings raised by " (:nxref :command 'pick-color) ".")))) + (:li "Fix warnings raised by " (:nxref :command 'pick-color) ".") + (:li "Fix " (:nxref :class-name 'nyxt/mode/hint:hint-mode) + " performance issues caused by " (:code "Shadow DOMs") " hinting algorithm.")))) (define-version "3.11.5" (:nsection :title "Bug fixes" diff --git a/source/mode/hint.lisp b/source/mode/hint.lisp index 85569f3e987..fa68aea2356 100644 --- a/source/mode/hint.lisp +++ b/source/mode/hint.lisp @@ -154,7 +154,7 @@ A positive value shifts to the bottom.") (style (ps:new (|CSSStyleSheet|))) (hints (ps:lisp (list 'quote hints))) (i 0)) - (dolist (hinted-element (nyxt/ps:qsa document "[nyxt-hintable]")) + (dolist (hinted-element (nyxt/ps:rqsa document "[nyxt-hintable]")) (let ((hint (aref hints i))) (ps:chain hinted-element (set-attribute "nyxt-hint" hint)) (ps:chain shadow (append-child (create-hint-overlay hinted-element hint))) @@ -196,14 +196,14 @@ A positive value shifts to the bottom.") alphabet)))))) (define-parenscript set-hintable-attribute (selector) - (ps:dolist (element (nyxt/ps:qsa document (ps:lisp selector))) + (ps:dolist (element (nyxt/ps:rqsa document (ps:lisp selector))) (if (ps:lisp (eq :vi (hinting-type (find-submode 'hint-mode)))) (when (nyxt/ps:element-in-view-port-p element) (ps:chain element (set-attribute "nyxt-hintable" ""))) (ps:chain element (set-attribute "nyxt-hintable" ""))))) (define-parenscript remove-hintable-attribute () - (ps:dolist (element (nyxt/ps:qsa document "[nyxt-hintable]")) + (ps:dolist (element (nyxt/ps:rqsa document "[nyxt-hintable]")) (ps:chain element (remove-attribute "nyxt-hintable")))) (defun add-hints (&key selector (buffer (current-buffer))) @@ -224,7 +224,7 @@ A positive value shifts to the bottom.") (ps:when hints-parent (ps:chain hints-parent (remove)))) (when (ps:lisp (show-hint-scope-p (find-submode 'hint-mode))) - (ps:dolist (element (nyxt/ps:qsa document ".nyxt-element-hint")) + (ps:dolist (element (nyxt/ps:rqsa document ".nyxt-element-hint")) (ps:chain element class-list (remove "nyxt-element-hint"))))) (defun remove-hints (&key (buffer (current-buffer))) diff --git a/source/parenscript-macro.lisp b/source/parenscript-macro.lisp index 141567682af..cb7fe9658fa 100644 --- a/source/parenscript-macro.lisp +++ b/source/parenscript-macro.lisp @@ -36,15 +36,16 @@ "Recursive version of `qs-nyxt-id` which goes through Shadow DOMs if there's at least one." `(flet ((recursive-query-selector (context selector) - (let ((node (qs context selector))) - (if node - node - (let ((node-iterator (chain document (create-node-iterator context (@ *node #:|ELEMENT_NODE|)))) - current-node) - (loop while (and (setf current-node (chain node-iterator (next-node))) (not node)) - do (when (@ current-node shadow-root) - (setf node (recursive-query-selector (@ current-node shadow-root) selector)))) - node))))) + (let ((node (qs context selector)) + (shadow-roots (chain *array (from (qsa context "[nyxt-shadow-root]")))) + shadow-root) + (do ((i 0 (1+ i))) + ((or node + (>= i (chain shadow-roots length)))) + (setf shadow-root (chain (elt shadow-roots i) shadow-root)) + (chain shadow-roots push (apply shadow-roots (chain *array (from (qsa shadow-root "[nyxt-shadow-root]"))))) + (setf node (qs shadow-root selector))) + node))) (if (chain ,context (query-selector "[nyxt-shadow-root]")) (recursive-query-selector ,context (stringify "[nyxt-identifier=\"" ,id "\"]")) (qs-nyxt-id ,context ,id)))) @@ -205,13 +206,15 @@ at least one." "Recursive version of context.querySelectorAll() which goes through Shadow DOMs if there's at least one." `(flet ((recursive-query-selector-all (context selector) - (ps:let ((nodes (ps:chain *array (from (nyxt/ps:qsa context selector)))) - (node-iterator (ps:chain document (create-node-iterator context (ps:@ *node #:|ELEMENT_NODE|)))) - current-node) - (ps:loop while (ps:setf current-node (ps:chain node-iterator (next-node))) - do (ps:when (ps:@ current-node shadow-root) - (ps:chain *array prototype push (apply nodes (recursive-query-selector-all (ps:@ current-node shadow-root) selector))))) - nodes))) + (ps:let ((tree-walker (ps:chain document (create-tree-walker context (ps:@ *Node +element_node+)))) + (results (array))) + (ps:loop while (ps:chain tree-walker (next-node)) + do (when (ps:chain tree-walker current-node (matches selector)) + (ps:chain results (push (ps:@ tree-walker current-node)))) + (let ((shadow-root (ps:@ tree-walker current-node shadow-root))) + (when shadow-root + (ps:chain *array prototype push (apply results (recursive-query-selector-all shadow-root selector)))))) + results))) (if (chain ,context (query-selector "[nyxt-shadow-root]")) (recursive-query-selector-all ,context ,selector) (qsa ,context ,selector))))