@@ -697,17 +697,27 @@ ExLazyHTML query(ErlNifEnv *env, ExLazyHTML ex_lazy_html,
697697 LXB_SELECTORS_OPT_MATCH_ROOT ));
698698
699699 auto nodes = std::vector<lxb_dom_node_t *>();
700+ auto inserted_nodes = std::unordered_set<lxb_dom_node_t *>();
701+
702+ struct FindCtx {
703+ std::vector<lxb_dom_node_t *> *nodes;
704+ std::unordered_set<lxb_dom_node_t *> *inserted_nodes;
705+ };
706+
707+ auto ctx = FindCtx{&nodes, &inserted_nodes};
700708
701709 for (auto node : ex_lazy_html.resource ->nodes ) {
702710 status = lxb_selectors_find (
703711 selectors, node, css_selector_list,
704712 [](lxb_dom_node_t *node, lxb_css_selector_specificity_t spec,
705713 void *ctx) -> lxb_status_t {
706- auto nodes_ptr = static_cast <std::vector<lxb_dom_node_t *> *>(ctx);
707- nodes_ptr->push_back (node);
714+ auto find_ctx = static_cast <FindCtx *>(ctx);
715+ if (find_ctx->inserted_nodes ->insert (node).second ) {
716+ find_ctx->nodes ->push_back (node);
717+ }
708718 return LXB_STATUS_OK ;
709719 },
710- &nodes );
720+ &ctx );
711721 if (status != LXB_STATUS_OK ) {
712722 throw std::runtime_error (" failed to run find" );
713723 }
@@ -789,22 +799,31 @@ bool matches_id(lxb_dom_node_t *node, ErlNifBinary *id) {
789799ExLazyHTML query_by_id (ErlNifEnv *env, ExLazyHTML ex_lazy_html,
790800 ErlNifBinary id) {
791801 auto nodes = std::vector<lxb_dom_node_t *>();
802+ auto seen = std::unordered_set<lxb_dom_node_t *>();
792803
793- auto ctx = std::make_tuple (&nodes, &id);
804+ struct WalkCtx {
805+ std::vector<lxb_dom_node_t *> *nodes;
806+ std::unordered_set<lxb_dom_node_t *> *seen;
807+ ErlNifBinary *id;
808+ };
809+
810+ auto ctx = WalkCtx{&nodes, &seen, &id};
794811
795812 for (auto node : ex_lazy_html.resource ->nodes ) {
796813 if (matches_id (node, &id)) {
797- nodes.push_back (node);
814+ if (seen.insert (node).second ) {
815+ nodes.push_back (node);
816+ }
798817 }
799818
800819 lxb_dom_node_simple_walk (
801820 node,
802821 [](lxb_dom_node_t *node, void *ctx) -> lexbor_action_t {
803- auto [nodes_ptr, id_ptr] = * static_cast <
804- std::tuple<std::vector< lxb_dom_node_t *> *, ErlNifBinary *> *>(
805- ctx);
806- if ( matches_id ( node, id_ptr)) {
807- nodes_ptr-> push_back (node);
822+ auto walk_ctx = static_cast <WalkCtx *>(ctx);
823+ if ( matches_id (node, walk_ctx-> id )) {
824+ if (walk_ctx-> seen -> insert (node). second ) {
825+ walk_ctx-> nodes -> push_back ( node);
826+ }
808827 }
809828
810829 return LEXBOR_ACTION_OK ;
@@ -843,9 +862,7 @@ ExLazyHTML parent_node(ErlNifEnv *env, ExLazyHTML ex_lazy_html) {
843862 auto parent = lxb_dom_node_parent (node);
844863 if (parent != NULL && parent->type == LXB_DOM_NODE_TYPE_ELEMENT &&
845864 (is_document || !lxb_html_tree_node_is (parent, LXB_TAG_HTML ))) {
846- auto inserted_node = inserted_nodes.find (parent);
847- if (inserted_node == inserted_nodes.end ()) {
848- inserted_nodes.insert (parent);
865+ if (inserted_nodes.insert (parent).second ) {
849866 nodes.push_back (parent);
850867 }
851868 }
0 commit comments