profile-viewer 0.0.4 → 0.0.5

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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/dist/029b9e4fd0218d7b09c6.svg +8 -0
  3. data/dist/{136.4ad3301b8aacf759ea70.bundle.js → 136.ad4176dc2a8e5cf33ef3.bundle.js} +2 -2
  4. data/dist/{136.4ad3301b8aacf759ea70.bundle.js.map → 136.ad4176dc2a8e5cf33ef3.bundle.js.map} +1 -1
  5. data/dist/{171.621b9df5978342be5662.bundle.js → 171.37d1e1824587d8df0ae2.bundle.js} +2 -2
  6. data/dist/{171.621b9df5978342be5662.bundle.js.map → 171.37d1e1824587d8df0ae2.bundle.js.map} +1 -1
  7. data/dist/234ed61ab185caff67e3.svg +8 -0
  8. data/dist/280.4edd20bd6228986bbf2e.bundle.js +2 -0
  9. data/dist/280.4edd20bd6228986bbf2e.bundle.js.map +1 -0
  10. data/dist/556.b8d3d4d402ced081615a.bundle.js +2 -0
  11. data/dist/{556.2be67a37a0c61fdc2485.bundle.js.map → 556.b8d3d4d402ced081615a.bundle.js.map} +1 -1
  12. data/dist/874.7cb94ee0732c5a2ca826.bundle.js +2 -0
  13. data/dist/874.7cb94ee0732c5a2ca826.bundle.js.map +1 -0
  14. data/dist/957.2f40be4cef3037bc352b.bundle.js +3 -0
  15. data/dist/957.2f40be4cef3037bc352b.bundle.js.LICENSE.txt +19 -0
  16. data/dist/957.2f40be4cef3037bc352b.bundle.js.map +1 -0
  17. data/dist/999.a1119c25d77e1883c1e1.bundle.js +2 -0
  18. data/dist/999.a1119c25d77e1883c1e1.bundle.js.map +1 -0
  19. data/dist/docs/_navbar.md +3 -3
  20. data/dist/docs/_sidebar.md +28 -28
  21. data/dist/docs/advanced-topics.md +5 -5
  22. data/dist/docs/async-posix-signal-control.md +5 -6
  23. data/dist/docs/bunny-2.md +3 -2
  24. data/dist/docs/bunny.md +29 -26
  25. data/dist/docs/gitpod.md +5 -10
  26. data/dist/docs/guide-android-profiling.md +18 -2
  27. data/dist/docs/guide-filtering-call-trees.md +11 -11
  28. data/dist/docs/guide-getting-started.md +4 -5
  29. data/dist/docs/guide-perf-profiling.md +8 -8
  30. data/dist/docs/guide-profiling-android-directly-on-device.md +14 -13
  31. data/dist/docs/guide-profiling-firefox-android.md +2 -3
  32. data/dist/docs/guide-remote-profiling.md +24 -23
  33. data/dist/docs/guide-removing-profiler.md +1 -0
  34. data/dist/docs/guide-stack-samples-and-call-trees.md +2 -0
  35. data/dist/docs/guide-startup-shutdown.md +14 -9
  36. data/dist/docs/guide-ui-tour-panels.md +4 -3
  37. data/dist/docs/guide-ui-tour-timeline.md +3 -0
  38. data/dist/docs/index.html +21 -18
  39. data/dist/docs/ipc-messages.md +6 -6
  40. data/dist/docs/js/docsify_v4.12.2+.min.js +1 -1
  41. data/dist/docs/memory-allocations.md +4 -4
  42. data/dist/docs/videos.md +10 -10
  43. data/dist/index.html +1 -1
  44. data/dist/locales/be/app.ftl +108 -0
  45. data/dist/locales/de/app.ftl +9 -0
  46. data/dist/locales/el/app.ftl +34 -11
  47. data/dist/locales/en-CA/app.ftl +23 -5
  48. data/dist/locales/en-GB/app.ftl +14 -5
  49. data/dist/locales/en-US/app.ftl +13 -4
  50. data/dist/locales/es-CL/app.ftl +17 -2
  51. data/dist/locales/fr/app.ftl +15 -0
  52. data/dist/locales/fur/app.ftl +16 -0
  53. data/dist/locales/fy-NL/app.ftl +9 -0
  54. data/dist/locales/ia/app.ftl +12 -0
  55. data/dist/locales/it/app.ftl +9 -0
  56. data/dist/locales/kab/app.ftl +12 -0
  57. data/dist/locales/nl/app.ftl +9 -0
  58. data/dist/locales/pt-BR/app.ftl +9 -0
  59. data/dist/locales/ru/app.ftl +9 -0
  60. data/dist/locales/sv-SE/app.ftl +18 -0
  61. data/dist/locales/tr/app.ftl +14 -0
  62. data/dist/locales/uk/app.ftl +18 -0
  63. data/dist/locales/zh-CN/app.ftl +14 -4
  64. data/dist/locales/zh-TW/app.ftl +10 -1
  65. data/dist/main.6cdc9308b67c00785584.bundle.js +198 -0
  66. data/dist/{main.89ba95fadf0fbee4977a.bundle.js.LICENSE.txt → main.6cdc9308b67c00785584.bundle.js.LICENSE.txt} +2 -2
  67. data/dist/main.6cdc9308b67c00785584.bundle.js.map +1 -0
  68. data/dist/photon/index.html +1 -1
  69. data/dist/photon/main.e1d25e5ea6d5812b127b.bundle.js +2 -0
  70. data/dist/photon/main.e1d25e5ea6d5812b127b.bundle.js.map +1 -0
  71. data/dist/sw.js +1 -1
  72. data/dist/sw.js.map +1 -1
  73. data/ruby-bin/profile-viewer +10 -1
  74. data/ruby-bin/profile-viewer-version.rb +1 -1
  75. metadata +24 -17
  76. data/dist/280.b4210a48e650408000c3.bundle.js +0 -2
  77. data/dist/280.b4210a48e650408000c3.bundle.js.map +0 -1
  78. data/dist/556.2be67a37a0c61fdc2485.bundle.js +0 -2
  79. data/dist/874.ca7a11f56438ad874b9d.bundle.js +0 -2
  80. data/dist/874.ca7a11f56438ad874b9d.bundle.js.map +0 -1
  81. data/dist/main.89ba95fadf0fbee4977a.bundle.js +0 -201
  82. data/dist/main.89ba95fadf0fbee4977a.bundle.js.map +0 -1
  83. data/dist/photon/main.fa2aec5d6b214ac1cdb3.bundle.js +0 -2
  84. data/dist/photon/main.fa2aec5d6b214ac1cdb3.bundle.js.map +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c050411e2d70822f985c891f5c897f96793e5422e7e36d879257f462e8530d2
