tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

context.js (4609B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 import {
      6  getThreadContext,
      7  getSelectedFrame,
      8  getCurrentThread,
      9  hasSource,
     10  hasSourceActor,
     11  getCurrentlyFetchedTopFrame,
     12  hasFrame,
     13 } from "../selectors/index";
     14 
     15 // Context encapsulates the main parameters of the current redux state, which
     16 // impact most other information tracked by the debugger.
     17 //
     18 // The main use of Context is to control when asynchronous operations are
     19 // allowed to make changes to the program state. Such operations might be
     20 // invalidated as the state changes from the time the operation was originally
     21 // initiated. For example, operations on pause state might still continue even
     22 // after the thread unpauses.
     23 //
     24 // The methods below can be used to compare an old context with the current one
     25 // and see if the operation is now invalid and should be abandoned. Actions can
     26 // also include a 'cx' Context property, which will be checked by the context
     27 // middleware. If the action fails validateContextAction() then it will not be
     28 // dispatched.
     29 //
     30 // Context can additionally be used as a shortcut to access the main properties
     31 // of the pause state.
     32 
     33 // A normal Context is invalidated if the target navigates.
     34 
     35 // A ThreadContext is invalidated if the target navigates, or if the current
     36 // thread changes, pauses, or resumes.
     37 
     38 export class ContextError extends Error {
     39  constructor(msg) {
     40    // Use a prefix string to help `PromiseTestUtils.allowMatchingRejectionsGlobally`
     41    // ignore all these exceptions as this is based on error strings.
     42    super(`DebuggerContextError: ${msg}`);
     43  }
     44 }
     45 
     46 export function validateNavigateContext(state, cx) {
     47  const newcx = getThreadContext(state);
     48 
     49  if (newcx.navigateCounter != cx.navigateCounter) {
     50    throw new ContextError("Page has navigated");
     51  }
     52 }
     53 
     54 export function validateThreadContext(state, cx) {
     55  const newcx = getThreadContext(state);
     56 
     57  if (cx.thread != newcx.thread) {
     58    throw new ContextError("Current thread has changed");
     59  }
     60 
     61  if (cx.pauseCounter != newcx.pauseCounter) {
     62    throw new ContextError("Current thread has paused or resumed");
     63  }
     64 }
     65 
     66 export function validateContext(state, cx) {
     67  validateNavigateContext(state, cx);
     68 
     69  if ("thread" in cx) {
     70    validateThreadContext(state, cx);
     71  }
     72 }
     73 
     74 export function validateSelectedFrame(state, selectedFrame) {
     75  const newThread = getCurrentThread(state);
     76  if (selectedFrame.thread != newThread) {
     77    throw new ContextError("Selected thread has changed");
     78  }
     79 
     80  const newSelectedFrame = getSelectedFrame(state);
     81  // Compare frame's IDs as frame objects are cloned during mapping
     82  if (selectedFrame.id != newSelectedFrame?.id) {
     83    throw new ContextError("Selected frame changed");
     84  }
     85 }
     86 
     87 export function validateBreakpoint(state, breakpoint) {
     88  // XHR breakpoint don't use any location and are always valid
     89  if (!breakpoint.location) {
     90    return;
     91  }
     92 
     93  if (!hasSource(state, breakpoint.location.source.id)) {
     94    throw new ContextError(
     95      `Breakpoint's location is obsolete (source '${breakpoint.location.source.id}' no longer exists)`
     96    );
     97  }
     98  if (!hasSource(state, breakpoint.generatedLocation.source.id)) {
     99    throw new ContextError(
    100      `Breakpoint's generated location is obsolete (source '${breakpoint.generatedLocation.source.id}' no longer exists)`
    101    );
    102  }
    103 }
    104 
    105 export function validateSource(state, source) {
    106  if (!hasSource(state, source.id)) {
    107    throw new ContextError(
    108      `Obsolete source (source '${source.id}' no longer exists)`
    109    );
    110  }
    111 }
    112 
    113 export function validateSourceActor(state, sourceActor) {
    114  if (!hasSourceActor(state, sourceActor.id)) {
    115    throw new ContextError(
    116      `Obsolete source actor (source '${sourceActor.id}' no longer exists)`
    117    );
    118  }
    119 }
    120 
    121 export function validateThreadFrames(state, thread, frames) {
    122  const newThread = getCurrentThread(state);
    123  if (thread != newThread) {
    124    throw new ContextError("Selected thread has changed");
    125  }
    126  const newTopFrame = getCurrentlyFetchedTopFrame(state, newThread);
    127  if (newTopFrame?.id != frames[0].id) {
    128    throw new ContextError("Thread moved to another location");
    129  }
    130 }
    131 
    132 export function validateFrame(state, frame) {
    133  if (!hasFrame(state, frame)) {
    134    throw new ContextError(
    135      `Obsolete frame (frame '${frame.id}' no longer exists)`
    136    );
    137  }
    138 }
    139 
    140 export function isValidThreadContext(state, cx) {
    141  const newcx = getThreadContext(state);
    142  return cx.thread == newcx.thread && cx.pauseCounter == newcx.pauseCounter;
    143 }