Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/devtools/client/debugger/src/utils/pause/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 7 kB image not shown  

Quelle  scopes.js   Sprache: JAVA

 
/* 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/>. */


// This file contains utility functions which supports the structure & display of
// scopes information in Scopes panel.

import * as objectInspector from "resource://devtools/client/shared/components/object-inspector/index.js";
import { simplifyDisplayName } from "../pause/frames/index";

const {
  utils: {
    node: { NODE_TYPES },
  },
} = objectInspector;

// The heading that should be displayed for the scope
function _getScopeTitle(type, scope) {
  if (type === "block" && scope.block && scope.block.displayName) {
    return scope.block.displayName;
  }

  if (type === "function" && scope.function) {
    return scope.function.displayName
      ? simplifyDisplayName(scope.function.displayName)
      : L10N.getStr("anonymousFunction");
  }
  return L10N.getStr("scopes.block");
}

function _getThisVariable(this_, path) {
  if (!this_) {
    return null;
  }

  return {
    name: "",
    path: `${path}/<this>`,
    contents: { value: this_ },
  };
}

/**
 * Builds a tree of nodes representing all the variables and arguments
 * for the bindings from a scope.
 *
 * Each binding => { variables: Array, arguments: Array }
 * Each binding argument => [name: string, contents: BindingContents]
 *
 * @param {Array} bindings
 * @param {String} parentName
 * @returns
 */

function _getBindingVariables(bindings, parentName) {
  if (!bindings) {
    return [];
  }

  const nodes = [];
  const addNode = (name, contents) =>
    nodes.push({ name, contents, path: `${parentName}/${name}` });

  for (const arg of bindings.arguments) {
    // `arg` is an object which only has a single property whose name is the name of the
    // argument. So here we can directly pick the first (and only) entry of `arg`
    const [name, contents] = Object.entries(arg)[0];
    addNode(name, contents);
  }

  for (const name in bindings.variables) {
    addNode(name, bindings.variables[name]);
  }

  return nodes;
}

/**
 * This generates the scope item for rendering in the scopes panel.
 *
 * @param {*} scope
 * @param {*} selectedFrame
 * @param {*} frameScopes
 * @param {*} why
 * @param {*} scopeIndex
 * @returns
 */

function _getScopeItem(scope, selectedFrame, frameScopes, why, scopeIndex) {
  const { type, actor } = scope;

  const isLocalScope = scope.actor === frameScopes.actor;

  const key = `${actor}-${scopeIndex}`;
  if (type === "function" || type === "block") {
    const { bindings } = scope;

    let vars = _getBindingVariables(bindings, key);

    // show exception, return, and this variables in innermost scope
    if (isLocalScope) {
      vars = vars.concat(_getFrameExceptionOrReturnedValueVariables(why, key));

      let thisDesc_ = selectedFrame.this;

      if (bindings && "this" in bindings) {
        // The presence of "this" means we're rendering a "this" binding
        // generated from mapScopes and this can override the binding
        // provided by the current frame.
        thisDesc_ = bindings.this ? bindings.this.value : null;
      }

      const this_ = _getThisVariable(thisDesc_, key);

      if (this_) {
        vars.push(this_);
      }
    }

    if (vars?.length) {
      const title = _getScopeTitle(type, scope) || "";
      vars.sort((a, b) => a.name.localeCompare(b.name));
      return {
        name: title,
        path: key,
        contents: vars,
        type: NODE_TYPES.BLOCK,
      };
    }
  } else if (type === "object" && scope.object) {
    let value = scope.object;
    // If this is the global window scope, mark it as such so that it will
    // preview Window: Global instead of Window: Window
    if (value.class === "Window") {
      value = { ...value, displayClass: "Global" };
    }
    return {
      name: scope.object.class,
      path: key,
      contents: { value },
    };
  }

  return null;
}
/**
 * Merge the scope bindings for lexical scopes and its parent function body scopes
 * Note: block scopes are not merged. See browser_dbg-merge-scopes.js for test examples
 * to better understand the scenario,
 *
 * @param {*} scope
 * @param {*} parentScope
 * @param {*} item
 * @param {*} parentItem
 * @returns
 */

export function _mergeLexicalScopesBindings(
  scope,
  parentScope,
  item,
  parentItem
) {
  if (scope.scopeKind == "function lexical" && parentScope.type == "function") {
    const contents = item.contents.concat(parentItem.contents);
    contents.sort((a, b) => a.name.localeCompare(b.name));

    return {
      name: parentItem.name,
      path: parentItem.path,
      contents,
      type: NODE_TYPES.BLOCK,
    };
  }
  return null;
}

/**
 * Returns a string path for an scope item which can be used
 * in different pauses for a thread.
 *
 * @param {Object} item
 * @returns
 */


export function getScopeItemPath(item) {
  // Calling toString() on item.path allows symbols to be handled.
  return item.path.toString();
}

// Generate variables when the function throws an exception or returned a value.
function _getFrameExceptionOrReturnedValueVariables(why, path) {
  const vars = [];

  if (why && why.frameFinished) {
    const { frameFinished } = why;

    // Always display a `throw` property if present, even if it is falsy.
    if (Object.prototype.hasOwnProperty.call(frameFinished, "throw")) {
      vars.push({
        name: "",
        path: `${path}/<exception>`,
        contents: { value: frameFinished.throw },
      });
    }

    if (Object.prototype.hasOwnProperty.call(frameFinished, "return")) {
      const returned = frameFinished.return;

      // Do not display undefined. Do display falsy values like 0 and false. The
      // protocol grip for undefined is a JSON object: { type: "undefined" }.
      if (typeof returned !== "object" || returned.type !== "undefined") {
        vars.push({
          name: "",
          path: `${path}/<return>`,
          contents: { value: returned },
        });
      }
    }
  }

  return vars;
}

/**
 * Generates the scope items (for scopes related to selected frame) to be rendered in the scope panel
 * @param {*} why
 * @param {*} selectedFrame
 * @param {*} frameScopes
 * @returns
 */

export function getScopesItemsForSelectedFrame(
  why,
  selectedFrame,
  frameScopes
) {
  if (!why || !selectedFrame) {
    return null;
  }

  if (!frameScopes) {
    return null;
  }

  const scopes = [];

  let currentScope = frameScopes;
  let currentScopeIndex = 1;

  let prevScope = null,
    prevScopeItem = null;

  while (currentScope) {
    let currentScopeItem = _getScopeItem(
      currentScope,
      selectedFrame,
      frameScopes,
      why,
      currentScopeIndex
    );

    if (currentScopeItem) {
      const mergedItem =
        prevScope && prevScopeItem
          ? _mergeLexicalScopesBindings(
              prevScope,
              currentScope,
              prevScopeItem,
              currentScopeItem
            )
          : null;
      if (mergedItem) {
        currentScopeItem = mergedItem;
        scopes.pop();
      }
      scopes.push(currentScopeItem);
    }

    prevScope = currentScope;
    prevScopeItem = currentScopeItem;
    currentScopeIndex++;
    currentScope = currentScope.parent;
  }

  return scopes;
}

87%


¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.