4
- data.tar.gz: 1ee558555f7d252d67d0cb7a9d380ad593f0878b334e618f742f9f3f4cc551e6
3
+ metadata.gz: 289c77cab5865c682c30fa40ed9eae3c5746a305e237e11d39a75a752cc85ed3
4
+ data.tar.gz: 790e06b133c96484423afbb8ad7422da808deba62993c3308ab8c9df2c23c627
5
5
  SHA512:
6
- metadata.gz: 0c920f1c3ac88fb2618d09102724cb503ded349d054c4cb1b0f691e0583a220e8e3a79d242bf520e9cbd844fd37ebdaed72ed6b95ebd8d73d30dba80073db079
7
- data.tar.gz: a93e22ab89721f8dc090afc2330c62c2b08a264886ade1efcf3674e18a29effab073f4ef92feccbb442a2009aa03cc5ae1c3fe87bc73bf8a422453fc6528a31c
6
+ metadata.gz: 8019a9615a8ae2fb3c958f4b2bfec9eecf3d280429f21c6d403be5265144a23b158c3f073f8a15d28f0e85c1655689fe06a7ac8174ad1d92a91a470057fc4d6f
7
+ data.tar.gz: e4f432bb91e689b652666ede1f0b0fd100988a828a40abfec0d096aad406b4d6e3e2dbe2113b4e690303536d8f3c08b5c2bf42fc26224a7435a31f2692de3668
@@ -0,0 +1,8 @@
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
+ <svg xmlns="http://www.w3.org/2000/svg"
5
+ xmlns:xlink="http://www.w3.org/1999/xlink"
6
+ width="48" height="48" viewBox="0 0 24 24">
7
+ <polyline points="4 0 6 0 18 12 6 24 4 24 16 12" stroke="white"/>
8
+ </svg>
@@ -1,2 +1,2 @@
1
- "use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[136],{136:(s,e,t)=>{t.r(e),t.d(e,{AssemblyViewEditor:()=>L});var n=t(4589),i=t(6585),o=t(5874),r=t(3720),d=t(3276),a=t.n(d),c=t(7837),l=t(8811);const f=i.Pe.define(),u=i.sU.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.cU)({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.ES(`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.lV)(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 T(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 L{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.$t.create({doc:m(s),extensions:[l.Lf,u,h,(0,o.y9)(r.sS),i.$t.readOnly.of(!0),n.Lz.editable.of(!1)]});const c=T(this._addressTimings,this._addressToLineMap);a=a.update({effects:[f.of(this._addressToLineMap),l.IU.of(c)]}).state,this._view=new n.Lz({state:a,parent:d})}setContents(s){this._addressToLineMap=new p(_(s));const e=T(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.IU.of(e)]})}setTimings(s){this._addressTimings=s;const e=T(this._addressTimings,this._addressToLineMap);this._view.dispatch({effects:l.IU.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.Lz.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)}}},8811:(s,e,t)=>{t.d(e,{ES:()=>h,IU:()=>a,Lf:()=>_});var n=t(4589),i=t(6585),o=t(6046);const r=new class extends n.wJ{constructor(...s){super(...s),this.elementClass="cm-nonZeroLine"}},d=n.NZ.line({class:"cm-nonZeroLine"}),a=i.Pe.define(),c=i.sU.define({create:()=>o.tB,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>=1&&s<=n)).map((e=>s.doc.line(e).from));return i.sort(((s,e)=>s-e)),i}const f=n.EV.compute(["doc",c],(s=>{const e=l(s);return i.om.of(e.map((s=>r.range(s))))})),u=n.Lz.decorations.compute(["doc",c],(s=>{const e=l(s);return i.om.of(e.map((s=>d.range(s))))}));class h extends n.wJ{constructor(s){super(),this._s=void 0,this._s=s}toDOM(){return document.createTextNode(this._s)}}const m=(0,n.cU)({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.cU)({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=136.4ad3301b8aacf759ea70.bundle.js.map
1
+ "use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[136],{136:(s,e,t)=>{t.r(e),t.d(e,{AssemblyViewEditor:()=>L});var n=t(4589),i=t(1638),o=t(5874),r=t(3720),d=t(3276),a=t.n(d),c=t(7837),l=t(8811);const f=i.Pe.define(),u=i.sU.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.cU)({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.ES(`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.lV)(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 T(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 L{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.$t.create({doc:m(s),extensions:[l.Lf,u,h,(0,o.y9)(r.sS),i.$t.readOnly.of(!0),n.Lz.editable.of(!1)]});const c=T(this._addressTimings,this._addressToLineMap);a=a.update({effects:[f.of(this._addressToLineMap),l.IU.of(c)]}).state,this._view=new n.Lz({state:a,parent:d})}setContents(s){this._addressToLineMap=new p(_(s));const e=T(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.IU.of(e)]})}setTimings(s){this._addressTimings=s;const e=T(this._addressTimings,this._addressToLineMap);this._view.dispatch({effects:l.IU.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.Lz.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)}}},8811:(s,e,t)=>{t.d(e,{ES:()=>h,IU:()=>a,Lf:()=>_});var n=t(4589),i=t(1638),o=t(6046);const r=new class extends n.wJ{constructor(...s){super(...s),this.elementClass="cm-nonZeroLine"}},d=n.NZ.line({class:"cm-nonZeroLine"}),a=i.Pe.define(),c=i.sU.define({create:()=>o.tB,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>=1&&s<=n)).map((e=>s.doc.line(e).from));return i.sort(((s,e)=>s-e)),i}const f=n.EV.compute(["doc",c],(s=>{const e=l(s);return i.om.of(e.map((s=>r.range(s))))})),u=n.Lz.decorations.compute(["doc",c],(s=>{const e=l(s);return i.om.of(e.map((s=>d.range(s))))}));class h extends n.wJ{constructor(s){super(),this._s=void 0,this._s=s}toDOM(){return document.createTextNode(this._s)}}const m=(0,n.cU)({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.cU)({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=136.ad4176dc2a8e5cf33ef3.bundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"136.4ad3301b8aacf759ea70.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 >= 1 && 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":""}
1
+ {"version":3,"file":"136.ad4176dc2a8e5cf33ef3.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 >= 1 && 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":""}
@@ -1,2 +1,2 @@
1
- "use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[171],{3171:(e,t,s)=>{s.r(t),s.d(t,{SourceViewEditor:()=>w});var n=s(4589),i=s(6585),o=s(5874),c=s(3720),r=s(5336),a=s(3032),d=s(7514),l=s(3276),f=s.n(l),h=s(8811);const u=new i.xx;function m(e){return null===e?[]:e.endsWith(".rs")?(0,a.T)():e.endsWith(".js")||e.endsWith(".jsm")||e.endsWith(".jsx")||e.endsWith(".mjs")||e.endsWith(".ts")||e.endsWith(".tsx")?(0,d.Q2)():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.I)():[]}const p=[n.Lz.editable.of(!1),n.Lz.contentAttributes.of({tabindex:"0"})];class w{constructor(e,t,s,r){this._view=void 0;let a=i.$t.create({doc:e,extensions:[h.Lf,(0,n.$K)(),u.of(m(t)),(0,o.y9)(c.sS),p]});a=a.update({effects:h.IU.of(s)}).state,this._view=new n.Lz({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:h.IU.of(e)})}scrollToLine(e){e=f()(e,1,this._view.state.doc.lines);const t=this._view.state.doc.line(e).from;this._view.dispatch({effects:n.Lz.scrollIntoView(t,{y:"start",yMargin:0})}),this._view.coordsAtPos(0)}}},8811:(e,t,s)=>{s.d(t,{ES:()=>u,IU:()=>a,Lf:()=>w});var n=s(4589),i=s(6585),o=s(6046);const c=new class extends n.wJ{constructor(...e){super(...e),this.elementClass="cm-nonZeroLine"}},r=n.NZ.line({class:"cm-nonZeroLine"}),a=i.Pe.define(),d=i.sU.define({create:()=>o.tB,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>=1&&e<=n)).map((t=>e.doc.line(t).from));return i.sort(((e,t)=>e-t)),i}const f=n.EV.compute(["doc",d],(e=>{const t=l(e);return i.om.of(t.map((e=>c.range(e))))})),h=n.Lz.decorations.compute(["doc",d],(e=>{const t=l(e);return i.om.of(t.map((e=>r.range(e))))}));class u extends n.wJ{constructor(e){super(),this._s=void 0,this._s=e}toDOM(){return document.createTextNode(this._s)}}const m=(0,n.cU)({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.cU)({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)))))}),w=[d,m,p,f,h]}}]);
2
- //# sourceMappingURL=171.621b9df5978342be5662.bundle.js.map
1
+ "use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[171],{3171:(e,t,s)=>{s.r(t),s.d(t,{SourceViewEditor:()=>w});var n=s(4589),i=s(1638),o=s(5874),c=s(3720),r=s(5336),a=s(3032),d=s(7514),l=s(3276),f=s.n(l),h=s(8811);const u=new i.xx;function m(e){return null===e?[]:e.endsWith(".rs")?(0,a.T)():e.endsWith(".js")||e.endsWith(".jsm")||e.endsWith(".jsx")||e.endsWith(".mjs")||e.endsWith(".ts")||e.endsWith(".tsx")?(0,d.Q2)():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.I)():[]}const p=[n.Lz.editable.of(!1),n.Lz.contentAttributes.of({tabindex:"0"})];class w{constructor(e,t,s,r){this._view=void 0;let a=i.$t.create({doc:e,extensions:[h.Lf,(0,n.$K)(),u.of(m(t)),(0,o.y9)(c.sS),p]});a=a.update({effects:h.IU.of(s)}).state,this._view=new n.Lz({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:h.IU.of(e)})}scrollToLine(e){e=f()(e,1,this._view.state.doc.lines);const t=this._view.state.doc.line(e).from;this._view.dispatch({effects:n.Lz.scrollIntoView(t,{y:"start",yMargin:0})}),this._view.coordsAtPos(0)}}},8811:(e,t,s)=>{s.d(t,{ES:()=>u,IU:()=>a,Lf:()=>w});var n=s(4589),i=s(1638),o=s(6046);const c=new class extends n.wJ{constructor(...e){super(...e),this.elementClass="cm-nonZeroLine"}},r=n.NZ.line({class:"cm-nonZeroLine"}),a=i.Pe.define(),d=i.sU.define({create:()=>o.tB,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>=1&&e<=n)).map((t=>e.doc.line(t).from));return i.sort(((e,t)=>e-t)),i}const f=n.EV.compute(["doc",d],(e=>{const t=l(e);return i.om.of(t.map((e=>c.range(e))))})),h=n.Lz.decorations.compute(["doc",d],(e=>{const t=l(e);return i.om.of(t.map((e=>r.range(e))))}));class u extends n.wJ{constructor(e){super(),this._s=void 0,this._s=e}toDOM(){return document.createTextNode(this._s)}}const m=(0,n.cU)({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.cU)({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)))))}),w=[d,m,p,f,h]}}]);
2
+ //# sourceMappingURL=171.37d1e1824587d8df0ae2.bundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"171.621b9df5978342be5662.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 >= 1 && 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
+ {"version":3,"file":"171.37d1e1824587d8df0ae2.bundle.js","mappings":"6OAuCA,MAAMA,EAAe,IAAIC,EAAAA,GAGzB,SAASC,EACPC,GAEA,OAAa,OAATA,EACK,GAELA,EAAKC,SAAS,QACTC,EAAAA,EAAAA,KAGPF,EAAKC,SAAS,QACdD,EAAKC,SAAS,SACdD,EAAKC,SAAS,SACdD,EAAKC,SAAS,SACdD,EAAKC,SAAS,QACdD,EAAKC,SAAS,SAEPE,EAAAA,EAAAA,MAGPH,EAAKC,SAAS,OACdD,EAAKC,SAAS,QACdD,EAAKC,SAAS,SACdD,EAAKC,SAAS,SACdD,EAAKC,SAAS,OACdD,EAAKC,SAAS,SACdD,EAAKC,SAAS,OACdD,EAAKC,SAAS,QAEPG,EAAAA,EAAAA,KAEF,EACT,CAGA,MAAMC,EAAsB,CAE1BC,EAAAA,GAAWC,SAASC,IAAG,GAGvBF,EAAAA,GAAWG,kBAAkBD,GAAG,CAAEE,SAAU,OAGvC,MAAMC,EAIXC,WAAAA,CACEC,EACAb,EACAc,EACAC,GACA,KARFC,WAAK,EASH,IAAIC,EAAQC,EAAAA,GAAYC,OAAO,CAC7BC,IAAKP,EACLQ,WAAY,CACVC,EAAAA,IACAC,EAAAA,EAAAA,MACA1B,EAAaW,GAAGT,EAAoBC,KACpCwB,EAAAA,EAAAA,IAAmBC,EAAAA,IACnBpB,KAGJY,EAAQA,EAAMS,OAAO,CACnBC,QAASC,EAAAA,GAAoBpB,GAAGM,KAC/BG,MACHY,KAAKb,MAAQ,IAAIV,EAAAA,GAAW,CAC1BW,QACAa,OAAQf,GAEZ,CAEAgB,yBAAAA,CAA0B/B,GACxB6B,KAAKb,MAAMgB,SAAS,CAClBL,QAAS9B,EAAaoC,YAAYlC,EAAoBC,KAE1D,CAEAkC,WAAAA,CAAYC,GAGVN,KAAKb,MAAMgB,SACTH,KAAKb,MAAMC,MAAMS,OAAO,CACtBU,QAAS,CACPC,OAAQF,EACRG,KAAM,EACNC,GAAIV,KAAKb,MAAMC,MAAMG,IAAIoB,UAIjC,CAEAC,UAAAA,CAAW3B,GAETe,KAAKb,MAAMgB,SAAS,CAClBL,QAASC,EAAAA,GAAoBpB,GAAGM,IAEpC,CAEA4B,YAAAA,CAAaC,GAEXA,EAAaC,IAAMD,EAAY,EAAGd,KAAKb,MAAMC,MAAMG,IAAIyB,OAGvD,MAAMC,EAAMjB,KAAKb,MAAMC,MAAMG,IAAI2B,KAAKJ,GAAYL,KAElDT,KAAKb,MAAMgB,SAAS,CAClBL,QAASrB,EAAAA,GAAW0C,eAAeF,EAAK,CAAEG,EAAG,QAASC,QAAS,MAIjErB,KAAKb,MAAMmC,YAAY,EACzB,E,uFClIF,MAAMC,EAA0B,IAAK,cAAcC,EAAAA,GAAazC,WAAAA,IAAA0C,GAAA,SAAAA,GAAA,KAC9DC,aAAe,gBAAgB,GAK3BC,EAAwBC,EAAAA,GAAWV,KAAK,CAAEW,MAAO,mBAI1C9B,EAAsB+B,EAAAA,GAAYC,SAGzCC,EAAeC,EAAAA,GAAWF,OAAoB,CAClDzC,OAAMA,IACG4C,EAAAA,GAETrC,MAAAA,CAAOZ,EAASkD,GAGd,IAAIC,EAAanD,EACjB,IAAK,MAAMoD,KAAUF,EAAYrC,QAC3BuC,EAAOC,GAAGvC,KACZqC,EAAaC,EAAOE,OAGxB,OAAOH,CACT,IAOF,SAASI,EAAsCpD,GAC7C,MAAMH,EAAUG,EAAMqD,MAAMT,GACtBU,EAAe,IAAIC,IACzB,IAAK,MAAM7B,KAAc7B,EAAQ2D,cAAcC,OAC7CH,EAAaI,IAAIhC,GAEnB,IAAK,MAAMA,KAAc7B,EAAQ8D,aAAaF,OAC5CH,EAAaI,IAAIhC,GAEnB,MAAMkC,EAAY5D,EAAMG,IAAIyB,MACtBiC,EAAY,IAAIP,GACnBQ,QAAQC,GAAMA,GAAK,GAAKA,GAAKH,IAC7BI,KAAKtC,GAAe1B,EAAMG,IAAI2B,KAAKJ,GAAYL,OAElD,OADAwC,EAAUI,MAAK,CAACC,EAAGC,IAAMD,EAAIC,IACtBN,CACT,CAUA,MAAMO,EAA+BC,EAAAA,GAAgBC,QACnD,CAAC,MAAO1B,IACP5C,IACC,MAAM6D,EAAYT,EAAsCpD,GACxD,OAAOuE,EAAAA,GAAShF,GAAGsE,EAAUG,KAAKQ,GAAMrC,EAAwBsC,MAAMD,KAAI,IAOxEE,EAAmCrF,EAAAA,GAAWsF,YAAYL,QAC9D,CAAC,MAAO1B,IACP5C,IACC,MAAM6D,EAAYT,EAAsCpD,GACxD,OAAOuE,EAAAA,GAAShF,GAAGsE,EAAUG,KAAKQ,GAAMjC,EAAsBkC,MAAMD,KAAI,IAOrE,MAAMI,UAAqBxC,EAAAA,GAGhCzC,WAAAA,CAAYkF,GACVC,QAAQ,KAHVC,QAAE,EAIAnE,KAAKmE,GAAKF,CACZ,CAEAG,KAAAA,GACE,OAAOC,SAASC,eAAetE,KAAKmE,GACtC,EAKF,MAAMI,GAAqBC,EAAAA,EAAAA,IAAO,CAChC3C,MAAO,0BACP4C,UAAAA,CAAWC,EAAMxD,GAEf,MAAMJ,EAAa4D,EAAKtF,MAAMG,IAAIoF,OAAOzD,EAAKT,MAAMmE,OAE9CC,EADUH,EAAKtF,MAAMqD,MAAMT,GACPY,cAAckC,IAAIhE,GAC5C,YAAqBiE,IAAdF,EAA0B,IAAIb,EAAaa,GAAa,IACjE,EACAG,iBAAiBnF,GAERA,EAAOoF,aAAaC,MAAMC,GAC/BA,EAAErF,QAAQoF,MAAME,GAAMA,EAAE9C,GAAGvC,SAO3BsF,GAAoBb,EAAAA,EAAAA,IAAO,CAC/B3C,MAAO,yBACP4C,UAAAA,CAAWC,EAAMxD,GAEf,MAAMJ,EAAa4D,EAAKtF,MAAMG,IAAIoF,OAAOzD,EAAKT,MAAMmE,OAE9CU,EADUZ,EAAKtF,MAAMqD,MAAMT,GACRe,aAAa+B,IAAIhE,GAC1C,YAAoBiE,IAAbO,EAAyB,IAAItB,EAAasB,GAAY,IAC/D,EACAN,iBAAiBnF,GAERA,EAAOoF,aAAaC,MAAMC,GAC/BA,EAAErF,QAAQoF,MAAME,GAAMA,EAAE9C,GAAGvC,SAMpBN,EAAmB,CAC9BuC,EACAuC,EACAc,EACA7B,EACAM,E","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 >= 1 && 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":""}
@@ -0,0 +1,8 @@
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
+ <svg xmlns="http://www.w3.org/2000/svg"
5
+ xmlns:xlink="http://www.w3.org/1999/xlink"
6
+ width="48" height="48" viewBox="0 0 24 24">
7
+ <polyline points="4 0 6 0 18 12 6 24 4 24 16 12" stroke="black"/>
8
+ </svg>