<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @flow
import { oneLine } from 'common-tags';
import queryString from 'query-string';
import {
  processProfile,
  unserializeProfileOfArbitraryFormat,
} from '../profile-logic/process-profile';
import { SymbolStore } from '../profile-logic/symbol-store';
import { symbolicateProfile } from '../profile-logic/symbolication';
import * as MozillaSymbolicationAPI from '../profile-logic/mozilla-symbolication-api';
import { mergeProfiles } from '../profile-logic/comparison';
import { decompress } from '../utils/gz';
import { expandUrl } from '../utils/shorten-url';
import { TemporaryError } from '../utils/errors';
import JSZip from 'jszip';
import {
  getSelectedThreadIndexOrNull,
  getGlobalTrackOrder,
  getHiddenGlobalTracks,
  getHiddenLocalTracksByPid,
  getLocalTrackOrderByPid,
  getLegacyThreadOrder,
  getLegacyHiddenThreads,
} from '../selectors/url-state';
import {
  stateFromLocation,
  getDataSourceFromPathParts,
} from '../app-logic/url-handling';
import {
  initializeLocalTrackOrderByPid,
  initializeHiddenLocalTracksByPid,
  computeLocalTracksByPid,
  computeGlobalTracks,
  initializeGlobalTrackOrder,
  initializeSelectedThreadIndex,
  initializeHiddenGlobalTracks,
  getVisibleThreads,
} from '../profile-logic/tracks';
import { getProfile, getProfileOrNull } from '../selectors/profile';
import { getView } from '../selectors/app';
import { setDataSource } from './profile-view';

import type {
  FunctionsUpdatePerThread,
  FuncToFuncMap,
  RequestedLib,
  ImplementationFilter,
} from '../types/actions';
import type { TransformStacksPerThread } from '../types/transforms';
import type { Action, ThunkAction, Dispatch } from '../types/store';
import type {
  Profile,
  ThreadIndex,
  IndexIntoFuncTable,
} from '../types/profile';

/**
 * This file collects all the actions that are used for receiving the profile in the
 * client and getting it into the processed format.
 */

export function triggerLoadingFromUrl(profileUrl: string): Action {
  return {
    type: 'TRIGGER_LOADING_FROM_URL',
    profileUrl,
  };
}

export function waitingForProfileFromAddon(): Action {
  return {
    type: 'WAITING_FOR_PROFILE_FROM_ADDON',
  };
}

/**
 * Call this function once the profile has been fetched and pre-processed from whatever
 * source (url, addon, file, etc).
 */
export function loadProfile(
  profile: Profile,
  config: $Shape<{|
    pathInZipFile: string,
    implementationFilter: ImplementationFilter,
    transformStacks: TransformStacksPerThread,
    geckoProfiler?: $GeckoProfiler,
  |}> = {},
  initialLoad: boolean = false
): ThunkAction<Promise<void>> {
  return async dispatch => {
    if (profile.threads.length === 0) {
      console.error('This profile has no threads.', profile);
      dispatch(
        fatalError(
          new Error(
            'No threads were captured in this profile, there is nothing to display.'
          )
        )
      );
      return;
    }

    dispatch({
      type: 'PROFILE_LOADED',<commit_msg>Add a comment that explains two dispatches in loadProfile<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @flow
import { oneLine } from 'common-tags';
import queryString from 'query-string';
import {
  processProfile,
  unserializeProfileOfArbitraryFormat,
} from '../profile-logic/process-profile';
import { SymbolStore } from '../profile-logic/symbol-store';
import { symbolicateProfile } from '../profile-logic/symbolication';
import * as MozillaSymbolicationAPI from '../profile-logic/mozilla-symbolication-api';
import { mergeProfiles } from '../profile-logic/comparison';
import { decompress } from '../utils/gz';
import { expandUrl } from '../utils/shorten-url';
import { TemporaryError } from '../utils/errors';
import JSZip from 'jszip';
import {
  getSelectedThreadIndexOrNull,
  getGlobalTrackOrder,
  getHiddenGlobalTracks,
  getHiddenLocalTracksByPid,
  getLocalTrackOrderByPid,
  getLegacyThreadOrder,
  getLegacyHiddenThreads,
} from '../selectors/url-state';
import {
  stateFromLocation,
  getDataSourceFromPathParts,
} from '../app-logic/url-handling';
import {
  initializeLocalTrackOrderByPid,
  initializeHiddenLocalTracksByPid,
  computeLocalTracksByPid,
  computeGlobalTracks,
  initializeGlobalTrackOrder,
  initializeSelectedThreadIndex,
  initializeHiddenGlobalTracks,
  getVisibleThreads,
} from '../profile-logic/tracks';
import { getProfile, getProfileOrNull } from '../selectors/profile';
import { getView } from '../selectors/app';
import { setDataSource } from './profile-view';

import type {
  FunctionsUpdatePerThread,
  FuncToFuncMap,
  RequestedLib,
  ImplementationFilter,
} from '../types/actions';
import type { TransformStacksPerThread } from '../types/transforms';
import type { Action, ThunkAction, Dispatch } from '../types/store';
import type {
  Profile,
  ThreadIndex,
  IndexIntoFuncTable,
} from '../types/profile';

/**
 * This file collects all the actions that are used for receiving the profile in the
 * client and getting it into the processed format.
 */

export function triggerLoadingFromUrl(profileUrl: string): Action {
  return {
    type: 'TRIGGER_LOADING_FROM_URL',
    profileUrl,
  };
}

export function waitingForProfileFromAddon(): Action {
  return {
    type: 'WAITING_FOR_PROFILE_FROM_ADDON',
  };
}

/**
 * Call this function once the profile has been fetched and pre-processed from whatever
 * source (url, addon, file, etc).
 */
export function loadProfile(
  profile: Profile,
  config: $Shape<{|
    pathInZipFile: string,
    implementationFilter: ImplementationFilter,
    transformStacks: TransformStacksPerThread,
    geckoProfiler?: $GeckoProfiler,
  |}> = {},
  initialLoad: boolean = false
): ThunkAction<Promise<void>> {
  return async dispatch => {
    if (profile.threads.length === 0) {
      console.error('This profile has no threads.', profile);
      dispatch(
        fatalError(
          new Error(
            'No threads were captured in this profile, there is nothing to display.'
          )
        )
      );
      return;
    }

    // We have a 'PROFILE_LOADED' dispatch here and a second dispatch for
    // `finalizeProfileView`. Normally this is an anti-pattern but that was
    // necessary for initial load url handling. We are not dispatching
    // `finalizeProfileView` here if it's initial load, instead are getting the
    // url, upgrading the url and then creating a UrlState that we can use
    // first. That is necessary because we need a UrlState inside `finalizeProfileView`.
    // If this is not the initial load, we are dispatching both of them.
    dispatch({
      type: 'PROFILE_LOADED',
{'fraction_non_alphanumeric': 0.10818546078992558, 'fraction_numerical': 0.0014310246136233543, 'mean_word_length': 3.897687456201822, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6250441', 'n_tokens_mistral': 2033, 'n_tokens_neox': 1980, 'n_words': 596}