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 => {
  console.log("annotator1")
  return {
    annotations: annotation1.of(true)
  }
})

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

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

view.dispatch({})

The console output is

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

Demo

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.

2 Likes

Thanks for your rapid response, as always.