function JsApiReporter(options) {
      const timer = options.timer || new j$.Timer();
      let status = 'loaded';

      this.started = false;
      this.finished = false;
      this.runDetails = {};

      this.jasmineStarted = function () {
        this.started = true;
        status = 'started';
        timer.start();
      };

      let executionTime;

      this.jasmineDone = function (runDetails) {
        this.finished = true;
        this.runDetails = runDetails;
        executionTime = timer.elapsed();
        status = 'done';
      };

      /**
       * Get the current status for the Jasmine environment.
       * @name jsApiReporter#status
       * @since 2.0.0
       * @function
       * @return {String} - One of `loaded`, `started`, or `done`
       */
      this.status = function () {
        return status;
      };

      const suites = [],
        suites_hash = {};

      this.suiteStarted = function (result) {
        suites_hash[result.id] = result;
      };

      this.suiteDone = function (result) {
        storeSuite(result);
      };

      /**
       * Get the results for a set of suites.
       *
       * Retrievable in slices for easier serialization.
       * @name jsApiReporter#suiteResults
       * @since 2.1.0
       * @function
       * @param {Number} index - The position in the suites list to start from.
       * @param {Number} length - Maximum number of suite results to return.
       * @return {SuiteResult[]}
       */
      this.suiteResults = function (index, length) {
        return JSON.stringify(suites.slice(index, index + length));
      };

      function storeSuite(result) {
        suites.push(result);
        suites_hash[result.id] = result;
      }

      /**
       * Get all of the suites in a single object, with their `id` as the key.
       * @name jsApiReporter#suites
       * @since 2.0.0
       * @function
       * @return {Object} - Map of suite id to {@link SuiteResult}
       */
      this.suites = function () {
        return JSON.stringify(suites_hash);
      };

      const specs = [];

      this.specDone = function (result) {
        specs.push(result);
      };

      /**
       * Get the results for a set of specs.
       *
       * Retrievable in slices for easier serialization.
       * @name jsApiReporter#specResults
       * @since 2.0.0
       * @function
       * @param {Number} index - The position in the specs list to start from.
       * @param {Number} length - Maximum number of specs results to return.
       * @return {SpecResult[]}
       */
      this.specResults = function (index, length) {
        return JSON.stringify(specs.slice(index, index + length));
      };

      /**
       * Get all spec results.
       * @name jsApiReporter#specs
       * @since 2.0.0
       * @function
       * @return {SpecResult[]}
       */
      this.specs = function () {
        return JSON.stringify(specs);
      };

      /**
       * Get the number of milliseconds it took for the full Jasmine suite to run.
       * @name jsApiReporter#executionTime
       * @since 2.0.0
       * @function
       * @return {Number}
       */
      this.executionTime = function () {
        return executionTime;
      };
    }
@name jsApiReporter
@classdesc {@link Reporter} added by default in `boot.js` to record results for retrieval in javascript code. An instance is made available as `jsApiReporter` on the global object.
@class
@hideconstructor