Repository: mozilla/pdf.js
File: src/display/touch_manager.js (JavaScript)

Code before:
  }

  get MIN_TOUCH_DISTANCE_TO_PINCH() {
    // The 35 is coming from:
    //  https://searchfox.org/mozilla-central/source/gfx/layers/apz/src/GestureEventListener.cpp#36
    //
    // The properties TouchEvent::screenX/Y are in screen CSS pixels:
    //  https://developer.mozilla.org/en-US/docs/Web/API/Touch/screenX#examples
    // MIN_TOUCH_DISTANCE_TO_PINCH is in CSS pixels.
    return shadow(
      this,
      "MIN_TOUCH_DISTANCE_TO_PINCH",
      35 / (window.devicePixelRatio || 1)
    );
  }

  #onTouchStart(evt) {
    if (this.#isPinchingDisabled?.()) {
      return;
    }

    if (evt.touches.length === 1) {
      const pointerDownAC = (this.#pointerDownAC = new AbortController());
      const signal = AbortSignal.any([this.#signal, pointerDownAC.signal]);
      const container = this.#container;

      // We want to have the events at the capture phase to make sure we can
      // cancel them.
      const opts = { capture: true, signal, passive: false };
      const cancelPointerDown = e => {
        if (e.pointerType === "touch") {
          this.#pointerDownAC.abort();
          this.#pointerDownAC = null;
        }
      };
      container.addEventListener(
        "pointerdown",
        e => {
          if (e.pointerType === "touch") {
            // This is the second finger so we don't want it select something
            // or whatever.
            stopEvent(e);
            cancelPointerDown(e);
          }
        },
        opts
      );
      container.addEventListener("pointerup", cancelPointerDown, opts);
      container.addEventListener("pointercancel", cancelPointerDown, opts);
      return;
    }

Review comment (refactor):
Possibly I'm not fully understanding the code, but is there ever a risk that we could be "overwriting" an existing `this.#pointerDownAC` here?
If so, is that not an issue since it'd lead to *duplicate* event listeners being attached?

Would the following make sense?
```suggestion
    if (evt.touches.length === 1) {
      if (this.#pointerDownAC) {
        return;
      }
      const pointerDownAC = (this.#pointerDownAC = new AbortController());
```

Code after:
  }

  get MIN_TOUCH_DISTANCE_TO_PINCH() {
    // The 35 is coming from:
    //  https://searchfox.org/mozilla-central/source/gfx/layers/apz/src/GestureEventListener.cpp#36
    //
    // The properties TouchEvent::screenX/Y are in screen CSS pixels:
    //  https://developer.mozilla.org/en-US/docs/Web/API/Touch/screenX#examples
    // MIN_TOUCH_DISTANCE_TO_PINCH is in CSS pixels.
    return shadow(
      this,
      "MIN_TOUCH_DISTANCE_TO_PINCH",
      35 / (window.devicePixelRatio || 1)
    );
  }

  #onTouchStart(evt) {
    if (this.#isPinchingDisabled?.()) {
      return;
    }

    if (evt.touches.length === 1) {
      if (this.#pointerDownAC) {
        return;
      }
      const pointerDownAC = (this.#pointerDownAC = new AbortController());
      const signal = AbortSignal.any([this.#signal, pointerDownAC.signal]);
      const container = this.#container;

      // We want to have the events at the capture phase to make sure we can
      // cancel them.
      const opts = { capture: true, signal, passive: false };
      const cancelPointerDown = e => {
        if (e.pointerType === "touch") {
          this.#pointerDownAC?.abort();
          this.#pointerDownAC = null;
        }
      };
      container.addEventListener(
        "pointerdown",
        e => {
          if (e.pointerType === "touch") {
            // This is the second finger so we don't want it select something
            // or whatever.
            stopEvent(e);
            cancelPointerDown(e);
          }
        },
        opts
      );
      container.addEventListener("pointerup", cancelPointerDown, opts);