• 
      

    Stop sharing tree-sitter Parser instances between callers.

    Review Request #15230 — Created Aug. 14, 2026 and updated

    Information

    Review Board
    release-9.x

    Reviewers

    get_parser() was decorated with @lru_cache, so every caller (and
    every thread under threaded WSGI) shared one stateful
    tree_sitter.Parser per language. Parsers are not thread-safe, and
    _highlight_injections() mutates included_ranges on the shared
    instance. A concurrent full-file parse could silently produce a tree
    covering only another request's injection ranges, and the corrupt
    highlighting would then be stored in the diff chunk cache.

    Language objects are immutable and remain cached via get_language().
    Parser construction is cheap, so get_parser() now returns a fresh
    instance per call.

    Added unit tests verifying parsers are not shared and that
    included_ranges mutations do not leak into later parsers. Ran all
    reviewboard/treesitter tests.

    Summary ID
    Stop sharing tree-sitter Parser instances between callers.
    `get_parser()` was decorated with `@lru_cache`, so every caller (and every thread under threaded WSGI) shared one stateful `tree_sitter.Parser` per language. Parsers are not thread-safe, and `_highlight_injections()` mutates `included_ranges` on the shared instance. A concurrent full-file parse could silently produce a tree covering only another request's injection ranges, and the corrupt highlighting would then be stored in the diff chunk cache. Language objects are immutable and remain cached via `get_language()`. Parser construction is cheap, so `get_parser()` now returns a fresh instance per call. Testing: Added unit tests verifying parsers are not shared and that included_ranges mutations do not leak into later parsers. Ran all reviewboard/treesitter tests.
    ozkosqpyoovrwwknopoxwlmqstwumtsl
    Description From Last Updated

    While here, this should be "Return a ..." to better describe what this does. The method isn't getting an instance …

    chipx86 chipx86

    I'd love to keep unit tests standardized across the codebase, but I know you already have a bunch that don't …

    chipx86 chipx86
    Checks run (2 succeeded)
    flake8 passed.
    JSHint passed.
    chipx86
    1. 
        
    2. reviewboard/treesitter/core.py (Diff revision 1)
       
       
      Show all issues

      While here, this should be "Return a ..." to better describe what this does. The method isn't getting an instance from somewhere, it's creating and returning one.

    3. reviewboard/treesitter/tests/test_core.py (Diff revision 1)
       
       
       
       
       
       
       
      Show all issues

      I'd love to keep unit tests standardized across the codebase, but I know you already have a bunch that don't use TestCase. But I'd still like to keep the docstring format the same so it's clear for us, for third-parties, and for AIs how unit tests are done across the codebase.

    4.