frame.js 6.58 KiB
/* @flow */
import { enableTabClick } from '../utils/dom/enableTabClick';
import { createCode } from './code';
import { isInternalFile } from '../utils/isInternalFile';
import type { StackFrame } from '../utils/stack-frame';
import type { FrameSetting, OmitsObject } from './frames';
import { applyStyles } from '../utils/dom/css';
import {
  omittedFramesStyle,
  functionNameStyle,
  depStyle,
  linkStyle,
  anchorStyle,
  hiddenStyle,
} from '../styles';
function getGroupToggle(
  document: Document,
  omitsCount: number,
  omitBundle: number
) {
  const omittedFrames = document.createElement('div');
  enableTabClick(omittedFrames);
  const text1 = document.createTextNode(
    '\u25B6 ' + omitsCount + ' stack frames were collapsed.'
  omittedFrames.appendChild(text1);
  omittedFrames.addEventListener('click', function() {
    const hide = text1.textContent.match(/▲/);
    const list = document.getElementsByName('bundle-' + omitBundle);
    for (let index = 0; index < list.length; ++index) {
      const n = list[index];
      if (hide) {
        n.style.display = 'none';
      } else {
        n.style.display = '';
    if (hide) {
      text1.textContent = text1.textContent.replace(/▲/, '▶');
      text1.textContent = text1.textContent.replace(/expanded/, 'collapsed');
    } else {
      text1.textContent = text1.textContent.replace(/▶/, '▲');
      text1.textContent = text1.textContent.replace(/collapsed/, 'expanded');
  });
  applyStyles(omittedFrames, omittedFramesStyle);
  return omittedFrames;
function insertBeforeBundle(
  document: Document,
  parent: Node,
  omitsCount: number,
  omitBundle: number,
  actionElement
) {
  const children = document.getElementsByName('bundle-' + omitBundle);
  if (children.length < 1) {
    return;
  let first: ?Node = children[0];
  while (first != null && first.parentNode !== parent) {
    first = first.parentNode;
  const div = document.createElement('div');
  enableTabClick(div);
  div.setAttribute('name', 'bundle-' + omitBundle);
  const text = document.createTextNode(
    '\u25BC ' + omitsCount + ' stack frames were expanded.'
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
); div.appendChild(text); div.addEventListener('click', function() { return actionElement.click(); }); applyStyles(div, omittedFramesStyle); div.style.display = 'none'; parent.insertBefore(div, first); } function frameDiv(document: Document, functionName, url, internalUrl) { const frame = document.createElement('div'); const frameFunctionName = document.createElement('div'); let cleanedFunctionName; if (!functionName || functionName === 'Object.<anonymous>') { cleanedFunctionName = '(anonymous function)'; } else { cleanedFunctionName = functionName; } const cleanedUrl = url.replace('webpack://', '.'); if (internalUrl) { applyStyles( frameFunctionName, Object.assign({}, functionNameStyle, depStyle) ); } else { applyStyles(frameFunctionName, functionNameStyle); } frameFunctionName.appendChild(document.createTextNode(cleanedFunctionName)); frame.appendChild(frameFunctionName); const frameLink = document.createElement('div'); applyStyles(frameLink, linkStyle); const frameAnchor = document.createElement('a'); applyStyles(frameAnchor, anchorStyle); frameAnchor.appendChild(document.createTextNode(cleanedUrl)); frameLink.appendChild(frameAnchor); frame.appendChild(frameLink); return frame; } function createFrame( document: Document, frameSetting: FrameSetting, frame: StackFrame, contextSize: number, critical: boolean, omits: OmitsObject, omitBundle: number, parentContainer: HTMLDivElement, lastElement: boolean ) { const { compiled } = frameSetting; let { functionName, _originalFileName: sourceFileName } = frame; const { fileName, lineNumber, columnNumber, _scriptCode: scriptLines, _originalLineNumber: sourceLineNumber, _originalColumnNumber: sourceColumnNumber, _originalScriptCode: sourceLines, } = frame;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
// TODO: find a better place for this. // Chrome has a bug with inferring function.name: // https://github.com/facebookincubator/create-react-app/issues/2097 // Let's ignore a meaningless name we get for top-level modules. if (functionName === 'Object.friendlySyntaxErrorLabel') { functionName = '(anonymous function)'; } let url; if (!compiled && sourceFileName && sourceLineNumber) { // Remove everything up to the first /src/ const trimMatch = /^[/|\\].*?[/|\\](src[/|\\].*)/.exec(sourceFileName); if (trimMatch && trimMatch[1]) { sourceFileName = trimMatch[1]; } url = sourceFileName + ':' + sourceLineNumber; if (sourceColumnNumber) { url += ':' + sourceColumnNumber; } } else if (fileName && lineNumber) { url = fileName + ':' + lineNumber; if (columnNumber) { url += ':' + columnNumber; } } else { url = 'unknown'; } let needsHidden = false; const internalUrl = isInternalFile(url, sourceFileName); if (internalUrl) { ++omits.value; needsHidden = true; } let collapseElement = null; if (!internalUrl || lastElement) { if (omits.value > 0) { const capV = omits.value; const omittedFrames = getGroupToggle(document, capV, omitBundle); window.requestAnimationFrame(() => { insertBeforeBundle( document, parentContainer, capV, omitBundle, omittedFrames ); }); if (lastElement && internalUrl) { collapseElement = omittedFrames; } else { parentContainer.appendChild(omittedFrames); } ++omits.bundle; } omits.value = 0; } const elem = frameDiv(document, functionName, url, internalUrl); if (needsHidden) { applyStyles(elem, hiddenStyle); elem.setAttribute('name', 'bundle-' + omitBundle); } let hasSource = false; if (!internalUrl) { if ( compiled && scriptLines && scriptLines.length !== 0 && lineNumber != null ) {
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
elem.appendChild( createCode( document, scriptLines, lineNumber, columnNumber, contextSize, critical ) ); hasSource = true; } else if ( !compiled && sourceLines && sourceLines.length !== 0 && sourceLineNumber != null ) { elem.appendChild( createCode( document, sourceLines, sourceLineNumber, sourceColumnNumber, contextSize, critical ) ); hasSource = true; } } return { elem: elem, hasSource: hasSource, collapseElement: collapseElement }; } export { createFrame };