@swmansion/argent 0.20.0 → 0.20.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
Binary file
Binary file
@@ -133964,6 +133964,98 @@ async function runPipeline(input, options) {
133964
133964
  };
133965
133965
  }
133966
133966
 
133967
+ // ../tool-server/src/utils/react-profiler/component-names.ts
133968
+ var WRAPPER_PATTERNS = [/^Forget\((.+)\)$/, /^Memo\((.+)\)$/, /^ForwardRef\((.+)\)$/];
133969
+ var MAX_WRAPPER_DEPTH = 4;
133970
+ function stripComponentWrappers(raw) {
133971
+ let name = raw;
133972
+ let hasForget = false;
133973
+ let hasMemo = false;
133974
+ let hasForwardRef = false;
133975
+ for (let i = 0; i < MAX_WRAPPER_DEPTH; i++) {
133976
+ const m = WRAPPER_PATTERNS.map((re) => name.match(re)).find(Boolean);
133977
+ if (!m) break;
133978
+ if (name.startsWith("Forget(")) hasForget = true;
133979
+ else if (name.startsWith("Memo(")) hasMemo = true;
133980
+ else if (name.startsWith("ForwardRef(")) hasForwardRef = true;
133981
+ name = m[1];
133982
+ }
133983
+ return { baseName: name, hasForget, hasMemo, hasForwardRef };
133984
+ }
133985
+ function annotateComponentName(raw) {
133986
+ const { baseName, hasForget, hasMemo, hasForwardRef } = stripComponentWrappers(raw);
133987
+ const parts2 = [];
133988
+ if (hasMemo) parts2.push("React.memo");
133989
+ if (hasForget) parts2.push("React Compiler");
133990
+ if (hasForwardRef) parts2.push("forwardRef");
133991
+ const tag3 = parts2.length > 0 ? ` [${parts2.join(" + ")}]` : "";
133992
+ return { displayName: baseName, tag: tag3, rawName: raw };
133993
+ }
133994
+ function resolveComponentName(query, recordedNames) {
133995
+ const names = [...new Set(recordedNames)];
133996
+ const sharingDisplayName = (raw) => {
133997
+ const display = annotateComponentName(raw).displayName;
133998
+ return names.filter((n) => n !== raw && annotateComponentName(n).displayName === display);
133999
+ };
134000
+ if (names.includes(query)) {
134001
+ return { kind: "exact", rawName: query, alsoMatching: sharingDisplayName(query) };
134002
+ }
134003
+ const candidates = names.filter((n) => annotateComponentName(n).displayName === query);
134004
+ if (candidates.length === 1) {
134005
+ return { kind: "display", rawName: candidates[0], query };
134006
+ }
134007
+ if (candidates.length > 1) {
134008
+ return { kind: "ambiguous", query, candidates };
134009
+ }
134010
+ return { kind: "missing", query, suggestions: suggestNames(query, names) };
134011
+ }
134012
+ function suggestNames(query, names, limit = 5) {
134013
+ const needle = query.toLowerCase();
134014
+ if (needle.length < 2) return [];
134015
+ return names.filter((n) => {
134016
+ const hay = `${n} ${annotateComponentName(n).displayName}`.toLowerCase();
134017
+ return hay.includes(needle) || needle.includes(annotateComponentName(n).displayName.toLowerCase());
134018
+ }).slice(0, limit);
134019
+ }
134020
+ function describeResolution(resolution) {
134021
+ if (resolution.kind === "display") {
134022
+ const { tag: tag3 } = annotateComponentName(resolution.rawName);
134023
+ const why = tag3 ? ` (${tag3.trim().slice(1, -1)})` : "";
134024
+ return `> Resolved \`${resolution.query}\` to the recorded component \`${resolution.rawName}\`${why}. Either name works here.`;
134025
+ }
134026
+ if (resolution.alsoMatching.length > 0) {
134027
+ const others = resolution.alsoMatching.map((n) => `\`${n}\``).join(", ");
134028
+ return `> Showing \`${resolution.rawName}\` only. ${others} also appear${resolution.alsoMatching.length === 1 ? "s" : ""} under this name once wrappers are stripped; they are separate fibers, so pass the exact name to target one.`;
134029
+ }
134030
+ return "";
134031
+ }
134032
+ function renderComponentNameMiss(resolution, context = {}) {
134033
+ if (resolution.kind === "ambiguous") {
134034
+ const list = resolution.candidates.map((c) => `- \`${c}\``).join("\n");
134035
+ return `_Component \`${resolution.query}\` is ambiguous: ${resolution.candidates.length} recorded components share this name once \`Memo(...)\` / \`ForwardRef(...)\` / \`Forget(...)\` wrappers are stripped. They are separate fibers and are not merged, because a combined total would not describe any real component. Re-run with one of these exact \`component_name\` values:_
134036
+
134037
+ ${list}`;
134038
+ }
134039
+ const recorded = context.fiberRenders != null && context.commits != null ? ` The session recorded ${context.fiberRenders} fiber renders across ${context.commits} commits.` : "";
134040
+ const suggestions = resolution.suggestions.length > 0 ? `
134041
+
134042
+ Closest recorded names \u2014 pass one verbatim as \`component_name\`:
134043
+ ` + resolution.suggestions.map((s) => `- \`${s}\``).join("\n") : "";
134044
+ return `_Component \`${resolution.query}\` not found in this profiling session \u2014 no exact match, and no component whose displayed name is \`${resolution.query}\` once \`Memo(...)\` / \`ForwardRef(...)\` / \`Forget(...)\` wrappers are stripped.${recorded}_${suggestions}
134045
+
134046
+ To list every component in a commit instead, run \`profiler-commit-query mode=by_index commit_index=<n>\`.`;
134047
+ }
134048
+ function astLookupCandidates(raw) {
134049
+ const keys = [raw];
134050
+ const { baseName } = stripComponentWrappers(raw);
134051
+ if (baseName !== raw) keys.push(baseName);
134052
+ const withoutSuffix = baseName.replace(/\(.*\)$/, "");
134053
+ if (withoutSuffix !== baseName && /^[A-Za-z_$][\w$]*$/.test(withoutSuffix)) {
134054
+ keys.push(withoutSuffix);
134055
+ }
134056
+ return keys;
134057
+ }
134058
+
133967
134059
  // ../tool-server/src/utils/react-profiler/pipeline/06-resolve/ast-index.ts
