Is it possible to call a function on every viewport once and only once?

I might have a tricky question, or maybe I am just approaching the problem wrong. I am working on a plugin which adds features to code blocks.

export interface CodeBlockPositions {
  codeBlockStartPos: number;
  codeBlockEndPos: number;
  parameters: Parameters;

  const codeBlockPositions = StateField.define<CodeBlockPositions[]>({
    create(state: EditorState): CodeBlockPositions[] {
      return [];
    update(value: CodeBlockPositions[], transaction: Transaction): CodeBlockPositions[] {
      return findCodeBlockPositions(transaction.state);  // this function collects the start and end positions of code blocks in the document, by walking the syntaxtree
  });// codeBlockPositions

  // stores the collapsed states
  const collapseField = StateField.define<RangeSet<Decoration>>({  
    create(state): RangeSet<Decoration> {
      return defaultFold(state); // calling defaultFold here, which processes the collected code blocks
    update(value, tr) {
      value =;
      for (const effect of tr.effects) {
        if (
          value = value.update({add: [effect.value], sort: true});
        else if ( {
          const { filterFrom, filterTo } = effect.value;
          value = value.update({ filter: (from, to) => to <= filterFrom || from >= filterTo, filterFrom: filterFrom, filterTo: filterTo });
      return value;
    provide: f => EditorView.decorations.from(f)
  })// collapseField

The problem is that if I open a document then the state only contains that part of the document which is in the current viewport, and therefore not all code blocks are processed. findCodeBlockPositions() finds the rest of the code blocks when I scroll, but then the create method of collapseField has already ended. What I want is basically to call defaultFold once and only once for every viewport. defaultFold would set an initial folding state for the code blocks. The only alternative I found was to process state.doc line by line, but this could be slow on large documents. Calling defaultFold in the update method of a Statefield would continously reapply the folded effect, which would result the unfolding is not possible. Somehow I needed to set a flag or something for a processed code block, but I couldn’t figure this out.

Any help would be appreciated!

Do you mean that the syntax tree doesn’t cover the whole document?

The state (and thus state field) has no access to the viewport. But you could check for changes in the document or the syntax tree in a state field update function and re-scan whenever either of those changes.