Repository: parcel-bundler/parcel
File: packages/core/core/src/ReporterRunner.js (JavaScript)

Code before:
      let reporters = this.reporters;
      if (!reporters) {
        this.reporters = await this.config.getReporters();
        reporters = this.reporters;
      }

      for (let reporter of this.reporters) {
        let measurement;
        try {
          // To avoid an infinite loop we don't measure trace events, as they'll
          // result in another trace!
          if (event.type !== 'trace') {
            measurement = tracer.createMeasurement(reporter.name, 'reporter');
          }
          await reporter.plugin.report({
            event,
            options: this.pluginOptions,
            logger: new PluginLogger({origin: reporter.name}),
            tracer: new PluginTracer({
              origin: reporter.name,
              category: 'reporter',
            }),
          });
        } catch (reportError) {
          INTERNAL_ORIGINAL_CONSOLE.error(reportError);
          process.exitCode = 1;
        } finally {
          measurement && measurement.end();
        }
      }
    } catch (err) {
      INTERNAL_ORIGINAL_CONSOLE.error(err);
    }
  }

  dispose() {
    bus.off('reporterEvent', this.eventHandler);
    instances.delete(this);
  }
}

export function reportWorker(workerApi: WorkerApi, event: ReporterEvent) {
  if (
    event.type === 'buildProgress' &&
    (event.phase === 'optimizing' || event.phase === 'packaging')
  ) {
    // Convert any public api bundles to their internal equivalents for
    // easy serialization
    bus.emit('reporterEvent', {
      ...event,
      bundle: bundleToInternalBundle(event.bundle),

Review comment (suggestion):
I wonder if it is unexpected to do this for people using the Parcel programmatic API rather than our CLI? Should we store our own property here (rather than setting the global exit code), and then throw/emit an error from the main Parcel object that the CLI could pick up? We do already set an exit code in the CLI when an error is thrown.

Code after:
      try {
        // To avoid an infinite loop we don't measure trace events, as they'll
        // result in another trace!
        if (event.type !== 'trace') {
          measurement = tracer.createMeasurement(reporter.name, 'reporter');
        }
        await reporter.plugin.report({
          event,
          options: this.pluginOptions,
          logger: new PluginLogger({origin: reporter.name}),
          tracer: new PluginTracer({
            origin: reporter.name,
            category: 'reporter',
          }),
        });
      } catch (reportError) {
        if (event.type !== 'buildSuccess') {
          // This will be captured by consumers
          INTERNAL_ORIGINAL_CONSOLE.error(reportError);
        }

        this.errors.push(reportError);
      } finally {
        measurement && measurement.end();
      }
    }
  }

  dispose() {
    bus.off('reporterEvent', this.eventHandler);
    instances.delete(this);
  }
}

export function reportWorker(workerApi: WorkerApi, event: ReporterEvent) {
  if (
    event.type === 'buildProgress' &&
    (event.phase === 'optimizing' || event.phase === 'packaging')
  ) {
    // Convert any public api bundles to their internal equivalents for
    // easy serialization
    bus.emit('reporterEvent', {
      ...event,
      bundle: bundleToInternalBundle(event.bundle),
      bundleGraphRef: workerApi.resolveSharedReference(
        bundleToInternalBundleGraph(event.bundle),
      ),
    });
    return;
  }