unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#73204: Tree-sitter in clojure-ts-mode causes memory leak during parsing
@ 2024-09-12 16:21 vinurs
  2024-09-13  4:24 ` Yuan Fu
  0 siblings, 1 reply; 5+ messages in thread
From: vinurs @ 2024-09-12 16:21 UTC (permalink / raw)
  To: 73204


[-- Attachment #1.1: Type: text/plain, Size: 1647 bytes --]

Hi,

I am using the precompiled version from https://emacsformacosx.com/builds 

https://emacsformacosx.com/emacs-builds/Emacs-2024-09-11_00-09-10-69e1aca041c57ba425425d31471e1c8f86d3bf04-universal.dmg

I have chosen the latest Emacs 30 version. The min configuration is as follows:

(add-to-list 'treesit-extra-load-path (expand-file-name "tree-sitter/" user-emacs-directory))
(add-to-list 'load-path "~/.emacs.d/site-lisp/clojure-ts-mode”) 
(require 'clojure-ts-mode) 
 ;; debug 
(setq debug-on-quit t)

and I only use clojure-ts-mode package

cd ~/.emacs.d/site-lisp
git clone https://github.com/clojure-emacs/clojure-ts-mode.git

Then, after opening Emacs, 
I opened the attached file b.clj, moved to line 57, 
and entered the following characters: 
(comment

At this point, Emacs freezes and becomes unresponsive. I noticed that Emacs' memory usage keeps increasing:
2024-09-12 21:12:23: 806624 KB
2024-09-12 21:12:28: 810720 KB
2024-09-12 21:12:33: 829840 KB
2024-09-12 21:12:38: 1582256 KB
2024-09-12 21:12:43: 4678816 KB
2024-09-12 21:12:48: 7831776 KB
2024-09-12 21:12:53: 10982384 KB
2024-09-12 21:12:58: 14140048 KB
2024-09-12 21:13:03: 17296176 KB
2024-09-12 21:13:08: 20440960 KB
2024-09-12 21:13:13: 23583008 KB
2024-09-12 21:13:18: 26726272 KB
2024-09-12 21:13:24: 29857312 KB
2024-09-12 21:13:29: 33011456 KB
2024-09-12 21:13:34: 36156624 KB
2024-09-12 21:13:39: 38685440 KB
2024-09-12 21:13:44: 34858560 KB
2024-09-12 21:13:49: 30892768 KB

Then, Emacs eventually gets killed by the system.

The bt.log is the information I was able to retrieve

------------

Sincerely,

[-- Attachment #1.2: Type: text/html, Size: 3239 bytes --]

[-- Attachment #2: b.clj --]
[-- Type: application/octet-stream, Size: 17325 bytes --]

(ns server.app.web.routes.hotel-sync.elong
  (:refer-clojure :exclude [])
  (:require
   [clj-commons.digest :as digest]
   [clj-http.client :as http-client]
   [clojure.data.xml :as xml]
   [clojure.data.zip.xml :as zx]
   [clojure.java.io :as io]
   [clojure.string :as str]
   [clojure.tools.logging :as log]
   [clojure.zip :as zip]
   [jsonista.core :as json]
      [java-time.api :as java-time]

   [ring.util.http-response :as http-resp]
   [server.app.app-data :refer [dev-env? query-fn snip-fn]]
   [server.app.web.controllers.health :as health]
   [server.app.web.middleware.auth :as auth-middleware]
   [server.app.web.routes.custom-schemas :as custom-schemas]
   [server.app.web.routes.errcode :refer [app-errcodes default-resp err-info]]
   [server.app.web.routes.hotel-sync.dossen :refer [check-hotel-price-and-cnt]]
   [server.app.web.routes.errcode :refer [default-resp]])
  (:import
   [javax.xml.parsers DocumentBuilderFactory]))

;; 

(comment
  (log/info "hello")
  )
(defn xml->clj
  "将 XML 解析为 Clojure 的数据结构,保留层次结构、属性和重复标签。"
  [xml-str]
  (letfn [(parse-node [node]
            (let [tag (keyword (:tag node))
                  attrs (:attrs node)
                  children (filter map? (:content node))
                  text (first (filter string? (:content node)))
                  child-content (if (seq children)
                                  (if (apply = (map :tag children))
                                    (mapv parse-node children)
                                    (reduce (fn [m child]
                                              (let [child-tag (keyword (:tag child))
                                                    parsed-child (parse-node child)]
                                                (update m child-tag (fnil conj []) parsed-child)))
                                            {} children))
                                  nil)]
              (cond-> {}
                (seq attrs) (assoc :attrs attrs)
                (seq child-content) (merge child-content)
                text (assoc tag (str/trim text))
                (and (empty? child-content) (empty? text)) (assoc tag nil))))]
    (-> xml-str
        xml/parse-str
        parse-node)))


(defn parse-xml-to-map
  "将 XML 字符串解析为 Clojure map,正确处理数组情况"
  [xml-string]
  (letfn [(node->map [node]
            (let [tag (keyword (:tag node))
                  content (:content node)
                  attrs (:attrs node)
                  child-elements (filter map? content)
                  text-content (first (filter string? content))]
              (cond-> {}
                (seq attrs) (merge attrs)
                (seq child-elements) (assoc tag
                                            (if (every? #(= (:tag %) (:tag (first child-elements))) child-elements)
                                              (mapv node->map child-elements)
                                              (into {} (map (fn [child] [(keyword (:tag child)) (node->map child)]) child-elements))))
                text-content (assoc tag text-content))))]
    (-> xml-string
        xml/parse-str
        node->map)))
(comment
  ;; 使用示例
  (let [xml-string "<root> <RoomTypes><RoomType RoomTypeCode=\"48678253\" />
                    <RoomType RoomTypeCode=\"48678255\" />
                            </RoomTypes><child1 attr1='value1'>text1</child1><child2><grandchild>text2</grandchild></child2></root>"
        result (parse-xml-to-map xml-string)]
    (println result))
  ;; 输出: {:root {:child1 {:attr1 "value1", :child1 "text1"}, :child2 {:grandchild "text2"}}}
  )


;; 解析 XML 根标签的通用函数
(defn get-root-tag
  "通过只解析 XML 的根标签来判断请求类型。"
  [xml-string]
  (let [factory      (DocumentBuilderFactory/newInstance)
        builder      (.newDocumentBuilder factory)
        input-stream (java.io.ByteArrayInputStream. (.getBytes xml-string "UTF-8"))
        document     (.parse builder input-stream)
        root-element (.getDocumentElement document)       ; 获取根元素
        root-tag     (keyword (.getTagName root-element)) ; 获取根标签名
        req-name     (cond
                       (= root-tag :OTA_HotelResRQ) "创建订单"
                       (= root-tag :OTA_CancelRQ) "取消订单"
                       (= root-tag :OTA_ModifyResRQ) "变更订单"
                       (= root-tag :OTA_InventoryCheckRQ) "可订检查"
                       (= root-tag :OTA_GetRerStatusRQ) "轮询获取订单状态"
                       :else "未知请求类型")]
    (log/info "请求类型:" root-tag req-name)
    root-tag))

;; 调试辅助函数:用于打印调试信息
(defn- debug-extract-attr
  [zip path attr-name]
  (let [value (apply zx/xml1-> zip (concat path [(zx/attr attr-name)]))]
    (log/info "Extracting" attr-name "from" path ":" value)
    value))


(defn- debug-extract
  "从给定的路径中提取文本内容并记录日志"
  [zip path]
  (let [value (apply zx/xml1-> zip (concat path [zx/text]))]
    (log/info "Extracting text from" path ":" value)
    value))

;; 构建 OTA_HotelResRS 响应 XML
(defn build-hotel-res-response
  []
  (let [response (xml/element :OTA_HotelResRS
                              {:TimeStamp "2013-02-28 16:07:22"
                               :Version "1.0"
                               :EchoToken "e9246d3e-2807-449c-bbc5-affedee739c2"}
                              ;; POS 元素
                              (xml/element :POS
                                           {}
                                           (xml/element :Source
                                                        {}
                                                        (xml/element :RequestorID
                                                                     {:Type "13"
                                                                      :ID "elong"})))
                              ;; Success 元素
                              (xml/element :Success {} "success")
                              ;; UniqueID 节点1
                              (xml/element :UniqueID
                                           {:Type "14"
                                            :ID "43143215"}
                                           (xml/element :CompanyName {} "elong"))
                              ;; UniqueID 节点2
                              (xml/element :UniqueID
                                           {:Type "10"
                                            :ID "s1302280038"}
                                           (xml/element :CompanyName {} "Jltour")))]
    ;; 输出为 XML 字符串
    (xml/emit-str response)))

(comment
  comment
  (log/info (build-hotel-res-response)))

;; 独立的根标签信息解析函数
(defn parse-root-tag-info
  "解析根标签信息,返回包含根标签名及其属性的 map"
  [zip-xml]
  (let [root-tag (:tag (zip/node zip-xml))]
    {;; 请求类型
     :root-tag root-tag
     ;; 时间戳
     :timestamp (debug-extract-attr zip-xml [root-tag] :TimeStamp)
     ;; 接口版本,默认 2.000
     :version (debug-extract-attr zip-xml [root-tag] :Version)
     ;; 请求验证码,要和response返回值相同
     :echo-token (debug-extract-attr zip-xml [root-tag] :EchoToken)
     ;; 用户名
     :username (debug-extract-attr zip-xml [root-tag] :UserName)
     ;; 密码
     :password (debug-extract-attr zip-xml [root-tag] :Password)
     ;; 语言编码,默认en-us
     :primary-lang (debug-extract-attr zip-xml [root-tag] :PrimaryLangID)
     ;; 提取通用的 RequestorID 信息
     :requestor-type (debug-extract-attr zip-xml [:POS :Source :RequestorID] :Type)
     :requestor-id (debug-extract-attr zip-xml [:POS :Source :RequestorID] :ID)}))

(defn parse-inventory-check-rq
  "可订检查请求——用于下单前检验价格和库存,确认产品是否可订"
  [xml-string]
  (let [parsed-xml (xml/parse-str xml-string)
        zip-xml    (zip/xml-zip parsed-xml)]
    ;; 打印 XML 结构,确认正确解析
    (log/info "Parsed XML structure:" parsed-xml)
    (let [root-tag-info (parse-root-tag-info zip-xml)]
        ;; 提取关键的字段信息
        {:root-tag-info root-tag-info
         ;; 供应商房型 ID
         :room-types (mapv #(hash-map :room-type-code (zx/attr % :RoomTypeCode))
                           (zx/xml-> zip-xml
                                     :HotelReservations :HotelReservation
                                     :RoomStay :RoomTypes :RoomType))
         ;; 供应商 RP ID
         :rate-plans (mapv #(hash-map :rate-plan-code (zx/attr % :RatePlanCode))
                           (zx/xml-> zip-xml
                                     :HotelReservations :HotelReservation
                                     :RoomStay :RatePlans :RatePlan))
         ;; 住客人数
         :guest-counts (mapv #(hash-map :age-qualifying-code (zx/attr % :AgeQualifyingCode)
                                        :count (zx/attr % :Count))
                             (zx/xml-> zip-xml
                                       :HotelReservations
                                       :HotelReservation :RoomStay
                                       :GuestCounts :GuestCount))
         ;; 供应商酒店 ID
         :hotel-code (zx/xml1-> zip-xml
                                :HotelReservations
                                :HotelReservation :RoomStay
                                :BasicPropertyInfo (zx/attr :HotelCode))
         ;; 房间数量
         :room-count (zx/xml1-> zip-xml
                                :HotelReservations
                                :HotelReservation :ResGlobalInfo
                                :RoomCount zx/text)
         ;; elong 会员等级
         :member-level (zx/xml1-> zip-xml
                                  :HotelReservations
                                  :HotelReservation :ResGlobalInfo
                                  :MemberLevel zx/text)
         ;; 到店日期,2007-06-29
         :start-date (zx/xml1-> zip-xml
                                :HotelReservations
                                :HotelReservation :ResGlobalInfo
                                :TimeSpan (zx/attr :Start))
         ;; 离店日期,2007-06-30
         :end-date (zx/xml1-> zip-xml
                              :HotelReservations
                              :HotelReservation :ResGlobalInfo
                              :TimeSpan (zx/attr :End))})))

(defn parse-hotel-res-rq
  "下单"
  [xml-string]
  (let [parsed-xml (xml/parse-str xml-string)
        zip-xml    (zip/xml-zip parsed-xml)]
    (log/info "解析的XML结构:" parsed-xml)
    (letfn [(extract [path] (debug-extract zip-xml path))
            (extract-attr [path attr] (debug-extract-attr zip-xml path attr))]
      (let [root-tag-info (parse-root-tag-info zip-xml)]
        {:root-tag-info root-tag-info
         :unique-id (zx/xml1-> zip-xml
                               :HotelReservations :HotelReservation
                               :UniqueID (zx/attr :ID))
         :room-type-code (zx/xml1-> zip-xml
                                    :HotelReservations :HotelReservation :RoomStays :RoomStay
                                    :RoomTypes :RoomType (zx/attr :RoomTypeCode))
         :rate-plan-code (zx/xml1-> zip-xml
                                    :HotelReservations :HotelReservation :RoomStays :RoomStay
                                    :RatePlans :RatePlan (zx/attr :RatePlanCode))
         :base-amount (zx/xml1-> zip-xml
                                 :HotelReservations :HotelReservation :RoomStays :RoomStay
                                 :RoomRates :RoomRate :Rates :Rate :Base (zx/attr :AmountAfterTax))
         :total-amount (zx/xml1-> zip-xml
                                  :HotelReservations :HotelReservation :RoomStays :RoomStay
                                  :RoomRates :RoomRate :Rates :Rate :Total (zx/attr :AmountAfterTax))
         :guest-count (zx/xml1-> zip-xml
                                 :HotelReservations :HotelReservation :RoomStays :RoomStay
                                 :GuestCounts :GuestCount (zx/attr :Count))
         :hotel-code (zx/xml1-> zip-xml
                                :HotelReservations :HotelReservation :RoomStays :RoomStay
                                :BasicPropertyInfo (zx/attr :HotelCode))
         :guests (mapv #(hash-map :given-name (zx/xml1-> % :GivenName zx/text)
                                  :middle-name (zx/xml1-> % :MiddleName zx/text)
                                  :surname (zx/xml1-> % :Surname zx/text))
                       (zx/xml-> zip-xml
                                 :HotelReservations :HotelReservation :ResGuests :ResGuest
                                 :Profiles :ProfileInfo :Profile :Customer :PersonName :RoomGuest))
         :room-num (zx/xml1-> zip-xml
                              :HotelReservations :HotelReservation :ResGlobalInfo
                              :RoomNum zx/text)
         :start-date (zx/xml1-> zip-xml
                                :HotelReservations :HotelReservation :ResGlobalInfo
                                :TimeSpan (zx/attr :Start))
         :end-date (zx/xml1-> zip-xml
                              :HotelReservations :HotelReservation :ResGlobalInfo
                              :TimeSpan (zx/attr :End))
         :earliest-check-in-time (zx/xml1-> zip-xml
                                            :HotelReservations :HotelReservation :ResGlobalInfo
                                            :EarliestCheckInTime zx/text)
         :latest-check-in-time (zx/xml1-> zip-xml
                                          :HotelReservations :HotelReservation :ResGlobalInfo
                                          :LatestCheckInTime zx/text)
         :remark (zx/xml1-> zip-xml
                            :HotelReservations :HotelReservation :ResGlobalInfo
                            :Remark zx/text)
         :guarantee-type (zx/xml1-> zip-xml
                                    :HotelReservations :HotelReservation :ResGlobalInfo
                                    :Guarantee (zx/attr :GuaranteeType))
         :can-be-canceled (zx/xml1-> zip-xml
                                     :RatePlanPolicy :CanBeCanceled zx/text)
         :cancel-before-days (zx/xml1-> zip-xml
                                        :RatePlanPolicy :CancelBeforeDays zx/text)
         :cancel-before-time (zx/xml1-> zip-xml
                                        :RatePlanPolicy :CancelBeforeTime zx/text)
         :cash-scale-type (zx/xml1-> zip-xml
                                     :RatePlanPolicy :CashScaleType zx/text)
         :elong-inventory-type (zx/xml1-> zip-xml
                                          :ElongInventoryType zx/text)}))))


(defn build-hotel-reservation-success-response
  "构建酒店预订成功的响应 XML"
  [{:keys [timestamp version echo-token elong-order-id supplier-order-id]}]
  (xml/element
   :OTA_HotelResRS
   {:TimeStamp timestamp
    :Version version
    :EchoToken echo-token}
   (xml/element
    :POS
    {}
    (xml/element
     :Source
     {}
     (xml/element :RequestorID {:Type "13" :ID "elong"})))
   (xml/element :Success {} "success")
   (xml/element
    :UniqueID
    {:Type "14" :ID elong-order-id}
    (xml/element :CompanyName {} "elong"))
   (xml/element
    :UniqueID
    {:Type "10" :ID supplier-order-id}
    (xml/element :CompanyName {} "Jltour"))))

(comment
  ;; 使用示例
  (let [response-xml (build-hotel-reservation-success-response
                      {:timestamp "2023-05-15 10:30:00"
                       :version "1.0"
                       :echo-token "e9246d3e-2807-449c-bbc5-affedee739c2"
                       :elong-order-id "43143215"
                       :supplier-order-id "s2305150001"})]
    (println (xml/emit-str response-xml)))
  )


(defn parse-cancel-order-request
  "解析取消订单请求的 XML"
  [xml-string]
  (let [parsed-xml (xml/parse-str xml-string)
        cancel-rq (zx/xml1-> parsed-xml :OTA_CancelRQ)]
    {:cancel-type (zx/attr cancel-rq :CancelType)
     :echo-token (zx/attr cancel-rq :EchoToken)
     :username (zx/attr cancel-rq :UserName)
     :password (zx/attr cancel-rq :Password)
     :primary-lang-id (zx/attr cancel-rq :PrimaryLangID)
     :timestamp (zx/attr cancel-rq :TimeStamp)
     :version (zx/attr cancel-rq :Version)
     :requestor-id (zx/xml1-> cancel-rq :POS :Source :RequestorID (zx/attr :ID))
     :cancel-out-of-rule (when-let [cor (zx/xml1-> cancel-rq :CancelOutOfRule)]
                           {:rule (zx/attr cor :Rule)
                            :pay-hotel-amount (zx/xml1-> cor :PayHotelAmount zx/text)
                            :client-unique-id (zx/xml1-> cor :clientUniqueId zx/text)
                            :deduct-hotel-amount (zx/xml1-> cor :deductHotelAmount zx/text)
                            :notes (zx/xml1-> cor :Notes zx/text)})
     :elong-order-id (zx/xml1-> cancel-rq :UniqueID [(zx/attr= :Type "14")] (zx/attr :ID))
     :supplier-order-id (zx/xml1-> cancel-rq :UniqueID [(zx/attr= :Type "10")] (zx/attr :ID))
     :reasons (zx/xml1-> cancel-rq :Reasons :Reason zx/text)}))

[-- Attachment #3: bt.log --]
[-- Type: application/octet-stream, Size: 3905 bytes --]

lldb -p $(pgrep Emacs)
(lldb) process attach --pid 35841
Process 35841 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x0000000102dc7050 libtree-sitter.0.dylib`ts_parser_parse + 5660
libtree-sitter.0.dylib`ts_parser_parse:
->  0x102dc7050 <+5660>: ldrb   w11, [x12, x9]
    0x102dc7054 <+5664>: add    x10, x10, x11, lsl #2
    0x102dc7058 <+5668>: br     x10
    0x102dc705c <+5672>: ldrb   w27, [x8, #0x1]
Executable module set to "/Applications/Emacs.app/Contents/MacOS/Emacs-arm64-11".
Architecture set to: arm64-apple-macosx-.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x0000000102dc7050 libtree-sitter.0.dylib`ts_parser_parse + 5660
    frame #1: 0x00000001023bfe0c Emacs-arm64-11`treesit_ensure_parsed + 128
    frame #2: 0x00000001023bfd34 Emacs-arm64-11`Ftreesit_parser_root_node + 52
    frame #3: 0x000000010234ee20 Emacs-arm64-11`funcall_subr + 344
    frame #4: 0x000000010234ec94 Emacs-arm64-11`funcall_general + 336
    frame #5: 0x000000010234ae68 Emacs-arm64-11`Ffuncall + 176
    frame #6: 0x000000010235a8c0 Emacs-arm64-11`mapcar1 + 216
    frame #7: 0x000000010235aa8c Emacs-arm64-11`Fmapcar + 168
    frame #8: 0x000000010234ed30 Emacs-arm64-11`funcall_subr + 104
    frame #9: 0x000000010238b118 Emacs-arm64-11`exec_byte_code + 2264
    frame #10: 0x000000010234f0a8 Emacs-arm64-11`funcall_lambda + 464
    frame #11: 0x000000010234ec7c Emacs-arm64-11`funcall_general + 312
    frame #12: 0x000000010234ae68 Emacs-arm64-11`Ffuncall + 176
    frame #13: 0x000000010234e998 Emacs-arm64-11`run_hook_wrapped_funcall + 28
    frame #14: 0x000000010234e7f4 Emacs-arm64-11`run_hook_with_args + 236
    frame #15: 0x000000010234e974 Emacs-arm64-11`Frun_hook_wrapped + 20
    frame #16: 0x000000010234ed30 Emacs-arm64-11`funcall_subr + 104
    frame #17: 0x000000010238b118 Emacs-arm64-11`exec_byte_code + 2264
    frame #18: 0x000000010234f0a8 Emacs-arm64-11`funcall_lambda + 464
    frame #19: 0x000000010234ec7c Emacs-arm64-11`funcall_general + 312
    frame #20: 0x000000010234ae68 Emacs-arm64-11`Ffuncall + 176
    frame #21: 0x000000010234d020 Emacs-arm64-11`internal_condition_case_n + 116
    frame #22: 0x0000000102236484 Emacs-arm64-11`dsafe__call + 160
    frame #23: 0x00000001022360c0 Emacs-arm64-11`dsafe_call1 + 88
    frame #24: 0x000000010224e6b0 Emacs-arm64-11`handle_fontified_prop + 812
    frame #25: 0x000000010224d858 Emacs-arm64-11`handle_stop + 112
    frame #26: 0x0000000102250838 Emacs-arm64-11`next_element_from_buffer + 236
    frame #27: 0x0000000102227df8 Emacs-arm64-11`get_next_display_element + 128
    frame #28: 0x0000000102239f4c Emacs-arm64-11`display_line + 956
    frame #29: 0x000000010225c9d4 Emacs-arm64-11`try_window_id + 2252
    frame #30: 0x0000000102259e1c Emacs-arm64-11`redisplay_window + 6032
    frame #31: 0x0000000102257a40 Emacs-arm64-11`redisplay_window_1 + 44
    frame #32: 0x000000010234cef4 Emacs-arm64-11`internal_condition_case_1 + 96
    frame #33: 0x0000000102234d60 Emacs-arm64-11`redisplay_internal + 2976
    frame #34: 0x0000000102238b0c Emacs-arm64-11`redisplay + 12
    frame #35: 0x00000001022c8aa0 Emacs-arm64-11`read_char + 720
    frame #36: 0x00000001022c6c5c Emacs-arm64-11`read_key_sequence + 908
    frame #37: 0x00000001022c5e08 Emacs-arm64-11`command_loop_1 + 680
    frame #38: 0x000000010234ce70 Emacs-arm64-11`internal_condition_case + 92
    frame #39: 0x00000001022c5b40 Emacs-arm64-11`command_loop_2 + 52
    frame #40: 0x000000010234c6e0 Emacs-arm64-11`internal_catch + 80
    frame #41: 0x00000001022c524c Emacs-arm64-11`command_loop + 308
    frame #42: 0x00000001022c5090 Emacs-arm64-11`recursive_edit_1 + 216
    frame #43: 0x00000001022c5458 Emacs-arm64-11`Frecursive_edit + 232
    frame #44: 0x00000001022c32d4 Emacs-arm64-11`main + 4208
    frame #45: 0x000000019aca0274 dyld`start + 2840

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-09-28  8:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-12 16:21 bug#73204: Tree-sitter in clojure-ts-mode causes memory leak during parsing vinurs
2024-09-13  4:24 ` Yuan Fu
2024-09-14  7:58   ` Yuan Fu
2024-09-14  9:14     ` vinurs
2024-09-28  8:51       ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).