Highest precedence transaction extender overrides other transaction extenders

It seems that only the highest precedence transaction extender is applied to a transaction. This is at least true of the transaction that reaches the update() method of a view plugin. The documentation and the code suggest that the idea is that effects and annotations should instead be combined. For example:

import {EditorView} from "@codemirror/view"
import {EditorState, Annotation} from "@codemirror/state"

const annotation1 = Annotation.define()
const annotation2 = Annotation.define()

const listener = EditorView.updateListener.of(update => {
  const hasAnnotation1 = update.transactions.some(tr => tr.annotation(annotation1))
  const hasAnnotation2 = update.transactions.some(tr => tr.annotation(annotation2))
  console.log(`Transaction has annotation 1 is ${hasAnnotation1}, has annotation 2 is ${hasAnnotation2}`)

const annotator1 = EditorState.transactionExtender.of(tr => {
  return {
    annotations: annotation1.of(true)

const annotator2 = EditorState.transactionExtender.of(tr => {
  return {
    annotations: annotation2.of(true)

const view = new EditorView({
  doc: "",
  extensions: [annotator1, annotator2, listener],
  parent: document.body


The console output is

Transaction has annotation 1 is true, has annotation 2 is false


I’d expect the transaction observed by the update listener to have both annotations but it only has annotation1, the highest precedence one.

This issue is also mentioned briefly near the end of this post:

That was a mistake in the library. This patch should fix it.


Thanks for your rapid response, as always.