133968
134060
  var import_fs3 = require("fs");
133969
134061
  var import_path6 = require("path");
@@ -134160,26 +134252,6 @@ var import_fs4 = require("fs");
134160
134252
  var import_path7 = require("path");
134161
134253
  var MAX_INLINE_COMMITS = 10;
134162
134254
  var REPORT_FILENAME = "react-profiler-report.md";
134163
- function annotateComponentName(raw) {
134164
- let name = raw;
134165
- let hasForget = false;
134166
- let hasMemo = false;
134167
- let hasForwardRef = false;
134168
- for (let i = 0; i < 4; i++) {
134169
- const m = name.match(/^Forget\((.+)\)$/) || name.match(/^Memo\((.+)\)$/) || name.match(/^ForwardRef\((.+)\)$/);
134170
- if (!m) break;
134171
- if (name.startsWith("Forget(")) hasForget = true;
134172
- else if (name.startsWith("Memo(")) hasMemo = true;
134173
- else if (name.startsWith("ForwardRef(")) hasForwardRef = true;
134174
- name = m[1];
134175
- }
134176
- const parts2 = [];
134177
- if (hasMemo) parts2.push("React.memo");
134178
- if (hasForget) parts2.push("React Compiler");
134179
- if (hasForwardRef) parts2.push("forwardRef");
134180
- const tag3 = parts2.length > 0 ? ` [${parts2.join(" + ")}]` : "";
134181
- return { displayName: name, tag: tag3, rawName: raw };
134182
- }
134183
134255
  async function renderProfilingReport(input) {
134184
134256
  const reportFile = (0, import_path7.join)(input.debugDir, REPORT_FILENAME);
134185
134257
  if (input.allClear) {
@@ -134696,7 +134768,7 @@ Fails if react-profiler-stop has not been called or no profiling data is stored.
134696
134768
  try {
134697
134769
  const astIndex = await buildAstIndexWithDiagnostics(params.project_root);
134698
134770
  for (const finding of pipelineOutput.componentFindings) {
134699
- const entry = astIndex.index.get(finding.component);
134771
+ const entry = astLookupCandidates(finding.component).map((k) => astIndex.index.get(k)).find(Boolean);
134700
134772
  if (entry) {
134701
134773
  finding.sourceLocation = {
134702
134774
  file: entry.file,
@@ -134789,7 +134861,9 @@ When several files define a component with the same name (e.g. platform variants
134789
134861
  services: () => ({}),
134790
134862
  async execute(_services, params) {
134791
134863
  const astIndex = await buildAstIndexWithDiagnostics(params.project_root);
134792
- const entry = astIndex.index.get(params.component_name);
134864
+ const lookupKeys = astLookupCandidates(params.component_name);
134865
+ const matchedKey = lookupKeys.find((k) => astIndex.index.has(k));
134866
+ const entry = matchedKey ? astIndex.index.get(matchedKey) : void 0;
134793
134867
  if (!entry) {
134794
134868
  if (!astIndex.treeSitterAvailable) {
134795
134869
  return {
@@ -134801,7 +134875,7 @@ When several files define a component with the same name (e.g. platform variants
134801
134875
  return {
134802
134876
  found: false,
134803
134877
  component: params.component_name,
134804
- message: `Component "${params.component_name}" not found in ${params.project_root} (searched ${astIndex.indexedFiles} files).`
134878
+ message: `Component "${params.component_name}" not found in ${params.project_root} (searched ${astIndex.indexedFiles} files; also tried ${lookupKeys.slice(1).map((k) => `"${k}"`).join(", ") || "no variants"}).`
134805
134879
  };
134806
134880
  }
134807
134881
  let source = "";
@@ -134815,7 +134889,10 @@ When several files define a component with the same name (e.g. platform variants
134815
134889
  }
134816
134890
  return {
134817
134891
  found: true,
134818
- component: params.component_name,
134892
+ // The key that actually matched, so the caller can tell which name hit
134893
+ // when a wrapped name resolved through to a bare source identifier.
134894
+ component: matchedKey ?? params.component_name,
134895
+ requested: params.component_name,
134819
134896
  file: entry.file,
134820
134897
  line: entry.line,
134821
134898
  col: entry.col,
@@ -140414,9 +140491,21 @@ function renderComponentCpu(index, commitTree, componentName, topN2) {
140414
140491
  if (!commitTree || commitTree.commits.length === 0) {
140415
140492
  return "_No commit data available. Run react-profiler-analyze first._";
140416
140493
  }
140417
- const componentCommits = commitTree.commits.filter((c) => c.componentName === componentName);
140494
+ const resolution = resolveComponentName(
140495
+ componentName,
140496
+ commitTree.commits.map((c) => c.componentName)
140497
+ );
140498
+ if (resolution.kind === "ambiguous" || resolution.kind === "missing") {
140499
+ return renderComponentNameMiss(resolution, {
140500
+ fiberRenders: commitTree.commits.length,
140501
+ commits: new Set(commitTree.commits.map((c) => c.commitIndex)).size
140502
+ });
140503
+ }
140504
+ const resolvedName = resolution.rawName;
140505
+ const resolutionNote = describeResolution(resolution);
140506
+ const componentCommits = commitTree.commits.filter((c) => c.componentName === resolvedName);
140418
140507
  if (componentCommits.length === 0) {
140419
- return `_Component \`${componentName}\` not found in commit data._`;
140508
+ return `_Component \`${resolvedName}\` not found in commit data._`;
140420
140509
  }
140421
140510
  const commitWindows = /* @__PURE__ */ new Map();
140422
140511
  for (const c of componentCommits) {
@@ -140448,12 +140537,13 @@ function renderComponentCpu(index, commitTree, componentName, topN2) {
140448
140537
  }
140449
140538
  const sorted = [...aggregated.entries()].sort((a, b) => b[1].selfMs - a[1].selfMs).slice(0, topN2);
140450
140539
  if (sorted.length === 0) {
140451
- return `_No CPU samples found during \`${componentName}\` commits._`;
140540
+ return `_No CPU samples found during \`${resolvedName}\` commits._`;
140452
140541
  }
140453
140542
  const totalCommitMs = [...commitWindows.values()].reduce((sum, w) => sum + w.duration, 0);
140454
140543
  const lines = [
140455
- `## CPU During \`${componentName}\` Commits`,
140544
+ `## CPU During \`${resolvedName}\` Commits`,
140456
140545
  "",
140546
+ ...resolutionNote ? [resolutionNote, ""] : [],
140457
140547
  `**Commits:** ${commitWindows.size} **Total commit time:** ${totalCommitMs.toFixed(1)}ms`,
140458
140548
  "",
140459
140549
  "| Function | Self (ms) | Total (ms) | Location |",
@@ -140628,9 +140718,21 @@ function formatReason2(commit) {
140628
140718
  return parts2.join(" ");
140629
140719
  }
140630
140720
  function renderByComponent(commits, componentName, topN2) {
140631
- const matching = commits.filter((c) => c.componentName === componentName);
140721
+ const resolution = resolveComponentName(
140722
+ componentName,
140723
+ commits.map((c) => c.componentName)
140724
+ );
140725
+ if (resolution.kind === "ambiguous" || resolution.kind === "missing") {
140726
+ return renderComponentNameMiss(resolution, {
140727
+ fiberRenders: commits.length,
140728
+ commits: new Set(commits.map((c) => c.commitIndex)).size
140729
+ });
140730
+ }
140731
+ const resolvedName = resolution.rawName;
140732
+ const resolutionNote = describeResolution(resolution);
140733
+ const matching = commits.filter((c) => c.componentName === resolvedName);
140632
140734
  if (matching.length === 0) {
140633
- return `_Component \`${componentName}\` not found in commit data._`;
140735
+ return `_Component \`${resolvedName}\` not found in commit data._`;
140634
140736
  }
140635
140737
  const byCommit = /* @__PURE__ */ new Map();
140636
140738
  for (const c of matching) {
@@ -140651,8 +140753,9 @@ function renderByComponent(commits, componentName, topN2) {
140651
140753
  parentName: entries[0].parentName ?? "\u2014"
140652
140754
  })).sort((a, b) => b.totalDuration - a.totalDuration).slice(0, topN2);
140653
140755
  const lines = [
140654
- `## Commits for \`${componentName}\``,
140756
+ `## Commits for \`${resolvedName}\``,
140655
140757
  "",
140758
+ ...resolutionNote ? [resolutionNote, ""] : [],
140656
140759
  `**Total occurrences:** ${matching.length} across ${byCommit.size} commits`,
140657
140760
  "",
140658
140761
  "| Commit | Instances | Duration (ms) | Commit Total (ms) | Time (ms) | Reason | Parent |",
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.20.0",
3
+ "version": "0.20.1-next.0",
4
4
  "mcpName": "io.github.software-mansion/argent",
5
5
  "description": "MCP server for iOS Simulator and Android Emulator control",
6
6
  "license": "Apache-2.0",
@@ -45,6 +45,13 @@ Call `profiler-cpu-query`. Modes:
45
45
  - `call_tree` — callers and callees of a specific `function_name`.
46
46
  - `component_cpu` — aggregate CPU during all commits of a `component_name`.
47
47
 
48
+ > **Component names:** pass the name exactly as the report shows it. The report strips
49
+ > `Forget(...)` / `Memo(...)` / `ForwardRef(...)` wrappers and marks them with a
50
+ > `[React Compiler]` / `[React.memo] `/ `[forwardRef]` tag; both that displayed name and the
51
+ > underlying wrapped name resolve. If a name maps to several distinct fibers the tool lists
52
+ > the exact names to retry with rather than merging them — a combined total would not describe
53
+ > any real component.
54
+
48
55
  ## Commit query
49
56
 
50
57
  ```json