_createFileRunner(pool, options) {
    /**
     * Emits event and sets `BAILING` state, if necessary.
     * @param {Object} event - Event having `eventName`, maybe `data` and maybe `error`
     * @param {number} failureCount - Failure count
     */
    const emitEvent = (event, failureCount) => {
      this.emit(event.eventName, event.data, event.error);
      if (
        this._state !== BAILING &&
        event.data &&
        event.data._bail &&
        (failureCount || event.error)
      ) {
        debug('run(): nonzero failure count & found bail flag');
        // we need to let the events complete for this file, as the worker
        // should run any cleanup hooks
        this._state = BAILING;
      }
    };

    /**
     * Given an event, recursively find any objects in its data that have ID's, and create object references to already-seen objects.
     * @param {Object} event - Event having `eventName`, maybe `data` and maybe `error`
     */
    const linkEvent = event => {
      const stack = [{parent: event, prop: 'data'}];
      while (stack.length) {
        const {parent, prop} = stack.pop();
        const obj = parent[prop];
        let newObj;
        if (obj && typeof obj === 'object') {
          if (obj[MOCHA_ID_PROP_NAME]) {
            const id = obj[MOCHA_ID_PROP_NAME];
            newObj = this._linkedObjectMap.has(id)
              ? Object.assign(this._linkedObjectMap.get(id), obj)
              : obj;
            this._linkedObjectMap.set(id, newObj);
            parent[prop] = newObj;
          } else {
            throw createFatalError(
              'Object missing ID received in event data',
              obj
            );
          }
        }
        Object.keys(newObj).forEach(key => {
          const value = obj[key];
          if (value && typeof value === 'object' && value[MOCHA_ID_PROP_NAME]) {
            stack.push({obj: value, parent: newObj, prop: key});
          }
        });
      }
    };

    return async file => {
      debug('run(): enqueueing test file %s', file);
      try {
        const {failureCount, events} = await pool.run(file, options);

        if (this._state === BAILED) {
          // short-circuit after a graceful bail. if this happens,
          // some other worker has bailed.
          // TODO: determine if this is the desired behavior, or if we
          // should report the events of this run anyway.
          return;
        }
        debug(
          'run(): completed run of file %s; %d failures / %d events',
          file,
          failureCount,
          events.length
        );
        this.failures += failureCount; // can this ever be non-numeric?
        let event = events.shift();

        if (this._linkPartialObjects) {
          while (event) {
            linkEvent(event);
            emitEvent(event, failureCount);
            event = events.shift();
          }
        } else {
          while (event) {
            emitEvent(event, failureCount);
            event = events.shift();
          }
        }
        if (this._state === BAILING) {
          debug('run(): terminating pool due to "bail" flag');
          this._state = BAILED;
          await pool.terminate();
        }
      } catch (err) {
        if (this._state === BAILED || this._state === ABORTING) {
          debug(
            'run(): worker pool terminated with intent; skipping file %s',
            file
          );
        } else {
          // this is an uncaught exception
          debug('run(): encountered uncaught exception: %O', err);
          if (this.allowUncaught) {
            // still have to clean up
            this._state = ABORTING;
            await pool.terminate(true);
          }
          throw err;
        }
      } finally {
        debug('run(): done running file %s', file);
      }
    };
  }
Returns a mapping function to enqueue a file in the worker pool and return results of its execution.
@param {BufferedWorkerPool} pool - Worker pool
@param {Options} options - Mocha options
@returns {FileRunner} Mapping function
@private