Repository: neovim/neovim
File: src/nvim/window.c (C)

Code before:
  // windows scrolled or changed size.  Store the current values before
  // triggering the event, if a scroll or resize happens as a side effect
  // then WinScrolled/WinResized is triggered for that later.
  snapshot_windows_scroll_size();

  recursive = true;

  // Save window info before autocmds since they can free windows
  char resize_winid[NUMBUFLEN];
  if (trigger_resize) {
    vim_snprintf(resize_winid, sizeof(resize_winid), "%d", first_size_win->handle);
  }

  char scroll_winid[NUMBUFLEN];
  if (trigger_scroll) {
    vim_snprintf(scroll_winid, sizeof(scroll_winid), "%d", first_scroll_win->handle);
  }

  // If both are to be triggered do WinResized first.
  if (trigger_resize) {
    save_v_event_T save_v_event;
    dict_T *v_event = get_v_event(&save_v_event);

    if (tv_dict_add_list(v_event, S_LEN("windows"), windows_list) == OK) {
      tv_dict_set_keys_readonly(v_event);
      apply_autocmds(EVENT_WINRESIZED, resize_winid, resize_winid, false, curbuf);
    }
    restore_v_event(v_event, &save_v_event);
  }

  if (trigger_scroll) {
    save_v_event_T save_v_event;
    dict_T *v_event = get_v_event(&save_v_event);

    // Move the entries from scroll_dict to v_event.
    tv_dict_extend(v_event, scroll_dict, "move");
    tv_dict_set_keys_readonly(v_event);
    tv_dict_unref(scroll_dict);

    apply_autocmds(EVENT_WINSCROLLED, scroll_winid, scroll_winid, false, curbuf);

    restore_v_event(v_event, &save_v_event);
  }

  recursive = false;
}

// Save the size of all windows in "gap".
void win_size_save(garray_T *gap)
{
  ga_init(gap, (int)sizeof(int), 1);

Review comment (suggestion):
Using `curbuf` here, I think, changes the meaning of `<abuf>`? If we save the handles as I described, then here we can check `bufref_valid` : 

```c
buf_T *buf = bufref_valid(resize_bufref) ? resize_bufref.br_buf : curbuf;
apply_autocmds(EVENT_WINRESIZED, resize_winid, resize_winid, false, curbuf);
```

Then we still may need to update the documentation. Or maybe we should throw an error instead of calling `apply_autocmds`, if the buf is no longer valid.

Code after:
  // windows scrolled or changed size.  Store the current values before
  // triggering the event, if a scroll or resize happens as a side effect
  // then WinScrolled/WinResized is triggered for that later.
  snapshot_windows_scroll_size();

  recursive = true;

  // Save window info before autocmds since they can free windows
  char resize_winid[NUMBUFLEN];
  bufref_T resize_bufref;
  if (trigger_resize) {
    vim_snprintf(resize_winid, sizeof(resize_winid), "%d", first_size_win->handle);
    set_bufref(&resize_bufref, first_size_win->w_buffer);
  }

  char scroll_winid[NUMBUFLEN];
  bufref_T scroll_bufref;
  if (trigger_scroll) {
    vim_snprintf(scroll_winid, sizeof(scroll_winid), "%d", first_scroll_win->handle);
    set_bufref(&scroll_bufref, first_scroll_win->w_buffer);
  }

  // If both are to be triggered do WinResized first.
  if (trigger_resize) {
    save_v_event_T save_v_event;
    dict_T *v_event = get_v_event(&save_v_event);

    if (tv_dict_add_list(v_event, S_LEN("windows"), windows_list) == OK) {
      tv_dict_set_keys_readonly(v_event);
      buf_T *buf = bufref_valid(&resize_bufref) ? resize_bufref.br_buf : curbuf;
      apply_autocmds(EVENT_WINRESIZED, resize_winid, resize_winid, false, buf);
    }
    restore_v_event(v_event, &save_v_event);
  }

  if (trigger_scroll) {
    save_v_event_T save_v_event;
    dict_T *v_event = get_v_event(&save_v_event);

    // Move the entries from scroll_dict to v_event.
    tv_dict_extend(v_event, scroll_dict, "move");
    tv_dict_set_keys_readonly(v_event);
    tv_dict_unref(scroll_dict);

    buf_T *buf = bufref_valid(&scroll_bufref) ? scroll_bufref.br_buf : curbuf;
    apply_autocmds(EVENT_WINSCROLLED, scroll_winid, scroll_winid, false, buf);

    restore_v_event(v_event, &save_v_event);
  }

  recursive = false;