<file_sep>import stackTrace from 'stacktrace-js';

let order = 0;

const sendMessageToExtension = (identifier, data, trace) => {
  window.postMessage({
    spit_event: true,
    identifier,
    data,
    trace,
    order: order++,
  }, '*');
};

const getStackTrace = (identifier, data, debugError) => {
  if (debugError) {
    stackTrace.fromError(debugError).then(trace => {
      sendMessageToExtension(identifier, data, trace);
    });
  } else {
    sendMessageToExtension(identifier, data, []);
  }
}

const Communicator = class Communicator {
  onChange(spitEvent, data, debugError) {
    getStackTrace(spitEvent.getIdentifier(), data, debugError);
  }

  set(data, ev, debugError) {
    this.onChange(ev, data, debugError);
  }

  onAddEvent(ev) {
    ev.addListener(this);
  }
}

Communicator.prototype.debug = true;


const registerStore = store => {
  window.postMessage({
    spit_event: true,
    page_init: true,
  }, '*');
  const communicator = new Communicator();
  store.addListener(communicator);
  store.getEvents().forEach(ev => {
    ev.addListener(communicator);
    communicator.onChange(ev, ev.get())
  });
}

window.__REACT_SPIT_DEV_TOOLS__ = registerStore;
<file_sep>/* global chrome */
const s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('/js/injected_file.js');
s.onload = function() {
  this.remove();
};
(document.head || document.documentElement).appendChild(s);


window.addEventListener('message', function(event) {

  // Only accept messages from same frame
  if (event.source !== window) {
    return;
  }

  const message = event.data;

  // Only accept messages that we know are ours
  if (typeof message !== 'object' || message === null || !message.spit_event) {
    return;
  }

  chrome.runtime.sendMessage(message);
});
<file_sep>import React from 'react';

export default class TraceView extends React.Component {
  render() {
    const { traces } = this.props;
    if (traces.length) {
      return (
        <div>
          {traces.slice(2).map(line => (
            <div>
              {line.fileName}:{line.lineNumber}:{line.functionName}
            </div>
          ))}
        </div>
      );
    }

    return <div>Initial data</div>;
  }
}
