Bug 1873432 - [devtools] Cleanup the use of parser worker for framework info r=devtools-reviewers,ochameau

Differential Revision: https://phabricator.services.mozilla.com/D197907
This commit is contained in:
Hubert Boma Manilla 2024-01-17 13:56:07 +00:00
Родитель b2aa371449
Коммит 2fa2142a50
13 изменённых файлов: 42 добавлений и 314 удалений

Просмотреть файл

@ -23,7 +23,7 @@
var lib$4 = {};
var isReactComponent$1 = {};
var isReactComponent = {};
var buildMatchMemberExpression = {};
@ -2935,20 +2935,20 @@
var hasRequiredIsReactComponent;
function requireIsReactComponent () {
if (hasRequiredIsReactComponent) return isReactComponent$1;
if (hasRequiredIsReactComponent) return isReactComponent;
hasRequiredIsReactComponent = 1;
Object.defineProperty(isReactComponent$1, "__esModule", {
Object.defineProperty(isReactComponent, "__esModule", {
value: true
});
isReactComponent$1.default = void 0;
isReactComponent.default = void 0;
var _buildMatchMemberExpression = requireBuildMatchMemberExpression();
const isReactComponent = (0, _buildMatchMemberExpression.default)("React.Component");
var _default = isReactComponent;
isReactComponent$1.default = _default;
const isReactComponent$1 = (0, _buildMatchMemberExpression.default)("React.Component");
var _default = isReactComponent$1;
isReactComponent.default = _default;
return isReactComponent$1;
return isReactComponent;
}
var isCompatTag = {};
@ -39058,61 +39058,6 @@ Please specify the "importAttributesKeyword" generator option, whose value can b
return "anonymous";
}
function getFramework(symbols) {
if (isReactComponent(symbols)) {
return "React";
}
if (isAngularComponent(symbols)) {
return "Angular";
}
if (isVueComponent(symbols)) {
return "Vue";
}
return null;
}
function isReactComponent({ importsReact, classes, identifiers }) {
return (
importsReact ||
extendsReactComponent(classes) ||
isReact(identifiers) ||
isRedux(identifiers)
);
}
function extendsReactComponent(classes) {
return classes.some(
classObj =>
libExports$2.isIdentifier(classObj.parent, { name: "Component" }) ||
libExports$2.isIdentifier(classObj.parent, { name: "PureComponent" }) ||
(libExports$2.isMemberExpression(classObj.parent, { computed: false }) &&
libExports$2.isIdentifier(classObj.parent, { name: "Component" }))
);
}
function isAngularComponent({ memberExpressions }) {
return memberExpressions.some(
item =>
item.expression == "angular.controller" ||
item.expression == "angular.module"
);
}
function isVueComponent({ identifiers }) {
return identifiers.some(identifier => identifier.name == "Vue");
}
/* This identifies the react lib file */
function isReact(identifiers) {
return identifiers.some(identifier => identifier.name == "isReactComponent");
}
/* This identifies the redux lib file */
function isRedux(identifiers) {
return identifiers.some(identifier => identifier.name == "Redux");
}
const symbolDeclarations = new Map();
function extractFunctionSymbol(path, state, symbols) {
@ -39196,7 +39141,6 @@ Please specify the "importAttributesKeyword" generator option, whose value can b
literals: [],
hasJsx: false,
hasTypes: false,
framework: undefined,
importsReact: false,
};
@ -39219,7 +39163,6 @@ Please specify the "importAttributesKeyword" generator option, whose value can b
// comments are extracted separately from the AST
symbols.comments = getComments(ast);
symbols.framework = getFramework(symbols);
return symbols;
}
@ -39492,9 +39435,7 @@ Please specify the "importAttributesKeyword" generator option, whose value can b
// functions: symbols.functions,
// The three following attributes are only used by `findBestMatchExpression` within the worker thread
// `memberExpressions`, `literals`
// This one is also used within the worker for framework computation
// `identifiers`
// `memberExpressions`, `literals`, `identifiers`
//
// These three memberExpressions, literals and identifiers attributes are arrays containing objects whose attributes are:
// * name: string
@ -39505,21 +39446,14 @@ Please specify the "importAttributesKeyword" generator option, whose value can b
// `findBestMatchExpression` uses `location`, `computed` and `expression` (not name).
// `expression` isn't used from the worker thread implementation of `findBestMatchExpression`.
// The main thread only uses `expression` and `location`.
// framework computation uses only:
// * `name` for identifiers
// * `expression` for memberExpression
// This is used within the worker for framework computation,
// and in the `getClassSymbols` function
// This is used by the `getClassSymbols` function in the Outline panel
// `classes`
// The two following are only used by the main thread for computing CodeMirror "mode"
hasJsx: symbols.hasJsx,
hasTypes: symbols.hasTypes,
// This is used in the main thread only to compute the source icon
framework: symbols.framework,
// This is only used by `findOutOfScopeLocations`:
// `comments`
};

