profile-viewer 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/dist/136.4ad3301b8aacf759ea70.bundle.js +2 -0
  3. data/dist/136.4ad3301b8aacf759ea70.bundle.js.map +1 -0
  4. data/dist/171.621b9df5978342be5662.bundle.js +2 -0
  5. data/dist/171.621b9df5978342be5662.bundle.js.map +1 -0
  6. data/dist/18a5d1d99f1c65c33b71.png +0 -0
  7. data/dist/1ddbc3ce40af8c7a648b.svg +6 -0
  8. data/dist/280.b4210a48e650408000c3.bundle.js +2 -0
  9. data/dist/280.b4210a48e650408000c3.bundle.js.map +1 -0
  10. data/dist/556.2be67a37a0c61fdc2485.bundle.js +2 -0
  11. data/dist/{914.b9bc213d93173ce6b0cb.bundle.js.map → 556.2be67a37a0c61fdc2485.bundle.js.map} +1 -1
  12. data/dist/874.2a087b9b5a296a9c3fcd.bundle.js +2 -0
  13. data/dist/874.2a087b9b5a296a9c3fcd.bundle.js.map +1 -0
  14. data/dist/_headers +1 -2
  15. data/dist/contribute.json +31 -35
  16. data/dist/d6df0017c0241dfe86ff.svg +6 -0
  17. data/dist/docs/_sidebar.md +1 -0
  18. data/dist/docs/advanced-topics.md +1 -0
  19. data/dist/docs/async-posix-signal-control.md +102 -0
  20. data/dist/docs/guide-startup-shutdown.md +7 -7
  21. data/dist/docs/js/init.js +1 -1
  22. data/dist/index.html +1 -1
  23. data/dist/locales/README.md +1 -0
  24. data/dist/locales/be/app.ftl +42 -6
  25. data/dist/locales/de/app.ftl +109 -3
  26. data/dist/locales/el/app.ftl +110 -4
  27. data/dist/locales/en-CA/app.ftl +1125 -0
  28. data/dist/locales/en-GB/app.ftl +110 -4
  29. data/dist/locales/en-US/app.ftl +123 -6
  30. data/dist/locales/es-CL/app.ftl +110 -4
  31. data/dist/locales/fr/app.ftl +66 -4
  32. data/dist/locales/fur/app.ftl +1093 -0
  33. data/dist/locales/fy-NL/app.ftl +109 -3
  34. data/dist/locales/ia/app.ftl +109 -3
  35. data/dist/locales/it/app.ftl +109 -3
  36. data/dist/locales/kab/app.ftl +32 -2
  37. data/dist/locales/nl/app.ftl +110 -4
  38. data/dist/locales/pt-BR/app.ftl +111 -5
  39. data/dist/locales/ru/app.ftl +109 -3
  40. data/dist/locales/sv-SE/app.ftl +109 -3
  41. data/dist/locales/tr/app.ftl +907 -0
  42. data/dist/locales/uk/app.ftl +110 -4
  43. data/dist/locales/zh-CN/app.ftl +112 -6
  44. data/dist/locales/zh-TW/app.ftl +109 -3
  45. data/dist/main.ac7130d34ce3b872712a.bundle.js +201 -0
  46. data/dist/{main.8208fda2d35ddbe38d55.bundle.js.LICENSE.txt → main.ac7130d34ce3b872712a.bundle.js.LICENSE.txt} +1 -30
  47. data/dist/main.ac7130d34ce3b872712a.bundle.js.map +1 -0
  48. data/dist/photon/index.html +3 -2
  49. data/dist/photon/main.aafbcdad3fb08c7ae5b4.bundle.js +2 -0
  50. data/dist/photon/main.aafbcdad3fb08c7ae5b4.bundle.js.map +1 -0
  51. data/dist/robots.txt +4 -0
  52. data/dist/sw.js +1 -1
  53. data/dist/sw.js.map +1 -1
  54. data/dist/{workbox-27b29e6f.js → workbox-e3490c72.js} +2 -2
  55. data/dist/{workbox-27b29e6f.js.map → workbox-e3490c72.js.map} +1 -1
  56. data/dist/zee-worker.js +1 -1
  57. data/ruby-bin/profile-viewer +53 -16
  58. data/ruby-bin/profile-viewer-version.rb +3 -0
  59. metadata +60 -25
  60. data/dist/119.cc58ce313e67f80f50f3.bundle.js +0 -2
  61. data/dist/119.cc58ce313e67f80f50f3.bundle.js.map +0 -1
  62. data/dist/131.c21d348572deab4ece66.bundle.js +0 -2
  63. data/dist/131.c21d348572deab4ece66.bundle.js.map +0 -1
  64. data/dist/308.4d236ce7e6451807cb54.bundle.js +0 -2
  65. data/dist/308.4d236ce7e6451807cb54.bundle.js.map +0 -1
  66. data/dist/9.071a712ea648c8b30416.bundle.js +0 -2
  67. data/dist/9.071a712ea648c8b30416.bundle.js.map +0 -1
  68. data/dist/914.b9bc213d93173ce6b0cb.bundle.js +0 -2
  69. data/dist/b45b29da558efa211628.jpg +0 -0
  70. data/dist/before-load.js +0 -1
  71. data/dist/main.8208fda2d35ddbe38d55.bundle.js +0 -199
  72. data/dist/main.8208fda2d35ddbe38d55.bundle.js.map +0 -1
  73. data/dist/photon/main.8c8260452e7439ec6df9.bundle.js +0 -2
  74. data/dist/photon/main.8c8260452e7439ec6df9.bundle.js.map +0 -1
  75. /data/dist/{ad13da76642d8099fe70.module.wasm → 2f37d1addc2d2f5b699e.module.wasm} +0 -0
