Repository: tanstack/query
File: packages/query-core/src/query.ts (TypeScript)

Code before:
    // Adds an enumerable signal property to the object that
    // which sets abortSignalConsumed to true when the signal
    // is read.
    const addSignalProperty = (object: unknown) => {
      Object.defineProperty(object, 'signal', {
        enumerable: true,
        get: () => {
          this.#abortSignalConsumed = true
          return abortController.signal
        },
      })
    }

    addSignalProperty(queryFnContext)

    // Create fetch function
    const fetchFn = () => {
      if (!this.options.queryFn) {
        return Promise.reject(
          new Error(`Missing queryFn: '${this.options.queryHash}'`),
        )
      }

      if (this.options.queryFn === skipToken) {
        return Promise.resolve(undefined)
      }

      this.#abortSignalConsumed = false
      if (this.options.persister) {
        return this.options.persister(
          this.options.queryFn,
          queryFnContext as QueryFunctionContext<TQueryKey>,
          this as unknown as Query,
        )
      }

      return this.options.queryFn(
        queryFnContext as QueryFunctionContext<TQueryKey>,
      )
    }

    // Trigger behavior hook
    const context: Omit<
      FetchContext<TQueryFnData, TError, TData, TQueryKey>,
      'signal'
    > = {
      fetchOptions,
      options: this.options,
      queryKey: this.queryKey,
      state: this.state,
      fetchFn,

Review comment (suggestion):
this isn't ideal because a resolved value can and should never be `undefined`. Instead, I guess we should set the `queryFn` itself back to `undefined`, or to a function that throws (maybe in dev mode with a descriptive message?), in `defaultQueryOptions` when we set `enabled: false`.

Usually, the queryFn won't run, but if you pass a `skipToken` and then call `refetch` manually - it would, but that's kind of an invariant

Code after:
    const addSignalProperty = (object: unknown) => {
      Object.defineProperty(object, 'signal', {
        enumerable: true,
        get: () => {
          this.#abortSignalConsumed = true
          return abortController.signal
        },
      })
    }

    addSignalProperty(queryFnContext)

    // Create fetch function
    const fetchFn = () => {
      if (process.env.NODE_ENV !== 'production') {
        if (this.options.queryFn === skipToken) {
          console.error(
            `Attempted to invoke queryFn when set to skipToken. This is likely a configuration error. Query hash: '${this.options.queryHash}'`,
          )
        }
      }

      if (!this.options.queryFn || this.options.queryFn === skipToken) {
        return Promise.reject(
          new Error(`Missing queryFn: '${this.options.queryHash}'`),
        )
      }

      this.#abortSignalConsumed = false
      if (this.options.persister) {
        return this.options.persister(
          this.options.queryFn,
          queryFnContext as QueryFunctionContext<TQueryKey>,
          this as unknown as Query,
        )
      }

      return this.options.queryFn(
        queryFnContext as QueryFunctionContext<TQueryKey>,
      )
    }

    // Trigger behavior hook
    const context: Omit<
      FetchContext<TQueryFnData, TError, TData, TQueryKey>,
      'signal'
    > = {
      fetchOptions,
      options: this.options,
      queryKey: this.queryKey,
      state: this.state,