Просмотреть файл

@ -109,7 +109,6 @@ class Tab extends PureComponent {
sourceActor,
}),
forTab: true,
modifier: icon => (["file", "javascript"].includes(icon) ? null : icon),
}),
div(
{

Просмотреть файл

@ -10,18 +10,14 @@ import { connect } from "devtools/client/shared/vendor/react-redux";
import AccessibleImage from "./AccessibleImage";
import { getSourceClassnames } from "../../utils/source";
import {
getSymbols,
isSourceBlackBoxed,
hasPrettyTab,
} from "../../selectors/index";
import { isSourceBlackBoxed, hasPrettyTab } from "../../selectors/index";
import "./SourceIcon.css";
class SourceIcon extends PureComponent {
static get propTypes() {
return {
modifier: PropTypes.func.isRequired,
modifier: PropTypes.func,
location: PropTypes.object.isRequired,
iconClass: PropTypes.string,
forTab: PropTypes.bool,
@ -47,13 +43,6 @@ class SourceIcon extends PureComponent {
export default connect((state, props) => {
const { forTab, location } = props;
// BreakpointHeading sometimes spawn locations without source actor for generated sources
// which disallows fetching symbols. In such race condition return the default icon.
// (this reproduces when running browser_dbg-breakpoints-popup.js)
if (!location.source.isOriginal && !location.sourceActor) {
return "file";
}
const symbols = getSymbols(state, location);
const isBlackBoxed = isSourceBlackBoxed(state, location.source);
// For the tab icon, we don't want to show the pretty icon for the non-pretty tab
const hasMatchingPrettyTab = !forTab && hasPrettyTab(state, location.source);
@ -62,7 +51,6 @@ export default connect((state, props) => {
// In addition to the "modifier" implemented by each callsite.
const iconClass = getSourceClassnames(
location.source,
symbols,
isBlackBoxed,
hasMatchingPrettyTab
);

Просмотреть файл

@ -19,7 +19,6 @@ const defaultSymbolDeclarations = {
literals: [],
hasJsx: false,
hasTypes: false,
framework: undefined,
};
describe("source-documents", () => {

Просмотреть файл

@ -75,7 +75,7 @@ export function formatSourceForList(
subtitle,
icon: hasTabOpened
? "tab result-item-icon"
: `result-item-icon ${getSourceClassnames(source, null, isBlackBoxed)}`,
: `result-item-icon ${getSourceClassnames(source, isBlackBoxed)}`,
id: source.id,
url: source.url,
source,

Просмотреть файл

@ -396,8 +396,6 @@ export function getTextAtPosition(sourceId, asyncContent, location) {
*
* @param {Object} source
* The reducer source object.
* @param {Object} symbols
* The reducer symbol object for the given source.
* @param {Boolean} isBlackBoxed
* To be set to true, when the given source is blackboxed.
* @param {Boolean} hasPrettyTab
@ -408,7 +406,6 @@ export function getTextAtPosition(sourceId, asyncContent, location) {
*/
export function getSourceClassnames(
source,
symbols,
isBlackBoxed,
hasPrettyTab = false
) {
@ -430,10 +427,6 @@ export function getSourceClassnames(
return "blackBox";
}
if (symbols && symbols.framework) {
return symbols.framework.toLowerCase();
}
if (isUrlExtension(source.url)) {
return "extension";
}

Просмотреть файл

@ -1,60 +0,0 @@
/* 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/>. */
import * as t from "@babel/types";
export function getFramework(symbols) {
if (isReactComponent(symbols)) {
return "React";
}
if (isAngularComponent(symbols)) {
return "Angular";
}
if (isVueComponent(symbols)) {
return "Vue";
}
return null;
}
function isReactComponent({ importsReact, classes, identifiers }) {
return (
importsReact ||
extendsReactComponent(classes) ||
isReact(identifiers) ||
isRedux(identifiers)
);
}
function extendsReactComponent(classes) {
return classes.some(
classObj =>
t.isIdentifier(classObj.parent, { name: "Component" }) ||
t.isIdentifier(classObj.parent, { name: "PureComponent" }) ||
(t.isMemberExpression(classObj.parent, { computed: false }) &&
t.isIdentifier(classObj.parent, { name: "Component" }))
);
}
function isAngularComponent({ memberExpressions }) {
return memberExpressions.some(
item =>
item.expression == "angular.controller" ||
item.expression == "angular.module"
);
}
function isVueComponent({ identifiers }) {
return identifiers.some(identifier => identifier.name == "Vue");
}
/* This identifies the react lib file */
function isReact(identifiers) {
return identifiers.some(identifier => identifier.name == "isReactComponent");
}
/* This identifies the redux lib file */
function isRedux(identifiers) {
return identifiers.some(identifier => identifier.name == "Redux");
}

Просмотреть файл

@ -20,7 +20,6 @@ import {
import { inferClassName } from "./utils/inferClassName";
import getFunctionName from "./utils/getFunctionName";
import { getFramework } from "./frameworks";
const symbolDeclarations = new Map();
@ -105,7 +104,6 @@ function extractSymbols(sourceId) {
literals: [],
hasJsx: false,
hasTypes: false,
framework: undefined,
importsReact: false,
};
@ -128,7 +126,6 @@ function extractSymbols(sourceId) {
// comments are extracted separately from the AST
symbols.comments = getComments(ast);
symbols.framework = getFramework(symbols);
return symbols;
}
@ -401,9 +398,7 @@ export function getSymbols(sourceId) {
// functions: symbols.functions,
// The three following attributes are only used by `findBestMatchExpression` within the worker thread
// `memberExpressions`, `literals`
// This one is also used within the worker for framework computation
// `identifiers`
// `memberExpressions`, `literals`, `identifiers`
//
// These three memberExpressions, literals and identifiers attributes are arrays containing objects whose attributes are:
// * name: string
@ -414,21 +409,14 @@ export function getSymbols(sourceId) {
// `findBestMatchExpression` uses `location`, `computed` and `expression` (not name).
// `expression` isn't used from the worker thread implementation of `findBestMatchExpression`.
// The main thread only uses `expression` and `location`.
// framework computation uses only:
// * `name` for identifiers
// * `expression` for memberExpression
// This is used within the worker for framework computation,
// and in the `getClassSymbols` function
// This is used by the `getClassSymbols` function in the Outline panel
// `classes`
// The two following are only used by the main thread for computing CodeMirror "mode"
hasJsx: symbols.hasJsx,
hasTypes: symbols.hasTypes,
// This is used in the main thread only to compute the source icon
framework: symbols.framework,
// This is only used by `findOutOfScopeLocations`:
// `comments`
};

Просмотреть файл

@ -3,167 +3,125 @@
exports[`Parser.getSymbols allSymbols 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols call expression 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols call sites 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols class 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols component 1`] = `
"hasJsx: true
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols destruct 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols es6 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols expression 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols finds symbols in an html file 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols flow 1`] = `
"hasJsx: false
hasTypes: true
framework: null"
hasTypes: true"
`;
exports[`Parser.getSymbols func 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols function names 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols jsx 1`] = `
"hasJsx: true
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols math 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols object expressions 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols optional chaining 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols private fields 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols proto 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols react component 1`] = `
"hasJsx: false
hasTypes: false
framework: React"
hasTypes: false"
`;
exports[`Parser.getSymbols regexp 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;
exports[`Parser.getSymbols var 1`] = `
"hasJsx: false
hasTypes: false
framework: null"
hasTypes: false"
`;

Просмотреть файл

@ -1,63 +0,0 @@
/* 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/>. */
import { getSymbols } from "../getSymbols";
import { populateOriginalSource } from "./helpers";
import cases from "jest-in-case";
cases(
"Parser.getFramework",
({ name, file, value }) => {
const source = populateOriginalSource("frameworks/plainJavascript");
const symbols = getSymbols(source.id);
expect(symbols.framework).toBeNull();
},
[
{
name: "is undefined when no framework",
file: "frameworks/plainJavascript",
value: null,
},
{
name: "does not get confused with angular (#6833)",
file: "frameworks/angular1FalsePositive",
value: null,
},
{
name: "recognizes ES6 React component",
file: "frameworks/reactComponent",
value: "React",
},
{
name: "recognizes ES5 React component",
file: "frameworks/reactComponentEs5",
value: "React",
},
{
name: "recognizes Angular 1 module",
file: "frameworks/angular1Module",
value: "Angular",
},
{
name: "recognizes declarative Vue file",
file: "frameworks/vueFileDeclarative",
value: "Vue",
},
{
name: "recognizes component Vue file",
file: "frameworks/vueFileComponent",
value: "Vue",
},
{
name: "recognizes the react library file",
file: "framework/reactLibrary",
value: "React",
},
{
name: "recognizes the redux library file",
file: "framework/reduxLibrary",
value: "React",
},
]
);

Просмотреть файл

@ -35,24 +35,15 @@ function summarize(symbol) {
return `${loc} ${expression} ${name}${params} ${klass} ${names} ${values} ${index}`.trim(); // eslint-disable-line max-len
}
const bools = ["hasJsx", "hasTypes"];
const strings = ["framework"];
function formatBool(name, symbols) {
return `${name}: ${symbols[name] ? "true" : "false"}`;
}
function formatString(name, symbols) {
return `${name}: ${symbols[name]}`;
}
function formatKey(name, symbols) {
if (bools.includes(name)) {
return formatBool(name, symbols);
}
if (strings.includes(name)) {
return formatString(name, symbols);
}
return `${name}:\n${symbols[name].map(summarize).join("\n")}`;
}

Просмотреть файл

@ -365,7 +365,7 @@ add_task(async function testSourceTreeOnTheIntegrationTestPage() {
// which happens when we select the source
assertSourceIcon(dbg, "react-component-module.js", "javascript");
await selectSource(dbg, "react-component-module.js");
assertSourceIcon(dbg, "react-component-module.js", "react");
assertSourceIcon(dbg, "react-component-module.js", "javascript");
info("Verify blackbox source icon");
await selectSource(dbg, "script.js");

Просмотреть файл

@ -28,11 +28,12 @@ add_task(async function () {
},
]);
info("Verify that the file is flagged as a React module");
info("Verify that the react file is flagged as a javascript module");
const sourceTab = findElementWithSelector(dbg, ".source-tab.active");
ok(
sourceTab.querySelector(".source-icon.react"),
"Source tab has a React icon"
sourceTab.querySelector(".source-icon.javascript"),
"Source tab for a react file has a Javascript icon"
);
assertSourceIcon(dbg, "App.js", "react");
assertSourceIcon(dbg, "App.js", "javascript");
});