@@ -1,2 +0,0 @@
1
- "use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[131],{3131:(e,t,s)=>{s.r(t),s.d(t,{SourceViewEditor:()=>g});var n=s(2864),i=s(8120),o=s(9119),c=s(5524),r=s(487),a=s(6905),d=s(360),l=s(5627),h=s.n(l),f=s(2265);const u=new i.F6;function m(e){return null===e?[]:e.endsWith(".rs")?(0,a.Q)():e.endsWith(".js")||e.endsWith(".jsm")||e.endsWith(".jsx")||e.endsWith(".mjs")||e.endsWith(".ts")||e.endsWith(".tsx")?(0,d.eJ)():e.endsWith(".c")||e.endsWith(".cc")||e.endsWith(".cpp")||e.endsWith(".cxx")||e.endsWith(".h")||e.endsWith(".hpp")||e.endsWith(".m")||e.endsWith(".mm")?(0,r.N)():[]}const p=[n.tk.editable.of(!1),n.tk.contentAttributes.of({tabindex:"0"})];class g{constructor(e,t,s,r){this._view=void 0;let a=i.yy.create({doc:e,extensions:[f.l$,(0,n.Eu)(),u.of(m(t)),(0,o.nF)(c.$d),p]});a=a.update({effects:f.gR.of(s)}).state,this._view=new n.tk({state:a,parent:r})}updateLanguageForFilePath(e){this._view.dispatch({effects:u.reconfigure(m(e))})}setContents(e){this._view.dispatch(this._view.state.update({changes:{insert:e,from:0,to:this._view.state.doc.length}}))}setTimings(e){this._view.dispatch({effects:f.gR.of(e)})}scrollToLine(e){e=h()(e,1,this._view.state.doc.lines);const t=this._view.state.doc.line(e).from;this._view.dispatch({effects:n.tk.scrollIntoView(t,{y:"start",yMargin:0})}),this._view.coordsAtPos(0)}}},2265:(e,t,s)=>{s.d(t,{cW:()=>u,gR:()=>a,l$:()=>g});var n=s(2864),i=s(8120),o=s(6093);const c=new class extends n.SJ{constructor(...e){super(...e),this.elementClass="cm-nonZeroLine"}},r=n.p.line({class:"cm-nonZeroLine"}),a=i.Py.define(),d=i.QQ.define({create:()=>o.KM,update(e,t){let s=e;for(const e of t.effects)e.is(a)&&(s=e.value);return s}});function l(e){const t=e.field(d),s=new Set;for(const e of t.totalLineHits.keys())s.add(e);for(const e of t.selfLineHits.keys())s.add(e);const n=e.doc.lines,i=[...s].filter((e=>e<=n)).map((t=>e.doc.line(t).from));return i.sort(((e,t)=>e-t)),i}const h=n.v7.compute(["doc",d],(e=>{const t=l(e);return i.Xs.of(t.map((e=>c.range(e))))})),f=n.tk.decorations.compute(["doc",d],(e=>{const t=l(e);return i.Xs.of(t.map((e=>r.range(e))))}));class u extends n.SJ{constructor(e){super(),this._s=void 0,this._s=e}toDOM(){return document.createTextNode(this._s)}}const m=(0,n.v5)({class:"cm-total-timings-gutter",lineMarker(e,t){const s=e.state.doc.lineAt(t.from).number,n=e.state.field(d).totalLineHits.get(s);return void 0!==n?new u(n):null},lineMarkerChange:e=>e.transactions.some((e=>e.effects.some((e=>e.is(a)))))}),p=(0,n.v5)({class:"cm-self-timings-gutter",lineMarker(e,t){const s=e.state.doc.lineAt(t.from).number,n=e.state.field(d).selfLineHits.get(s);return void 0!==n?new u(n):null},lineMarkerChange:e=>e.transactions.some((e=>e.effects.some((e=>e.is(a)))))}),g=[d,m,p,h,f]}}]);
2
- //# sourceMappingURL=131.c21d348572deab4ece66.bundle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"131.c21d348572deab4ece66.bundle.js","mappings":"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","sources":["webpack:///./src/components/shared/SourceView-codemirror.js","webpack:///./src/utils/codemirror-shared.js"],"sourcesContent":["/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n// @flow\n\n/**\n * This module wraps all the interaction with the CodeMirror API into a\n * SourceViewEditor class.\n *\n * This module is intended to be imported asynchronously, so that all the\n * CodeMirror code can be split into a separate bundle chunk.\n *\n * This file implements the following features:\n * - Display source code with syntax highlighting.\n * - Display a gutter with:\n * - \"Total\" timings for each line\n * - \"Self\" timings for each line\n * - The line number for each line\n * - Highlight source code lines which have a non-zero timing, by applying\n * a cm-nonZeroLine class to them. This highlight line goes across the entire\n * width of the editor, it covers both the gutter and the main area.\n */\nimport { EditorView, lineNumbers } from '@codemirror/view';\nimport { EditorState, Compartment } from '@codemirror/state';\nimport { syntaxHighlighting } from '@codemirror/language';\nimport { classHighlighter } from '@lezer/highlight';\nimport { cpp } from '@codemirror/lang-cpp';\nimport { rust } from '@codemirror/lang-rust';\nimport { javascript } from '@codemirror/lang-javascript';\nimport clamp from 'clamp';\n\nimport type { LineTimings } from 'firefox-profiler/types';\nimport {\n timingsExtension,\n updateTimingsEffect,\n} from 'firefox-profiler/utils/codemirror-shared';\n\n// This \"compartment\" allows us to swap the syntax highlighting language when\n// the file path changes.\nconst languageConf = new Compartment();\n\n// Detect the right language based on the file extension.\nfunction _languageExtForPath(\n path: string | null\n): any /* LanguageSupport | [] */ {\n if (path === null) {\n return [];\n }\n if (path.endsWith('.rs')) {\n return rust();\n }\n if (\n path.endsWith('.js') ||\n path.endsWith('.jsm') ||\n path.endsWith('.jsx') ||\n path.endsWith('.mjs') ||\n path.endsWith('.ts') ||\n path.endsWith('.tsx')\n ) {\n return javascript();\n }\n if (\n path.endsWith('.c') ||\n path.endsWith('.cc') ||\n path.endsWith('.cpp') ||\n path.endsWith('.cxx') ||\n path.endsWith('.h') ||\n path.endsWith('.hpp') ||\n path.endsWith('.m') ||\n path.endsWith('.mm')\n ) {\n return cpp();\n }\n return [];\n}\n\n// Adjustments to make a CodeMirror editor work as a non-editable code viewer.\nconst codeViewerExtension = [\n // Make the editor non-editable.\n EditorView.editable.of(false),\n // Allow tabbing to the view (to an element *inside* the scroller so that the\n // up / down keys trigger scrolling), and take focus on mousedown.\n EditorView.contentAttributes.of({ tabindex: '0' }),\n];\n\nexport class SourceViewEditor {\n _view: EditorView;\n\n // Create a CodeMirror editor and add it as a child element of domParent.\n constructor(\n initialText: string,\n path: string,\n timings: LineTimings,\n domParent: Element\n ) {\n let state = EditorState.create({\n doc: initialText,\n extensions: [\n timingsExtension,\n lineNumbers(),\n languageConf.of(_languageExtForPath(path)),\n syntaxHighlighting(classHighlighter),\n codeViewerExtension,\n ],\n });\n state = state.update({\n effects: updateTimingsEffect.of(timings),\n }).state;\n this._view = new EditorView({\n state,\n parent: domParent,\n });\n }\n\n updateLanguageForFilePath(path: string | null) {\n this._view.dispatch({\n effects: languageConf.reconfigure(_languageExtForPath(path)),\n });\n }\n\n setContents(text: string) {\n // The CodeMirror way of replacing the entire contents is to insert new text\n // and overwrite the full range of existing text.\n this._view.dispatch(\n this._view.state.update({\n changes: {\n insert: text,\n from: 0,\n to: this._view.state.doc.length,\n },\n })\n );\n }\n\n setTimings(timings: LineTimings) {\n // Update the value of the timings field by dispatching an updateTimingsEffect.\n this._view.dispatch({\n effects: updateTimingsEffect.of(timings),\n });\n }\n\n scrollToLine(lineNumber: number) {\n // Clamp the line number to the document's line count.\n lineNumber = clamp(lineNumber, 1, this._view.state.doc.lines);\n\n // Convert the line number into a position.\n const pos = this._view.state.doc.line(lineNumber).from;\n // Dispatch the scroll action.\n this._view.dispatch({\n effects: EditorView.scrollIntoView(pos, { y: 'start', yMargin: 0 }),\n });\n // Trigger a measure flush, to work around\n // https://github.com/codemirror/codemirror.next/issues/676\n this._view.coordsAtPos(0);\n }\n}\n","/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n// @flow\n\nimport {\n EditorView,\n Decoration,\n GutterMarker,\n gutter,\n gutterLineClass,\n} from '@codemirror/view';\nimport {\n EditorState,\n StateField,\n StateEffect,\n RangeSet,\n} from '@codemirror/state';\n\nimport type { LineTimings } from 'firefox-profiler/types';\n\nimport { emptyLineTimings } from 'firefox-profiler/profile-logic/line-timings';\n\n// This gutter marker applies the \"cm-nonZeroLine\" class to gutter elements.\nconst nonZeroLineGutterMarker = new (class extends GutterMarker {\n elementClass = 'cm-nonZeroLine';\n})();\n\n// This \"decoration\" applies the \"cm-nonZeroLine\" class to the line of assembly\n// code in the main editor contents (not the gutter).\nconst nonZeroLineDecoration = Decoration.line({ class: 'cm-nonZeroLine' });\n\n// An \"effect\" is like a redux action. This effect is used to replace the value\n// of the timingsField state field.\nexport const updateTimingsEffect = StateEffect.define<LineTimings>();\n\n// A \"state field\" for the timings.\nconst timingsField = StateField.define<LineTimings>({\n create() {\n return emptyLineTimings;\n },\n update(timings, transaction) {\n // This is like a reducer. Find an updateTimingsEffect in the transaction\n // and set this field to the timings in it.\n let newTimings = timings;\n for (const effect of transaction.effects) {\n if (effect.is(updateTimingsEffect)) {\n newTimings = effect.value;\n }\n }\n return newTimings;\n },\n});\n\n// Finds all lines with non-zero line timings, for the highlight line.\n// The line numbers are then converted into \"positions\", i.e. character offsets\n// in the document, for the start of the line.\n// Then they are sorted, because our caller wants to have a sorted list.\nfunction getSortedStartPositionsOfNonZeroLines(state: EditorState): number[] {\n const timings = state.field(timingsField);\n const nonZeroLines = new Set();\n for (const lineNumber of timings.totalLineHits.keys()) {\n nonZeroLines.add(lineNumber);\n }\n for (const lineNumber of timings.selfLineHits.keys()) {\n nonZeroLines.add(lineNumber);\n }\n const lineCount = state.doc.lines;\n const positions = [...nonZeroLines]\n .filter((l) => l <= lineCount)\n .map((lineNumber) => state.doc.line(lineNumber).from);\n positions.sort((a, b) => a - b);\n return positions;\n}\n\n// This is an \"extension\" which applies the \"cm-nonZeroLine\" class to all gutter\n// elements for lines with non-zero timings. It is like a piece of derived state;\n// it needs to be recomputed whenever one of the input states change. The input\n// states are the editor contents (\"doc\") and the value of the timings field.\n// The editor contents are relevant because the output is expressed in terms of\n// positions, i.e. character offsets from the document start, and those positions\n// need to be updated if the amount of text in a line changes. This happens when\n// we replace the file placeholder content with the actual file content.\nconst nonZeroLineGutterHighlighter = gutterLineClass.compute(\n ['doc', timingsField],\n (state) => {\n const positions = getSortedStartPositionsOfNonZeroLines(state);\n return RangeSet.of(positions.map((p) => nonZeroLineGutterMarker.range(p)));\n }\n);\n\n// Same as the previous extension, but this one is for the main editor. There\n// doesn't seem to be a way to set a class for the entire line, i.e. both the\n// gutter elements and the main editor elements of that line.\nconst nonZeroLineDecorationHighlighter = EditorView.decorations.compute(\n ['doc', timingsField],\n (state) => {\n const positions = getSortedStartPositionsOfNonZeroLines(state);\n return RangeSet.of(positions.map((p) => nonZeroLineDecoration.range(p)));\n }\n);\n\n// This is a \"gutter marker\" which renders just a string and nothing else.\n// It is used for the AddressTimings annotations, i.e. for the numbers in the\n// gutter.\nexport class StringMarker extends GutterMarker {\n _s: string;\n\n constructor(s: string) {\n super();\n this._s = s;\n }\n\n toDOM() {\n return document.createTextNode(this._s);\n }\n}\n\n// The \"extension\" which manages the elements in the gutter for the \"total\"\n// column.\nconst totalTimingsGutter = gutter({\n class: 'cm-total-timings-gutter',\n lineMarker(view, line) {\n // Return a gutter marker for this line, or null.\n const lineNumber = view.state.doc.lineAt(line.from).number;\n const timings = view.state.field(timingsField);\n const totalTime = timings.totalLineHits.get(lineNumber);\n return totalTime !== undefined ? new StringMarker(totalTime) : null;\n },\n lineMarkerChange(update) {\n // Return true if the update affects the total timings in the gutter.\n return update.transactions.some((t) =>\n t.effects.some((e) => e.is(updateTimingsEffect))\n );\n },\n});\n\n// The \"extension\" which manages the elements in the gutter for the \"self\"\n// column.\nconst selfTimingsGutter = gutter({\n class: 'cm-self-timings-gutter',\n lineMarker(view, line) {\n // Return a gutter marker for this line, or null.\n const lineNumber = view.state.doc.lineAt(line.from).number;\n const timings = view.state.field(timingsField);\n const selfTime = timings.selfLineHits.get(lineNumber);\n return selfTime !== undefined ? new StringMarker(selfTime) : null;\n },\n lineMarkerChange(update) {\n // Return true if the update affects the self timings in the gutter.\n return update.transactions.some((t) =>\n t.effects.some((e) => e.is(updateTimingsEffect))\n );\n },\n});\n\n// All extensions which have to do with timings, grouped into one extension.\nexport const timingsExtension = [\n timingsField,\n totalTimingsGutter,\n selfTimingsGutter,\n nonZeroLineGutterHighlighter,\n nonZeroLineDecorationHighlighter,\n];\n"],"names":["languageConf","Compartment","_languageExtForPath","path","endsWith","rust","javascript","cpp","codeViewerExtension","EditorView","editable","of","contentAttributes","tabindex","SourceViewEditor","constructor","initialText","timings","domParent","_view","state","EditorState","create","doc","extensions","timingsExtension","lineNumbers","syntaxHighlighting","classHighlighter","update","effects","updateTimingsEffect","this","parent","updateLanguageForFilePath","dispatch","reconfigure","setContents","text","changes","insert","from","to","length","setTimings","scrollToLine","lineNumber","clamp","lines","pos","line","scrollIntoView","y","yMargin","coordsAtPos","nonZeroLineGutterMarker","GutterMarker","args","elementClass","nonZeroLineDecoration","Decoration","class","StateEffect","define","timingsField","StateField","emptyLineTimings","transaction","newTimings","effect","is","value","getSortedStartPositionsOfNonZeroLines","field","nonZeroLines","Set","totalLineHits","keys","add","selfLineHits","lineCount","positions","filter","l","map","sort","a","b","nonZeroLineGutterHighlighter","gutterLineClass","compute","RangeSet","p","range","nonZeroLineDecorationHighlighter","decorations","StringMarker","s","super","_s","toDOM","document","createTextNode","totalTimingsGutter","gutter","lineMarker","view","lineAt","number","totalTime","get","undefined","lineMarkerChange","transactions","some","t","e","selfTimingsGutter","selfTime"],"sourceRoot":""}
@@ -1,2 +0,0 @@
1
- "use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[308],{7308:(s,e,t)=>{t.r(e),t.d(e,{AssemblyViewEditor:()=>T});var n=t(2864),i=t(8120),o=t(9119),r=t(5524),d=t(5627),a=t.n(d),c=t(7365),l=t(2265);const f=i.Py.define(),u=i.QQ.define({create:()=>[],update(s,e){let t=s;for(const s of e.effects)s.is(f)&&(t=s.value);return t}}),h=(0,n.v5)({class:"cm-instruction-address-gutter",lineMarker(s,e){const t=s.state.doc.lineAt(e.from).number,n=s.state.field(u).lineToAddress(t);return null!==n?new l.cW(`0x${n.toString(16)}`):null},lineMarkerChange:s=>s.transactions.some((s=>s.effects.some((s=>s.is(f)))))});function m(s){return s.map((s=>s.decodedString)).join("\n")}class p{constructor(s){this._instructionAddresses=void 0,this._instructionAddresses=s}addressToLine(s){const e=(0,c.e)(this._instructionAddresses,s);return 0===e?null:e-1+1}lineToAddress(s){if(s<1||s>this._instructionAddresses.length)return null;const e=s-1;return this._instructionAddresses[e]}}function _(s){return s.map((s=>s.address))}function g(s,e){const t=new Map;for(const[n,i]of s.totalAddressHits){const s=e.addressToLine(n);if(null!==s){const e=t.get(s)??0;t.set(s,e+i)}}const n=new Map;for(const[t,i]of s.selfAddressHits){const s=e.addressToLine(t);if(null!==s){const e=n.get(s)??0;n.set(s,e+i)}}return{totalLineHits:t,selfLineHits:n}}class T{constructor(s,e,t,d){this._view=void 0,this._addressToLineMap=void 0,this._addressTimings=void 0,this._addressToLineMap=new p(_(s)),this._addressTimings=t;let a=i.yy.create({doc:m(s),extensions:[l.l$,u,h,(0,o.nF)(r.$d),i.yy.readOnly.of(!0),n.tk.editable.of(!1)]});const c=g(this._addressTimings,this._addressToLineMap);a=a.update({effects:[f.of(this._addressToLineMap),l.gR.of(c)]}).state,this._view=new n.tk({state:a,parent:d})}setContents(s){this._addressToLineMap=new p(_(s));const e=g(this._addressTimings,this._addressToLineMap),t=m(s);this._view.dispatch(this._view.state.update({changes:{insert:t,from:0,to:this._view.state.doc.length}})),this._view.dispatch({effects:[f.of(this._addressToLineMap),l.gR.of(e)]})}setTimings(s){this._addressTimings=s;const e=g(this._addressTimings,this._addressToLineMap);this._view.dispatch({effects:l.gR.of(e)})}scrollToLine(s){s=a()(s,1,this._view.state.doc.lines);const e=this._view.state.doc.line(s).from;this._view.dispatch({effects:n.tk.scrollIntoView(e,{y:"start",yMargin:0})}),this._view.coordsAtPos(0)}scrollToAddress(s){const e=this._addressToLineMap.addressToLine(s);null!==e&&this.scrollToLine(e)}scrollToAddressWithSpaceOnTop(s,e){const t=this._addressToLineMap.addressToLine(s);null!==t&&this.scrollToLine(t-e)}}},2265:(s,e,t)=>{t.d(e,{cW:()=>h,gR:()=>a,l$:()=>_});var n=t(2864),i=t(8120),o=t(6093);const r=new class extends n.SJ{constructor(...s){super(...s),this.elementClass="cm-nonZeroLine"}},d=n.p.line({class:"cm-nonZeroLine"}),a=i.Py.define(),c=i.QQ.define({create:()=>o.KM,update(s,e){let t=s;for(const s of e.effects)s.is(a)&&(t=s.value);return t}});function l(s){const e=s.field(c),t=new Set;for(const s of e.totalLineHits.keys())t.add(s);for(const s of e.selfLineHits.keys())t.add(s);const n=s.doc.lines,i=[...t].filter((s=>s<=n)).map((e=>s.doc.line(e).from));return i.sort(((s,e)=>s-e)),i}const f=n.v7.compute(["doc",c],(s=>{const e=l(s);return i.Xs.of(e.map((s=>r.range(s))))})),u=n.tk.decorations.compute(["doc",c],(s=>{const e=l(s);return i.Xs.of(e.map((s=>d.range(s))))}));class h extends n.SJ{constructor(s){super(),this._s=void 0,this._s=s}toDOM(){return document.createTextNode(this._s)}}const m=(0,n.v5)({class:"cm-total-timings-gutter",lineMarker(s,e){const t=s.state.doc.lineAt(e.from).number,n=s.state.field(c).totalLineHits.get(t);return void 0!==n?new h(n):null},lineMarkerChange:s=>s.transactions.some((s=>s.effects.some((s=>s.is(a)))))}),p=(0,n.v5)({class:"cm-self-timings-gutter",lineMarker(s,e){const t=s.state.doc.lineAt(e.from).number,n=s.state.field(c).selfLineHits.get(t);return void 0!==n?new h(n):null},lineMarkerChange:s=>s.transactions.some((s=>s.effects.some((s=>s.is(a)))))}),_=[c,m,p,f,u]}}]);
2
- //# sourceMappingURL=308.4d236ce7e6451807cb54.bundle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"308.4d236ce7e6451807cb54.bundle.js","mappings":"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","sources":["webpack:///./src/components/shared/AssemblyView-codemirror.js","webpack:///./src/utils/codemirror-shared.js"],"sourcesContent":["/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n// @flow\n\n/**\n * This module wraps all the interaction with the CodeMirror API into a\n * AssemblyViewEditor class.\n *\n * This module is intended to be imported asynchronously, so that all the\n * CodeMirror code can be split into a separate bundle chunk.\n *\n * This file implements the following features:\n * - Display assembly code.\n * - Display a gutter with:\n * - \"Total\" timings for each instruction\n * - \"Self\" timings for each instruction\n * - The address for each instruction\n * - Highlight assembly code lines which have a non-zero timing, by applying\n * a cm-nonZeroLine class to them. This highlight line goes across the entire\n * width of the editor, it covers both the gutter and the main area.\n */\nimport { EditorView, gutter } from '@codemirror/view';\nimport { EditorState, StateField, StateEffect } from '@codemirror/state';\nimport { syntaxHighlighting } from '@codemirror/language';\nimport { classHighlighter } from '@lezer/highlight';\nimport clamp from 'clamp';\n\nimport type {\n AddressTimings,\n Address,\n LineTimings,\n LineNumber,\n NativeSymbolInfo,\n DecodedInstruction,\n} from 'firefox-profiler/types';\n\nimport { bisectionRight } from 'firefox-profiler/utils/bisect';\nimport {\n timingsExtension,\n updateTimingsEffect,\n StringMarker,\n} from 'firefox-profiler/utils/codemirror-shared';\n\n// An \"effect\" is like a redux action. This effect is used to replace the value\n// of the state field addressToLineMapField.\nconst updateAddressToLineMapEffect = StateEffect.define<AddressToLineMap>();\n\n// This \"state field\" stores the current AddressToLineMap. This field allows the\n// instructionAddressGutter to map line numbers to addresses.\nconst addressToLineMapField = StateField.define<AddressToLineMap>({\n create() {\n return [];\n },\n update(instructionAddresses, transaction) {\n // Get the new value from an effect in the transaction.\n let newSortedAddresses = instructionAddresses;\n for (const effect of transaction.effects) {\n if (effect.is(updateAddressToLineMapEffect)) {\n newSortedAddresses = effect.value;\n }\n }\n return newSortedAddresses;\n },\n});\n\n// A gutter which displays the address of each instruction.\nconst instructionAddressGutter = gutter({\n class: 'cm-instruction-address-gutter',\n\n // Returns a gutter marker for this line, or null.\n lineMarker(view, line) {\n const lineNumber = view.state.doc.lineAt(line.from).number;\n const map = view.state.field(addressToLineMapField);\n const address = map.lineToAddress(lineNumber);\n return address !== null\n ? new StringMarker(`0x${address.toString(16)}`)\n : null;\n },\n\n // Returns true if the update affects the instruction addresses in the gutter.\n lineMarkerChange(update) {\n return update.transactions.some((t) =>\n t.effects.some((e) => e.is(updateAddressToLineMapEffect))\n );\n },\n});\n\nfunction instructionsToText(assemblyCode: DecodedInstruction[]): string {\n return assemblyCode.map((instr) => instr.decodedString).join('\\n');\n}\n\n/**\n * This map is used to convert between instruction addresses and editor line\n * numbers.\n */\nclass AddressToLineMap {\n // The address of each instruction. This stays constant for the entire lifetime\n // of this AddressToLineMap instance.\n //\n // _instructionAddresses[0] contains the address of the instruction which is\n // displayed in line 1. (Line numbers are 1-based.)\n //\n // The addresses need to be ordered from low to high, so that the binary search\n // works.\n _instructionAddresses: Address[];\n\n constructor(instructionAddresses) {\n this._instructionAddresses = instructionAddresses;\n }\n\n // Find the line which displays the instruction which covers `address`.\n // `address` doesn't need to be a perfect match for the instruction address;\n // for example, in the example below, address 0x10e4 is mapped to line 3:\n //\n // 1: 0x10da: mov r14, rdi\n // 2: 0x10dd: mov rdi, rsi\n // 3: 0x10e0: call _malloc_usable_size\n // 4: 0x10e5: test rax, rax\n // 5: 0x10e8: je loc_10f6\n addressToLine(address: Address): LineNumber | null {\n const insertionIndex = bisectionRight(this._instructionAddresses, address);\n if (insertionIndex === 0) {\n // address < instructionAddresses[0]\n return null;\n }\n\n const elementIndex = insertionIndex - 1;\n const lineNumber = elementIndex + 1;\n return lineNumber;\n }\n\n // Return the address of the instruction which is displayed in line `lineNumber`.\n lineToAddress(lineNumber: LineNumber): Address | null {\n if (lineNumber < 1 || lineNumber > this._instructionAddresses.length) {\n return null;\n }\n\n const elementIndex = lineNumber - 1;\n return this._instructionAddresses[elementIndex];\n }\n}\n\nfunction getInstructionAddresses(\n assemblyCode: DecodedInstruction[]\n): Address[] {\n return assemblyCode.map((instr) => instr.address);\n}\n\n// Convert AddressTimings to LineTimings with the help of an AddressToLineMap.\nfunction addressTimingsToLineTimings(\n addressTimings: AddressTimings,\n map: AddressToLineMap\n): LineTimings {\n const totalLineHits = new Map();\n for (const [address, hitCount] of addressTimings.totalAddressHits) {\n const line = map.addressToLine(address);\n if (line !== null) {\n const currentHitCount = totalLineHits.get(line) ?? 0;\n totalLineHits.set(line, currentHitCount + hitCount);\n }\n }\n\n const selfLineHits = new Map();\n for (const [address, hitCount] of addressTimings.selfAddressHits) {\n const line = map.addressToLine(address);\n if (line !== null) {\n const currentHitCount = selfLineHits.get(line) ?? 0;\n selfLineHits.set(line, currentHitCount + hitCount);\n }\n }\n\n return { totalLineHits, selfLineHits };\n}\n\nexport class AssemblyViewEditor {\n _view: EditorView;\n _addressToLineMap: AddressToLineMap;\n _addressTimings: AddressTimings;\n\n // Create a CodeMirror editor and add it as a child element of domParent.\n constructor(\n initialAssemblyCode: DecodedInstruction[],\n nativeSymbol: NativeSymbolInfo,\n addressTimings: AddressTimings,\n domParent: Element\n ) {\n this._addressToLineMap = new AddressToLineMap(\n getInstructionAddresses(initialAssemblyCode)\n );\n this._addressTimings = addressTimings;\n let state = EditorState.create({\n doc: instructionsToText(initialAssemblyCode),\n extensions: [\n timingsExtension,\n addressToLineMapField,\n instructionAddressGutter,\n syntaxHighlighting(classHighlighter),\n EditorState.readOnly.of(true),\n EditorView.editable.of(false),\n ],\n });\n const lineTimings = addressTimingsToLineTimings(\n this._addressTimings,\n this._addressToLineMap\n );\n state = state.update({\n effects: [\n updateAddressToLineMapEffect.of(this._addressToLineMap),\n updateTimingsEffect.of(lineTimings),\n ],\n }).state;\n this._view = new EditorView({\n state,\n parent: domParent,\n });\n }\n\n setContents(assemblyCode: DecodedInstruction[]) {\n this._addressToLineMap = new AddressToLineMap(\n getInstructionAddresses(assemblyCode)\n );\n const lineTimings = addressTimingsToLineTimings(\n this._addressTimings,\n this._addressToLineMap\n );\n // The CodeMirror way of replacing the entire contents is to insert new text\n // and overwrite the full range of existing text.\n const text = instructionsToText(assemblyCode);\n this._view.dispatch(\n this._view.state.update({\n changes: {\n insert: text,\n from: 0,\n to: this._view.state.doc.length,\n },\n })\n );\n this._view.dispatch({\n effects: [\n updateAddressToLineMapEffect.of(this._addressToLineMap),\n updateTimingsEffect.of(lineTimings),\n ],\n });\n }\n\n setTimings(addressTimings: AddressTimings) {\n // Update the value of the timings field by dispatching an updateTimingsEffect.\n this._addressTimings = addressTimings;\n const lineTimings = addressTimingsToLineTimings(\n this._addressTimings,\n this._addressToLineMap\n );\n this._view.dispatch({\n effects: updateTimingsEffect.of(lineTimings),\n });\n }\n\n scrollToLine(lineNumber: number) {\n // Clamp the line number to the document's line count.\n lineNumber = clamp(lineNumber, 1, this._view.state.doc.lines);\n\n // Convert the line number into a position.\n const pos = this._view.state.doc.line(lineNumber).from;\n // Dispatch the scroll action.\n this._view.dispatch({\n effects: EditorView.scrollIntoView(pos, { y: 'start', yMargin: 0 }),\n });\n // Trigger a measure flush, to work around\n // https://github.com/codemirror/codemirror.next/issues/676\n this._view.coordsAtPos(0);\n }\n\n scrollToAddress(address: Address) {\n const lineNumber = this._addressToLineMap.addressToLine(address);\n if (lineNumber !== null) {\n this.scrollToLine(lineNumber);\n }\n }\n\n scrollToAddressWithSpaceOnTop(address: Address, topSpaceLines: number) {\n const lineNumber = this._addressToLineMap.addressToLine(address);\n if (lineNumber !== null) {\n this.scrollToLine(lineNumber - topSpaceLines);\n }\n }\n}\n","/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n// @flow\n\nimport {\n EditorView,\n Decoration,\n GutterMarker,\n gutter,\n gutterLineClass,\n} from '@codemirror/view';\nimport {\n EditorState,\n StateField,\n StateEffect,\n RangeSet,\n} from '@codemirror/state';\n\nimport type { LineTimings } from 'firefox-profiler/types';\n\nimport { emptyLineTimings } from 'firefox-profiler/profile-logic/line-timings';\n\n// This gutter marker applies the \"cm-nonZeroLine\" class to gutter elements.\nconst nonZeroLineGutterMarker = new (class extends GutterMarker {\n elementClass = 'cm-nonZeroLine';\n})();\n\n// This \"decoration\" applies the \"cm-nonZeroLine\" class to the line of assembly\n// code in the main editor contents (not the gutter).\nconst nonZeroLineDecoration = Decoration.line({ class: 'cm-nonZeroLine' });\n\n// An \"effect\" is like a redux action. This effect is used to replace the value\n// of the timingsField state field.\nexport const updateTimingsEffect = StateEffect.define<LineTimings>();\n\n// A \"state field\" for the timings.\nconst timingsField = StateField.define<LineTimings>({\n create() {\n return emptyLineTimings;\n },\n update(timings, transaction) {\n // This is like a reducer. Find an updateTimingsEffect in the transaction\n // and set this field to the timings in it.\n let newTimings = timings;\n for (const effect of transaction.effects) {\n if (effect.is(updateTimingsEffect)) {\n newTimings = effect.value;\n }\n }\n return newTimings;\n },\n});\n\n// Finds all lines with non-zero line timings, for the highlight line.\n// The line numbers are then converted into \"positions\", i.e. character offsets\n// in the document, for the start of the line.\n// Then they are sorted, because our caller wants to have a sorted list.\nfunction getSortedStartPositionsOfNonZeroLines(state: EditorState): number[] {\n const timings = state.field(timingsField);\n const nonZeroLines = new Set();\n for (const lineNumber of timings.totalLineHits.keys()) {\n nonZeroLines.add(lineNumber);\n }\n for (const lineNumber of timings.selfLineHits.keys()) {\n nonZeroLines.add(lineNumber);\n }\n const lineCount = state.doc.lines;\n const positions = [...nonZeroLines]\n .filter((l) => l <= lineCount)\n .map((lineNumber) => state.doc.line(lineNumber).from);\n positions.sort((a, b) => a - b);\n return positions;\n}\n\n// This is an \"extension\" which applies the \"cm-nonZeroLine\" class to all gutter\n// elements for lines with non-zero timings. It is like a piece of derived state;\n// it needs to be recomputed whenever one of the input states change. The input\n// states are the editor contents (\"doc\") and the value of the timings field.\n// The editor contents are relevant because the output is expressed in terms of\n// positions, i.e. character offsets from the document start, and those positions\n// need to be updated if the amount of text in a line changes. This happens when\n// we replace the file placeholder content with the actual file content.\nconst nonZeroLineGutterHighlighter = gutterLineClass.compute(\n ['doc', timingsField],\n (state) => {\n const positions = getSortedStartPositionsOfNonZeroLines(state);\n return RangeSet.of(positions.map((p) => nonZeroLineGutterMarker.range(p)));\n }\n);\n\n// Same as the previous extension, but this one is for the main editor. There\n// doesn't seem to be a way to set a class for the entire line, i.e. both the\n// gutter elements and the main editor elements of that line.\nconst nonZeroLineDecorationHighlighter = EditorView.decorations.compute(\n ['doc', timingsField],\n (state) => {\n const positions = getSortedStartPositionsOfNonZeroLines(state);\n return RangeSet.of(positions.map((p) => nonZeroLineDecoration.range(p)));\n }\n);\n\n// This is a \"gutter marker\" which renders just a string and nothing else.\n// It is used for the AddressTimings annotations, i.e. for the numbers in the\n// gutter.\nexport class StringMarker extends GutterMarker {\n _s: string;\n\n constructor(s: string) {\n super();\n this._s = s;\n }\n\n toDOM() {\n return document.createTextNode(this._s);\n }\n}\n\n// The \"extension\" which manages the elements in the gutter for the \"total\"\n// column.\nconst totalTimingsGutter = gutter({\n class: 'cm-total-timings-gutter',\n lineMarker(view, line) {\n // Return a gutter marker for this line, or null.\n const lineNumber = view.state.doc.lineAt(line.from).number;\n const timings = view.state.field(timingsField);\n const totalTime = timings.totalLineHits.get(lineNumber);\n return totalTime !== undefined ? new StringMarker(totalTime) : null;\n },\n lineMarkerChange(update) {\n // Return true if the update affects the total timings in the gutter.\n return update.transactions.some((t) =>\n t.effects.some((e) => e.is(updateTimingsEffect))\n );\n },\n});\n\n// The \"extension\" which manages the elements in the gutter for the \"self\"\n// column.\nconst selfTimingsGutter = gutter({\n class: 'cm-self-timings-gutter',\n lineMarker(view, line) {\n // Return a gutter marker for this line, or null.\n const lineNumber = view.state.doc.lineAt(line.from).number;\n const timings = view.state.field(timingsField);\n const selfTime = timings.selfLineHits.get(lineNumber);\n return selfTime !== undefined ? new StringMarker(selfTime) : null;\n },\n lineMarkerChange(update) {\n // Return true if the update affects the self timings in the gutter.\n return update.transactions.some((t) =>\n t.effects.some((e) => e.is(updateTimingsEffect))\n );\n },\n});\n\n// All extensions which have to do with timings, grouped into one extension.\nexport const timingsExtension = [\n timingsField,\n totalTimingsGutter,\n selfTimingsGutter,\n nonZeroLineGutterHighlighter,\n nonZeroLineDecorationHighlighter,\n];\n"],"names":["updateAddressToLineMapEffect","StateEffect","define","addressToLineMapField","StateField","create","update","instructionAddresses","transaction","newSortedAddresses","effect","effects","is","value","instructionAddressGutter","gutter","class","lineMarker","view","line","lineNumber","state","doc","lineAt","from","number","address","field","lineToAddress","StringMarker","toString","lineMarkerChange","transactions","some","t","e","instructionsToText","assemblyCode","map","instr","decodedString","join","AddressToLineMap","constructor","_instructionAddresses","this","addressToLine","insertionIndex","bisectionRight","length","elementIndex","getInstructionAddresses","addressTimingsToLineTimings","addressTimings","totalLineHits","Map","hitCount","totalAddressHits","currentHitCount","get","set","selfLineHits","selfAddressHits","AssemblyViewEditor","initialAssemblyCode","nativeSymbol","domParent","_view","_addressToLineMap","_addressTimings","EditorState","extensions","timingsExtension","syntaxHighlighting","classHighlighter","readOnly","of","EditorView","editable","lineTimings","updateTimingsEffect","parent","setContents","text","dispatch","changes","insert","to","setTimings","scrollToLine","clamp","lines","pos","scrollIntoView","y","yMargin","coordsAtPos","scrollToAddress","scrollToAddressWithSpaceOnTop","topSpaceLines","nonZeroLineGutterMarker","GutterMarker","args","elementClass","nonZeroLineDecoration","Decoration","timingsField","emptyLineTimings","timings","newTimings","getSortedStartPositionsOfNonZeroLines","nonZeroLines","Set","keys","add","lineCount","positions","filter","l","sort","a","b","nonZeroLineGutterHighlighter","gutterLineClass","compute","RangeSet","p","range","nonZeroLineDecorationHighlighter","decorations","s","super","_s","toDOM","document","createTextNode","totalTimingsGutter","totalTime","undefined","selfTimingsGutter","selfTime"],"sourceRoot":""}