From 40117fd2378e3eb4943731a2921ff81a4d42b174 Mon Sep 17 00:00:00 2001 From: Jason Laster Date: Thu, 10 May 2018 09:24:21 -0400 Subject: [PATCH] Bug 1460371 - Update Debugger Frontend v51 r=jdescottes --HG-- rename : devtools/client/debugger/new/debugger.css => devtools/client/debugger/new/dist/debugger.css rename : devtools/client/debugger/new/parser-worker.js => devtools/client/debugger/new/dist/parser-worker.js rename : devtools/client/debugger/new/pretty-print-worker.js => devtools/client/debugger/new/dist/pretty-print-worker.js rename : devtools/client/debugger/new/search-worker.js => devtools/client/debugger/new/dist/search-worker.js --- .../test/static/browser_parsable_css.js | 2 +- devtools/client/debugger/new/debugger.js | 39672 ---------------- .../debugger/new/{ => dist}/debugger.css | 0 devtools/client/debugger/new/dist/moz.build | 12 + .../debugger/new/{ => dist}/parser-worker.js | 0 .../new/{ => dist}/pretty-print-worker.js | 0 .../debugger/new/{ => dist}/search-worker.js | 0 devtools/client/debugger/new/dist/vendors.css | 466 + devtools/client/debugger/new/dist/vendors.js | 9634 ++++ devtools/client/debugger/new/index.html | 48 +- devtools/client/debugger/new/moz.build | 10 +- .../client/debugger/new/src/actions/ast.js | 127 + .../debugger/new/src/actions/ast/moz.build | 12 + .../new/src/actions/ast/setInScopeLines.js | 46 + .../debugger/new/src/actions/breakpoints.js | 497 + .../src/actions/breakpoints/addBreakpoint.js | 75 + .../new/src/actions/breakpoints/moz.build | 14 + .../src/actions/breakpoints/remapLocations.js | 27 + .../src/actions/breakpoints/syncBreakpoint.js | 119 + .../debugger/new/src/actions/coverage.js | 27 + .../debugger/new/src/actions/debuggee.js | 24 + .../new/src/actions/event-listeners.js | 180 + .../debugger/new/src/actions/expressions.js | 218 + .../debugger/new/src/actions/file-search.js | 201 + .../client/debugger/new/src/actions/index.js | 81 + .../client/debugger/new/src/actions/moz.build | 31 + .../debugger/new/src/actions/navigation.js | 103 + .../new/src/actions/pause/breakOnNext.js | 31 + .../new/src/actions/pause/commands.js | 257 + .../new/src/actions/pause/continueToHere.js | 43 + .../debugger/new/src/actions/pause/extra.js | 111 + .../new/src/actions/pause/fetchScopes.js | 40 + .../debugger/new/src/actions/pause/index.js | 161 + .../new/src/actions/pause/mapFrames.js | 84 + .../new/src/actions/pause/mapScopes.js | 54 + .../debugger/new/src/actions/pause/moz.build | 25 + .../src/actions/pause/pauseOnExceptions.js | 31 + .../debugger/new/src/actions/pause/paused.js | 105 + .../debugger/new/src/actions/pause/resumed.js | 41 + .../new/src/actions/pause/selectFrame.js | 37 + .../actions/pause/setPopupObjectProperties.js | 36 + .../new/src/actions/pause/skipPausing.js | 33 + .../debugger/new/src/actions/preview.js | 174 + .../new/src/actions/project-text-search.js | 117 + .../debugger/new/src/actions/quick-open.js | 37 + .../client/debugger/new/src/actions/replay.js | 45 + .../debugger/new/src/actions/source-tree.js | 21 + .../new/src/actions/sources/blackbox.js | 35 + .../debugger/new/src/actions/sources/index.js | 77 + .../new/src/actions/sources/loadSourceText.js | 114 + .../new/src/actions/sources/moz.build | 18 + .../new/src/actions/sources/newSources.js | 206 + .../new/src/actions/sources/prettyPrint.js | 139 + .../new/src/actions/sources/select.js | 251 + .../debugger/new/src/actions/sources/tabs.js | 91 + .../debugger/new/src/actions/toolbox.js | 61 + .../client/debugger/new/src/actions/ui.js | 226 + .../new/src/actions/utils/create-store.js | 73 + .../src/actions/utils/middleware/history.js | 32 + .../new/src/actions/utils/middleware/log.js | 117 + .../src/actions/utils/middleware/moz.build | 17 + .../src/actions/utils/middleware/promise.js | 70 + .../new/src/actions/utils/middleware/thunk.js | 34 + .../src/actions/utils/middleware/timing.js | 29 + .../actions/utils/middleware/wait-service.js | 75 + .../debugger/new/src/actions/utils/moz.build | 12 + .../client/debugger/new/src/client/firefox.js | 89 + .../new/src/client/firefox/commands.js | 437 + .../debugger/new/src/client/firefox/create.js | 85 + .../debugger/new/src/client/firefox/events.js | 104 + .../new/src/client/firefox/fronts-device.js | 21 + .../debugger/new/src/client/firefox/moz.build | 15 + .../client/debugger/new/src/client/index.js | 73 + .../client/debugger/new/src/client/moz.build | 13 + .../client/debugger/new/src/components/App.js | 297 + .../new/src/components/Editor/Breakpoint.js | 138 + .../new/src/components/Editor/Breakpoints.js | 63 + .../new/src/components/Editor/CallSite.js | 99 + .../new/src/components/Editor/CallSites.js | 257 + .../src/components/Editor/ConditionalPanel.js | 213 + .../new/src/components/Editor/DebugLine.js | 134 + .../new/src/components/Editor/EditorMenu.js | 242 + .../new/src/components/Editor/EmptyLines.js | 80 + .../new/src/components/Editor/Footer.js | 202 + .../new/src/components/Editor/GutterMenu.js | 176 + .../src/components/Editor/HighlightLine.js | 132 + .../src/components/Editor/HighlightLines.js | 96 + .../new/src/components/Editor/HitMarker.js | 53 + .../src/components/Editor/Preview/Popup.js | 336 + .../src/components/Editor/Preview/index.js | 161 + .../src/components/Editor/Preview/moz.build | 13 + .../new/src/components/Editor/SearchBar.js | 368 + .../debugger/new/src/components/Editor/Tab.js | 194 + .../new/src/components/Editor/Tabs.js | 216 + .../new/src/components/Editor/index.js | 638 + .../new/src/components/Editor/moz.build | 28 + .../src/components/PrimaryPanes/Outline.js | 205 + .../components/PrimaryPanes/SourcesTree.js | 415 + .../new/src/components/PrimaryPanes/index.js | 127 + .../new/src/components/PrimaryPanes/moz.build | 14 + .../new/src/components/ProjectSearch.js | 324 + .../new/src/components/QuickOpenModal.js | 484 + .../components/SecondaryPanes/Breakpoint.js | 200 + .../components/SecondaryPanes/Breakpoints.js | 204 + .../SecondaryPanes/BreakpointsContextMenu.js | 201 + .../components/SecondaryPanes/CommandBar.js | 294 + .../SecondaryPanes/EventListeners.js | 117 + .../components/SecondaryPanes/Expressions.js | 326 + .../components/SecondaryPanes/Frames/Frame.js | 132 + .../SecondaryPanes/Frames/FrameMenu.js | 68 + .../components/SecondaryPanes/Frames/Group.js | 154 + .../SecondaryPanes/Frames/WhyPaused.js | 61 + .../components/SecondaryPanes/Frames/index.js | 177 + .../SecondaryPanes/Frames/moz.build | 16 + .../SecondaryPanes/FrameworkComponent.js | 116 + .../SecondaryPanes/ReactComponentStack.js | 42 + .../src/components/SecondaryPanes/Scopes.js | 148 + .../src/components/SecondaryPanes/UtilsBar.js | 37 + .../src/components/SecondaryPanes/Workers.js | 64 + .../src/components/SecondaryPanes/index.js | 411 + .../src/components/SecondaryPanes/moz.build | 23 + .../new/src/components/ShortcutsModal.js | 87 + .../debugger/new/src/components/WelcomeBox.js | 91 + .../debugger/new/src/components/moz.build | 20 + .../new/src/components/shared/Accordion.js | 76 + .../new/src/components/shared/Badge.js | 22 + .../new/src/components/shared/BracketArrow.js | 36 + .../new/src/components/shared/Button/Close.js | 30 + .../shared/Button/CommandBarButton.js | 49 + .../components/shared/Button/PaneToggle.js | 54 + .../src/components/shared/Button/moz.build | 14 + .../new/src/components/shared/Dropdown.js | 68 + .../new/src/components/shared/ManagedTree.js | 155 + .../new/src/components/shared/Modal.js | 79 + .../new/src/components/shared/Popover.js | 309 + .../src/components/shared/PreviewFunction.js | 60 + .../new/src/components/shared/ResultList.js | 81 + .../new/src/components/shared/SearchInput.js | 189 + .../debugger/new/src/components/shared/Svg.js | 20 + .../new/src/components/shared/moz.build | 22 + .../new/src/components/test/Outline.spec.js | 316 + .../src/components/test/ProjectSearch.spec.js | 248 + .../components/test/QuickOpenModal.spec.js | 277 + .../components/test/ShortcutsModal.spec.js | 28 + .../src/components/test/SourcesTree.spec.js | 639 + .../src/components/test/WelcomeBox.spec.js | 50 + .../new/src/components/test/WhyPaused.spec.js | 45 + .../new/src/components/test/moz.build | 18 + devtools/client/debugger/new/src/main.js | 82 + devtools/client/debugger/new/src/moz.build | 18 + .../client/debugger/new/src/reducers/ast.js | 233 + .../new/src/reducers/async-requests.js | 39 + .../debugger/new/src/reducers/breakpoints.js | 237 + .../debugger/new/src/reducers/coverage.js | 62 + .../debugger/new/src/reducers/debuggee.js | 48 + .../new/src/reducers/event-listeners.js | 50 + .../debugger/new/src/reducers/expressions.js | 171 + .../debugger/new/src/reducers/file-search.js | 94 + .../client/debugger/new/src/reducers/index.js | 98 + .../debugger/new/src/reducers/moz.build | 28 + .../client/debugger/new/src/reducers/pause.js | 416 + .../new/src/reducers/pending-breakpoints.js | 176 + .../new/src/reducers/project-text-search.js | 100 + .../debugger/new/src/reducers/quick-open.js | 71 + .../debugger/new/src/reducers/replay.js | 216 + .../debugger/new/src/reducers/source-tree.js | 41 + .../debugger/new/src/reducers/sources.js | 408 + .../client/debugger/new/src/reducers/ui.js | 184 + .../new/src/selectors/breakpointAtLocation.js | 74 + .../new/src/selectors/getCallStackFrames.js | 51 + .../new/src/selectors/getRelativeSources.js | 41 + .../debugger/new/src/selectors/index.js | 245 + .../src/selectors/isSelectedFrameVisible.js | 43 + .../debugger/new/src/selectors/moz.build | 18 + .../selectors/test/getCallStackFrames.spec.js | 189 + .../debugger/new/src/selectors/test/moz.build | 12 + .../new/src/selectors/visibleBreakpoints.js | 60 + .../new/src/selectors/visibleSelectedFrame.js | 39 + .../debugger/new/src/utils/DevToolsUtils.js | 27 + .../client/debugger/new/src/utils/assert.js | 17 + devtools/client/debugger/new/src/utils/ast.js | 114 + .../debugger/new/src/utils/bootstrap.js | 154 + .../utils/breakpoint/astBreakpointLocation.js | 49 + .../new/src/utils/breakpoint/create-editor.js | 33 + .../new/src/utils/breakpoint/index.js | 202 + .../new/src/utils/breakpoint/moz.build | 14 + .../debugger/new/src/utils/clipboard.js | 25 + devtools/client/debugger/new/src/utils/dbg.js | 98 + .../client/debugger/new/src/utils/defer.js | 25 + .../new/src/utils/editor/create-editor.js | 48 + .../new/src/utils/editor/get-expression.js | 83 + .../src/utils/editor/get-token-location.js | 29 + .../debugger/new/src/utils/editor/index.js | 265 + .../debugger/new/src/utils/editor/moz.build | 18 + .../new/src/utils/editor/source-documents.js | 183 + .../new/src/utils/editor/source-editor.js | 157 + .../new/src/utils/editor/source-search.js | 375 + .../debugger/new/src/utils/expressions.js | 111 + .../client/debugger/new/src/utils/fromJS.js | 106 + .../client/debugger/new/src/utils/function.js | 39 + .../debugger/new/src/utils/indentation.js | 33 + .../debugger/new/src/utils/isMinified.js | 62 + .../client/debugger/new/src/utils/location.js | 23 + devtools/client/debugger/new/src/utils/log.js | 37 + .../debugger/new/src/utils/makeRecord.js | 37 + .../client/debugger/new/src/utils/moz.build | 47 + .../client/debugger/new/src/utils/path.js | 35 + .../src/utils/pause/frames/annotateFrames.js | 75 + .../src/utils/pause/frames/collapseFrames.js | 77 + .../new/src/utils/pause/frames/displayName.js | 100 + .../new/src/utils/pause/frames/getFrameUrl.js | 15 + .../utils/pause/frames/getLibraryFromUrl.js | 95 + .../new/src/utils/pause/frames/index.js | 65 + .../new/src/utils/pause/frames/moz.build | 17 + .../debugger/new/src/utils/pause/index.js | 29 + .../mapScopes/buildGeneratedBindingList.js | 117 + .../src/utils/pause/mapScopes/filtering.js | 55 + .../findGeneratedBindingFromPosition.js | 331 + .../mapScopes/getGeneratedLocationRanges.js | 126 + .../new/src/utils/pause/mapScopes/index.js | 309 + .../src/utils/pause/mapScopes/locColumn.js | 19 + .../utils/pause/mapScopes/mappingContains.js | 15 + .../new/src/utils/pause/mapScopes/moz.build | 19 + .../src/utils/pause/mapScopes/positionCmp.js | 32 + .../debugger/new/src/utils/pause/moz.build | 17 + .../new/src/utils/pause/pausePoints.js | 57 + .../new/src/utils/pause/scopes/getScope.js | 92 + .../src/utils/pause/scopes/getVariables.js | 29 + .../new/src/utils/pause/scopes/index.js | 38 + .../new/src/utils/pause/scopes/moz.build | 15 + .../new/src/utils/pause/scopes/utils.js | 59 + .../debugger/new/src/utils/pause/stepping.js | 44 + .../debugger/new/src/utils/pause/why.js | 63 + .../client/debugger/new/src/utils/prefs.js | 121 + .../client/debugger/new/src/utils/preview.js | 45 + .../debugger/new/src/utils/project-search.js | 37 + .../debugger/new/src/utils/quick-open.js | 129 + .../debugger/new/src/utils/result-list.js | 58 + .../debugger/new/src/utils/source-maps.js | 35 + .../debugger/new/src/utils/source-queue.js | 40 + .../client/debugger/new/src/utils/source.js | 441 + .../new/src/utils/sources-tree/addToTree.js | 141 + .../src/utils/sources-tree/collapseTree.js | 35 + .../new/src/utils/sources-tree/createTree.js | 35 + .../new/src/utils/sources-tree/formatTree.js | 25 + .../src/utils/sources-tree/getDirectories.js | 63 + .../new/src/utils/sources-tree/getURL.js | 124 + .../new/src/utils/sources-tree/index.js | 140 + .../new/src/utils/sources-tree/moz.build | 22 + .../new/src/utils/sources-tree/sortTree.js | 60 + .../new/src/utils/sources-tree/treeOrder.js | 160 + .../new/src/utils/sources-tree/updateTree.js | 44 + .../new/src/utils/sources-tree/utils.js | 113 + .../client/debugger/new/src/utils/tabs.js | 125 + .../client/debugger/new/src/utils/task.js | 53 + .../debugger/new/src/utils/test-head.js | 167 + .../client/debugger/new/src/utils/text.js | 44 + .../client/debugger/new/src/utils/timings.js | 48 + devtools/client/debugger/new/src/utils/ui.js | 61 + .../client/debugger/new/src/utils/utils.js | 62 + .../client/debugger/new/src/utils/wasm.js | 190 + .../client/debugger/new/src/utils/worker.js | 74 + .../client/debugger/new/src/workers/moz.build | 14 + .../workers/parser/findOutOfScopeLocations.js | 149 + .../new/src/workers/parser/frameworks.js | 88 + .../new/src/workers/parser/getScopes/index.js | 78 + .../src/workers/parser/getScopes/moz.build | 13 + .../src/workers/parser/getScopes/visitor.js | 673 + .../new/src/workers/parser/getSymbols.js | 471 + .../debugger/new/src/workers/parser/index.js | 34 + .../workers/parser/mapOriginalExpression.js | 114 + .../debugger/new/src/workers/parser/moz.build | 22 + .../new/src/workers/parser/pausePoints.js | 194 + .../new/src/workers/parser/sources.js | 34 + .../debugger/new/src/workers/parser/steps.js | 64 + .../new/src/workers/parser/utils/ast.js | 169 + .../new/src/workers/parser/utils/closest.js | 41 + .../new/src/workers/parser/utils/contains.js | 43 + .../src/workers/parser/utils/formatSymbols.js | 60 + .../workers/parser/utils/getFunctionName.js | 105 + .../new/src/workers/parser/utils/helpers.js | 191 + .../workers/parser/utils/inferClassName.js | 98 + .../new/src/workers/parser/utils/moz.build | 19 + .../src/workers/parser/utils/simple-path.js | 161 + .../new/src/workers/parser/validate.js | 20 + .../debugger/new/src/workers/parser/worker.js | 54 + .../new/src/workers/pretty-print/index.js | 42 + .../new/src/workers/pretty-print/moz.build | 13 + .../new/src/workers/pretty-print/worker.js | 57 + .../new/src/workers/search/build-query.js | 84 + .../new/src/workers/search/get-matches.js | 41 + .../debugger/new/src/workers/search/index.js | 20 + .../debugger/new/src/workers/search/moz.build | 16 + .../new/src/workers/search/project-search.js | 43 + .../debugger/new/src/workers/search/worker.js | 22 + .../client/shared/components/reps/reps.js | 10 +- devtools/client/shared/source-map/index.js | 10 +- devtools/client/shared/source-map/worker.js | 10 +- 298 files changed, 41364 insertions(+), 39707 deletions(-) delete mode 100644 devtools/client/debugger/new/debugger.js rename devtools/client/debugger/new/{ => dist}/debugger.css (100%) create mode 100644 devtools/client/debugger/new/dist/moz.build rename devtools/client/debugger/new/{ => dist}/parser-worker.js (100%) rename devtools/client/debugger/new/{ => dist}/pretty-print-worker.js (100%) rename devtools/client/debugger/new/{ => dist}/search-worker.js (100%) create mode 100644 devtools/client/debugger/new/dist/vendors.css create mode 100644 devtools/client/debugger/new/dist/vendors.js create mode 100644 devtools/client/debugger/new/src/actions/ast.js create mode 100644 devtools/client/debugger/new/src/actions/ast/moz.build create mode 100644 devtools/client/debugger/new/src/actions/ast/setInScopeLines.js create mode 100644 devtools/client/debugger/new/src/actions/breakpoints.js create mode 100644 devtools/client/debugger/new/src/actions/breakpoints/addBreakpoint.js create mode 100644 devtools/client/debugger/new/src/actions/breakpoints/moz.build create mode 100644 devtools/client/debugger/new/src/actions/breakpoints/remapLocations.js create mode 100644 devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js create mode 100644 devtools/client/debugger/new/src/actions/coverage.js create mode 100644 devtools/client/debugger/new/src/actions/debuggee.js create mode 100644 devtools/client/debugger/new/src/actions/event-listeners.js create mode 100644 devtools/client/debugger/new/src/actions/expressions.js create mode 100644 devtools/client/debugger/new/src/actions/file-search.js create mode 100644 devtools/client/debugger/new/src/actions/index.js create mode 100644 devtools/client/debugger/new/src/actions/moz.build create mode 100644 devtools/client/debugger/new/src/actions/navigation.js create mode 100644 devtools/client/debugger/new/src/actions/pause/breakOnNext.js create mode 100644 devtools/client/debugger/new/src/actions/pause/commands.js create mode 100644 devtools/client/debugger/new/src/actions/pause/continueToHere.js create mode 100644 devtools/client/debugger/new/src/actions/pause/extra.js create mode 100644 devtools/client/debugger/new/src/actions/pause/fetchScopes.js create mode 100644 devtools/client/debugger/new/src/actions/pause/index.js create mode 100644 devtools/client/debugger/new/src/actions/pause/mapFrames.js create mode 100644 devtools/client/debugger/new/src/actions/pause/mapScopes.js create mode 100644 devtools/client/debugger/new/src/actions/pause/moz.build create mode 100644 devtools/client/debugger/new/src/actions/pause/pauseOnExceptions.js create mode 100644 devtools/client/debugger/new/src/actions/pause/paused.js create mode 100644 devtools/client/debugger/new/src/actions/pause/resumed.js create mode 100644 devtools/client/debugger/new/src/actions/pause/selectFrame.js create mode 100644 devtools/client/debugger/new/src/actions/pause/setPopupObjectProperties.js create mode 100644 devtools/client/debugger/new/src/actions/pause/skipPausing.js create mode 100644 devtools/client/debugger/new/src/actions/preview.js create mode 100644 devtools/client/debugger/new/src/actions/project-text-search.js create mode 100644 devtools/client/debugger/new/src/actions/quick-open.js create mode 100644 devtools/client/debugger/new/src/actions/replay.js create mode 100644 devtools/client/debugger/new/src/actions/source-tree.js create mode 100644 devtools/client/debugger/new/src/actions/sources/blackbox.js create mode 100644 devtools/client/debugger/new/src/actions/sources/index.js create mode 100644 devtools/client/debugger/new/src/actions/sources/loadSourceText.js create mode 100644 devtools/client/debugger/new/src/actions/sources/moz.build create mode 100644 devtools/client/debugger/new/src/actions/sources/newSources.js create mode 100644 devtools/client/debugger/new/src/actions/sources/prettyPrint.js create mode 100644 devtools/client/debugger/new/src/actions/sources/select.js create mode 100644 devtools/client/debugger/new/src/actions/sources/tabs.js create mode 100644 devtools/client/debugger/new/src/actions/toolbox.js create mode 100644 devtools/client/debugger/new/src/actions/ui.js create mode 100644 devtools/client/debugger/new/src/actions/utils/create-store.js create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/history.js create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/log.js create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/moz.build create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/promise.js create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/thunk.js create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/timing.js create mode 100644 devtools/client/debugger/new/src/actions/utils/middleware/wait-service.js create mode 100644 devtools/client/debugger/new/src/actions/utils/moz.build create mode 100644 devtools/client/debugger/new/src/client/firefox.js create mode 100644 devtools/client/debugger/new/src/client/firefox/commands.js create mode 100644 devtools/client/debugger/new/src/client/firefox/create.js create mode 100644 devtools/client/debugger/new/src/client/firefox/events.js create mode 100644 devtools/client/debugger/new/src/client/firefox/fronts-device.js create mode 100644 devtools/client/debugger/new/src/client/firefox/moz.build create mode 100644 devtools/client/debugger/new/src/client/index.js create mode 100644 devtools/client/debugger/new/src/client/moz.build create mode 100644 devtools/client/debugger/new/src/components/App.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Breakpoint.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Breakpoints.js create mode 100644 devtools/client/debugger/new/src/components/Editor/CallSite.js create mode 100644 devtools/client/debugger/new/src/components/Editor/CallSites.js create mode 100644 devtools/client/debugger/new/src/components/Editor/ConditionalPanel.js create mode 100644 devtools/client/debugger/new/src/components/Editor/DebugLine.js create mode 100644 devtools/client/debugger/new/src/components/Editor/EditorMenu.js create mode 100644 devtools/client/debugger/new/src/components/Editor/EmptyLines.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Footer.js create mode 100644 devtools/client/debugger/new/src/components/Editor/GutterMenu.js create mode 100644 devtools/client/debugger/new/src/components/Editor/HighlightLine.js create mode 100644 devtools/client/debugger/new/src/components/Editor/HighlightLines.js create mode 100644 devtools/client/debugger/new/src/components/Editor/HitMarker.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Preview/Popup.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Preview/index.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Preview/moz.build create mode 100644 devtools/client/debugger/new/src/components/Editor/SearchBar.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Tab.js create mode 100644 devtools/client/debugger/new/src/components/Editor/Tabs.js create mode 100644 devtools/client/debugger/new/src/components/Editor/index.js create mode 100644 devtools/client/debugger/new/src/components/Editor/moz.build create mode 100644 devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js create mode 100644 devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js create mode 100644 devtools/client/debugger/new/src/components/PrimaryPanes/index.js create mode 100644 devtools/client/debugger/new/src/components/PrimaryPanes/moz.build create mode 100644 devtools/client/debugger/new/src/components/ProjectSearch.js create mode 100644 devtools/client/debugger/new/src/components/QuickOpenModal.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/BreakpointsContextMenu.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Frames/WhyPaused.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Frames/moz.build create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/FrameworkComponent.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/ReactComponentStack.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/UtilsBar.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/Workers.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/index.js create mode 100644 devtools/client/debugger/new/src/components/SecondaryPanes/moz.build create mode 100644 devtools/client/debugger/new/src/components/ShortcutsModal.js create mode 100644 devtools/client/debugger/new/src/components/WelcomeBox.js create mode 100644 devtools/client/debugger/new/src/components/moz.build create mode 100644 devtools/client/debugger/new/src/components/shared/Accordion.js create mode 100644 devtools/client/debugger/new/src/components/shared/Badge.js create mode 100644 devtools/client/debugger/new/src/components/shared/BracketArrow.js create mode 100644 devtools/client/debugger/new/src/components/shared/Button/Close.js create mode 100644 devtools/client/debugger/new/src/components/shared/Button/CommandBarButton.js create mode 100644 devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js create mode 100644 devtools/client/debugger/new/src/components/shared/Button/moz.build create mode 100644 devtools/client/debugger/new/src/components/shared/Dropdown.js create mode 100644 devtools/client/debugger/new/src/components/shared/ManagedTree.js create mode 100644 devtools/client/debugger/new/src/components/shared/Modal.js create mode 100644 devtools/client/debugger/new/src/components/shared/Popover.js create mode 100644 devtools/client/debugger/new/src/components/shared/PreviewFunction.js create mode 100644 devtools/client/debugger/new/src/components/shared/ResultList.js create mode 100644 devtools/client/debugger/new/src/components/shared/SearchInput.js create mode 100644 devtools/client/debugger/new/src/components/shared/Svg.js create mode 100644 devtools/client/debugger/new/src/components/shared/moz.build create mode 100644 devtools/client/debugger/new/src/components/test/Outline.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/QuickOpenModal.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/ShortcutsModal.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/SourcesTree.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/WelcomeBox.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/WhyPaused.spec.js create mode 100644 devtools/client/debugger/new/src/components/test/moz.build create mode 100644 devtools/client/debugger/new/src/main.js create mode 100644 devtools/client/debugger/new/src/moz.build create mode 100644 devtools/client/debugger/new/src/reducers/ast.js create mode 100644 devtools/client/debugger/new/src/reducers/async-requests.js create mode 100644 devtools/client/debugger/new/src/reducers/breakpoints.js create mode 100644 devtools/client/debugger/new/src/reducers/coverage.js create mode 100644 devtools/client/debugger/new/src/reducers/debuggee.js create mode 100644 devtools/client/debugger/new/src/reducers/event-listeners.js create mode 100644 devtools/client/debugger/new/src/reducers/expressions.js create mode 100644 devtools/client/debugger/new/src/reducers/file-search.js create mode 100644 devtools/client/debugger/new/src/reducers/index.js create mode 100644 devtools/client/debugger/new/src/reducers/moz.build create mode 100644 devtools/client/debugger/new/src/reducers/pause.js create mode 100644 devtools/client/debugger/new/src/reducers/pending-breakpoints.js create mode 100644 devtools/client/debugger/new/src/reducers/project-text-search.js create mode 100644 devtools/client/debugger/new/src/reducers/quick-open.js create mode 100644 devtools/client/debugger/new/src/reducers/replay.js create mode 100644 devtools/client/debugger/new/src/reducers/source-tree.js create mode 100644 devtools/client/debugger/new/src/reducers/sources.js create mode 100644 devtools/client/debugger/new/src/reducers/ui.js create mode 100644 devtools/client/debugger/new/src/selectors/breakpointAtLocation.js create mode 100644 devtools/client/debugger/new/src/selectors/getCallStackFrames.js create mode 100644 devtools/client/debugger/new/src/selectors/getRelativeSources.js create mode 100644 devtools/client/debugger/new/src/selectors/index.js create mode 100644 devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js create mode 100644 devtools/client/debugger/new/src/selectors/moz.build create mode 100644 devtools/client/debugger/new/src/selectors/test/getCallStackFrames.spec.js create mode 100644 devtools/client/debugger/new/src/selectors/test/moz.build create mode 100644 devtools/client/debugger/new/src/selectors/visibleBreakpoints.js create mode 100644 devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js create mode 100644 devtools/client/debugger/new/src/utils/DevToolsUtils.js create mode 100644 devtools/client/debugger/new/src/utils/assert.js create mode 100644 devtools/client/debugger/new/src/utils/ast.js create mode 100644 devtools/client/debugger/new/src/utils/bootstrap.js create mode 100644 devtools/client/debugger/new/src/utils/breakpoint/astBreakpointLocation.js create mode 100644 devtools/client/debugger/new/src/utils/breakpoint/create-editor.js create mode 100644 devtools/client/debugger/new/src/utils/breakpoint/index.js create mode 100644 devtools/client/debugger/new/src/utils/breakpoint/moz.build create mode 100644 devtools/client/debugger/new/src/utils/clipboard.js create mode 100644 devtools/client/debugger/new/src/utils/dbg.js create mode 100644 devtools/client/debugger/new/src/utils/defer.js create mode 100644 devtools/client/debugger/new/src/utils/editor/create-editor.js create mode 100644 devtools/client/debugger/new/src/utils/editor/get-expression.js create mode 100644 devtools/client/debugger/new/src/utils/editor/get-token-location.js create mode 100644 devtools/client/debugger/new/src/utils/editor/index.js create mode 100644 devtools/client/debugger/new/src/utils/editor/moz.build create mode 100644 devtools/client/debugger/new/src/utils/editor/source-documents.js create mode 100644 devtools/client/debugger/new/src/utils/editor/source-editor.js create mode 100644 devtools/client/debugger/new/src/utils/editor/source-search.js create mode 100644 devtools/client/debugger/new/src/utils/expressions.js create mode 100644 devtools/client/debugger/new/src/utils/fromJS.js create mode 100644 devtools/client/debugger/new/src/utils/function.js create mode 100644 devtools/client/debugger/new/src/utils/indentation.js create mode 100644 devtools/client/debugger/new/src/utils/isMinified.js create mode 100644 devtools/client/debugger/new/src/utils/location.js create mode 100644 devtools/client/debugger/new/src/utils/log.js create mode 100644 devtools/client/debugger/new/src/utils/makeRecord.js create mode 100644 devtools/client/debugger/new/src/utils/moz.build create mode 100644 devtools/client/debugger/new/src/utils/path.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/annotateFrames.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/displayName.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/getFrameUrl.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/getLibraryFromUrl.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/index.js create mode 100644 devtools/client/debugger/new/src/utils/pause/frames/moz.build create mode 100644 devtools/client/debugger/new/src/utils/pause/index.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/buildGeneratedBindingList.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/filtering.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/findGeneratedBindingFromPosition.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/getGeneratedLocationRanges.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/index.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/locColumn.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/mappingContains.js create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build create mode 100644 devtools/client/debugger/new/src/utils/pause/mapScopes/positionCmp.js create mode 100644 devtools/client/debugger/new/src/utils/pause/moz.build create mode 100644 devtools/client/debugger/new/src/utils/pause/pausePoints.js create mode 100644 devtools/client/debugger/new/src/utils/pause/scopes/getScope.js create mode 100644 devtools/client/debugger/new/src/utils/pause/scopes/getVariables.js create mode 100644 devtools/client/debugger/new/src/utils/pause/scopes/index.js create mode 100644 devtools/client/debugger/new/src/utils/pause/scopes/moz.build create mode 100644 devtools/client/debugger/new/src/utils/pause/scopes/utils.js create mode 100644 devtools/client/debugger/new/src/utils/pause/stepping.js create mode 100644 devtools/client/debugger/new/src/utils/pause/why.js create mode 100644 devtools/client/debugger/new/src/utils/prefs.js create mode 100644 devtools/client/debugger/new/src/utils/preview.js create mode 100644 devtools/client/debugger/new/src/utils/project-search.js create mode 100644 devtools/client/debugger/new/src/utils/quick-open.js create mode 100644 devtools/client/debugger/new/src/utils/result-list.js create mode 100644 devtools/client/debugger/new/src/utils/source-maps.js create mode 100644 devtools/client/debugger/new/src/utils/source-queue.js create mode 100644 devtools/client/debugger/new/src/utils/source.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/addToTree.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/collapseTree.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/createTree.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/formatTree.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/getDirectories.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/getURL.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/index.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/moz.build create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/sortTree.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/treeOrder.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/updateTree.js create mode 100644 devtools/client/debugger/new/src/utils/sources-tree/utils.js create mode 100644 devtools/client/debugger/new/src/utils/tabs.js create mode 100644 devtools/client/debugger/new/src/utils/task.js create mode 100644 devtools/client/debugger/new/src/utils/test-head.js create mode 100644 devtools/client/debugger/new/src/utils/text.js create mode 100644 devtools/client/debugger/new/src/utils/timings.js create mode 100644 devtools/client/debugger/new/src/utils/ui.js create mode 100644 devtools/client/debugger/new/src/utils/utils.js create mode 100644 devtools/client/debugger/new/src/utils/wasm.js create mode 100644 devtools/client/debugger/new/src/utils/worker.js create mode 100644 devtools/client/debugger/new/src/workers/moz.build create mode 100644 devtools/client/debugger/new/src/workers/parser/findOutOfScopeLocations.js create mode 100644 devtools/client/debugger/new/src/workers/parser/frameworks.js create mode 100644 devtools/client/debugger/new/src/workers/parser/getScopes/index.js create mode 100644 devtools/client/debugger/new/src/workers/parser/getScopes/moz.build create mode 100644 devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js create mode 100644 devtools/client/debugger/new/src/workers/parser/getSymbols.js create mode 100644 devtools/client/debugger/new/src/workers/parser/index.js create mode 100644 devtools/client/debugger/new/src/workers/parser/mapOriginalExpression.js create mode 100644 devtools/client/debugger/new/src/workers/parser/moz.build create mode 100644 devtools/client/debugger/new/src/workers/parser/pausePoints.js create mode 100644 devtools/client/debugger/new/src/workers/parser/sources.js create mode 100644 devtools/client/debugger/new/src/workers/parser/steps.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/ast.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/closest.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/contains.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/getFunctionName.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/helpers.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/inferClassName.js create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/moz.build create mode 100644 devtools/client/debugger/new/src/workers/parser/utils/simple-path.js create mode 100644 devtools/client/debugger/new/src/workers/parser/validate.js create mode 100644 devtools/client/debugger/new/src/workers/parser/worker.js create mode 100644 devtools/client/debugger/new/src/workers/pretty-print/index.js create mode 100644 devtools/client/debugger/new/src/workers/pretty-print/moz.build create mode 100644 devtools/client/debugger/new/src/workers/pretty-print/worker.js create mode 100644 devtools/client/debugger/new/src/workers/search/build-query.js create mode 100644 devtools/client/debugger/new/src/workers/search/get-matches.js create mode 100644 devtools/client/debugger/new/src/workers/search/index.js create mode 100644 devtools/client/debugger/new/src/workers/search/moz.build create mode 100644 devtools/client/debugger/new/src/workers/search/project-search.js create mode 100644 devtools/client/debugger/new/src/workers/search/worker.js diff --git a/browser/base/content/test/static/browser_parsable_css.js b/browser/base/content/test/static/browser_parsable_css.js index b0204ea2f2ef..84ffd9ea50ac 100644 --- a/browser/base/content/test/static/browser_parsable_css.js +++ b/browser/base/content/test/static/browser_parsable_css.js @@ -14,7 +14,7 @@ let whitelist = [ {sourceName: /codemirror\.css$/i, isFromDevTools: true}, // The debugger uses cross-browser CSS. - {sourceName: /devtools\/client\/debugger\/new\/debugger.css/i, + {sourceName: /devtools\/client\/debugger\/new\/dist\/debugger.css/i, isFromDevTools: true}, // Reps uses cross-browser CSS. {sourceName: /devtools-client-shared\/components\/reps\/reps.css/i, diff --git a/devtools/client/debugger/new/debugger.js b/devtools/client/debugger/new/debugger.js deleted file mode 100644 index afb736805978..000000000000 --- a/devtools/client/debugger/new/debugger.js +++ /dev/null @@ -1,39672 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/sourceeditor/editor"), require("devtools/client/shared/vendor/WasmParser"), require("devtools/client/shared/vendor/WasmDis"), require("devtools/client/shared/vendor/react-redux"), require("devtools/client/shared/vendor/redux"), require("devtools/client/shared/vendor/immutable"), require("devtools/shared/fronts/device"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")); - else if(typeof define === 'function' && define.amd) - define(["devtools/client/shared/vendor/react", "devtools/client/shared/vendor/lodash", "devtools/client/shared/vendor/react-dom", "Services", "devtools/shared/flags", "devtools/client/sourceeditor/editor", "devtools/client/shared/vendor/WasmParser", "devtools/client/shared/vendor/WasmDis", "devtools/client/shared/vendor/react-redux", "devtools/client/shared/vendor/redux", "devtools/client/shared/vendor/immutable", "devtools/shared/fronts/device", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react-dom-factories"], factory); - else { - var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/sourceeditor/editor"), require("devtools/client/shared/vendor/WasmParser"), require("devtools/client/shared/vendor/WasmDis"), require("devtools/client/shared/vendor/react-redux"), require("devtools/client/shared/vendor/redux"), require("devtools/client/shared/vendor/immutable"), require("devtools/shared/fronts/device"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")) : factory(root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/lodash"], root["devtools/client/shared/vendor/react-dom"], root["Services"], root["devtools/shared/flags"], root["devtools/client/sourceeditor/editor"], root["devtools/client/shared/vendor/WasmParser"], root["devtools/client/shared/vendor/WasmDis"], root["devtools/client/shared/vendor/react-redux"], root["devtools/client/shared/vendor/redux"], root["devtools/client/shared/vendor/immutable"], root["devtools/shared/fronts/device"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react-dom-factories"]); - for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; - } -})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_52__, __WEBPACK_EXTERNAL_MODULE_197__, __WEBPACK_EXTERNAL_MODULE_677__, __WEBPACK_EXTERNAL_MODULE_678__, __WEBPACK_EXTERNAL_MODULE_3592__, __WEBPACK_EXTERNAL_MODULE_3593__, __WEBPACK_EXTERNAL_MODULE_3594__, __WEBPACK_EXTERNAL_MODULE_3626__, __WEBPACK_EXTERNAL_MODULE_3642__, __WEBPACK_EXTERNAL_MODULE_3643__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = "/assets/build"; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 46); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ 0: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_0__; - -/***/ }), - -/***/ 10: -/***/ (function(module, exports, __webpack_require__) { - -var Symbol = __webpack_require__(7); - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString = objectProto.toString; - -/** Built-in value references. */ -var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - -/** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ -function getRawTag(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag), - tag = value[symToStringTag]; - - try { - value[symToStringTag] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag] = tag; - } else { - delete value[symToStringTag]; - } - } - return result; -} - -module.exports = getRawTag; - - -/***/ }), - -/***/ 1000: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1001: -/***/ (function(module, exports) { - -module.exports = "icon" - -/***/ }), - -/***/ 1002: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1003: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1004: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1043: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1044: -/***/ (function(module, exports) { - -module.exports = "Created with Sketch." - -/***/ }), - -/***/ 1045: -/***/ (function(module, exports) { - -module.exports = "Created with Sketch." - -/***/ }), - -/***/ 108: -/***/ (function(module, exports, __webpack_require__) { - -var baseToString = __webpack_require__(109); - -/** - * Converts `value` to a string. An empty string is returned for `null` - * and `undefined` values. The sign of `-0` is preserved. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - * @example - * - * _.toString(null); - * // => '' - * - * _.toString(-0); - * // => '-0' - * - * _.toString([1, 2, 3]); - * // => '1,2,3' - */ -function toString(value) { - return value == null ? '' : baseToString(value); -} - -module.exports = toString; - - -/***/ }), - -/***/ 109: -/***/ (function(module, exports, __webpack_require__) { - -var Symbol = __webpack_require__(7), - arrayMap = __webpack_require__(110), - isArray = __webpack_require__(70), - isSymbol = __webpack_require__(72); - -/** Used as references for various `Number` constants. */ -var INFINITY = 1 / 0; - -/** Used to convert symbols to primitives and strings. */ -var symbolProto = Symbol ? Symbol.prototype : undefined, - symbolToString = symbolProto ? symbolProto.toString : undefined; - -/** - * The base implementation of `_.toString` which doesn't convert nullish - * values to empty strings. - * - * @private - * @param {*} value The value to process. - * @returns {string} Returns the string. - */ -function baseToString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value; - } - if (isArray(value)) { - // Recursively convert values (susceptible to call stack limits). - return arrayMap(value, baseToString) + ''; - } - if (isSymbol(value)) { - return symbolToString ? symbolToString.call(value) : ''; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; -} - -module.exports = baseToString; - - -/***/ }), - -/***/ 11: -/***/ (function(module, exports) { - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString = objectProto.toString; - -/** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ -function objectToString(value) { - return nativeObjectToString.call(value); -} - -module.exports = objectToString; - - -/***/ }), - -/***/ 110: -/***/ (function(module, exports) { - -/** - * A specialized version of `_.map` for arrays without support for iteratee - * shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the new mapped array. - */ -function arrayMap(array, iteratee) { - var index = -1, - length = array == null ? 0 : array.length, - result = Array(length); - - while (++index < length) { - result[index] = iteratee(array[index], index, array); - } - return result; -} - -module.exports = arrayMap; - - -/***/ }), - -/***/ 1117: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1118: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1119: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1174: -/***/ (function(module, exports) { - -module.exports = "image/svg+xml" - -/***/ }), - -/***/ 120: -/***/ (function(module, exports) { - -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - - -/***/ }), - -/***/ 121: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - - -/***/ }), - -/***/ 122: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return map(objectKeys(obj), function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (isArray(obj[k])) { - return map(obj[k], function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -function map (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f(xs[i], i)); - } - return res; -} - -var objectKeys = Object.keys || function (obj) { - var res = []; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - - -/***/ }), - -/***/ 1233: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1290: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1295: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1296: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1301: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1302: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1303: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1304: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1305: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1306: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1307: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1308: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1309: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1310: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1311: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1312: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1313: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1316: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1318: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1319: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1320: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1321: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1322: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1323: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1326: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1327: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1328: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1329: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1331: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1332: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1333: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1334: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1335: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1336: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1337: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1338: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1339: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1340: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1341: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1342: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1343: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1344: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1345: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1347: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1348: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1354: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _breakpoints = __webpack_require__(1396); - -var breakpoints = _interopRequireWildcard(_breakpoints); - -var _expressions = __webpack_require__(1398); - -var expressions = _interopRequireWildcard(_expressions); - -var _eventListeners = __webpack_require__(1527); - -var eventListeners = _interopRequireWildcard(_eventListeners); - -var _pause = __webpack_require__(1639); - -var pause = _interopRequireWildcard(_pause); - -var _navigation = __webpack_require__(1529); - -var navigation = _interopRequireWildcard(_navigation); - -var _ui = __webpack_require__(1385); - -var ui = _interopRequireWildcard(_ui); - -var _fileSearch = __webpack_require__(1530); - -var fileSearch = _interopRequireWildcard(_fileSearch); - -var _ast = __webpack_require__(1399); - -var ast = _interopRequireWildcard(_ast); - -var _coverage = __webpack_require__(1531); - -var coverage = _interopRequireWildcard(_coverage); - -var _projectTextSearch = __webpack_require__(1433); - -var projectTextSearch = _interopRequireWildcard(_projectTextSearch); - -var _replay = __webpack_require__(2343); - -var replay = _interopRequireWildcard(_replay); - -var _quickOpen = __webpack_require__(1647); - -var quickOpen = _interopRequireWildcard(_quickOpen); - -var _sourceTree = __webpack_require__(1532); - -var sourceTree = _interopRequireWildcard(_sourceTree); - -var _sources = __webpack_require__(1797); - -var sources = _interopRequireWildcard(_sources); - -var _debuggee = __webpack_require__(1533); - -var debuggee = _interopRequireWildcard(_debuggee); - -var _toolbox = __webpack_require__(1534); - -var toolbox = _interopRequireWildcard(_toolbox); - -var _preview = __webpack_require__(1786); - -var preview = _interopRequireWildcard(_preview); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -exports.default = _extends({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, fileSearch, ast, coverage, projectTextSearch, replay, quickOpen, sourceTree, debuggee, toolbox, preview); - -/***/ }), - -/***/ 1356: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sourceTypes = exports.isMinified = undefined; - -var _isMinified = __webpack_require__(1778); - -Object.defineProperty(exports, "isMinified", { - enumerable: true, - get: function () { - return _isMinified.isMinified; - } -}); -exports.shouldPrettyPrint = shouldPrettyPrint; -exports.isJavaScript = isJavaScript; -exports.isPretty = isPretty; -exports.isPrettyURL = isPrettyURL; -exports.isThirdParty = isThirdParty; -exports.getPrettySourceURL = getPrettySourceURL; -exports.getRawSourceURL = getRawSourceURL; -exports.getFilenameFromURL = getFilenameFromURL; -exports.getFormattedSourceId = getFormattedSourceId; -exports.getFilename = getFilename; -exports.getFileURL = getFileURL; -exports.getSourcePath = getSourcePath; -exports.getSourceLineCount = getSourceLineCount; -exports.getMode = getMode; -exports.isLoaded = isLoaded; -exports.isLoading = isLoading; -exports.getTextAtPosition = getTextAtPosition; -exports.getSourceClassnames = getSourceClassnames; - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _utils = __webpack_require__(1366); - -var _path = __webpack_require__(1393); - -var _url = __webpack_require__(334); - -var _sourcesTree = __webpack_require__(1442); - -const sourceTypes = exports.sourceTypes = { - coffee: "coffeescript", - js: "javascript", - jsx: "react", - ts: "typescript" -}; - -/** - * Trims the query part or reference identifier of a url string, if necessary. - * - * @memberof utils/source - * @static - */ -function trimUrlQuery(url) { - const length = url.length; - const q1 = url.indexOf("?"); - const q2 = url.indexOf("&"); - const q3 = url.indexOf("#"); - const q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length); - - return url.slice(0, q); -} - -function shouldPrettyPrint(source) { - if (!source) { - return false; - } - const _isPretty = isPretty(source); - const _isJavaScript = isJavaScript(source); - const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(source.id); - const hasSourceMap = source.get("sourceMapURL"); - - if (_isPretty || isOriginal || hasSourceMap || !_isJavaScript) { - return false; - } - - return true; -} - -/** - * Returns true if the specified url and/or content type are specific to - * javascript files. - * - * @return boolean - * True if the source is likely javascript. - * - * @memberof utils/source - * @static - */ -function isJavaScript(source) { - const url = source.url; - const contentType = source.contentType; - return url && /\.(jsm|js)?$/.test(trimUrlQuery(url)) || !!(contentType && contentType.includes("javascript")); -} - -/** - * @memberof utils/source - * @static - */ -function isPretty(source) { - const url = source.url; - return isPrettyURL(url); -} - -function isPrettyURL(url) { - return url ? /formatted$/.test(url) : false; -} - -function isThirdParty(source) { - const url = source.url; - if (!source || !url) { - return false; - } - - return !!url.match(/(node_modules|bower_components)/); -} - -/** - * @memberof utils/source - * @static - */ -function getPrettySourceURL(url) { - if (!url) { - url = ""; - } - return `${url}:formatted`; -} - -/** - * @memberof utils/source - * @static - */ -function getRawSourceURL(url) { - return url ? url.replace(/:formatted$/, "") : url; -} - -function resolveFileURL(url, transformUrl = initialUrl => initialUrl) { - url = getRawSourceURL(url || ""); - const name = transformUrl(url); - return (0, _utils.endTruncateStr)(name, 50); -} - -function getFilenameFromURL(url) { - return resolveFileURL(url, initialUrl => (0, _path.basename)(initialUrl) || "(index)"); -} - -function getFormattedSourceId(id) { - const sourceId = id.split("/")[1]; - return `SOURCE${sourceId}`; -} - -/** - * Show a source url's filename. - * If the source does not have a url, use the source id. - * - * @memberof utils/source - * @static - */ -function getFilename(source) { - const { url, id } = source; - if (!url) { - return getFormattedSourceId(id); - } - - let filename = getFilenameFromURL(url); - const qMarkIdx = filename.indexOf("?"); - if (qMarkIdx > 0) { - filename = filename.slice(0, qMarkIdx); - } - return filename; -} - -/** - * Show a source url. - * If the source does not have a url, use the source id. - * - * @memberof utils/source - * @static - */ -function getFileURL(source) { - const { url, id } = source; - if (!url) { - return getFormattedSourceId(id); - } - - return resolveFileURL(url); -} - -const contentTypeModeMap = { - "text/javascript": { name: "javascript" }, - "text/typescript": { name: "javascript", typescript: true }, - "text/coffeescript": { name: "coffeescript" }, - "text/typescript-jsx": { - name: "jsx", - base: { name: "javascript", typescript: true } - }, - "text/jsx": { name: "jsx" }, - "text/x-elm": { name: "elm" }, - "text/x-clojure": { name: "clojure" }, - "text/wasm": { name: "text" }, - "text/html": { name: "htmlmixed" } -}; - -function getSourcePath(url) { - if (!url) { - return ""; - } - - const { path, href } = (0, _url.parse)(url); - // for URLs like "about:home" the path is null so we pass the full href - return path || href; -} - -/** - * Returns amount of lines in the source. If source is a WebAssembly binary, - * the function returns amount of bytes. - */ -function getSourceLineCount(source) { - if (source.isWasm && !source.error) { - const { binary } = source.text; - return binary.length; - } - return source.text != undefined ? source.text.split("\n").length : 0; -} - -/** - * - * Checks if a source is minified based on some heuristics - * @param key - * @param text - * @return boolean - * @memberof utils/source - * @static - */ - -/** - * - * Returns Code Mirror mode for source content type - * @param contentType - * @return String - * @memberof utils/source - * @static - */ - -function getMode(source, symbols) { - const { contentType, text, isWasm, url } = source; - - if (!text || isWasm) { - return { name: "text" }; - } - - if (url && url.match(/\.jsx$/i) || symbols && symbols.hasJsx) { - if (symbols && symbols.hasTypes) { - return { name: "text/typescript-jsx" }; - } - return { name: "jsx" }; - } - - if (symbols && symbols.hasTypes) { - if (symbols.hasJsx) { - return { name: "text/typescript-jsx" }; - } - - return { name: "text/typescript" }; - } - - const languageMimeMap = [{ ext: ".c", mode: "text/x-csrc" }, { ext: ".kt", mode: "text/x-kotlin" }, { ext: ".cpp", mode: "text/x-c++src" }, { ext: ".m", mode: "text/x-objectivec" }, { ext: ".rs", mode: "text/x-rustsrc" }]; - - // check for C and other non JS languages - if (url) { - const result = languageMimeMap.find(({ ext }) => url.endsWith(ext)); - - if (result !== undefined) { - return { name: result.mode }; - } - } - - // if the url ends with .marko we set the name to Javascript so - // syntax highlighting works for marko too - if (url && url.match(/\.marko$/i)) { - return { name: "javascript" }; - } - - // Use HTML mode for files in which the first non whitespace - // character is `<` regardless of extension. - const isHTMLLike = text.match(/^\s*. */ - -var _sourceDocuments = __webpack_require__(1436); - -Object.keys(_sourceDocuments).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _sourceDocuments[key]; - } - }); -}); - -var _getTokenLocation = __webpack_require__(2244); - -Object.keys(_getTokenLocation).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _getTokenLocation[key]; - } - }); -}); - -var _sourceSearch = __webpack_require__(1526); - -Object.keys(_sourceSearch).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _sourceSearch[key]; - } - }); -}); - -var _ui = __webpack_require__(1439); - -Object.keys(_ui).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _ui[key]; - } - }); -}); - -var _createEditor = __webpack_require__(1806); - -Object.keys(_createEditor).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _createEditor[key]; - } - }); -}); -exports.setEditor = setEditor; -exports.getEditor = getEditor; -exports.removeEditor = removeEditor; -exports.shouldShowPrettyPrint = shouldShowPrettyPrint; -exports.shouldShowFooter = shouldShowFooter; -exports.traverseResults = traverseResults; -exports.toEditorLine = toEditorLine; -exports.toEditorPosition = toEditorPosition; -exports.toEditorRange = toEditorRange; -exports.toSourceLine = toSourceLine; -exports.scrollToColumn = scrollToColumn; -exports.markText = markText; -exports.lineAtHeight = lineAtHeight; -exports.getSourceLocationFromMouseEvent = getSourceLocationFromMouseEvent; -exports.forEachLine = forEachLine; -exports.removeLineClass = removeLineClass; -exports.clearLineClass = clearLineClass; -exports.getTextForLine = getTextForLine; -exports.getCursorLine = getCursorLine; - -var _source = __webpack_require__(1356); - -var _wasm = __webpack_require__(1401); - -var _devtoolsSourceMap = __webpack_require__(3646); - -let editor; - -function setEditor(_editor) { - editor = _editor; -} - -function getEditor() { - return editor; -} - -function removeEditor() { - editor = null; -} - -function shouldShowPrettyPrint(selectedSource) { - if (!selectedSource) { - return false; - } - - return (0, _source.shouldPrettyPrint)(selectedSource); -} - -function shouldShowFooter(selectedSource, horizontal) { - if (!horizontal) { - return true; - } - if (!selectedSource) { - return false; - } - return shouldShowPrettyPrint(selectedSource) || (0, _devtoolsSourceMap.isOriginalId)(selectedSource.get("id")); -} - -function traverseResults(e, ctx, query, dir, modifiers) { - e.stopPropagation(); - e.preventDefault(); - - if (dir == "prev") { - (0, _sourceSearch.findPrev)(ctx, query, true, modifiers); - } else if (dir == "next") { - (0, _sourceSearch.findNext)(ctx, query, true, modifiers); - } -} - -function toEditorLine(sourceId, lineOrOffset) { - if ((0, _wasm.isWasm)(sourceId)) { - // TODO ensure offset is always "mappable" to edit line. - return (0, _wasm.wasmOffsetToLine)(sourceId, lineOrOffset) || 0; - } - - return lineOrOffset ? lineOrOffset - 1 : 1; -} - -function toEditorPosition(location) { - return { - line: toEditorLine(location.sourceId, location.line), - column: (0, _wasm.isWasm)(location.sourceId) || !location.column ? 0 : location.column - }; -} - -function toEditorRange(sourceId, location) { - const { start, end } = location; - return { - start: toEditorPosition(_extends({}, start, { sourceId })), - end: toEditorPosition(_extends({}, end, { sourceId })) - }; -} - -function toSourceLine(sourceId, line) { - return (0, _wasm.isWasm)(sourceId) ? (0, _wasm.lineToWasmOffset)(sourceId, line) : line + 1; -} - -function scrollToColumn(codeMirror, line, column) { - const { top, left } = codeMirror.charCoords({ line: line, ch: column }, "local"); - - if (!isVisible(codeMirror, top, left)) { - const scroller = codeMirror.getScrollerElement(); - const centeredX = Math.max(left - scroller.offsetWidth / 2, 0); - const centeredY = Math.max(top - scroller.offsetHeight / 2, 0); - - codeMirror.scrollTo(centeredX, centeredY); - } -} - -function isVisible(codeMirror, top, left) { - function withinBounds(x, min, max) { - return x >= min && x <= max; - } - - const scrollArea = codeMirror.getScrollInfo(); - - const charWidth = codeMirror.defaultCharWidth(); - const inXView = withinBounds(left, scrollArea.left, scrollArea.left + (scrollArea.clientWidth - 30) - charWidth); - - const fontHeight = codeMirror.defaultTextHeight(); - const inYView = withinBounds(top, scrollArea.top, scrollArea.top + scrollArea.clientHeight - fontHeight); - - return inXView && inYView; -} - -function markText(_editor, className, { start, end }) { - return _editor.codeMirror.markText({ ch: start.column, line: start.line }, { ch: end.column, line: end.line }, { className }); -} - -function lineAtHeight(_editor, sourceId, event) { - const _editorLine = _editor.codeMirror.lineAtHeight(event.clientY); - return toSourceLine(sourceId, _editorLine); -} - -function getSourceLocationFromMouseEvent(_editor, selectedLocation, e) { - const { line, ch } = _editor.codeMirror.coordsChar({ - left: e.clientX, - top: e.clientY - }); - - return { - sourceId: selectedLocation.sourceId, - line: line + 1, - column: ch + 1 - }; -} - -function forEachLine(codeMirror, iter) { - codeMirror.operation(() => { - codeMirror.doc.iter(0, codeMirror.lineCount(), iter); - }); -} - -function removeLineClass(codeMirror, line, className) { - codeMirror.removeLineClass(line, "line", className); -} - -function clearLineClass(codeMirror, className) { - forEachLine(codeMirror, line => { - removeLineClass(codeMirror, line, className); - }); -} - -function getTextForLine(codeMirror, line) { - return codeMirror.getLine(line - 1).trim(); -} - -function getCursorLine(codeMirror) { - return codeMirror.getCursor().line; -} - -/***/ }), - -/***/ 1359: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _Svg = __webpack_require__(1540); - -var _Svg2 = _interopRequireDefault(_Svg); - -__webpack_require__(1310); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * This file maps the SVG React Components in the assets/images directory. - */ - -exports.default = _Svg2.default; - -/***/ }), - -/***/ 1361: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -/** - * Make an immutable record type - * - * @param spec - the keys and their default values - * @return a state record factory function - * @memberof utils/makeRecord - * @static - */ - - -/** - * @memberof utils/makeRecord - * @static - */ -function makeRecord(spec) { - return I.Record(spec); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * When Flow 0.29 is released (very soon), we can use this Record type - * instead of the builtin immutable.js Record type. This is better - * because all the fields are actually typed, unlike the builtin one. - * This depends on a performance fix that will go out in 0.29 though; - * @module utils/makeRecord - */ - -exports.default = makeRecord; - -/***/ }), - -/***/ 1363: -/***/ (function(module, exports, __webpack_require__) { - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const networkRequest = __webpack_require__(1367); -const workerUtils = __webpack_require__(1368); - -module.exports = { - networkRequest, - workerUtils -}; - -/***/ }), - -/***/ 1364: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.findScopeByName = exports.getASTLocation = exports.createEditor = undefined; - -var _createEditor = __webpack_require__(3628); - -Object.defineProperty(exports, "createEditor", { - enumerable: true, - get: function () { - return _createEditor.createEditor; - } -}); - -var _astBreakpointLocation = __webpack_require__(1416); - -Object.defineProperty(exports, "getASTLocation", { - enumerable: true, - get: function () { - return _astBreakpointLocation.getASTLocation; - } -}); -Object.defineProperty(exports, "findScopeByName", { - enumerable: true, - get: function () { - return _astBreakpointLocation.findScopeByName; - } -}); -exports.firstString = firstString; -exports.locationMoved = locationMoved; -exports.makeLocationId = makeLocationId; -exports.makePendingLocationId = makePendingLocationId; -exports.assertBreakpoint = assertBreakpoint; -exports.assertPendingBreakpoint = assertPendingBreakpoint; -exports.assertLocation = assertLocation; -exports.assertPendingLocation = assertPendingLocation; -exports.breakpointAtLocation = breakpointAtLocation; -exports.breakpointExists = breakpointExists; -exports.createBreakpoint = createBreakpoint; -exports.createPendingBreakpoint = createPendingBreakpoint; - -var _selectors = __webpack_require__(3590); - -var _assert = __webpack_require__(1384); - -var _assert2 = _interopRequireDefault(_assert); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// Return the first argument that is a string, or null if nothing is a -// string. -function firstString(...args) { - for (const arg of args) { - if (typeof arg === "string") { - return arg; - } - } - return null; -} - -function locationMoved(location, newLocation) { - return location.line !== newLocation.line || location.column !== newLocation.column; -} - -function makeLocationId(location) { - const { sourceId, line, column } = location; - const columnString = column || ""; - return `${sourceId}:${line}:${columnString}`; -} - -function makePendingLocationId(location) { - assertPendingLocation(location); - const { sourceUrl, line, column } = location; - const sourceUrlString = sourceUrl || ""; - const columnString = column || ""; - - return `${sourceUrlString}:${line}:${columnString}`; -} - -function assertBreakpoint(breakpoint) { - assertLocation(breakpoint.location); - assertLocation(breakpoint.generatedLocation); -} - -function assertPendingBreakpoint(pendingBreakpoint) { - assertPendingLocation(pendingBreakpoint.location); - assertPendingLocation(pendingBreakpoint.generatedLocation); -} - -function assertLocation(location) { - assertPendingLocation(location); - const { sourceId } = location; - (0, _assert2.default)(!!sourceId, "location must have a source id"); -} - -function assertPendingLocation(location) { - (0, _assert2.default)(!!location, "location must exist"); - - const { sourceUrl } = location; - - // sourceUrl is null when the source does not have a url - (0, _assert2.default)(sourceUrl !== undefined, "location must have a source url"); - (0, _assert2.default)(location.hasOwnProperty("line"), "location must have a line"); - (0, _assert2.default)(location.hasOwnProperty("column") != null, "location must have a column"); -} - -// syncing -function breakpointAtLocation(breakpoints, { line, column }) { - return breakpoints.find(breakpoint => { - const sameLine = breakpoint.location.line === line; - if (!sameLine) { - return false; - } - - // NOTE: when column breakpoints are disabled we want to find - // the first breakpoint - if (!_prefs.features.columnBreakpoints) { - return true; - } - - return breakpoint.location.column === column; - }); -} - -function breakpointExists(state, location) { - const currentBp = (0, _selectors.getBreakpoint)(state, location); - return currentBp && !currentBp.disabled; -} - -function createBreakpoint(location, overrides = {}) { - const { - condition, - disabled, - hidden, - generatedLocation, - astLocation, - id, - text, - originalText - } = overrides; - - const defaultASTLocation = { name: undefined, offset: location }; - const properties = { - id, - condition: condition || null, - disabled: disabled || false, - hidden: hidden || false, - loading: false, - astLocation: astLocation || defaultASTLocation, - generatedLocation: generatedLocation || location, - location, - text, - originalText - }; - - return properties; -} - -function createPendingLocation(location) { - const { sourceUrl, line, column } = location; - return { sourceUrl, line, column }; -} - -function createPendingBreakpoint(bp) { - const pendingLocation = createPendingLocation(bp.location); - const pendingGeneratedLocation = createPendingLocation(bp.generatedLocation); - - assertPendingLocation(pendingLocation); - - return { - condition: bp.condition, - disabled: bp.disabled, - location: pendingLocation, - astLocation: bp.astLocation, - generatedLocation: pendingGeneratedLocation - }; -} - -/***/ }), - -/***/ 1365: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.replaceOriginalVariableName = exports.getPausePoints = exports.getFramework = exports.mapOriginalExpression = exports.hasSyntaxError = exports.clearSources = exports.setSource = exports.hasSource = exports.getNextStep = exports.clearASTs = exports.clearScopes = exports.clearSymbols = exports.findOutOfScopeLocations = exports.getScopes = exports.getSymbols = exports.getClosestExpression = exports.stop = exports.start = undefined; - -var _devtoolsUtils = __webpack_require__(1363); - -const { WorkerDispatcher } = _devtoolsUtils.workerUtils; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const dispatcher = new WorkerDispatcher(); -const start = exports.start = dispatcher.start.bind(dispatcher); -const stop = exports.stop = dispatcher.stop.bind(dispatcher); - -const getClosestExpression = exports.getClosestExpression = dispatcher.task("getClosestExpression"); -const getSymbols = exports.getSymbols = dispatcher.task("getSymbols"); -const getScopes = exports.getScopes = dispatcher.task("getScopes"); -const findOutOfScopeLocations = exports.findOutOfScopeLocations = dispatcher.task("findOutOfScopeLocations"); -const clearSymbols = exports.clearSymbols = dispatcher.task("clearSymbols"); -const clearScopes = exports.clearScopes = dispatcher.task("clearScopes"); -const clearASTs = exports.clearASTs = dispatcher.task("clearASTs"); -const getNextStep = exports.getNextStep = dispatcher.task("getNextStep"); -const hasSource = exports.hasSource = dispatcher.task("hasSource"); -const setSource = exports.setSource = dispatcher.task("setSource"); -const clearSources = exports.clearSources = dispatcher.task("clearSources"); -const hasSyntaxError = exports.hasSyntaxError = dispatcher.task("hasSyntaxError"); -const mapOriginalExpression = exports.mapOriginalExpression = dispatcher.task("mapOriginalExpression"); -const getFramework = exports.getFramework = dispatcher.task("getFramework"); -const getPausePoints = exports.getPausePoints = dispatcher.task("getPausePoints"); -const replaceOriginalVariableName = exports.replaceOriginalVariableName = dispatcher.task("replaceOriginalVariableName"); - -/***/ }), - -/***/ 1366: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Utils for utils, by utils - * @module utils/utils - */ - -/** - * @memberof utils/utils - * @static - */ -function handleError(err) { - console.log("ERROR: ", err); -} - -/** - * @memberof utils/utils - * @static - */ -function promisify(context, method, ...args) { - return new Promise((resolve, reject) => { - args.push(response => { - if (response.error) { - reject(response); - } else { - resolve(response); - } - }); - method.apply(context, args); - }); -} - -/** - * @memberof utils/utils - * @static - */ -function endTruncateStr(str, size) { - if (str.length > size) { - return `...${str.slice(str.length - size)}`; - } - return str; -} - -function waitForMs(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -exports.handleError = handleError; -exports.promisify = promisify; -exports.endTruncateStr = endTruncateStr; -exports.waitForMs = waitForMs; - -/***/ }), - -/***/ 1367: -/***/ (function(module, exports) { - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -function networkRequest(url, opts) { - return fetch(url, { - cache: opts.loadFromCache ? "default" : "no-cache" - }).then(res => { - if (res.status >= 200 && res.status < 300) { - return res.text().then(text => ({ content: text })); - } - return Promise.reject(`request failed with status ${res.status}`); - }); -} - -module.exports = networkRequest; - -/***/ }), - -/***/ 1368: -/***/ (function(module, exports) { - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -function WorkerDispatcher() { - this.msgId = 1; - this.worker = null; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -WorkerDispatcher.prototype = { - start(url) { - this.worker = new Worker(url); - this.worker.onerror = () => { - console.error(`Error in worker ${url}`); - }; - }, - - stop() { - if (!this.worker) { - return; - } - - this.worker.terminate(); - this.worker = null; - }, - - task(method, { queue = false } = {}) { - const calls = []; - const push = args => { - return new Promise((resolve, reject) => { - if (queue && calls.length === 0) { - Promise.resolve().then(flush); - } - - calls.push([args, resolve, reject]); - - if (!queue) { - flush(); - } - }); - }; - - const flush = () => { - const items = calls.slice(); - calls.length = 0; - - const id = this.msgId++; - this.worker.postMessage({ id, method, calls: items.map(item => item[0]) }); - - const listener = ({ data: result }) => { - if (result.id !== id) { - return; - } - - if (!this.worker) { - return; - } - - this.worker.removeEventListener("message", listener); - - result.results.forEach((resultData, i) => { - const [, resolve, reject] = items[i]; - - if (resultData.error) { - reject(resultData.error); - } else { - resolve(resultData.response); - } - }); - }; - - this.worker.addEventListener("message", listener); - }; - - return (...args) => push(args); - } -}; - -function workerHandler(publicInterface) { - return function (msg) { - const { id, method, calls } = msg.data; - - Promise.all(calls.map(args => { - try { - const response = publicInterface[method].apply(undefined, args); - if (response instanceof Promise) { - return response.then(val => ({ response: val }), - // Error can't be sent via postMessage, so be sure to - // convert to string. - err => ({ error: err.toString() })); - } else { - return { response }; - } - } catch (error) { - // Error can't be sent via postMessage, so be sure to convert to - // string. - return { error: error.toString() }; - } - })).then(results => { - self.postMessage({ id, results }); - }); - }; -} - -function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) { - let streamingWorker = (() => { - var _ref = _asyncToGenerator(function* (id, tasks) { - let isWorking = true; - - const intervalId = setTimeout(function () { - isWorking = false; - }, timeout); - - const results = []; - while (tasks.length !== 0 && isWorking) { - const { callback, context, args } = tasks.shift(); - const result = yield callback.call(context, args); - results.push(result); - } - worker.postMessage({ id, status: "pending", data: results }); - clearInterval(intervalId); - - if (tasks.length !== 0) { - yield streamingWorker(id, tasks); - } - }); - - return function streamingWorker(_x, _x2) { - return _ref.apply(this, arguments); - }; - })(); - - return (() => { - var _ref2 = _asyncToGenerator(function* (msg) { - const { id, method, args } = msg.data; - const workerMethod = publicInterface[method]; - if (!workerMethod) { - console.error(`Could not find ${method} defined in worker.`); - } - worker.postMessage({ id, status: "start" }); - - try { - const tasks = workerMethod(args); - yield streamingWorker(id, tasks); - worker.postMessage({ id, status: "done" }); - } catch (error) { - worker.postMessage({ id, status: "error", error }); - } - }); - - return function (_x3) { - return _ref2.apply(this, arguments); - }; - })(); -} - -module.exports = { - WorkerDispatcher, - workerHandler, - streamingWorkerHandler -}; - -/***/ }), - -/***/ 1369: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getSelectedSourceText = exports.getSelectedSource = exports.getSelectedLocation = exports.getSourcesForTabs = exports.getSourceTabs = exports.getTabs = exports.getSources = exports.SourceRecordClass = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Sources reducer - * @module reducers/sources - */ - -exports.initialSourcesState = initialSourcesState; -exports.removeSourceFromTabList = removeSourceFromTabList; -exports.removeSourcesFromTabList = removeSourcesFromTabList; -exports.getBlackBoxList = getBlackBoxList; -exports.getNewSelectedSourceId = getNewSelectedSourceId; -exports.getSource = getSource; -exports.getSourceByURL = getSourceByURL; -exports.getGeneratedSource = getGeneratedSource; -exports.getPendingSelectedLocation = getPendingSelectedLocation; -exports.getPrettySource = getPrettySource; -exports.hasPrettySource = hasPrettySource; -exports.getSourceInSources = getSourceInSources; - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _reselect = __webpack_require__(993); - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _source = __webpack_require__(1356); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function initialSourcesState() { - return (0, _makeRecord2.default)({ - sources: I.Map(), - selectedLocation: undefined, - pendingSelectedLocation: _prefs.prefs.pendingSelectedLocation, - sourcesText: I.Map(), - tabs: I.List(restoreTabs()) - })(); -} - -const SourceRecordClass = exports.SourceRecordClass = new I.Record({ - id: undefined, - url: undefined, - sourceMapURL: undefined, - isBlackBoxed: false, - isPrettyPrinted: false, - isWasm: false, - text: undefined, - contentType: "", - error: undefined, - loadedState: "unloaded" -}); - -function update(state = initialSourcesState(), action) { - let location = null; - - switch (action.type) { - case "UPDATE_SOURCE": - { - const source = action.source; - return updateSource(state, source); - } - - case "ADD_SOURCE": - { - const source = action.source; - return updateSource(state, source); - } - - case "ADD_SOURCES": - { - return action.sources.reduce((newState, source) => updateSource(newState, source), state); - } - - case "SELECT_SOURCE": - location = _extends({}, action.location, { - url: action.source.url - }); - - _prefs.prefs.pendingSelectedLocation = location; - return state.set("selectedLocation", _extends({ - sourceId: action.source.id - }, action.location)).set("pendingSelectedLocation", location); - - case "CLEAR_SELECTED_SOURCE": - location = { url: "" }; - _prefs.prefs.pendingSelectedLocation = location; - - return state.set("selectedLocation", { sourceId: "" }).set("pendingSelectedLocation", location); - - case "SELECT_SOURCE_URL": - location = { - url: action.url, - line: action.line - }; - - _prefs.prefs.pendingSelectedLocation = location; - return state.set("pendingSelectedLocation", location); - - case "ADD_TAB": - return state.merge({ - tabs: updateTabList({ sources: state }, action.source.url) - }); - - case "MOVE_TAB": - return state.merge({ - tabs: updateTabList({ sources: state }, action.url, action.tabIndex) - }); - - case "CLOSE_TAB": - _prefs.prefs.tabs = action.tabs; - return state.merge({ tabs: action.tabs }); - - case "CLOSE_TABS": - _prefs.prefs.tabs = action.tabs; - return state.merge({ tabs: action.tabs }); - - case "LOAD_SOURCE_TEXT": - return setSourceTextProps(state, action); - - case "BLACKBOX": - if (action.status === "done") { - const url = action.source.url; - const { isBlackBoxed } = action.value; - updateBlackBoxList(url, isBlackBoxed); - return state.setIn(["sources", action.source.id, "isBlackBoxed"], isBlackBoxed); - } - break; - - case "NAVIGATE": - const source = getSelectedSource({ sources: state }); - const url = source && source.url; - - if (!url) { - return initialSourcesState(); - } - - return initialSourcesState().set("pendingSelectedLocation", { url }); - } - - return state; -} - -function getTextPropsFromAction(action) { - const { value, sourceId } = action; - - if (action.status === "start") { - return { id: sourceId, loadedState: "loading" }; - } else if (action.status === "error") { - return { id: sourceId, error: action.error, loadedState: "loaded" }; - } - - return { - text: value.text, - id: sourceId, - contentType: value.contentType, - loadedState: "loaded" - }; -} - -// TODO: Action is coerced to `any` unfortunately because how we type -// asynchronous actions is wrong. The `value` may be null for the -// "start" and "error" states but we don't type it like that. We need -// to rethink how we type async actions. -function setSourceTextProps(state, action) { - const text = getTextPropsFromAction(action); - return updateSource(state, text); -} - -function updateSource(state, source) { - if (!source.id) { - return state; - } - - const existingSource = state.sources.get(source.id); - - if (existingSource) { - const updatedSource = existingSource.merge(source); - return state.setIn(["sources", source.id], updatedSource); - } - - return state.setIn(["sources", source.id], new SourceRecordClass(source)); -} - -function removeSourceFromTabList(tabs, url) { - return tabs.filter(tab => tab != url); -} - -function removeSourcesFromTabList(tabs, urls) { - return urls.reduce((t, url) => removeSourceFromTabList(t, url), tabs); -} - -function restoreTabs() { - const prefsTabs = _prefs.prefs.tabs || []; - if (prefsTabs.length == 0) { - return; - } - - return prefsTabs; -} - -/** - * Adds the new source to the tab list if it is not already there - * @memberof reducers/sources - * @static - */ -function updateTabList(state, url, tabIndex) { - let tabs = state.sources.tabs; - - const urlIndex = tabs.indexOf(url); - const includesUrl = !!tabs.find(tab => tab == url); - - if (includesUrl) { - if (tabIndex != undefined) { - tabs = tabs.delete(urlIndex).insert(tabIndex, url); - } - } else { - tabs = tabs.insert(0, url); - } - - _prefs.prefs.tabs = tabs.toJS(); - return tabs; -} - -function updateBlackBoxList(url, isBlackBoxed) { - const tabs = getBlackBoxList(); - const i = tabs.indexOf(url); - if (i >= 0) { - if (!isBlackBoxed) { - tabs.splice(i, 1); - } - } else if (isBlackBoxed) { - tabs.push(url); - } - _prefs.prefs.tabsBlackBoxed = tabs; -} - -function getBlackBoxList() { - return _prefs.prefs.tabsBlackBoxed || []; -} - -/** - * Gets the next tab to select when a tab closes. Heuristics: - * 1. if the selected tab is available, it remains selected - * 2. if it is gone, the next available tab to the left should be active - * 3. if the first tab is active and closed, select the second tab - * - * @memberof reducers/sources - * @static - */ -function getNewSelectedSourceId(state, availableTabs) { - const selectedLocation = state.sources.selectedLocation; - if (!selectedLocation) { - return ""; - } - - const selectedTab = state.sources.sources.get(selectedLocation.sourceId); - - const selectedTabUrl = selectedTab ? selectedTab.url : ""; - - if (availableTabs.includes(selectedTabUrl)) { - const sources = state.sources.sources; - if (!sources) { - return ""; - } - - const selectedSource = sources.find(source => source.url == selectedTabUrl); - - if (selectedSource) { - return selectedSource.id; - } - - return ""; - } - - const tabUrls = state.sources.tabs; - const leftNeighborIndex = Math.max(tabUrls.indexOf(selectedTabUrl) - 1, 0); - const lastAvailbleTabIndex = availableTabs.size - 1; - const newSelectedTabIndex = Math.min(leftNeighborIndex, lastAvailbleTabIndex); - const availableTab = availableTabs.get(newSelectedTabIndex); - const tabSource = getSourceByUrlInSources(state.sources.sources, availableTab); - - if (tabSource) { - return tabSource.id; - } - - return ""; -} - -// Selectors - -// Unfortunately, it's really hard to make these functions accept just -// the state that we care about and still type it with Flow. The -// problem is that we want to re-export all selectors from a single -// module for the UI, and all of those selectors should take the -// top-level app state, so we'd have to "wrap" them to automatically -// pick off the piece of state we're interested in. It's impossible -// (right now) to type those wrapped functions. - - -const getSourcesState = state => state.sources; - -function getSource(state, id) { - return getSourceInSources(getSources(state), id); -} - -function getSourceByURL(state, url) { - return getSourceByUrlInSources(state.sources.sources, url); -} - -function getGeneratedSource(state, source) { - if (!source || !(0, _devtoolsSourceMap.isOriginalId)(source.id)) { - return null; - } - return getSource(state, (0, _devtoolsSourceMap.originalToGeneratedId)(source.id)); -} - -function getPendingSelectedLocation(state) { - return state.sources.pendingSelectedLocation; -} - -function getPrettySource(state, id) { - const source = getSource(state, id); - if (!source) { - return; - } - - return getSourceByURL(state, (0, _source.getPrettySourceURL)(source.url)); -} - -function hasPrettySource(state, id) { - return !!getPrettySource(state, id); -} - -function getSourceByUrlInSources(sources, url) { - if (!url) { - return null; - } - - return sources.find(source => source.url === url); -} - -function getSourceInSources(sources, id) { - return sources.get(id); -} - -const getSources = exports.getSources = (0, _reselect.createSelector)(getSourcesState, sources => sources.sources); - -const getTabs = exports.getTabs = (0, _reselect.createSelector)(getSourcesState, sources => sources.tabs); - -const getSourceTabs = exports.getSourceTabs = (0, _reselect.createSelector)(getTabs, getSources, (tabs, sources) => tabs.filter(tab => getSourceByUrlInSources(sources, tab))); - -const getSourcesForTabs = exports.getSourcesForTabs = (0, _reselect.createSelector)(getSourceTabs, getSources, (tabs, sources) => { - return tabs.map(tab => getSourceByUrlInSources(sources, tab)).filter(source => source); -}); - -const getSelectedLocation = exports.getSelectedLocation = (0, _reselect.createSelector)(getSourcesState, sources => sources.selectedLocation); - -const getSelectedSource = exports.getSelectedSource = (0, _reselect.createSelector)(getSelectedLocation, getSources, (selectedLocation, sources) => { - if (!selectedLocation) { - return; - } - - return sources.get(selectedLocation.sourceId); -}); - -const getSelectedSourceText = exports.getSelectedSourceText = (0, _reselect.createSelector)(getSelectedSource, getSourcesState, (selectedSource, sources) => { - const id = selectedSource.id; - return id ? sources.sourcesText.get(id) : null; -}); - -exports.default = update; - -/***/ }), - -/***/ 1371: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.nodeHasChildren = nodeHasChildren; -exports.isExactUrlMatch = isExactUrlMatch; -exports.isDirectory = isDirectory; -exports.getExtension = getExtension; -exports.isNotJavaScript = isNotJavaScript; -exports.isInvalidUrl = isInvalidUrl; -exports.partIsFile = partIsFile; -exports.createNode = createNode; -exports.createParentMap = createParentMap; -exports.getRelativePath = getRelativePath; - -var _url = __webpack_require__(334); - -var _source = __webpack_require__(1356); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const IGNORED_URLS = ["debugger eval code", "XStringBundle"]; - -function nodeHasChildren(item) { - return Array.isArray(item.contents); -} - -function isExactUrlMatch(pathPart, debuggeeUrl) { - // compare to hostname with an optional 'www.' prefix - const { host } = (0, _url.parse)(debuggeeUrl); - if (!host) { - return false; - } - return host.replace(/^www\./, "") === pathPart.replace(/^www\./, ""); -} - -function isDirectory(url) { - const parts = url.path.split("/").filter(p => p !== ""); - - // Assume that all urls point to files except when they end with '/' - // Or directory node has children - return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)"; -} - -function getExtension(source) { - const url = source.get ? source.get("url") : source.url; - const parsedUrl = (0, _url.parse)(url).pathname; - if (!parsedUrl) { - return ""; - } - return parsedUrl.split(".").pop(); -} - -function isNotJavaScript(source) { - return ["css", "svg", "png"].includes(getExtension(source)); -} - -function isInvalidUrl(url, source) { - return IGNORED_URLS.indexOf(url) != -1 || !source.get("url") || !url.group || (0, _source.isPretty)(source) || isNotJavaScript(source); -} - -function partIsFile(index, parts, url) { - const isLastPart = index === parts.length - 1; - return !isDirectory(url) && isLastPart; -} - -function createNode(name, path, contents) { - return { - name, - path, - contents - }; -} - -function createParentMap(tree) { - const map = new WeakMap(); - - function _traverse(subtree) { - if (nodeHasChildren(subtree)) { - for (const child of subtree.contents) { - map.set(child, subtree); - _traverse(child); - } - } - } - - // Don't link each top-level path to the "root" node because the - // user never sees the root - tree.contents.forEach(_traverse); - return map; -} - -function getRelativePath(url) { - const { pathname } = (0, _url.parse)(url); - if (!pathname) { - return url; - } - const path = pathname.split("/"); - path.shift(); - return path.join("/"); -} - -/***/ }), - -/***/ 1374: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -__webpack_require__(1312); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function CloseButton({ handleClick, buttonClass, tooltip }) { - return _react2.default.createElement( - "button", - { - className: buttonClass ? `close-btn ${buttonClass}` : "close-btn", - onClick: handleClick, - title: tooltip - }, - _react2.default.createElement("img", { className: "close" }) - ); -} - -exports.default = CloseButton; - -/***/ }), - -/***/ 1376: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const Menu = __webpack_require__(1464); -const MenuItem = __webpack_require__(1466); -const { PrefsHelper } = __webpack_require__(1467); -const Services = __webpack_require__(22); -const KeyShortcuts = __webpack_require__(1468); -const { ZoomKeys } = __webpack_require__(1469); -const EventEmitter = __webpack_require__(1382); -const SourceUtils = __webpack_require__(3637); -const { getUnicodeHostname, getUnicodeUrlPath, getUnicodeUrl } = __webpack_require__(3638); - -module.exports = { - KeyShortcuts, - Menu, - MenuItem, - PrefsHelper, - Services, - ZoomKeys, - EventEmitter, - SourceUtils, - getUnicodeHostname, - getUnicodeUrlPath, - getUnicodeUrl -}; - -/***/ }), - -/***/ 1378: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Breakpoints reducer - * @module reducers/breakpoints - */ - -exports.initialBreakpointsState = initialBreakpointsState; -exports.getBreakpoints = getBreakpoints; -exports.getBreakpoint = getBreakpoint; -exports.getBreakpointsDisabled = getBreakpointsDisabled; -exports.getBreakpointsLoading = getBreakpointsLoading; -exports.getBreakpointsForSource = getBreakpointsForSource; -exports.getBreakpointForLine = getBreakpointForLine; -exports.getHiddenBreakpoint = getHiddenBreakpoint; -exports.getHiddenBreakpointLocation = getHiddenBreakpointLocation; - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _breakpoint = __webpack_require__(1364); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function initialBreakpointsState() { - return (0, _makeRecord2.default)({ - breakpoints: I.Map(), - breakpointsDisabled: false - })(); -} - -function update(state = initialBreakpointsState(), action) { - switch (action.type) { - case "ADD_BREAKPOINT": - { - return addBreakpoint(state, action); - } - - case "SYNC_BREAKPOINT": - { - return syncBreakpoint(state, action); - } - - case "ENABLE_BREAKPOINT": - { - return addBreakpoint(state, action); - } - - case "DISABLE_BREAKPOINT": - { - return updateBreakpoint(state, action); - } - - case "DISABLE_ALL_BREAKPOINTS": - { - return updateAllBreakpoints(state, action); - } - - case "ENABLE_ALL_BREAKPOINTS": - { - return updateAllBreakpoints(state, action); - } - - case "SET_BREAKPOINT_CONDITION": - { - return updateBreakpoint(state, action); - } - - case "REMOVE_BREAKPOINT": - { - return removeBreakpoint(state, action); - } - - case "REMAP_BREAKPOINTS": - { - return remapBreakpoints(state, action); - } - - case "NAVIGATE": - { - return initialBreakpointsState(); - } - } - - return state; -} - -function addBreakpoint(state, action) { - if (action.status === "start" && action.breakpoint) { - const { breakpoint } = action; - const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); - return state.setIn(["breakpoints", locationId], breakpoint); - } - - // when the action completes, we can commit the breakpoint - if (action.status === "done") { - const { value } = action; - return syncBreakpoint(state, value); - } - - // Remove the optimistic update - if (action.status === "error" && action.breakpoint) { - const locationId = (0, _breakpoint.makeLocationId)(action.breakpoint.location); - return state.deleteIn(["breakpoints", locationId]); - } - - return state; -} - -function syncBreakpoint(state, data) { - const { breakpoint, previousLocation } = data; - - if (previousLocation) { - state = state.deleteIn(["breakpoints", (0, _breakpoint.makeLocationId)(previousLocation)]); - } - - if (!breakpoint) { - return state; - } - - const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); - return state.setIn(["breakpoints", locationId], breakpoint); -} - -function updateBreakpoint(state, action) { - const { breakpoint } = action; - const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); - return state.setIn(["breakpoints", locationId], breakpoint); -} - -function updateAllBreakpoints(state, action) { - const { breakpoints } = action; - breakpoints.forEach(breakpoint => { - const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); - state = state.setIn(["breakpoints", locationId], breakpoint); - }); - return state; -} - -function remapBreakpoints(state, action) { - const breakpoints = action.breakpoints.reduce((updatedBreakpoints, breakpoint) => { - const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); - return _extends({}, updatedBreakpoints, { [locationId]: breakpoint }); - }, {}); - - return state.set("breakpoints", I.Map(breakpoints)); -} - -function removeBreakpoint(state, action) { - const { breakpoint } = action; - const id = (0, _breakpoint.makeLocationId)(breakpoint.location); - return state.deleteIn(["breakpoints", id]); -} - -// Selectors -// TODO: these functions should be moved out of the reducer - -function getBreakpoints(state) { - return state.breakpoints.breakpoints; -} - -function getBreakpoint(state, location) { - const breakpoints = getBreakpoints(state); - return breakpoints.get((0, _breakpoint.makeLocationId)(location)); -} - -function getBreakpointsDisabled(state) { - return state.breakpoints.breakpoints.every(x => x.disabled); -} - -function getBreakpointsLoading(state) { - const breakpoints = getBreakpoints(state); - const isLoading = !!breakpoints.valueSeq().filter(bp => bp.loading).first(); - - return breakpoints.size > 0 && isLoading; -} - -function getBreakpointsForSource(state, sourceId) { - if (!sourceId) { - return I.Map(); - } - - const isGeneratedSource = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); - const breakpoints = getBreakpoints(state); - - return breakpoints.filter(bp => { - const location = isGeneratedSource ? bp.generatedLocation || bp.location : bp.location; - return location.sourceId === sourceId; - }); -} - -function getBreakpointForLine(state, sourceId, line) { - if (!sourceId) { - return I.Map(); - } - const breakpoints = getBreakpointsForSource(state, sourceId); - return breakpoints.find(breakpoint => breakpoint.location.line === line); -} - -function getHiddenBreakpoint(state) { - return getBreakpoints(state).valueSeq().filter(breakpoint => breakpoint.hidden).first(); -} - -function getHiddenBreakpointLocation(state) { - const hiddenBreakpoint = getHiddenBreakpoint(state); - if (!hiddenBreakpoint) { - return null; - } - return hiddenBreakpoint.location; -} - -exports.default = update; - -/***/ }), - -/***/ 1379: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _Close = __webpack_require__(1374); - -var _Close2 = _interopRequireDefault(_Close); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -__webpack_require__(1313); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const arrowBtn = (onClick, type, className, tooltip) => { - const props = { - className, - key: type, - onClick, - title: tooltip, - type - }; - - return _react2.default.createElement( - "button", - props, - _react2.default.createElement(_Svg2.default, { name: type }) - ); -}; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class SearchInput extends _react.Component { - - constructor(props) { - super(props); - - this.onFocus = e => { - const { onFocus } = this.props; - - this.setState({ inputFocused: true }); - if (onFocus) { - onFocus(e); - } - }; - - this.onBlur = e => { - const { onBlur } = this.props; - - this.setState({ inputFocused: false }); - if (onBlur) { - onBlur(e); - } - }; - - this.state = { - inputFocused: false - }; - } - - componentDidMount() { - this.setFocus(); - } - - componentDidUpdate(prevProps) { - if (this.props.shouldFocus && !prevProps.shouldFocus) { - this.setFocus(); - } - } - - setFocus() { - if (this.$input) { - const input = this.$input; - input.focus(); - - if (!input.value) { - return; - } - - // omit prefix @:# from being selected - const selectStartPos = this.props.hasPrefix ? 1 : 0; - input.setSelectionRange(selectStartPos, input.value.length + 1); - } - } - - renderSvg() { - const svgName = this.props.showErrorEmoji ? "sad-face" : "magnifying-glass"; - return _react2.default.createElement(_Svg2.default, { name: svgName }); - } - - renderArrowButtons() { - const { handleNext, handlePrev } = this.props; - - return [arrowBtn(handleNext, "arrow-down", (0, _classnames2.default)("nav-btn", "next"), L10N.getFormatStr("editor.searchResults.nextResult")), arrowBtn(handlePrev, "arrow-up", (0, _classnames2.default)("nav-btn", "prev"), L10N.getFormatStr("editor.searchResults.prevResult"))]; - } - - renderNav() { - const { count, handleNext, handlePrev } = this.props; - if (!handleNext && !handlePrev || !count || count == 1) { - return; - } - - return _react2.default.createElement( - "div", - { className: "search-nav-buttons" }, - this.renderArrowButtons() - ); - } - - render() { - const { - expanded, - handleClose, - onChange, - onKeyDown, - onKeyUp, - placeholder, - query, - selectedItemId, - showErrorEmoji, - size, - summaryMsg - } = this.props; - - const inputProps = { - className: (0, _classnames2.default)({ - empty: showErrorEmoji - }), - onChange, - onKeyDown, - onKeyUp, - onFocus: e => this.onFocus(e), - onBlur: e => this.onBlur(e), - "aria-autocomplete": "list", - "aria-controls": "result-list", - "aria-activedescendant": expanded && selectedItemId ? `${selectedItemId}-title` : "", - placeholder, - value: query, - spellCheck: false, - ref: c => this.$input = c - }; - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("search-shadow", { - focused: this.state.inputFocused - }) - }, - _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("search-field", size), - role: "combobox", - "aria-haspopup": "listbox", - "aria-owns": "result-list", - "aria-expanded": expanded - }, - this.renderSvg(), - _react2.default.createElement("input", inputProps), - summaryMsg && _react2.default.createElement( - "div", - { className: "summary" }, - summaryMsg - ), - this.renderNav(), - _react2.default.createElement(_Close2.default, { handleClick: handleClose, buttonClass: size }) - ) - ); - } -} - -SearchInput.defaultProps = { - expanded: false, - hasPrefix: false, - selectedItemId: "", - size: "" -}; -exports.default = SearchInput; - -/***/ }), - -/***/ 1382: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -var EventEmitter = function EventEmitter() {}; -module.exports = EventEmitter; - -const promise = __webpack_require__(1465); - -/** - * Decorate an object with event emitter functionality. - * - * @param Object aObjectToDecorate - * Bind all public methods of EventEmitter to - * the aObjectToDecorate object. - */ -EventEmitter.decorate = function EventEmitter_decorate(aObjectToDecorate) { - let emitter = new EventEmitter(); - aObjectToDecorate.on = emitter.on.bind(emitter); - aObjectToDecorate.off = emitter.off.bind(emitter); - aObjectToDecorate.once = emitter.once.bind(emitter); - aObjectToDecorate.emit = emitter.emit.bind(emitter); -}; - -EventEmitter.prototype = { - /** - * Connect a listener. - * - * @param string aEvent - * The event name to which we're connecting. - * @param function aListener - * Called when the event is fired. - */ - on: function EventEmitter_on(aEvent, aListener) { - if (!this._eventEmitterListeners) this._eventEmitterListeners = new Map(); - if (!this._eventEmitterListeners.has(aEvent)) { - this._eventEmitterListeners.set(aEvent, []); - } - this._eventEmitterListeners.get(aEvent).push(aListener); - }, - - /** - * Listen for the next time an event is fired. - * - * @param string aEvent - * The event name to which we're connecting. - * @param function aListener - * (Optional) Called when the event is fired. Will be called at most - * one time. - * @return promise - * A promise which is resolved when the event next happens. The - * resolution value of the promise is the first event argument. If - * you need access to second or subsequent event arguments (it's rare - * that this is needed) then use aListener - */ - once: function EventEmitter_once(aEvent, aListener) { - let deferred = promise.defer(); - - let handler = (aEvent, aFirstArg, ...aRest) => { - this.off(aEvent, handler); - if (aListener) { - aListener.apply(null, [aEvent, aFirstArg, ...aRest]); - } - deferred.resolve(aFirstArg); - }; - - handler._originalListener = aListener; - this.on(aEvent, handler); - - return deferred.promise; - }, - - /** - * Remove a previously-registered event listener. Works for events - * registered with either on or once. - * - * @param string aEvent - * The event name whose listener we're disconnecting. - * @param function aListener - * The listener to remove. - */ - off: function EventEmitter_off(aEvent, aListener) { - if (!this._eventEmitterListeners) return; - let listeners = this._eventEmitterListeners.get(aEvent); - if (listeners) { - this._eventEmitterListeners.set(aEvent, listeners.filter(l => { - return l !== aListener && l._originalListener !== aListener; - })); - } - }, - - /** - * Emit an event. All arguments to this method will - * be sent to listener functions. - */ - emit: function EventEmitter_emit(aEvent) { - if (!this._eventEmitterListeners || !this._eventEmitterListeners.has(aEvent)) { - return; - } - - let originalListeners = this._eventEmitterListeners.get(aEvent); - for (let listener of this._eventEmitterListeners.get(aEvent)) { - // If the object was destroyed during event emission, stop - // emitting. - if (!this._eventEmitterListeners) { - break; - } - - // If listeners were removed during emission, make sure the - // event handler we're going to fire wasn't removed. - if (originalListeners === this._eventEmitterListeners.get(aEvent) || this._eventEmitterListeners.get(aEvent).some(l => l === listener)) { - try { - listener.apply(null, arguments); - } catch (ex) { - // Prevent a bad listener from interfering with the others. - let msg = ex + ": " + ex.stack; - //console.error(msg); - console.log(msg); - } - } - } - } -}; - -/***/ }), - -/***/ 1383: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Ast reducer - * @module reducers/ast - */ - -exports.initialASTState = initialASTState; -exports.getSymbols = getSymbols; -exports.hasSymbols = hasSymbols; -exports.isSymbolsLoading = isSymbolsLoading; -exports.isEmptyLineInSource = isEmptyLineInSource; -exports.getEmptyLines = getEmptyLines; -exports.getPausePoints = getPausePoints; -exports.getPausePoint = getPausePoint; -exports.hasPausePoints = hasPausePoints; -exports.getOutOfScopeLocations = getOutOfScopeLocations; -exports.getPreview = getPreview; -exports.getSourceMetaData = getSourceMetaData; -exports.hasSourceMetaData = hasSourceMetaData; -exports.getInScopeLines = getInScopeLines; -exports.isLineInScope = isLineInScope; - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _ast = __webpack_require__(1638); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function initialASTState() { - return (0, _makeRecord2.default)({ - symbols: I.Map(), - emptyLines: I.Map(), - outOfScopeLocations: null, - inScopeLines: null, - preview: null, - pausePoints: I.Map(), - sourceMetaData: I.Map() - })(); -} - -function update(state = initialASTState(), action) { - switch (action.type) { - case "SET_SYMBOLS": - { - const { sourceId } = action; - if (action.status === "start") { - return state.setIn(["symbols", sourceId], { loading: true }); - } - - const value = action.value; - return state.setIn(["symbols", sourceId], value); - } - - case "SET_PAUSE_POINTS": - { - const { source, pausePoints } = action; - const emptyLines = (0, _ast.findEmptyLines)(source, pausePoints); - - return state.setIn(["pausePoints", source.id], pausePoints).setIn(["emptyLines", source.id], emptyLines); - } - - case "OUT_OF_SCOPE_LOCATIONS": - { - return state.set("outOfScopeLocations", action.locations); - } - - case "IN_SCOPE_LINES": - { - return state.set("inScopeLines", action.lines); - } - - case "CLEAR_SELECTION": - { - return state.set("preview", null); - } - - case "SET_PREVIEW": - { - if (action.status == "start") { - return state.set("preview", { updating: true }); - } - - if (!action.value) { - return state.set("preview", null); - } - - return state.set("preview", _extends({}, action.value, { - updating: false - })); - } - - case "RESUME": - { - return state.set("outOfScopeLocations", null); - } - - case "NAVIGATE": - { - return initialASTState(); - } - - case "SET_SOURCE_METADATA": - { - return state.setIn(["sourceMetaData", action.sourceId], action.sourceMetaData); - } - - default: - { - return state; - } - } -} - -// NOTE: we'd like to have the app state fully typed -// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 -function getSymbols(state, source) { - if (!source) { - return null; - } - - return state.ast.symbols.get(source.id) || null; -} - -function hasSymbols(state, source) { - const symbols = getSymbols(state, source); - - if (!symbols) { - return false; - } - - return !symbols.hasOwnProperty("loading"); -} - -function isSymbolsLoading(state, source) { - const symbols = getSymbols(state, source); - if (!symbols) { - return false; - } - - return symbols.hasOwnProperty("loading"); -} - -function isEmptyLineInSource(state, line, selectedSource) { - const emptyLines = getEmptyLines(state, selectedSource); - return emptyLines && emptyLines.includes(line); -} - -function getEmptyLines(state, source) { - if (!source) { - return null; - } - - return state.ast.emptyLines.get(source.id); -} - -function getPausePoints(state, sourceId) { - return state.ast.pausePoints.get(sourceId); -} - -function getPausePoint(state, location) { - if (!location) { - return; - } - - const { column, line, sourceId } = location; - const pausePoints = getPausePoints(state, sourceId); - if (!pausePoints) { - return; - } - - const linePoints = pausePoints[line]; - return linePoints && linePoints[column]; -} - -function hasPausePoints(state, sourceId) { - const pausePoints = getPausePoints(state, sourceId); - return !!pausePoints; -} - -function getOutOfScopeLocations(state) { - return state.ast.get("outOfScopeLocations"); -} - -function getPreview(state) { - return state.ast.get("preview"); -} - -const emptySourceMetaData = {}; -function getSourceMetaData(state, sourceId) { - return state.ast.sourceMetaData.get(sourceId) || emptySourceMetaData; -} - -function hasSourceMetaData(state, sourceId) { - return state.ast.hasIn(["sourceMetaData", sourceId]); -} - -function getInScopeLines(state) { - return state.ast.get("inScopeLines"); -} - -function isLineInScope(state, line) { - const linesInScope = state.ast.get("inScopeLines"); - return linesInScope && linesInScope.includes(line); -} - -exports.default = update; - -/***/ }), - -/***/ 1384: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = assert; - -var _devtoolsEnvironment = __webpack_require__(3721); - -function assert(condition, message) { - if ((0, _devtoolsEnvironment.isDevelopment)() && !condition) { - throw new Error(`Assertion failure: ${message}`); - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1385: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setContextMenu = setContextMenu; -exports.setPrimaryPaneTab = setPrimaryPaneTab; -exports.closeActiveSearch = closeActiveSearch; -exports.setActiveSearch = setActiveSearch; -exports.toggleFrameworkGrouping = toggleFrameworkGrouping; -exports.showSource = showSource; -exports.togglePaneCollapse = togglePaneCollapse; -exports.highlightLineRange = highlightLineRange; -exports.flashLineRange = flashLineRange; -exports.clearHighlightLineRange = clearHighlightLineRange; -exports.openConditionalPanel = openConditionalPanel; -exports.closeConditionalPanel = closeConditionalPanel; -exports.clearProjectDirectoryRoot = clearProjectDirectoryRoot; -exports.setProjectDirectoryRoot = setProjectDirectoryRoot; -exports.setOrientation = setOrientation; - -var _selectors = __webpack_require__(3590); - -var _ui = __webpack_require__(1421); - -var _source = __webpack_require__(1356); - -function setContextMenu(type, event) { - return ({ dispatch }) => { - dispatch({ type: "SET_CONTEXT_MENU", contextMenu: { type, event } }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function setPrimaryPaneTab(tabName) { - return { type: "SET_PRIMARY_PANE_TAB", tabName }; -} - -function closeActiveSearch() { - return { - type: "TOGGLE_ACTIVE_SEARCH", - value: null - }; -} - -function setActiveSearch(activeSearch) { - return ({ dispatch, getState }) => { - const activeSearchState = (0, _selectors.getActiveSearch)(getState()); - if (activeSearchState === activeSearch) { - return; - } - - if ((0, _selectors.getQuickOpenEnabled)(getState())) { - dispatch({ type: "CLOSE_QUICK_OPEN" }); - } - - dispatch({ - type: "TOGGLE_ACTIVE_SEARCH", - value: activeSearch - }); - }; -} - -function toggleFrameworkGrouping(toggleValue) { - return ({ dispatch, getState }) => { - dispatch({ - type: "TOGGLE_FRAMEWORK_GROUPING", - value: toggleValue - }); - }; -} - -function showSource(sourceId) { - return ({ dispatch, getState }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - - if ((0, _selectors.getPaneCollapse)(getState(), "start")) { - dispatch({ - type: "TOGGLE_PANE", - position: "start", - paneCollapsed: false - }); - } - - dispatch(setPrimaryPaneTab("sources")); - dispatch({ - type: "SHOW_SOURCE", - sourceUrl: "" - }); - - dispatch({ - type: "SHOW_SOURCE", - sourceUrl: (0, _source.getRawSourceURL)(source.get("url")) - }); - }; -} - -function togglePaneCollapse(position, paneCollapsed) { - return ({ dispatch, getState }) => { - const prevPaneCollapse = (0, _selectors.getPaneCollapse)(getState(), position); - if (prevPaneCollapse === paneCollapsed) { - return; - } - - dispatch({ - type: "TOGGLE_PANE", - position, - paneCollapsed - }); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function highlightLineRange(location) { - return { - type: "HIGHLIGHT_LINES", - location - }; -} - -function flashLineRange(location) { - return ({ dispatch }) => { - dispatch(highlightLineRange(location)); - setTimeout(() => dispatch(clearHighlightLineRange()), 200); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function clearHighlightLineRange() { - return { - type: "CLEAR_HIGHLIGHT_LINES" - }; -} - -function openConditionalPanel(line) { - if (!line) { - return; - } - - return { - type: "OPEN_CONDITIONAL_PANEL", - line - }; -} - -function closeConditionalPanel() { - return { - type: "CLOSE_CONDITIONAL_PANEL" - }; -} - -function clearProjectDirectoryRoot() { - return { - type: "SET_PROJECT_DIRECTORY_ROOT", - url: "" - }; -} - -function setProjectDirectoryRoot(newRoot) { - return ({ dispatch, getState }) => { - const curRoot = (0, _ui.getProjectDirectoryRoot)(getState()); - if (newRoot && curRoot) { - const newRootArr = newRoot.replace(/\/+/g, "/").split("/"); - const curRootArr = curRoot.replace(/^\//, "").replace(/\/+/g, "/").split("/"); - if (newRootArr[0] !== curRootArr[0]) { - newRootArr.splice(0, 2); - newRoot = `${curRoot}/${newRootArr.join("/")}`; - } - } - - dispatch({ - type: "SET_PROJECT_DIRECTORY_ROOT", - url: newRoot - }); - }; -} - -function setOrientation(orientation) { - return { type: "SET_ORIENTATION", orientation }; -} - -/***/ }), - -/***/ 1387: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.formatKeyShortcut = undefined; - -var _devtoolsModules = __webpack_require__(1376); - -const { appinfo } = _devtoolsModules.Services; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Utils for keyboard command strings - * @module utils/text - */ - - -const isMacOS = appinfo.OS === "Darwin"; - -/** - * Formats key for use in tooltips - * For macOS we use the following unicode - * - * cmd ⌘ = \u2318 - * shift ⇧ – \u21E7 - * option (alt) ⌥ \u2325 - * - * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl - * - * @memberof utils/text - * @static - */ -function formatKeyShortcut(shortcut) { - if (isMacOS) { - return shortcut.replace(/Shift\+/g, "\u21E7 ").replace(/Command\+|Cmd\+/g, "\u2318 ").replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318 ").replace(/Alt\+/g, "\u2325 "); - } - return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")} `).replace(/Shift\+/g, "Shift "); -} - -exports.formatKeyShortcut = formatKeyShortcut; - -/***/ }), - -/***/ 1388: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.copyToTheClipboard = copyToTheClipboard; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Clipboard function taken from - * https://dxr.mozilla.org/mozilla-central/source/devtools/shared/platform/content/clipboard.js - */ - -function copyToTheClipboard(string) { - const doCopy = function (e) { - e.clipboardData.setData("text/plain", string); - e.preventDefault(); - }; - - document.addEventListener("copy", doCopy); - document.execCommand("copy", false, null); - document.removeEventListener("copy", doCopy); -} - -/***/ }), - -/***/ 1393: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function basename(path) { - return path.split("/").pop(); -} - -function dirname(path) { - const idx = path.lastIndexOf("/"); - return path.slice(0, idx); -} - -function isURL(str) { - return str.indexOf("://") !== -1; -} - -function isAbsolute(str) { - return str[0] === "/"; -} - -function join(base, dir) { - return `${base}/${dir}`; -} - -exports.basename = basename; -exports.dirname = dirname; -exports.isURL = isURL; -exports.isAbsolute = isAbsolute; -exports.join = join; - -/***/ }), - -/***/ 1394: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getSelectedFrame = exports.getAllPopupObjectProperties = exports.createPauseState = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* eslint complexity: ["error", 30]*/ - -/** - * Pause reducer - * @module reducers/pause - */ - -exports.getPauseReason = getPauseReason; -exports.getPauseCommand = getPauseCommand; -exports.isStepping = isStepping; -exports.isPaused = isPaused; -exports.getPreviousPauseFrameLocation = getPreviousPauseFrameLocation; -exports.isEvaluatingExpression = isEvaluatingExpression; -exports.getPopupObjectProperties = getPopupObjectProperties; -exports.getIsWaitingOnBreak = getIsWaitingOnBreak; -exports.getShouldPauseOnExceptions = getShouldPauseOnExceptions; -exports.getShouldPauseOnCaughtExceptions = getShouldPauseOnCaughtExceptions; -exports.getCanRewind = getCanRewind; -exports.getExtra = getExtra; -exports.getFrames = getFrames; -exports.getGeneratedFrameScope = getGeneratedFrameScope; -exports.getOriginalFrameScope = getOriginalFrameScope; -exports.getFrameScopes = getFrameScopes; -exports.getFrameScope = getFrameScope; -exports.getSelectedScope = getSelectedScope; -exports.getSelectedScopeMappings = getSelectedScopeMappings; -exports.getSelectedFrameId = getSelectedFrameId; -exports.getTopFrame = getTopFrame; -exports.getDebuggeeUrl = getDebuggeeUrl; -exports.getSkipPausing = getSkipPausing; -exports.getChromeScopes = getChromeScopes; - -var _reselect = __webpack_require__(993); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _prefs = __webpack_require__(226); - -var _sources = __webpack_require__(1369); - -const createPauseState = exports.createPauseState = () => ({ - extra: {}, - why: null, - isWaitingOnBreak: false, - frames: undefined, - selectedFrameId: undefined, - frameScopes: { - generated: {}, - original: {}, - mappings: {} - }, - loadedObjects: {}, - shouldPauseOnExceptions: _prefs.prefs.pauseOnExceptions, - shouldPauseOnCaughtExceptions: _prefs.prefs.pauseOnCaughtExceptions, - canRewind: false, - debuggeeUrl: "", - command: null, - previousLocation: null, - skipPausing: _prefs.prefs.skipPausing -}); - -const emptyPauseState = { - frames: null, - frameScopes: { - generated: {}, - original: {}, - mappings: {} - }, - selectedFrameId: null, - loadedObjects: {}, - why: null -}; - -function update(state = createPauseState(), action) { - switch (action.type) { - case "PAUSED": - { - const { selectedFrameId, frames, loadedObjects, why } = action; - - // turn this into an object keyed by object id - const objectMap = {}; - loadedObjects.forEach(obj => { - objectMap[obj.value.objectId] = obj; - }); - - return _extends({}, state, { - isWaitingOnBreak: false, - selectedFrameId, - frames, - frameScopes: _extends({}, emptyPauseState.frameScopes), - loadedObjects: objectMap, - why - }); - } - - case "MAP_FRAMES": - { - return _extends({}, state, { frames: action.frames }); - } - - case "ADD_EXTRA": - { - return _extends({}, state, { extra: action.extra }); - } - - case "ADD_SCOPES": - { - const { frame, status, value } = action; - const selectedFrameId = frame.id; - - const generated = _extends({}, state.frameScopes.generated, { - [selectedFrameId]: { - pending: status !== "done", - scope: value - } - }); - return _extends({}, state, { - frameScopes: _extends({}, state.frameScopes, { - generated - }) - }); - } - - case "TRAVEL_TO": - return _extends({}, state, action.data.paused); - - case "MAP_SCOPES": - { - const { frame, status, value } = action; - const selectedFrameId = frame.id; - - const original = _extends({}, state.frameScopes.original, { - [selectedFrameId]: { - pending: status !== "done", - scope: value && value.scope - } - }); - - const mappings = _extends({}, state.frameScopes.mappings, { - [selectedFrameId]: value && value.mappings - }); - return _extends({}, state, { - frameScopes: _extends({}, state.frameScopes, { - original, - mappings - }) - }); - } - - case "BREAK_ON_NEXT": - return _extends({}, state, { isWaitingOnBreak: true }); - - case "SELECT_FRAME": - return _extends({}, state, { - selectedFrameId: action.frame.id - }); - - case "SET_POPUP_OBJECT_PROPERTIES": - if (!action.properties) { - return _extends({}, state); - } - - return _extends({}, state, { - loadedObjects: _extends({}, state.loadedObjects, { - [action.objectId]: action.properties - }) - }); - - case "CONNECT": - return _extends({}, createPauseState(), { - debuggeeUrl: action.url, - canRewind: action.canRewind - }); - - case "PAUSE_ON_EXCEPTIONS": - const { shouldPauseOnExceptions, shouldPauseOnCaughtExceptions } = action; - - _prefs.prefs.pauseOnExceptions = shouldPauseOnExceptions; - _prefs.prefs.pauseOnCaughtExceptions = shouldPauseOnCaughtExceptions; - - // Preserving for the old debugger - _prefs.prefs.ignoreCaughtExceptions = !shouldPauseOnCaughtExceptions; - - return _extends({}, state, { - shouldPauseOnExceptions, - shouldPauseOnCaughtExceptions - }); - - case "COMMAND": - { - return action.status === "start" ? _extends({}, state, emptyPauseState, { - command: action.command, - previousLocation: buildPreviousLocation(state, action) - }) : _extends({}, state, { command: null }); - } - - case "RESUME": - return _extends({}, state, emptyPauseState); - - case "EVALUATE_EXPRESSION": - return _extends({}, state, { - command: action.status === "start" ? "expression" : null - }); - - case "NAVIGATE": - return _extends({}, state, emptyPauseState, { debuggeeUrl: action.url }); - - case "TOGGLE_SKIP_PAUSING": - { - const { skipPausing } = action; - _prefs.prefs.skipPausing = skipPausing; - - return _extends({}, state, { skipPausing }); - } - } - - return state; -} - -function buildPreviousLocation(state, action) { - const { frames, previousLocation } = state; - - if (action.command !== "stepOver") { - return null; - } - - const frame = frames && frames.length > 0 ? frames[0] : null; - if (!frame) { - return previousLocation; - } - - return { - location: frame.location, - generatedLocation: frame.generatedLocation - }; -} - -// Selectors - -// Unfortunately, it's really hard to make these functions accept just -// the state that we care about and still type it with Flow. The -// problem is that we want to re-export all selectors from a single -// module for the UI, and all of those selectors should take the -// top-level app state, so we'd have to "wrap" them to automatically -// pick off the piece of state we're interested in. It's impossible -// (right now) to type those wrapped functions. - - -const getPauseState = state => state.pause; - -const getAllPopupObjectProperties = exports.getAllPopupObjectProperties = (0, _reselect.createSelector)(getPauseState, pauseWrapper => pauseWrapper.loadedObjects); - -function getPauseReason(state) { - return state.pause.why; -} - -function getPauseCommand(state) { - return state.pause && state.pause.command; -} - -function isStepping(state) { - return ["stepIn", "stepOver", "stepOut"].includes(getPauseCommand(state)); -} - -function isPaused(state) { - return !!getFrames(state); -} - -function getPreviousPauseFrameLocation(state) { - return state.pause.previousLocation; -} - -function isEvaluatingExpression(state) { - return state.pause.command === "expression"; -} - -function getPopupObjectProperties(state, objectId) { - return getAllPopupObjectProperties(state)[objectId]; -} - -function getIsWaitingOnBreak(state) { - return state.pause.isWaitingOnBreak; -} - -function getShouldPauseOnExceptions(state) { - return state.pause.shouldPauseOnExceptions; -} - -function getShouldPauseOnCaughtExceptions(state) { - return state.pause.shouldPauseOnCaughtExceptions; -} - -function getCanRewind(state) { - return state.pause.canRewind; -} - -function getExtra(state) { - return state.pause.extra; -} - -function getFrames(state) { - return state.pause.frames; -} - -function getGeneratedFrameScope(state, frameId) { - if (!frameId) { - return null; - } - - return getFrameScopes(state).generated[frameId]; -} - -function getOriginalFrameScope(state, sourceId, frameId) { - if (!frameId || !sourceId) { - return null; - } - - const isGenerated = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); - const original = getFrameScopes(state).original[frameId]; - - if (!isGenerated && original && (original.pending || original.scope)) { - return original; - } - - return null; -} - -function getFrameScopes(state) { - return state.pause.frameScopes; -} - -function getFrameScope(state, sourceId, frameId) { - return getOriginalFrameScope(state, sourceId, frameId) || getGeneratedFrameScope(state, frameId); -} - -function getSelectedScope(state) { - const sourceRecord = (0, _sources.getSelectedSource)(state); - const frameId = getSelectedFrameId(state); - const { scope } = getFrameScope(state, sourceRecord && sourceRecord.get("id"), frameId) || {}; - return scope || null; -} - -function getSelectedScopeMappings(state) { - const frameId = getSelectedFrameId(state); - if (!frameId) { - return null; - } - - return getFrameScopes(state).mappings[frameId]; -} - -function getSelectedFrameId(state) { - return state.pause.selectedFrameId; -} - -function getTopFrame(state) { - const frames = getFrames(state); - return frames && frames[0]; -} - -const getSelectedFrame = exports.getSelectedFrame = (0, _reselect.createSelector)(getSelectedFrameId, getFrames, (selectedFrameId, frames) => { - if (!frames) { - return null; - } - return frames.find(frame => frame.id == selectedFrameId); -}); - -function getDebuggeeUrl(state) { - return state.pause.debuggeeUrl; -} - -function getSkipPausing(state) { - return state.pause.skipPausing; -} - -// NOTE: currently only used for chrome -function getChromeScopes(state) { - const frame = getSelectedFrame(state); - return frame ? frame.scopeChain : undefined; -} - -exports.default = update; - -/***/ }), - -/***/ 1395: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.findSourceMatches = exports.getMatches = exports.stop = exports.start = undefined; - -var _devtoolsUtils = __webpack_require__(1363); - -const { WorkerDispatcher } = _devtoolsUtils.workerUtils; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const dispatcher = new WorkerDispatcher(); -const start = exports.start = dispatcher.start.bind(dispatcher); -const stop = exports.stop = dispatcher.stop.bind(dispatcher); - -const getMatches = exports.getMatches = dispatcher.task("getMatches"); -const findSourceMatches = exports.findSourceMatches = dispatcher.task("findSourceMatches"); - -/***/ }), - -/***/ 1396: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for breakpoints - * @module actions/breakpoints - */ - -// this will need to be changed so that addCLientBreakpoint is removed - - -exports.syncBreakpoint = syncBreakpoint; -exports.addBreakpoint = addBreakpoint; -exports.addHiddenBreakpoint = addHiddenBreakpoint; -exports.removeBreakpoint = removeBreakpoint; -exports.enableBreakpoint = enableBreakpoint; -exports.disableBreakpoint = disableBreakpoint; -exports.toggleAllBreakpoints = toggleAllBreakpoints; -exports.toggleBreakpoints = toggleBreakpoints; -exports.removeAllBreakpoints = removeAllBreakpoints; -exports.removeBreakpoints = removeBreakpoints; -exports.remapBreakpoints = remapBreakpoints; -exports.setBreakpointCondition = setBreakpointCondition; -exports.toggleBreakpoint = toggleBreakpoint; -exports.addOrToggleDisabledBreakpoint = addOrToggleDisabledBreakpoint; -exports.toggleDisabledBreakpoint = toggleDisabledBreakpoint; - -var _promise = __webpack_require__(1653); - -var _selectors = __webpack_require__(3590); - -var _breakpoint = __webpack_require__(1364); - -var _addBreakpoint = __webpack_require__(1519); - -var _addBreakpoint2 = _interopRequireDefault(_addBreakpoint); - -var _remapLocations = __webpack_require__(1520); - -var _remapLocations2 = _interopRequireDefault(_remapLocations); - -var _ast = __webpack_require__(1383); - -var _syncBreakpoint = __webpack_require__(1521); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Syncing a breakpoint add breakpoint information that is stored, and - * contact the server for more data. - * - * @memberof actions/breakpoints - * @static - * @param {String} $1.sourceId String value - * @param {PendingBreakpoint} $1.location PendingBreakpoint value - */ -function syncBreakpoint(sourceId, pendingBreakpoint) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const { breakpoint, previousLocation } = await (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, sourceId, pendingBreakpoint); - - return dispatch({ - type: "SYNC_BREAKPOINT", - breakpoint, - previousLocation - }); - }; -} - -/** - * Add a new breakpoint - * - * @memberof actions/breakpoints - * @static - * @param {String} $1.condition Conditional breakpoint condition value - * @param {Boolean} $1.disabled Disable value for breakpoint value - */ - -function addBreakpoint(location, { condition, hidden } = {}) { - const breakpoint = (0, _breakpoint.createBreakpoint)(location, { condition, hidden }); - return ({ dispatch, getState, sourceMaps, client }) => { - return dispatch({ - type: "ADD_BREAKPOINT", - breakpoint, - [_promise.PROMISE]: (0, _addBreakpoint2.default)(getState, client, sourceMaps, breakpoint) - }); - }; -} - -/** - * Add a new hidden breakpoint - * - * @memberOf actions/breakpoints - * @param location - * @return {function(ThunkArgs)} - */ -function addHiddenBreakpoint(location) { - return ({ dispatch }) => { - return dispatch(addBreakpoint(location, { hidden: true })); - }; -} - -/** - * Remove a single breakpoint - * - * @memberof actions/breakpoints - * @static - */ -function removeBreakpoint(location) { - return ({ dispatch, getState, client }) => { - const bp = (0, _selectors.getBreakpoint)(getState(), location); - if (!bp || bp.loading) { - return; - } - - // If the breakpoint is already disabled, we don't need to communicate - // with the server. We just need to dispatch an action - // simulating a successful server request - if (bp.disabled) { - return dispatch({ - type: "REMOVE_BREAKPOINT", - breakpoint: bp, - status: "done" - }); - } - - return dispatch({ - type: "REMOVE_BREAKPOINT", - breakpoint: bp, - disabled: false, - [_promise.PROMISE]: client.removeBreakpoint(bp.generatedLocation) - }); - }; -} - -/** - * Enabling a breakpoint - * will reuse the existing breakpoint information that is stored. - * - * @memberof actions/breakpoints - * @static - * @param {Location} $1.location Location value - */ -function enableBreakpoint(location) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const breakpoint = (0, _selectors.getBreakpoint)(getState(), location); - if (!breakpoint || breakpoint.loading) { - return; - } - - return dispatch({ - type: "ENABLE_BREAKPOINT", - breakpoint, - [_promise.PROMISE]: (0, _addBreakpoint2.default)(getState, client, sourceMaps, breakpoint) - }); - }; -} - -/** - * Disable a single breakpoint - * - * @memberof actions/breakpoints - * @static - */ -function disableBreakpoint(location) { - return async ({ dispatch, getState, client }) => { - const bp = (0, _selectors.getBreakpoint)(getState(), location); - - if (!bp || bp.loading) { - return; - } - - await client.removeBreakpoint(bp.generatedLocation); - const newBreakpoint = _extends({}, bp, { disabled: true }); - - return dispatch({ - type: "DISABLE_BREAKPOINT", - breakpoint: newBreakpoint - }); - }; -} - -/** - * Toggle All Breakpoints - * - * @memberof actions/breakpoints - * @static - */ -function toggleAllBreakpoints(shouldDisableBreakpoints) { - return async ({ dispatch, getState, client }) => { - const breakpoints = (0, _selectors.getBreakpoints)(getState()); - - const modifiedBreakpoints = []; - - for (const [, breakpoint] of breakpoints) { - if (shouldDisableBreakpoints) { - await client.removeBreakpoint(breakpoint.generatedLocation); - const newBreakpoint = _extends({}, breakpoint, { disabled: true }); - modifiedBreakpoints.push(newBreakpoint); - } else { - const newBreakpoint = _extends({}, breakpoint, { disabled: false }); - modifiedBreakpoints.push(newBreakpoint); - } - } - - if (shouldDisableBreakpoints) { - return dispatch({ - type: "DISABLE_ALL_BREAKPOINTS", - breakpoints: modifiedBreakpoints - }); - } - - return dispatch({ - type: "ENABLE_ALL_BREAKPOINTS", - breakpoints: modifiedBreakpoints - }); - }; -} - -/** - * Toggle Breakpoints - * - * @memberof actions/breakpoints - * @static - */ -function toggleBreakpoints(shouldDisableBreakpoints, breakpoints) { - return async ({ dispatch }) => { - for (const [, breakpoint] of breakpoints) { - if (shouldDisableBreakpoints) { - await dispatch(disableBreakpoint(breakpoint.location)); - } else { - await dispatch(enableBreakpoint(breakpoint.location)); - } - } - }; -} - -/** - * Removes all breakpoints - * - * @memberof actions/breakpoints - * @static - */ -function removeAllBreakpoints() { - return async ({ dispatch, getState }) => { - const breakpoints = (0, _selectors.getBreakpoints)(getState()); - for (const [, breakpoint] of breakpoints) { - await dispatch(removeBreakpoint(breakpoint.location)); - } - }; -} - -/** - * Removes breakpoints - * - * @memberof actions/breakpoints - * @static - */ -function removeBreakpoints(breakpoints) { - return async ({ dispatch }) => { - for (const [, breakpoint] of breakpoints) { - await dispatch(removeBreakpoint(breakpoint.location)); - } - }; -} - -function remapBreakpoints(sourceId) { - return async ({ dispatch, getState, sourceMaps }) => { - const breakpoints = (0, _selectors.getBreakpoints)(getState()); - const newBreakpoints = await (0, _remapLocations2.default)(breakpoints, sourceId, sourceMaps); - - return dispatch({ - type: "REMAP_BREAKPOINTS", - breakpoints: newBreakpoints - }); - }; -} - -/** - * Update the condition of a breakpoint. - * - * @throws {Error} "not implemented" - * @memberof actions/breakpoints - * @static - * @param {Location} location - * @see DebuggerController.Breakpoints.addBreakpoint - * @param {string} condition - * The condition to set on the breakpoint - * @param {Boolean} $1.disabled Disable value for breakpoint value - */ -function setBreakpointCondition(location, { condition } = {}) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const bp = (0, _selectors.getBreakpoint)(getState(), location); - if (!bp) { - return dispatch(addBreakpoint(location, { condition })); - } - - if (bp.loading) { - return; - } - - if (bp.disabled) { - await dispatch(enableBreakpoint(location)); - bp.disabled = !bp.disabled; - } - - await client.setBreakpointCondition(bp.id, location, condition, sourceMaps.isOriginalId(bp.location.sourceId)); - - const newBreakpoint = _extends({}, bp, { condition }); - - (0, _breakpoint.assertBreakpoint)(newBreakpoint); - - return dispatch({ - type: "SET_BREAKPOINT_CONDITION", - breakpoint: newBreakpoint - }); - }; -} - -function toggleBreakpoint(line, column) { - return ({ dispatch, getState, client, sourceMaps }) => { - if (!line) { - return; - } - - const state = getState(); - const selectedSource = (0, _selectors.getSelectedSource)(state); - const bp = (0, _selectors.getBreakpointAtLocation)(state, { line, column }); - const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource); - - if (!bp && isEmptyLine || bp && bp.loading) { - return; - } - - if (bp) { - // NOTE: it's possible the breakpoint has slid to a column - return dispatch(removeBreakpoint({ - sourceId: bp.location.sourceId, - sourceUrl: bp.location.sourceUrl, - line: bp.location.line, - column: column || bp.location.column - })); - } - return dispatch(addBreakpoint({ - sourceId: selectedSource.get("id"), - sourceUrl: selectedSource.get("url"), - line: line, - column: column - })); - }; -} - -function addOrToggleDisabledBreakpoint(line, column) { - return ({ dispatch, getState, client, sourceMaps }) => { - if (!line) { - return; - } - - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - const bp = (0, _selectors.getBreakpointAtLocation)(getState(), { line, column }); - - if (bp && bp.loading) { - return; - } - - if (bp) { - // NOTE: it's possible the breakpoint has slid to a column - return dispatch(toggleDisabledBreakpoint(line, column || bp.location.column)); - } - - return dispatch(addBreakpoint({ - sourceId: selectedSource.get("id"), - sourceUrl: selectedSource.get("url"), - line: line, - column: column - })); - }; -} - -function toggleDisabledBreakpoint(line, column) { - return ({ dispatch, getState, client, sourceMaps }) => { - const bp = (0, _selectors.getBreakpointAtLocation)(getState(), { line, column }); - if (!bp || bp.loading) { - return; - } - - if (!bp.disabled) { - return dispatch(disableBreakpoint(bp.location)); - } - return dispatch(enableBreakpoint(bp.location)); - }; -} - -/***/ }), - -/***/ 1397: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getGeneratedLocation = getGeneratedLocation; - -var _selectors = __webpack_require__(3590); - -async function getGeneratedLocation(state, source, location, sourceMaps) { - if (!sourceMaps.isOriginalId(location.sourceId)) { - return location; - } - - const { line, sourceId, column } = await sourceMaps.getGeneratedLocation(location, source.toJS()); - - const generatedSource = (0, _selectors.getSource)(state, sourceId); - if (!generatedSource) { - return location; - } - - return { - line, - sourceId, - column: column === 0 ? undefined : column, - sourceUrl: generatedSource.url - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1398: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.addExpression = addExpression; -exports.autocomplete = autocomplete; -exports.clearExpressionError = clearExpressionError; -exports.updateExpression = updateExpression; -exports.deleteExpression = deleteExpression; -exports.evaluateExpressions = evaluateExpressions; -exports.getMappedExpression = getMappedExpression; - -var _selectors = __webpack_require__(3590); - -var _promise = __webpack_require__(1653); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _expressions = __webpack_require__(1437); - -var _parser = __webpack_require__(1365); - -var parser = _interopRequireWildcard(_parser); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -/** - * Add expression for debugger to watch - * - * @param {object} expression - * @param {number} expression.id - * @memberof actions/pause - * @static - */ -function addExpression(input) { - return async ({ dispatch, getState }) => { - if (!input) { - return; - } - - const expressionError = await parser.hasSyntaxError(input); - - const expression = (0, _selectors.getExpression)(getState(), input); - if (expression) { - return dispatch(evaluateExpression(expression)); - } - - dispatch({ type: "ADD_EXPRESSION", input, expressionError }); - - const newExpression = (0, _selectors.getExpression)(getState(), input); - if (newExpression) { - return dispatch(evaluateExpression(newExpression)); - } - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function autocomplete(input, cursor) { - return async ({ dispatch, getState, client }) => { - if (!input) { - return; - } - const frameId = (0, _selectors.getSelectedFrameId)(getState()); - const result = await client.autocomplete(input, cursor, frameId); - await dispatch({ type: "AUTOCOMPLETE", input, result }); - }; -} - -function clearExpressionError() { - return { type: "CLEAR_EXPRESSION_ERROR" }; -} - -function updateExpression(input, expression) { - return async ({ dispatch, getState }) => { - if (!input) { - return; - } - - const expressionError = await parser.hasSyntaxError(input); - dispatch({ - type: "UPDATE_EXPRESSION", - expression, - input: expressionError ? expression.input : input, - expressionError - }); - - dispatch(evaluateExpressions()); - }; -} - -/** - * - * @param {object} expression - * @param {number} expression.id - * @memberof actions/pause - * @static - */ -function deleteExpression(expression) { - return ({ dispatch }) => { - dispatch({ - type: "DELETE_EXPRESSION", - input: expression.input - }); - }; -} - -/** - * - * @memberof actions/pause - * @param {number} selectedFrameId - * @static - */ -function evaluateExpressions() { - return async function ({ dispatch, getState, client }) { - const expressions = (0, _selectors.getExpressions)(getState()).toJS(); - const inputs = expressions.map(({ input }) => input); - const frameId = (0, _selectors.getSelectedFrameId)(getState()); - const results = await client.evaluateExpressions(inputs, frameId); - dispatch({ type: "EVALUATE_EXPRESSIONS", inputs, results }); - }; -} - -function evaluateExpression(expression) { - return async function ({ dispatch, getState, client, sourceMaps }) { - if (!expression.input) { - console.warn("Expressions should not be empty"); - return; - } - - let input = expression.input; - const frame = (0, _selectors.getSelectedFrame)(getState()); - - if (frame) { - const { location } = frame; - const source = (0, _selectors.getSource)(getState(), location.sourceId); - const sourceId = source.get("id"); - - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - - if (selectedSource && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) && !(0, _devtoolsSourceMap.isGeneratedId)(selectedSource.get("id"))) { - input = await dispatch(getMappedExpression(input)); - } - } - - const frameId = (0, _selectors.getSelectedFrameId)(getState()); - - return dispatch({ - type: "EVALUATE_EXPRESSION", - input: expression.input, - [_promise.PROMISE]: client.evaluateInFrame((0, _expressions.wrapExpression)(input), frameId) - }); - }; -} - -/** - * Gets information about original variable names from the source map - * and replaces all posible generated names. - */ -function getMappedExpression(expression) { - return async function ({ dispatch, getState, client, sourceMaps }) { - const mappings = (0, _selectors.getSelectedScopeMappings)(getState()); - if (!mappings) { - return expression; - } - - return parser.mapOriginalExpression(expression, mappings); - }; -} - -/***/ }), - -/***/ 1399: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setSourceMetaData = setSourceMetaData; -exports.setSymbols = setSymbols; -exports.setOutOfScopeLocations = setOutOfScopeLocations; -exports.setPausePoints = setPausePoints; - -var _selectors = __webpack_require__(3590); - -var _pause = __webpack_require__(1639); - -var _setInScopeLines = __webpack_require__(1781); - -var _parser = __webpack_require__(1365); - -var _promise = __webpack_require__(1653); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _prefs = __webpack_require__(226); - -function setSourceMetaData(sourceId) { - return async ({ dispatch, getState }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - if (!source || !source.text || source.isWasm) { - return; - } - - const framework = await (0, _parser.getFramework)(source.id); - - dispatch({ - type: "SET_SOURCE_METADATA", - sourceId: source.id, - sourceMetaData: { - framework - } - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function setSymbols(sourceId) { - return async ({ dispatch, getState }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - if (!source || !source.text || source.isWasm || (0, _selectors.hasSymbols)(getState(), source)) { - return; - } - - await dispatch({ - type: "SET_SYMBOLS", - sourceId, - [_promise.PROMISE]: (0, _parser.getSymbols)(sourceId) - }); - - if ((0, _selectors.isPaused)(getState())) { - await dispatch((0, _pause.fetchExtra)()); - await dispatch((0, _pause.mapFrames)()); - } - - await dispatch(setPausePoints(sourceId)); - await dispatch(setSourceMetaData(sourceId)); - }; -} - -function setOutOfScopeLocations() { - return async ({ dispatch, getState }) => { - const location = (0, _selectors.getSelectedLocation)(getState()); - if (!location) { - return; - } - - const source = (0, _selectors.getSource)(getState(), location.sourceId); - - let locations = null; - if (location.line && source && (0, _selectors.isPaused)(getState())) { - locations = await (0, _parser.findOutOfScopeLocations)(source.get("id"), location); - } - - dispatch({ - type: "OUT_OF_SCOPE_LOCATIONS", - locations - }); - dispatch((0, _setInScopeLines.setInScopeLines)()); - }; -} - -function setPausePoints(sourceId) { - return async ({ dispatch, getState, client }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - if (!_prefs.features.pausePoints || !source || !source.text || source.isWasm) { - return; - } - - const pausePoints = await (0, _parser.getPausePoints)(source.id); - - if ((0, _devtoolsSourceMap.isGeneratedId)(source.id)) { - await client.setPausePoints(source.id, pausePoints); - } - - dispatch({ - type: "SET_PAUSE_POINTS", - source: source.toJS(), - pausePoints - }); - }; -} - -/***/ }), - -/***/ 14: -/***/ (function(module, exports) { - -/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value) { - return value != null && typeof value == 'object'; -} - -module.exports = isObjectLike; - - -/***/ }), - -/***/ 1401: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.renderWasmText = exports.clearWasmStates = exports.wasmOffsetToLine = exports.lineToWasmOffset = exports.isWasm = exports.getWasmLineNumberFormatter = exports.getWasmText = undefined; - -var _WasmParser = __webpack_require__(677); - -var _WasmDis = __webpack_require__(678); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var wasmStates = Object.create(null); - -function maybeWasmSectionNameResolver(data) { - try { - const parser = new _WasmParser.BinaryReader(); - parser.setData(data.buffer, 0, data.length); - const reader = new _WasmDis.NameSectionReader(); - reader.read(parser); - return reader.hasValidNames() ? reader.getNameResolver() : null; - } catch (ex) { - // Ignoring any errors during names section retrival. - return null; - } -} - -/** - * @memberof utils/wasm - * @static - */ -function getWasmText(sourceId, data) { - const nameResolver = maybeWasmSectionNameResolver(data); - const parser = new _WasmParser.BinaryReader(); - parser.setData(data.buffer, 0, data.length); - const dis = new _WasmDis.WasmDisassembler(); - if (nameResolver) { - dis.nameResolver = nameResolver; - } - dis.addOffsets = true; - const done = dis.disassembleChunk(parser); - let result = dis.getResult(); - if (result.lines.length === 0) { - result = { lines: ["No luck with wast conversion"], offsets: [0], done }; - } - - const offsets = result.offsets; - const lines = []; - for (let i = 0; i < offsets.length; i++) { - lines[offsets[i]] = i; - } - - wasmStates[sourceId] = { offsets, lines }; - - return { lines: result.lines, done: result.done }; -} - -/** - * @memberof utils/wasm - * @static - */ -function getWasmLineNumberFormatter(sourceId) { - const codeOf0 = 48, - codeOfA = 65; - const buffer = [codeOf0, codeOf0, codeOf0, codeOf0, codeOf0, codeOf0, codeOf0, codeOf0]; - let last0 = 7; - return function (number) { - const offset = lineToWasmOffset(sourceId, number - 1); - if (offset == undefined) { - return ""; - } - let i = 7; - for (let n = offset; n !== 0 && i >= 0; n >>= 4, i--) { - const nibble = n & 15; - buffer[i] = nibble < 10 ? codeOf0 + nibble : codeOfA - 10 + nibble; - } - for (let j = i; j > last0; j--) { - buffer[j] = codeOf0; - } - last0 = i; - return String.fromCharCode.apply(null, buffer); - }; -} - -/** - * @memberof utils/wasm - * @static - */ -function isWasm(sourceId) { - return sourceId in wasmStates; -} - -/** - * @memberof utils/wasm - * @static - */ -function lineToWasmOffset(sourceId, number) { - const wasmState = wasmStates[sourceId]; - if (!wasmState) { - return undefined; - } - let offset = wasmState.offsets[number]; - while (offset === undefined && number > 0) { - offset = wasmState.offsets[--number]; - } - return offset; -} - -/** - * @memberof utils/wasm - * @static - */ -function wasmOffsetToLine(sourceId, offset) { - const wasmState = wasmStates[sourceId]; - if (!wasmState) { - return undefined; - } - return wasmState.lines[offset]; -} - -/** - * @memberof utils/wasm - * @static - */ -function clearWasmStates() { - wasmStates = Object.create(null); -} - -function renderWasmText(sourceId, { binary }) { - // binary does not survive as Uint8Array, converting from string - const data = new Uint8Array(binary.length); - for (let i = 0; i < data.length; i++) { - data[i] = binary.charCodeAt(i); - } - const { lines } = getWasmText(sourceId, data); - const MAX_LINES = 1000000; - if (lines.length > MAX_LINES) { - lines.splice(MAX_LINES, lines.length - MAX_LINES); - lines.push(";; .... text is truncated due to the size"); - } - return lines; -} - -exports.getWasmText = getWasmText; -exports.getWasmLineNumberFormatter = getWasmLineNumberFormatter; -exports.isWasm = isWasm; -exports.lineToWasmOffset = lineToWasmOffset; -exports.wasmOffsetToLine = wasmOffsetToLine; -exports.clearWasmStates = clearWasmStates; -exports.renderWasmText = renderWasmText; - -/***/ }), - -/***/ 1402: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = buildQuery; - -var _escapeRegExp = __webpack_require__(259); - -var _escapeRegExp2 = _interopRequireDefault(_escapeRegExp); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Ignore doing outline matches for less than 3 whitespaces - * - * @memberof utils/source-search - * @static - */ -function ignoreWhiteSpace(str) { - return (/^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str - ); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function wholeMatch(query, wholeWord) { - if (query === "" || !wholeWord) { - return query; - } - - return `\\b${query}\\b`; -} - -function buildFlags(caseSensitive, isGlobal) { - if (caseSensitive && isGlobal) { - return "g"; - } - - if (!caseSensitive && isGlobal) { - return "gi"; - } - - if (!caseSensitive && !isGlobal) { - return "i"; - } - - return; -} - -function buildQuery(originalQuery, modifiers, { isGlobal = false, ignoreSpaces = false }) { - const { caseSensitive, regexMatch, wholeWord } = modifiers; - - if (originalQuery === "") { - return new RegExp(originalQuery); - } - - let query = originalQuery; - if (ignoreSpaces) { - query = ignoreWhiteSpace(query); - } - - if (!regexMatch) { - query = (0, _escapeRegExp2.default)(query); - } - - query = wholeMatch(query, wholeWord); - const flags = buildFlags(caseSensitive, isGlobal); - - if (flags) { - return new RegExp(query, flags); - } - - return new RegExp(query); -} - -/***/ }), - -/***/ 1403: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Modal = exports.transitionTimeout = undefined; -exports.default = Slide; - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Transition = __webpack_require__(333); - -var _Transition2 = _interopRequireDefault(_Transition); - -__webpack_require__(1303); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const transitionTimeout = exports.transitionTimeout = 175; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Modal extends _react2.default.Component { - constructor(...args) { - var _temp; - - return _temp = super(...args), this.onClick = e => { - e.stopPropagation(); - }, _temp; - } - - render() { - const { additionalClass, children, handleClose, status } = this.props; - - return _react2.default.createElement( - "div", - { className: "modal-wrapper", onClick: handleClose }, - _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("modal", additionalClass, status), - onClick: this.onClick - }, - children - ) - ); - } -} - -exports.Modal = Modal; -Modal.contextTypes = { - shortcuts: _propTypes2.default.object -}; - -function Slide({ - in: inProp, - children, - additionalClass, - handleClose -}) { - return _react2.default.createElement( - _Transition2.default, - { "in": inProp, timeout: transitionTimeout, appear: true }, - status => _react2.default.createElement( - Modal, - { - status: status, - additionalClass: additionalClass, - handleClose: handleClose - }, - children - ) - ); -} - -/***/ }), - -/***/ 1404: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -__webpack_require__(1311); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { Tree } = __webpack_require__(3669); - -class ManagedTree extends _react.Component { - constructor(props) { - super(props); - - this.setExpanded = (item, isExpanded, shouldIncludeChildren) => { - const expandItem = i => { - const path = this.props.getPath(i); - if (isExpanded) { - expanded.add(path); - } else { - expanded.delete(path); - } - }; - const { expanded } = this.state; - expandItem(item); - - if (shouldIncludeChildren) { - let parents = [item]; - while (parents.length) { - const children = []; - for (const parent of parents) { - if (parent.contents && parent.contents.length) { - for (const child of parent.contents) { - expandItem(child); - children.push(child); - } - } - } - parents = children; - } - } - this.setState({ expanded }); - - if (isExpanded && this.props.onExpand) { - this.props.onExpand(item, expanded); - } else if (!isExpanded && this.props.onCollapse) { - this.props.onCollapse(item, expanded); - } - }; - - this.focusItem = item => { - if (!this.props.disabledFocus && this.state.focusedItem !== item) { - this.setState({ focusedItem: item }); - - if (this.props.onFocus) { - this.props.onFocus(item); - } - } - }; - - this.state = { - expanded: props.expanded || new Set(), - focusedItem: null - }; - } - - componentWillReceiveProps(nextProps) { - const { listItems, highlightItems, focused } = this.props; - if (nextProps.listItems && nextProps.listItems != listItems && nextProps.listItems.length) { - this.expandListItems(nextProps.listItems); - } - - if (nextProps.highlightItems && nextProps.highlightItems != highlightItems && nextProps.highlightItems.length) { - this.highlightItem(nextProps.highlightItems); - } - - if (nextProps.focused && nextProps.focused !== focused) { - this.focusItem(nextProps.focused); - } - } - - expandListItems(listItems) { - const { expanded } = this.state; - listItems.forEach(item => expanded.add(this.props.getPath(item))); - this.focusItem(listItems[0]); - this.setState({ expanded }); - } - - highlightItem(highlightItems) { - const { expanded } = this.state; - // This file is visible, so we highlight it. - if (expanded.has(this.props.getPath(highlightItems[0]))) { - this.focusItem(highlightItems[0]); - } else { - // Look at folders starting from the top-level until finds a - // closed folder and highlights this folder - const index = highlightItems.reverse().findIndex(item => !expanded.has(this.props.getPath(item))); - this.focusItem(highlightItems[index]); - } - } - - render() { - const { expanded, focusedItem } = this.state; - return _react2.default.createElement( - "div", - { className: "managed-tree" }, - _react2.default.createElement(Tree, _extends({}, this.props, { - isExpanded: item => expanded.has(this.props.getPath(item)), - focused: focusedItem, - getKey: this.props.getPath, - onExpand: item => this.setExpanded(item, true, false), - onCollapse: item => this.setExpanded(item, false, false), - onFocus: this.focusItem, - renderItem: (...args) => this.props.renderItem(...args, { - setExpanded: this.setExpanded - }) - })) - ); - } -} - -exports.default = ManagedTree; - -/***/ }), - -/***/ 1405: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getFilenameFromPath = getFilenameFromPath; -exports.getURL = getURL; - -var _url = __webpack_require__(334); - -var _lodash = __webpack_require__(2); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getFilenameFromPath(pathname) { - let filename = ""; - if (pathname) { - filename = pathname.substring(pathname.lastIndexOf("/") + 1); - // This file does not have a name. Default should be (index). - if (filename == "" || !filename.includes(".")) { - filename = "(index)"; - } - } - return filename; -} - -const NoDomain = "(no domain)"; -function getURL(sourceUrl, debuggeeUrl = "") { - const url = sourceUrl; - const def = { path: "", group: "", filename: "" }; - if (!url) { - return def; - } - - const { pathname, protocol, host, path } = (0, _url.parse)(url); - const defaultDomain = (0, _url.parse)(debuggeeUrl).host; - const filename = getFilenameFromPath(pathname); - - switch (protocol) { - case "javascript:": - // Ignore `javascript:` URLs for now - return def; - - case "webpack:": - // A Webpack source is a special case - return (0, _lodash.merge)(def, { - path: path, - group: "webpack://", - filename: filename - }); - - case "ng:": - // An Angular source is a special case - return (0, _lodash.merge)(def, { - path: path, - group: "ng://", - filename: filename - }); - - case "about:": - // An about page is a special case - return (0, _lodash.merge)(def, { - path: "/", - group: url, - filename: filename - }); - - case "data:": - return (0, _lodash.merge)(def, { - path: "/", - group: NoDomain, - filename: url - }); - - case null: - if (pathname && pathname.startsWith("/")) { - // If it's just a URL like "/foo/bar.js", resolve it to the file - // protocol - return (0, _lodash.merge)(def, { - path: path, - group: "file://", - filename: filename - }); - } else if (host === null) { - // We don't know what group to put this under, and it's a script - // with a weird URL. Just group them all under an anonymous group. - return (0, _lodash.merge)(def, { - path: url, - group: defaultDomain, - filename: filename - }); - } - break; - - case "http:": - case "https:": - return (0, _lodash.merge)(def, { - path: pathname, - group: host, - filename: filename - }); - } - - return (0, _lodash.merge)(def, { - path: path, - group: protocol ? `${protocol}//` : "", - filename: filename - }); -} - -/***/ }), - -/***/ 1406: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.scrollList = undefined; - -var _devtoolsEnvironment = __webpack_require__(3721); - -var _Modal = __webpack_require__(1403); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function scrollList(resultList, index, delayed = false) { - if (!resultList.hasOwnProperty(index)) { - return; - } - - const resultEl = resultList[index]; - - const scroll = () => { - if ((0, _devtoolsEnvironment.isFirefox)()) { - resultEl.scrollIntoView({ block: "center", behavior: "smooth" }); - } else { - chromeScrollList(resultEl, index); - } - }; - - if (delayed) { - // Wait for Modal Transition timeout before scrolling to resultEl. - setTimeout(scroll, _Modal.transitionTimeout + 10); - return; - } - - scroll(); -} - -function chromeScrollList(elem, index) { - const resultsEl = elem.parentNode; - if (!resultsEl || resultsEl.children.length === 0) { - return; - } - - const resultsHeight = resultsEl.clientHeight; - const itemHeight = resultsEl.children[0].clientHeight; - const numVisible = resultsHeight / itemHeight; - const positionsToScroll = index - numVisible + 1; - const itemOffset = resultsHeight % itemHeight; - const scroll = positionsToScroll * (itemHeight + 2) + itemOffset; - - resultsEl.scrollTop = Math.max(0, scroll); -} - -exports.scrollList = scrollList; - -/***/ }), - -/***/ 1407: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _CommandBarButton = __webpack_require__(1764); - -var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton); - -__webpack_require__(1321); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class PaneToggleButton extends _react.PureComponent { - - render() { - const { position, collapsed, horizontal, handleClick } = this.props; - const title = !collapsed ? L10N.getStr("expandPanes") : L10N.getStr("collapsePanes"); - - return _react2.default.createElement( - _CommandBarButton2.default, - { - className: (0, _classnames2.default)("toggle-button", position, { - collapsed, - vertical: !horizontal - }), - onClick: () => handleClick(position, collapsed), - title: title - }, - _react2.default.createElement(_Svg2.default, { name: "togglePanes" }) - ); - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -PaneToggleButton.defaultProps = { - horizontal: false -}; -exports.default = PaneToggleButton; - -/***/ }), - -/***/ 1413: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const { Menu, MenuItem } = __webpack_require__(1376); - -function inToolbox() { - return window.parent.document.documentURI == "about:devtools-toolbox"; -} - -if (!inToolbox()) { - __webpack_require__(1301); -} - -function createPopup(doc) { - let popup = doc.createElement("menupopup"); - popup.className = "landing-popup"; - if (popup.openPopupAtScreen) { - return popup; - } - - function preventDefault(e) { - e.preventDefault(); - e.returnValue = false; - } - - let mask = document.querySelector("#contextmenu-mask"); - if (!mask) { - mask = doc.createElement("div"); - mask.id = "contextmenu-mask"; - document.body.appendChild(mask); - } - - mask.onclick = () => popup.hidePopup(); - - popup.openPopupAtScreen = function (clientX, clientY) { - this.style.setProperty("left", `${clientX}px`); - this.style.setProperty("top", `${clientY}px`); - mask = document.querySelector("#contextmenu-mask"); - window.onwheel = preventDefault; - mask.classList.add("show"); - this.dispatchEvent(new Event("popupshown")); - this.popupshown; - }; - - popup.hidePopup = function () { - this.remove(); - mask = document.querySelector("#contextmenu-mask"); - mask.classList.remove("show"); - window.onwheel = null; - }; - - return popup; -} - -if (!inToolbox()) { - Menu.prototype.createPopup = createPopup; -} - -function onShown(menu, popup) { - popup.childNodes.forEach((menuItemNode, i) => { - let item = menu.items[i]; - - if (!item.disabled && item.visible) { - menuItemNode.onclick = () => { - item.click(); - popup.hidePopup(); - }; - - showSubMenu(item.submenu, menuItemNode, popup); - } - }); -} - -function showMenu(evt, items) { - if (items.length === 0) { - return; - } - - let menu = new Menu(); - items.filter(item => item.visible === undefined || item.visible === true).forEach(item => { - let menuItem = new MenuItem(item); - menuItem.submenu = createSubMenu(item.submenu); - menu.append(menuItem); - }); - - if (inToolbox()) { - menu.popup(evt.screenX, evt.screenY, { doc: window.parent.document }); - return; - } - - menu.on("open", (_, popup) => onShown(menu, popup)); - menu.popup(evt.clientX, evt.clientY, { doc: document }); -} - -function createSubMenu(subItems) { - if (subItems) { - let subMenu = new Menu(); - subItems.forEach(subItem => { - subMenu.append(new MenuItem(subItem)); - }); - return subMenu; - } - return null; -} - -function showSubMenu(subMenu, menuItemNode, popup) { - if (subMenu) { - let subMenuNode = menuItemNode.querySelector("menupopup"); - let { top } = menuItemNode.getBoundingClientRect(); - let { left, width } = popup.getBoundingClientRect(); - subMenuNode.style.setProperty("left", `${left + width - 1}px`); - subMenuNode.style.setProperty("top", `${top}px`); - - let subMenuItemNodes = menuItemNode.querySelector("menupopup:not(.landing-popup)").childNodes; - subMenuItemNodes.forEach((subMenuItemNode, j) => { - let subMenuItem = subMenu.items.filter(item => item.visible === undefined || item.visible === true)[j]; - if (!subMenuItem.disabled && subMenuItem.visible) { - subMenuItemNode.onclick = () => { - subMenuItem.click(); - popup.hidePopup(); - }; - } - }); - } -} - -function buildMenu(items) { - return items.map(itm => { - const hide = typeof itm.hidden === "function" ? itm.hidden() : itm.hidden; - return hide ? null : itm.item; - }).filter(itm => itm !== null); -} - -module.exports = { - showMenu, - buildMenu -}; - -/***/ }), - -/***/ 1416: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getASTLocation = getASTLocation; -exports.findScopeByName = findScopeByName; - -var _parser = __webpack_require__(1365); - -var _ast = __webpack_require__(1638); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getASTLocation(source, symbols, location) { - if (source.isWasm || !symbols || symbols.loading) { - return { name: undefined, offset: location }; - } - - const scope = (0, _ast.findClosestFunction)(symbols, location); - if (scope) { - // we only record the line, but at some point we may - // also do column offsets - const line = location.line - scope.location.start.line; - return { - name: scope.name, - offset: { line, column: undefined } - }; - } - return { name: undefined, offset: location }; -} - -async function findScopeByName(source, name) { - const symbols = await (0, _parser.getSymbols)(source.id); - const functions = symbols.functions; - - return functions.find(node => node.name === name); -} - -/***/ }), - -/***/ 1417: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getExpressionError = exports.getAutocompleteMatches = exports.getExpressions = exports.createExpressionState = undefined; -exports.getExpression = getExpression; -exports.getAutocompleteMatchset = getAutocompleteMatchset; - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _immutable = __webpack_require__(3594); - -var _lodash = __webpack_require__(2); - -var _reselect = __webpack_require__(993); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const createExpressionState = exports.createExpressionState = (0, _makeRecord2.default)({ - expressions: (0, _immutable.List)(restoreExpressions()), - expressionError: false, - autocompleteMatches: (0, _immutable.Map)({}) -}); /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Expressions reducer - * @module reducers/expressions - */ - -function update(state = createExpressionState(), action) { - switch (action.type) { - case "ADD_EXPRESSION": - if (action.expressionError) { - return state.set("expressionError", !!action.expressionError); - } - return appendExpressionToList(state, { - input: action.input, - value: null, - updating: true - }); - - case "UPDATE_EXPRESSION": - const key = action.expression.input; - return updateExpressionInList(state, key, { - input: action.input, - value: null, - updating: true - }).set("expressionError", !!action.expressionError); - - case "EVALUATE_EXPRESSION": - return updateExpressionInList(state, action.input, { - input: action.input, - value: action.value, - updating: false - }); - - case "EVALUATE_EXPRESSIONS": - const { inputs, results } = action; - - return (0, _lodash.zip)(inputs, results).reduce((newState, [input, result]) => updateExpressionInList(newState, input, { - input: input, - value: result, - updating: false - }), state); - - case "DELETE_EXPRESSION": - return deleteExpression(state, action.input); - - case "CLEAR_EXPRESSION_ERROR": - return state.set("expressionError", false); - - // respond to time travel - case "TRAVEL_TO": - return travelTo(state, action); - - case "AUTOCOMPLETE": - const { matchProp, matches } = action.result; - return state.updateIn(["autocompleteMatches", matchProp], list => matches); - } - - return state; -} - -function travelTo(state, action) { - const { expressions } = action.data; - if (!expressions) { - return state; - } - return expressions.reduce((finalState, previousState) => updateExpressionInList(finalState, previousState.input, { - input: previousState.input, - value: previousState.value, - updating: false - }), state); -} - -function restoreExpressions() { - const exprs = _prefs.prefs.expressions; - if (exprs.length == 0) { - return; - } - return exprs; -} - -function storeExpressions({ expressions }) { - _prefs.prefs.expressions = expressions.map(expression => (0, _lodash.omit)(expression, "value")).toJS(); -} - -function appendExpressionToList(state, value) { - const newState = state.update("expressions", () => { - return state.expressions.push(value); - }); - - storeExpressions(newState); - return newState; -} - -function updateExpressionInList(state, key, value) { - const newState = state.update("expressions", () => { - const list = state.expressions; - const index = list.findIndex(e => e.input == key); - return list.update(index, () => value); - }); - - storeExpressions(newState); - return newState; -} - -function deleteExpression(state, input) { - const index = getExpressions({ expressions: state }).findIndex(e => e.input == input); - const newState = state.deleteIn(["expressions", index]); - storeExpressions(newState); - return newState; -} - -const getExpressionsWrapper = state => state.expressions; - -const getExpressions = exports.getExpressions = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.expressions); - -const getAutocompleteMatches = exports.getAutocompleteMatches = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.autocompleteMatches); - -function getExpression(state, input) { - return getExpressions(state).find(exp => exp.input == input); -} - -function getAutocompleteMatchset(state, input) { - return getAutocompleteMatches(state).get(input); -} - -const getExpressionError = exports.getExpressionError = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.expressionError); - -exports.default = update; - -/***/ }), - -/***/ 1418: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getWorkers = exports.createDebuggeeState = undefined; -exports.default = debuggee; -exports.getWorker = getWorker; - -var _reselect = __webpack_require__(993); - -var _immutable = __webpack_require__(3594); - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const createDebuggeeState = exports.createDebuggeeState = (0, _makeRecord2.default)({ - workers: (0, _immutable.List)() -}); /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Debuggee reducer - * @module reducers/debuggee - */ - -function debuggee(state = createDebuggeeState(), action) { - switch (action.type) { - case "SET_WORKERS": - return state.set("workers", (0, _immutable.List)(action.workers)); - default: - return state; - } -} - -const getDebuggeeWrapper = state => state.debuggee; - -const getWorkers = exports.getWorkers = (0, _reselect.createSelector)(getDebuggeeWrapper, debuggeeState => debuggeeState.get("workers")); - -function getWorker(state, url) { - return getWorkers(state).find(value => url); -} - -/***/ }), - -/***/ 1419: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.initialPendingBreakpointsState = initialPendingBreakpointsState; -exports.getPendingBreakpoints = getPendingBreakpoints; -exports.getPendingBreakpointsForSource = getPendingBreakpointsForSource; - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _breakpoint = __webpack_require__(1364); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Pending breakpoints reducer - * @module reducers/pending-breakpoints - */ - -function initialPendingBreakpointsState() { - return (0, _makeRecord2.default)({ - pendingBreakpoints: restorePendingBreakpoints() - })(); -} - -function update(state = initialPendingBreakpointsState(), action) { - switch (action.type) { - case "ADD_BREAKPOINT": - { - if (action.breakpoint.hidden) { - return state; - } - return addBreakpoint(state, action); - } - - case "SYNC_BREAKPOINT": - { - return syncBreakpoint(state, action); - } - - case "ENABLE_BREAKPOINT": - { - return addBreakpoint(state, action); - } - - case "DISABLE_BREAKPOINT": - { - return updateBreakpoint(state, action); - } - - case "DISABLE_ALL_BREAKPOINTS": - { - return updateAllBreakpoints(state, action); - } - - case "ENABLE_ALL_BREAKPOINTS": - { - return updateAllBreakpoints(state, action); - } - - case "SET_BREAKPOINT_CONDITION": - { - return updateBreakpoint(state, action); - } - - case "REMOVE_BREAKPOINT": - { - if (action.breakpoint.hidden) { - return state; - } - return removeBreakpoint(state, action); - } - } - - return state; -} - -function addBreakpoint(state, action) { - if (action.status !== "done") { - return state; - } - // when the action completes, we can commit the breakpoint - const { breakpoint } = action.value; - const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); - const pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint); - - return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint); -} - -function syncBreakpoint(state, action) { - const { breakpoint, previousLocation } = action; - - if (previousLocation) { - state = state.deleteIn(["pendingBreakpoints", (0, _breakpoint.makePendingLocationId)(previousLocation)]); - } - - if (!breakpoint) { - return state; - } - - const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); - const pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint); - - return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint); -} - -function updateBreakpoint(state, action) { - const { breakpoint } = action; - const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); - const pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint); - - return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint); -} - -function updateAllBreakpoints(state, action) { - const { breakpoints } = action; - breakpoints.forEach(breakpoint => { - const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); - state = state.setIn(["pendingBreakpoints", locationId], breakpoint); - }); - return state; -} - -function removeBreakpoint(state, action) { - const { breakpoint } = action; - - const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); - const pendingBp = state.pendingBreakpoints.get(locationId); - - if (!pendingBp && action.status == "start") { - return state.set("pendingBreakpoints", I.Map()); - } - - return state.deleteIn(["pendingBreakpoints", locationId]); -} - -// Selectors -// TODO: these functions should be moved out of the reducer - -function getPendingBreakpoints(state) { - return state.pendingBreakpoints.pendingBreakpoints; -} - -function getPendingBreakpointsForSource(state, sourceUrl) { - const pendingBreakpoints = state.pendingBreakpoints.pendingBreakpoints || I.Map(); - return pendingBreakpoints.filter(pendingBreakpoint => pendingBreakpoint.location.sourceUrl === sourceUrl); -} - -function restorePendingBreakpoints() { - return I.Map(_prefs.prefs.pendingBreakpoints); -} - -exports.default = update; - -/***/ }), - -/***/ 1420: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getEventListeners = getEventListeners; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Event listeners reducer - * @module reducers/event-listeners - */ - -const initialEventListenersState = { - activeEventNames: [], - listeners: [], - fetchingListeners: false -}; - -function update(state = initialEventListenersState, action, emit) { - switch (action.type) { - case "UPDATE_EVENT_BREAKPOINTS": - state.activeEventNames = action.eventNames; - // emit("activeEventNames", state.activeEventNames); - break; - case "FETCH_EVENT_LISTENERS": - if (action.status === "begin") { - state.fetchingListeners = true; - } else if (action.status === "done") { - state.fetchingListeners = false; - state.listeners = action.listeners; - } - break; - case "NAVIGATE": - return initialEventListenersState; - } - - return state; -} - -function getEventListeners(state) { - return state.eventListeners.listeners; -} - -exports.default = update; - -/***/ }), - -/***/ 1421: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createUIState = undefined; -exports.getSelectedPrimaryPaneTab = getSelectedPrimaryPaneTab; -exports.getActiveSearch = getActiveSearch; -exports.getContextMenu = getContextMenu; -exports.getFrameworkGroupingState = getFrameworkGroupingState; -exports.getShownSource = getShownSource; -exports.getPaneCollapse = getPaneCollapse; -exports.getHighlightedLineRange = getHighlightedLineRange; -exports.getConditionalPanelLine = getConditionalPanelLine; -exports.getProjectDirectoryRoot = getProjectDirectoryRoot; -exports.getOrientation = getOrientation; - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * UI reducer - * @module reducers/ui - */ - -const createUIState = exports.createUIState = (0, _makeRecord2.default)({ - selectedPrimaryPaneTab: "sources", - activeSearch: null, - contextMenu: {}, - shownSource: "", - projectDirectoryRoot: _prefs.prefs.projectDirectoryRoot, - startPanelCollapsed: _prefs.prefs.startPanelCollapsed, - endPanelCollapsed: _prefs.prefs.endPanelCollapsed, - frameworkGroupingOn: _prefs.prefs.frameworkGroupingOn, - highlightedLineRange: undefined, - conditionalPanelLine: null, - orientation: "horizontal" -}); - -function update(state = createUIState(), action) { - switch (action.type) { - case "TOGGLE_ACTIVE_SEARCH": - { - return state.set("activeSearch", action.value); - } - - case "TOGGLE_FRAMEWORK_GROUPING": - { - _prefs.prefs.frameworkGroupingOn = action.value; - return state.set("frameworkGroupingOn", action.value); - } - - case "SET_CONTEXT_MENU": - { - return state.set("contextMenu", action.contextMenu); - } - - case "SET_ORIENTATION": - { - return state.set("orientation", action.orientation); - } - - case "SHOW_SOURCE": - { - return state.set("shownSource", action.sourceUrl); - } - - case "TOGGLE_PANE": - { - if (action.position == "start") { - _prefs.prefs.startPanelCollapsed = action.paneCollapsed; - return state.set("startPanelCollapsed", action.paneCollapsed); - } - - _prefs.prefs.endPanelCollapsed = action.paneCollapsed; - return state.set("endPanelCollapsed", action.paneCollapsed); - } - - case "HIGHLIGHT_LINES": - const { start, end, sourceId } = action.location; - let lineRange = {}; - - if (start && end && sourceId) { - lineRange = { start, end, sourceId }; - } - - return state.set("highlightedLineRange", lineRange); - - case "CLOSE_QUICK_OPEN": - case "CLEAR_HIGHLIGHT_LINES": - return state.set("highlightedLineRange", {}); - - case "OPEN_CONDITIONAL_PANEL": - return state.set("conditionalPanelLine", action.line); - - case "CLOSE_CONDITIONAL_PANEL": - return state.set("conditionalPanelLine", null); - - case "SET_PROJECT_DIRECTORY_ROOT": - _prefs.prefs.projectDirectoryRoot = action.url; - return state.set("projectDirectoryRoot", action.url); - - case "SET_PRIMARY_PANE_TAB": - return state.set("selectedPrimaryPaneTab", action.tabName); - - case "CLOSE_PROJECT_SEARCH": - { - if (state.get("activeSearch") === "project") { - return state.set("activeSearch", null); - } - return state; - } - - default: - { - return state; - } - } -} - -// NOTE: we'd like to have the app state fully typed -// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 -function getSelectedPrimaryPaneTab(state) { - return state.ui.get("selectedPrimaryPaneTab"); -} - -function getActiveSearch(state) { - return state.ui.get("activeSearch"); -} - -function getContextMenu(state) { - return state.ui.get("contextMenu"); -} - -function getFrameworkGroupingState(state) { - return state.ui.get("frameworkGroupingOn"); -} - -function getShownSource(state) { - return state.ui.get("shownSource"); -} - -function getPaneCollapse(state, position) { - if (position == "start") { - return state.ui.get("startPanelCollapsed"); - } - - return state.ui.get("endPanelCollapsed"); -} - -function getHighlightedLineRange(state) { - return state.ui.get("highlightedLineRange"); -} - -function getConditionalPanelLine(state) { - return state.ui.get("conditionalPanelLine"); -} - -function getProjectDirectoryRoot(state) { - return state.ui.get("projectDirectoryRoot"); -} - -function getOrientation(state) { - return state.ui.get("orientation"); -} - -exports.default = update; - -/***/ }), - -/***/ 1422: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createFileSearchState = undefined; -exports.getFileSearchQuery = getFileSearchQuery; -exports.getFileSearchModifiers = getFileSearchModifiers; -exports.getFileSearchResults = getFileSearchResults; - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * File Search reducer - * @module reducers/fileSearch - */ - -const createFileSearchState = exports.createFileSearchState = (0, _makeRecord2.default)({ - query: "", - searchResults: { - matches: [], - matchIndex: -1, - index: -1, - count: 0 - }, - modifiers: (0, _makeRecord2.default)({ - caseSensitive: _prefs.prefs.fileSearchCaseSensitive, - wholeWord: _prefs.prefs.fileSearchWholeWord, - regexMatch: _prefs.prefs.fileSearchRegexMatch - })() -}); - -function update(state = createFileSearchState(), action) { - switch (action.type) { - case "UPDATE_FILE_SEARCH_QUERY": - { - return state.set("query", action.query); - } - - case "UPDATE_SEARCH_RESULTS": - { - return state.set("searchResults", action.results); - } - - case "TOGGLE_FILE_SEARCH_MODIFIER": - { - const actionVal = !state.modifiers[action.modifier]; - - if (action.modifier == "caseSensitive") { - _prefs.prefs.fileSearchCaseSensitive = actionVal; - } - - if (action.modifier == "wholeWord") { - _prefs.prefs.fileSearchWholeWord = actionVal; - } - - if (action.modifier == "regexMatch") { - _prefs.prefs.fileSearchRegexMatch = actionVal; - } - - return state.setIn(["modifiers", action.modifier], actionVal); - } - - default: - { - return state; - } - } -} - -// NOTE: we'd like to have the app state fully typed -// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 -function getFileSearchQuery(state) { - return state.fileSearch.query; -} - -function getFileSearchModifiers(state) { - return state.fileSearch.modifiers; -} - -function getFileSearchResults(state) { - return state.fileSearch.searchResults; -} - -exports.default = update; - -/***/ }), - -/***/ 1423: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createCoverageState = undefined; -exports.getHitCountForSource = getHitCountForSource; -exports.getCoverageEnabled = getCoverageEnabled; - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _fromJS = __webpack_require__(1502); - -var _fromJS2 = _interopRequireDefault(_fromJS); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const createCoverageState = exports.createCoverageState = (0, _makeRecord2.default)({ - coverageOn: false, - hitCount: I.Map() -}); /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Code coverage reducer - * @module reducers/coverage - */ - -function update(state = createCoverageState(), action) { - switch (action.type) { - case "RECORD_COVERAGE": - return state.mergeIn(["hitCount"], (0, _fromJS2.default)(action.value.coverage)).setIn(["coverageOn"], true); - - default: - { - return state; - } - } -} - -// NOTE: we'd like to have the app state fully typed -// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 -function getHitCountForSource(state, sourceId) { - const hitCount = state.coverage.get("hitCount"); - return hitCount.get(sourceId); -} - -function getCoverageEnabled(state) { - return state.coverage.get("coverageOn"); -} - -exports.default = update; - -/***/ }), - -/***/ 1424: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.statusType = undefined; -exports.initialProjectTextSearchState = initialProjectTextSearchState; -exports.getTextSearchResults = getTextSearchResults; -exports.getTextSearchStatus = getTextSearchStatus; -exports.getTextSearchQuery = getTextSearchQuery; - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// @format - -/** - * Project text search reducer - * @module reducers/project-text-search - */ - -const statusType = exports.statusType = { - initial: "INITIAL", - fetching: "FETCHING", - done: "DONE", - error: "ERROR" -}; - -function initialProjectTextSearchState() { - return (0, _makeRecord2.default)({ - query: "", - results: I.List(), - status: statusType.initial - })(); -} - -function update(state = initialProjectTextSearchState(), action) { - switch (action.type) { - case "ADD_QUERY": - const actionCopy = action; - return state.update("query", value => actionCopy.query); - - case "CLEAR_QUERY": - return state.merge({ - query: "", - status: statusType.initial - }); - - case "ADD_SEARCH_RESULT": - const results = state.get("results"); - return state.merge({ results: results.push(action.result) }); - - case "UPDATE_STATUS": - return state.merge({ status: action.status }); - - case "CLEAR_SEARCH_RESULTS": - return state.merge({ - results: state.get("results").clear() - }); - - case "CLEAR_SEARCH": - case "CLOSE_PROJECT_SEARCH": - return state.merge({ - query: "", - results: state.get("results").clear(), - status: statusType.initial - }); - } - return state; -} - -function getTextSearchResults(state) { - return state.projectTextSearch.get("results"); -} - -function getTextSearchStatus(state) { - return state.projectTextSearch.get("status"); -} - -function getTextSearchQuery(state) { - return state.projectTextSearch.get("query"); -} - -exports.default = update; - -/***/ }), - -/***/ 1426: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.InitialState = InitialState; -exports.default = update; -exports.getExpandedState = getExpandedState; - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function InitialState() { - return (0, _makeRecord2.default)({ - expanded: null - })(); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Source tree reducer - * @module reducers/source-tree - */ - -function update(state = InitialState(), action) { - switch (action.type) { - case "SET_EXPANDED_STATE": - return state.set("expanded", action.expanded); - } - return state; -} - -function getExpandedState(state) { - return state.sourceTree.get("expanded"); -} - -/***/ }), - -/***/ 1427: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getVisibleBreakpoints = getVisibleBreakpoints; - -var _breakpoints = __webpack_require__(1378); - -var _sources = __webpack_require__(1369); - -var _devtoolsSourceMap = __webpack_require__(3646); - -function getLocation(breakpoint, isGeneratedSource) { - return isGeneratedSource ? breakpoint.generatedLocation || breakpoint.location : breakpoint.location; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function formatBreakpoint(breakpoint, selectedSource) { - const { condition, loading, disabled, hidden } = breakpoint; - const sourceId = selectedSource.get("id"); - const isGeneratedSource = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); - - return { - location: getLocation(breakpoint, isGeneratedSource), - condition, - loading, - disabled, - hidden - }; -} - -function isVisible(breakpoint, selectedSource) { - const sourceId = selectedSource.get("id"); - const isGeneratedSource = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); - - const location = getLocation(breakpoint, isGeneratedSource); - return location.sourceId === sourceId; -} - -/* - * Finds the breakpoints, which appear in the selected source. - * - * This - */ -function getVisibleBreakpoints(state) { - const selectedSource = (0, _sources.getSelectedSource)(state); - if (!selectedSource) { - return null; - } - - return (0, _breakpoints.getBreakpoints)(state).filter(bp => isVisible(bp, selectedSource)).map(bp => formatBreakpoint(bp, selectedSource)); -} - -/***/ }), - -/***/ 1428: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -exports.createFrame = createFrame; -exports.createSource = createSource; -exports.createPause = createPause; -exports.createBreakpointLocation = createBreakpointLocation; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// This module converts Firefox specific types to the generic types - -function createFrame(frame) { - if (!frame) { - return null; - } - let title; - if (frame.type == "call") { - const c = frame.callee; - title = c.name || c.userDisplayName || c.displayName || L10N.getStr("anonymous"); - } else { - title = `(${frame.type})`; - } - const location = { - sourceId: frame.where.source.actor, - line: frame.where.line, - column: frame.where.column - }; - - return { - id: frame.actor, - displayName: title, - location, - generatedLocation: location, - this: frame.this, - scope: frame.environment - }; -} - -function createSource(source, { supportsWasm }) { - return { - id: source.actor, - url: source.url, - isPrettyPrinted: false, - isWasm: supportsWasm && source.introductionType === "wasm", - sourceMapURL: source.sourceMapURL, - isBlackBoxed: false, - loadedState: "unloaded" - }; -} - -function createPause(packet, response) { - // NOTE: useful when the debugger is already paused - const frame = packet.frame || response.frames[0]; - - return _extends({}, packet, { - frame: createFrame(frame), - frames: response.frames.map(createFrame) - }); -} - -// Firefox only returns `actualLocation` if it actually changed, -// but we want it always to exist. Format `actualLocation` if it -// exists, otherwise use `location`. - -function createBreakpointLocation(location, actualLocation) { - if (!actualLocation) { - return location; - } - - return { - sourceId: actualLocation.source.actor, - sourceUrl: actualLocation.source.url, - line: actualLocation.line, - column: actualLocation.column - }; -} - -/***/ }), - -/***/ 1430: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.bootstrapStore = bootstrapStore; -exports.bootstrapWorkers = bootstrapWorkers; -exports.teardownWorkers = teardownWorkers; -exports.bootstrapApp = bootstrapApp; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _redux = __webpack_require__(3593); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _devtoolsEnvironment = __webpack_require__(3721); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _search = __webpack_require__(1395); - -var search = _interopRequireWildcard(_search); - -var _prettyPrint = __webpack_require__(1431); - -var prettyPrint = _interopRequireWildcard(_prettyPrint); - -var _parser = __webpack_require__(1365); - -var parser = _interopRequireWildcard(_parser); - -var _createStore = __webpack_require__(1658); - -var _createStore2 = _interopRequireDefault(_createStore); - -var _reducers = __webpack_require__(1516); - -var _reducers2 = _interopRequireDefault(_reducers); - -var _selectors = __webpack_require__(3590); - -var selectors = _interopRequireWildcard(_selectors); - -var _App = __webpack_require__(1518); - -var _App2 = _interopRequireDefault(_App); - -var _prefs = __webpack_require__(226); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { Provider } = __webpack_require__(3592); - -function renderPanel(component, store) { - const root = document.createElement("div"); - root.className = "launchpad-root theme-body"; - root.style.setProperty("flex", "1"); - const mount = document.querySelector("#mount"); - if (!mount) { - return; - } - mount.appendChild(root); - - _reactDom2.default.render(_react2.default.createElement(Provider, { store }, _react2.default.createElement(component)), root); -} - -function bootstrapStore(client, { services, toolboxActions }) { - const createStore = (0, _createStore2.default)({ - log: (0, _devtoolsEnvironment.isTesting)(), - timing: (0, _devtoolsEnvironment.isDevelopment)(), - makeThunkArgs: (args, state) => { - return _extends({}, args, { client }, services, toolboxActions); - } - }); - - const store = createStore((0, _redux.combineReducers)(_reducers2.default)); - store.subscribe(() => updatePrefs(store.getState())); - - const actions = (0, _redux.bindActionCreators)(__webpack_require__(1354).default, store.dispatch); - - return { store, actions, selectors }; -} - -function bootstrapWorkers() { - const workerPath = (0, _devtoolsEnvironment.isDevelopment)() ? "assets/build" : "resource://devtools/client/debugger/new"; - - if ((0, _devtoolsEnvironment.isDevelopment)()) { - // When used in Firefox, the toolbox manages the source map worker. - (0, _devtoolsSourceMap.startSourceMapWorker)(`${workerPath}/source-map-worker.js`); - } - - prettyPrint.start(`${workerPath}/pretty-print-worker.js`); - parser.start(`${workerPath}/parser-worker.js`); - search.start(`${workerPath}/search-worker.js`); - return { prettyPrint, parser, search }; -} - -function teardownWorkers() { - if (!(0, _devtoolsEnvironment.isFirefoxPanel)()) { - // When used in Firefox, the toolbox manages the source map worker. - (0, _devtoolsSourceMap.stopSourceMapWorker)(); - } - prettyPrint.stop(); - parser.stop(); - search.stop(); -} - -function bootstrapApp(store) { - if ((0, _devtoolsEnvironment.isFirefoxPanel)()) { - renderPanel(_App2.default, store); - } else { - const { renderRoot } = __webpack_require__(52); - renderRoot(_react2.default, _reactDom2.default, _App2.default, store); - } -} - -function updatePrefs(state) { - const pendingBreakpoints = selectors.getPendingBreakpoints(state); - - if (_prefs.prefs.pendingBreakpoints !== pendingBreakpoints) { - _prefs.prefs.pendingBreakpoints = pendingBreakpoints; - } -} - -/***/ }), - -/***/ 1431: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.stop = exports.start = undefined; -exports.prettyPrint = prettyPrint; - -var _devtoolsUtils = __webpack_require__(1363); - -var _source = __webpack_require__(1356); - -var _assert = __webpack_require__(1384); - -var _assert2 = _interopRequireDefault(_assert); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { WorkerDispatcher } = _devtoolsUtils.workerUtils; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const dispatcher = new WorkerDispatcher(); -const start = exports.start = dispatcher.start.bind(dispatcher); -const stop = exports.stop = dispatcher.stop.bind(dispatcher); -const _prettyPrint = dispatcher.task("prettyPrint"); - -async function prettyPrint({ source, url }) { - const indent = 2; - - (0, _assert2.default)((0, _source.isJavaScript)(source), "Can't prettify non-javascript files."); - - return await _prettyPrint({ - url, - indent, - sourceText: source.text - }); -} - -/***/ }), - -/***/ 1432: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.reportException = reportException; -exports.executeSoon = executeSoon; - -var _assert = __webpack_require__(1384); - -var _assert2 = _interopRequireDefault(_assert); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function reportException(who, exception) { - const msg = `${who} threw an exception: `; - console.error(msg, exception); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function executeSoon(fn) { - setTimeout(fn, 0); -} - -exports.default = _assert2.default; - -/***/ }), - -/***/ 1433: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.addSearchQuery = addSearchQuery; -exports.clearSearchQuery = clearSearchQuery; -exports.clearSearchResults = clearSearchResults; -exports.clearSearch = clearSearch; -exports.updateSearchStatus = updateSearchStatus; -exports.closeProjectSearch = closeProjectSearch; -exports.searchSources = searchSources; -exports.searchSource = searchSource; - -var _search = __webpack_require__(1395); - -var _selectors = __webpack_require__(3590); - -var _source = __webpack_require__(1356); - -var _loadSourceText = __webpack_require__(1435); - -var _projectTextSearch = __webpack_require__(1424); - -function addSearchQuery(query) { - return { type: "ADD_QUERY", query }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for the search state - * @module actions/search - */ - -function clearSearchQuery() { - return { type: "CLEAR_QUERY" }; -} - -function clearSearchResults() { - return { type: "CLEAR_SEARCH_RESULTS" }; -} - -function clearSearch() { - return { type: "CLEAR_SEARCH" }; -} - -function updateSearchStatus(status) { - return { type: "UPDATE_STATUS", status }; -} - -function closeProjectSearch() { - return { type: "CLOSE_PROJECT_SEARCH" }; -} - -function searchSources(query) { - return async ({ dispatch, getState }) => { - await dispatch(clearSearchResults()); - await dispatch(addSearchQuery(query)); - dispatch(updateSearchStatus(_projectTextSearch.statusType.fetching)); - const sources = (0, _selectors.getSources)(getState()); - const validSources = sources.valueSeq().filter(source => !(0, _selectors.hasPrettySource)(getState(), source.id) && !(0, _source.isThirdParty)(source)); - for (const source of validSources) { - await dispatch((0, _loadSourceText.loadSourceText)(source)); - await dispatch(searchSource(source.id, query)); - } - dispatch(updateSearchStatus(_projectTextSearch.statusType.done)); - }; -} - -function searchSource(sourceId, query) { - return async ({ dispatch, getState }) => { - const sourceRecord = (0, _selectors.getSource)(getState(), sourceId); - if (!sourceRecord) { - return; - } - - const matches = await (0, _search.findSourceMatches)(sourceRecord.toJS(), query); - if (!matches.length) { - return; - } - dispatch({ - type: "ADD_SEARCH_RESULT", - result: { - sourceId: sourceRecord.id, - filepath: sourceRecord.url, - matches - } - }); - }; -} - -/***/ }), - -/***/ 1435: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.loadSourceText = loadSourceText; - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _promise = __webpack_require__(1653); - -var _selectors = __webpack_require__(3590); - -var _parser = __webpack_require__(1365); - -var parser = _interopRequireWildcard(_parser); - -var _source = __webpack_require__(1356); - -var _defer = __webpack_require__(1800); - -var _defer2 = _interopRequireDefault(_defer); - -var _devtoolsModules = __webpack_require__(1376); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const requests = new Map(); - -const loadSourceHistogram = _devtoolsModules.Services.telemetry.getHistogramById("DEVTOOLS_DEBUGGER_LOAD_SOURCE_MS"); - -async function loadSource(source, { sourceMaps, client }) { - const id = source.get("id"); - if ((0, _devtoolsSourceMap.isOriginalId)(id)) { - return await sourceMaps.getOriginalSourceText(source.toJS()); - } - - const response = await client.sourceContents(id); - - return { - id, - text: response.source, - contentType: response.contentType || "text/javascript" - }; -} - -/** - * @memberof actions/sources - * @static - */ -function loadSourceText(source) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const id = source.get("id"); - - // Fetch the source text only once. - if (requests.has(id)) { - return requests.get(id); - } - - if ((0, _source.isLoaded)(source)) { - return Promise.resolve(); - } - - const telemetryStart = performance.now(); - const deferred = (0, _defer2.default)(); - requests.set(id, deferred.promise); - - try { - await dispatch({ - type: "LOAD_SOURCE_TEXT", - sourceId: id, - [_promise.PROMISE]: loadSource(source, { sourceMaps, client }) - }); - } catch (e) { - deferred.resolve(); - requests.delete(id); - return; - } - - const newSource = (0, _selectors.getSource)(getState(), source.get("id")).toJS(); - - if ((0, _devtoolsSourceMap.isOriginalId)(newSource.id) && !newSource.isWasm) { - const generatedSource = (0, _selectors.getGeneratedSource)(getState(), source.toJS()); - await dispatch(loadSourceText(generatedSource)); - } - - if (!newSource.isWasm) { - await parser.setSource(newSource); - } - - // signal that the action is finished - deferred.resolve(); - requests.delete(id); - - const telemetryEnd = performance.now(); - const duration = telemetryEnd - telemetryStart; - loadSourceHistogram.add(duration); - }; -} - -/***/ }), - -/***/ 1436: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.showLoading = exports.showErrorMessage = exports.showSourceText = exports.clearEditor = exports.updateDocument = exports.updateLineNumberFormat = exports.clearDocuments = exports.removeDocument = exports.hasDocument = exports.setDocument = exports.getDocument = undefined; - -var _source = __webpack_require__(1356); - -var _wasm = __webpack_require__(1401); - -var _ui = __webpack_require__(1439); - -var _sourceEditor = __webpack_require__(197); - -var _sourceEditor2 = _interopRequireDefault(_sourceEditor); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -let sourceDocs = {}; - -function getDocument(key) { - return sourceDocs[key]; -} - -function hasDocument(key) { - return !!getDocument(key); -} - -function setDocument(key, doc) { - sourceDocs[key] = doc; -} - -function removeDocument(key) { - delete sourceDocs[key]; -} - -function clearDocuments() { - sourceDocs = {}; -} - -function resetLineNumberFormat(editor) { - const cm = editor.codeMirror; - cm.setOption("lineNumberFormatter", number => number); - (0, _ui.resizeBreakpointGutter)(cm); - (0, _ui.resizeToggleButton)(cm); -} - -function updateLineNumberFormat(editor, sourceId) { - if (!(0, _wasm.isWasm)(sourceId)) { - return resetLineNumberFormat(editor); - } - const cm = editor.codeMirror; - const lineNumberFormatter = (0, _wasm.getWasmLineNumberFormatter)(sourceId); - cm.setOption("lineNumberFormatter", lineNumberFormatter); - (0, _ui.resizeBreakpointGutter)(cm); - (0, _ui.resizeToggleButton)(cm); -} - -function updateDocument(editor, source) { - if (!source) { - return; - } - - const sourceId = source.get("id"); - const doc = getDocument(sourceId) || editor.createDocument(); - editor.replaceDocument(doc); - - updateLineNumberFormat(editor, sourceId); -} - -function clearEditor(editor) { - const doc = editor.createDocument(); - editor.replaceDocument(doc); - editor.setText(""); - editor.setMode({ name: "text" }); - resetLineNumberFormat(editor); -} - -function showLoading(editor) { - if (hasDocument("loading")) { - return; - } - - const doc = editor.createDocument(); - setDocument("loading", doc); - editor.replaceDocument(doc); - editor.setText(L10N.getStr("loadingText")); - editor.setMode({ name: "text" }); -} - -function showErrorMessage(editor, msg) { - let error; - if (msg.includes("WebAssembly binary source is not available")) { - error = L10N.getStr("wasmIsNotAvailable"); - } else { - error = L10N.getFormatStr("errorLoadingText3", msg); - } - const doc = editor.createDocument(); - editor.replaceDocument(doc); - editor.setText(error); - editor.setMode({ name: "text" }); - resetLineNumberFormat(editor); -} - -function setEditorText(editor, source) { - const { text, id: sourceId } = source; - if (source.isWasm) { - const wasmLines = (0, _wasm.renderWasmText)(sourceId, text); - // cm will try to split into lines anyway, saving memory - const wasmText = { split: () => wasmLines, match: () => false }; - editor.setText(wasmText); - } else { - editor.setText(text); - } -} - -/** - * Handle getting the source document or creating a new - * document with the correct mode and text. - */ -function showSourceText(editor, source, symbols) { - if (!source) { - return; - } - - if (hasDocument(source.id)) { - const doc = getDocument(source.id); - if (editor.codeMirror.doc === doc) { - const mode = (0, _source.getMode)(source, symbols); - - if (doc.mode.name !== mode.name) { - editor.setMode(mode); - } - - return; - } - - editor.replaceDocument(doc); - updateLineNumberFormat(editor, source.id); - editor.setMode((0, _source.getMode)(source, symbols)); - return doc; - } - - const doc = editor.createDocument(); - setDocument(source.id, doc); - editor.replaceDocument(doc); - - setEditorText(editor, source); - editor.setMode((0, _source.getMode)(source, symbols)); - updateLineNumberFormat(editor, source.id); -} - -exports.getDocument = getDocument; -exports.setDocument = setDocument; -exports.hasDocument = hasDocument; -exports.removeDocument = removeDocument; -exports.clearDocuments = clearDocuments; -exports.updateLineNumberFormat = updateLineNumberFormat; -exports.updateDocument = updateDocument; -exports.clearEditor = clearEditor; -exports.showSourceText = showSourceText; -exports.showErrorMessage = showErrorMessage; -exports.showLoading = showLoading; - -/***/ }), - -/***/ 1437: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sanitizeInput = sanitizeInput; -exports.wrapExpression = wrapExpression; -exports.getValue = getValue; - -var _indentation = __webpack_require__(1438); - -// replace quotes that could interfere with the evaluation. -function sanitizeInput(input) { - return input.replace(/"/g, '"'); -} - -/* - * wrap the expression input in a try/catch so that it can be safely - * evaluated. - * - * NOTE: we add line after the expression to protect against comments. -*/ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function wrapExpression(input) { - return (0, _indentation.correctIndentation)(` - try { - ${sanitizeInput(input)} - } catch (e) { - e - } - `); -} - -function isUnavailable(value) { - if (!value.preview || !value.preview.name) { - return false; - } - - return ["ReferenceError", "TypeError"].includes(value.preview.name); -} - -function getValue(expression) { - const value = expression.value; - if (!value) { - return { - path: expression.from, - value: { unavailable: true } - }; - } - - if (value.exception) { - if (isUnavailable(value.exception)) { - return { value: { unavailable: true } }; - } - return { - path: value.from, - value: value.exception - }; - } - - if (value.error) { - return { - path: value.from, - value: value.error - }; - } - - if (value.result && value.result.class == "Error") { - const { name, message } = value.result.preview; - if (isUnavailable(value.result)) { - return { value: { unavailable: true } }; - } - - const newValue = `${name}: ${message}`; - return { path: value.input, value: newValue }; - } - - if (typeof value.result == "object") { - return { - path: value.result.actor, - value: value.result - }; - } - - return { - path: value.input, - value: value.result - }; -} - -/***/ }), - -/***/ 1438: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getIndentation = getIndentation; -exports.correctIndentation = correctIndentation; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getIndentation(line) { - if (!line) { - return 0; - } - return line.match(/^\s*/)[0].length; -} - -function getMaxIndentation(lines) { - const firstLine = lines[0]; - const secondLine = lines[1]; - const lastLine = lines[lines.length - 1]; - - const indentations = [getIndentation(firstLine), getIndentation(secondLine), getIndentation(lastLine)]; - - return Math.max(...indentations); -} - -function correctIndentation(text) { - const lines = text.trim().split("\n"); - const indentation = getMaxIndentation(lines); - const formattedLines = lines.map(_line => _line.replace(new RegExp(`^\\s{0,${indentation - 1}}`), "")); - - return formattedLines.join("\n"); -} - -/***/ }), - -/***/ 1439: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isVisible = isVisible; -exports.getLineNumberWidth = getLineNumberWidth; -exports.resizeBreakpointGutter = resizeBreakpointGutter; -exports.resizeToggleButton = resizeToggleButton; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - - -/* Checks to see if the root element is available and - * if the element is visible. We check the width of the element - * because it is more reliable than either checking a focus state or - * the visibleState or hidden property. - */ -function isVisible() { - const el = document.querySelector("#mount"); - return el && el.getBoundingClientRect().width; -} - -/* Gets the line numbers width in the code editor - */ -function getLineNumberWidth(editor) { - const gutters = editor.display.gutters; - const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers"); - return lineNumbers && lineNumbers.clientWidth; -} - -/** - * Forces the breakpoint gutter to be the same size as the line - * numbers gutter. Editor CSS will absolutely position the gutter - * beneath the line numbers. This makes it easy to be flexible with - * how we overlay breakpoints. - */ -function resizeBreakpointGutter(editor) { - const gutters = editor.display.gutters; - const breakpoints = gutters.querySelector(".breakpoints"); - if (breakpoints) { - breakpoints.style.width = `${getLineNumberWidth(editor)}px`; - } -} - -/** - * Forces the left toggle button in source header to be the same size - * as the line numbers gutter. - */ -function resizeToggleButton(editor) { - const toggleButton = document.querySelector(".source-header .toggle-button-start"); - if (toggleButton) { - toggleButton.style.width = `${getLineNumberWidth(editor)}px`; - } -} - -/***/ }), - -/***/ 1440: -/***/ (function(module, exports, __webpack_require__) { - -const SplitBox = __webpack_require__(1536); - -module.exports = SplitBox; - -/***/ }), - -/***/ 1442: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _addToTree = __webpack_require__(1443); - -Object.defineProperty(exports, "addToTree", { - enumerable: true, - get: function () { - return _addToTree.addToTree; - } -}); - -var _collapseTree = __webpack_require__(1444); - -Object.defineProperty(exports, "collapseTree", { - enumerable: true, - get: function () { - return _collapseTree.collapseTree; - } -}); - -var _createTree = __webpack_require__(1546); - -Object.defineProperty(exports, "createTree", { - enumerable: true, - get: function () { - return _createTree.createTree; - } -}); - -var _formatTree = __webpack_require__(1542); - -Object.defineProperty(exports, "formatTree", { - enumerable: true, - get: function () { - return _formatTree.formatTree; - } -}); - -var _getDirectories = __webpack_require__(1545); - -Object.defineProperty(exports, "getDirectories", { - enumerable: true, - get: function () { - return _getDirectories.getDirectories; - } -}); - -var _getURL = __webpack_require__(1405); - -Object.defineProperty(exports, "getFilenameFromPath", { - enumerable: true, - get: function () { - return _getURL.getFilenameFromPath; - } -}); -Object.defineProperty(exports, "getURL", { - enumerable: true, - get: function () { - return _getURL.getURL; - } -}); - -var _sortTree = __webpack_require__(1544); - -Object.defineProperty(exports, "sortEntireTree", { - enumerable: true, - get: function () { - return _sortTree.sortEntireTree; - } -}); -Object.defineProperty(exports, "sortTree", { - enumerable: true, - get: function () { - return _sortTree.sortTree; - } -}); - -var _updateTree = __webpack_require__(2245); - -Object.defineProperty(exports, "updateTree", { - enumerable: true, - get: function () { - return _updateTree.updateTree; - } -}); - -var _utils = __webpack_require__(1371); - -Object.defineProperty(exports, "createNode", { - enumerable: true, - get: function () { - return _utils.createNode; - } -}); -Object.defineProperty(exports, "createParentMap", { - enumerable: true, - get: function () { - return _utils.createParentMap; - } -}); -Object.defineProperty(exports, "getRelativePath", { - enumerable: true, - get: function () { - return _utils.getRelativePath; - } -}); -Object.defineProperty(exports, "isDirectory", { - enumerable: true, - get: function () { - return _utils.isDirectory; - } -}); -Object.defineProperty(exports, "isExactUrlMatch", { - enumerable: true, - get: function () { - return _utils.isExactUrlMatch; - } -}); -Object.defineProperty(exports, "isNotJavaScript", { - enumerable: true, - get: function () { - return _utils.isNotJavaScript; - } -}); -Object.defineProperty(exports, "nodeHasChildren", { - enumerable: true, - get: function () { - return _utils.nodeHasChildren; - } -}); -Object.defineProperty(exports, "getExtension", { - enumerable: true, - get: function () { - return _utils.getExtension; - } -}); - -/***/ }), - -/***/ 1443: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.addToTree = addToTree; - -var _utils = __webpack_require__(1371); - -var _treeOrder = __webpack_require__(1543); - -var _getURL = __webpack_require__(1405); - -function isUnderRoot(url, projectRoot) { - if (!projectRoot) { - return true; - } - - return `${url.group}${url.path}`.startsWith(projectRoot); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function removeProjectRoot(parts, projectRoot) { - const rootParts = projectRoot.replace("://", "").split("/"); - return parts.splice(0, rootParts.length - 2); -} - -function createNodeInTree(part, path, tree, index) { - const node = (0, _utils.createNode)(part, path, []); - - // we are modifying the tree - const contents = tree.contents.slice(0); - contents.splice(index, 0, node); - tree.contents = contents; - - return node; -} - -/* - * Look for the child directory - * 1. if it exists return it - * 2. if it does not exist create it - * 3. if it is a file, replace it with a directory - */ -function findOrCreateNode(parts, subTree, path, part, index, url, debuggeeHost) { - const addedPartIsFile = (0, _utils.partIsFile)(index, parts, url); - const { found: childFound, index: childIndex } = (0, _treeOrder.findNodeInContents)(subTree, (0, _treeOrder.createTreeNodeMatcher)(part, !addedPartIsFile, debuggeeHost)); - - // we create and enter the new node - if (!childFound) { - return createNodeInTree(part, path, subTree, childIndex); - } - - // we found a path with the same name as the part. We need to determine - // if this is the correct child, or if we have a naming conflict - const child = subTree.contents[childIndex]; - const childIsFile = !(0, _utils.nodeHasChildren)(child); - - // if we have a naming conflict, we'll create a new node - if (childIsFile && !addedPartIsFile || !childIsFile && addedPartIsFile) { - return createNodeInTree(part, path, subTree, childIndex); - } - - // if there is no naming conflict, we can traverse into the child - return child; -} - -/* - * walk the source tree to the final node for a given url, - * adding new nodes along the way - */ -function traverseTree(url, tree, debuggeeHost, projectRoot) { - url.path = decodeURIComponent(url.path); - - const parts = url.path.split("/").filter(p => p !== ""); - parts.unshift(url.group); - - if (projectRoot) { - removeProjectRoot(parts, projectRoot); - } - - let path = ""; - return parts.reduce((subTree, part, index) => { - path = path ? `${path}/${part}` : part; - const debuggeeHostIfRoot = index === 0 ? debuggeeHost : null; - return findOrCreateNode(parts, subTree, path, part, index, url, debuggeeHostIfRoot); - }, tree); -} - -/* - * Add a source file to a directory node in the tree - */ -function addSourceToNode(node, url, source) { - const isFile = !(0, _utils.isDirectory)(url); - - // if we have a file, and the subtree has no elements, overwrite the - // subtree contents with the source - if (isFile) { - return source; - } - - const { filename } = url; - const { found: childFound, index: childIndex } = (0, _treeOrder.findNodeInContents)(node, (0, _treeOrder.createTreeNodeMatcher)(filename, false, null)); - - // if we are readding an existing file in the node, overwrite the existing - // file and return the node's contents - if (childFound) { - const existingNode = node.contents[childIndex]; - existingNode.contents = source; - return node.contents; - } - - // if this is a new file, add the new file; - const newNode = (0, _utils.createNode)(filename, source.get("url"), source); - const contents = node.contents.slice(0); - contents.splice(childIndex, 0, newNode); - return contents; -} - -/** - * @memberof utils/sources-tree - * @static - */ -function addToTree(tree, source, debuggeeUrl, projectRoot) { - const url = (0, _getURL.getURL)(source.get("url"), debuggeeUrl); - const debuggeeHost = (0, _treeOrder.getDomain)(debuggeeUrl); - - if ((0, _utils.isInvalidUrl)(url, source) || !isUnderRoot(url, projectRoot)) { - return; - } - - const finalNode = traverseTree(url, tree, debuggeeHost, projectRoot); - finalNode.contents = addSourceToNode(finalNode, url, source); -} - -/***/ }), - -/***/ 1444: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.collapseTree = collapseTree; - -var _utils = __webpack_require__(1371); - -/** - * Take an existing source tree, and return a new one with collapsed nodes. - */ -function collapseTree(node, depth = 0) { - // Node is a folder. - if (Array.isArray(node.contents)) { - // Node is not a root/domain node, and only contains 1 item. - if (depth > 1 && node.contents.length === 1) { - const next = node.contents[0]; - // Do not collapse if the next node is a leaf node. - if ((0, _utils.nodeHasChildren)(next)) { - return collapseTree((0, _utils.createNode)(`${node.name}/${next.name}`, next.path, next.contents), depth + 1); - } - } - // Map the contents. - return (0, _utils.createNode)(node.name, node.path, node.contents.map(next => collapseTree(next, depth + 1))); - } - // Node is a leaf, not a folder, do not modify it. - return node; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1445: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -__webpack_require__(1316); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class ResultList extends _react.Component { - - constructor(props) { - super(props); - - _initialiseProps.call(this); - } - - render() { - const { size, items, role } = this.props; - - return _react2.default.createElement( - "ul", - { - className: (0, _classnames2.default)("result-list", size), - id: "result-list", - role: role, - "aria-live": "polite" - }, - items.map(this.renderListItem) - ); - } -} -exports.default = ResultList; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -ResultList.defaultProps = { - size: "small", - role: "listbox" -}; - -var _initialiseProps = function () { - this.renderListItem = (item, index) => { - if (item.value === "/" && item.title === "") { - item.title = "(index)"; - } - - const { selectItem, selected } = this.props; - const props = { - onClick: event => selectItem(event, item, index), - key: `${item.id}${item.value}${index}`, - ref: String(index), - title: item.value, - "aria-labelledby": `${item.id}-title`, - "aria-describedby": `${item.id}-subtitle`, - role: "option", - className: (0, _classnames2.default)("result-item", { - selected: index === selected - }) - }; - - return _react2.default.createElement( - "li", - props, - item.icon && _react2.default.createElement( - "div", - null, - _react2.default.createElement("img", { className: item.icon }) - ), - _react2.default.createElement( - "div", - { id: `${item.id}-title`, className: "title" }, - item.title - ), - _react2.default.createElement( - "div", - { id: `${item.id}-subtitle`, className: "subtitle" }, - item.subtitle - ) - ); - }; -}; - -/***/ }), - -/***/ 1446: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _lodash = __webpack_require__(2); - -var _frames = __webpack_require__(3605); - -__webpack_require__(1320); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getFunctionName(func) { - const name = func.userDisplayName || func.displayName || func.name; - return (0, _frames.simplifyDisplayName)(name); -} - -class PreviewFunction extends _react.Component { - renderFunctionName(func) { - const name = getFunctionName(func); - return _react2.default.createElement( - "span", - { className: "function-name" }, - name - ); - } - - renderParams(func) { - const { parameterNames = [] } = func; - const params = parameterNames.filter(i => i).map(param => _react2.default.createElement( - "span", - { className: "param", key: param }, - param - )); - - const commas = (0, _lodash.times)(params.length - 1).map((_, i) => _react2.default.createElement( - "span", - { className: "delimiter", key: i }, - ", " - )); - - return (0, _lodash.flatten)((0, _lodash.zip)(params, commas)); - } - - render() { - return _react2.default.createElement( - "span", - { className: "function-signature" }, - this.renderFunctionName(this.props.func), - _react2.default.createElement( - "span", - { className: "paren" }, - "(" - ), - this.renderParams(this.props.func), - _react2.default.createElement( - "span", - { className: "paren" }, - ")" - ) - ); - } -} -exports.default = PreviewFunction; - -/***/ }), - -/***/ 1453: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _frames = __webpack_require__(3605); - -var _source = __webpack_require__(1356); - -var _FrameMenu = __webpack_require__(1454); - -var _FrameMenu2 = _interopRequireDefault(_FrameMenu); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function FrameTitle({ frame, options }) { - const displayName = (0, _frames.formatDisplayName)(frame, options); - return _react2.default.createElement( - "div", - { className: "title" }, - displayName - ); -} - -function FrameLocation({ frame }) { - if (!frame.source) { - return; - } - - if (frame.library) { - return _react2.default.createElement( - "div", - { className: "location" }, - frame.library, - _react2.default.createElement(_Svg2.default, { name: frame.library.toLowerCase(), className: "annotation-logo" }) - ); - } - - const filename = (0, _source.getFilename)(frame.source); - return _react2.default.createElement( - "div", - { className: "location" }, - `${filename}: ${frame.location.line}` - ); -} - -FrameLocation.displayName = "FrameLocation"; - -class FrameComponent extends _react.Component { - - onContextMenu(event) { - const { - frame, - copyStackTrace, - toggleFrameworkGrouping, - toggleBlackBox, - frameworkGroupingOn - } = this.props; - (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { copyStackTrace, toggleFrameworkGrouping, toggleBlackBox }, event); - } - - onMouseDown(e, frame, selectedFrame) { - if (e.nativeEvent.which == 3) { - return; - } - this.props.selectFrame(frame); - } - - onKeyUp(event, frame, selectedFrame) { - if (event.key != "Enter") { - return; - } - this.props.selectFrame(frame); - } - - render() { - const { - frame, - selectedFrame, - hideLocation, - shouldMapDisplayName - } = this.props; - - const className = (0, _classnames2.default)("frame", { - selected: selectedFrame && selectedFrame.id === frame.id - }); - return _react2.default.createElement( - "li", - { - key: frame.id, - className: className, - onMouseDown: e => this.onMouseDown(e, frame, selectedFrame), - onKeyUp: e => this.onKeyUp(e, frame, selectedFrame), - onContextMenu: e => this.onContextMenu(e), - tabIndex: 0 - }, - _react2.default.createElement(FrameTitle, { frame: frame, options: { shouldMapDisplayName } }), - !hideLocation && _react2.default.createElement(FrameLocation, { frame: frame }) - ); - } -} - -exports.default = FrameComponent; -FrameComponent.defaultProps = { - hideLocation: false, - shouldMapDisplayName: true -}; -FrameComponent.displayName = "Frame"; - -/***/ }), - -/***/ 1454: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = FrameMenu; - -var _devtoolsContextmenu = __webpack_require__(1413); - -var _clipboard = __webpack_require__(1388); - -var _lodash = __webpack_require__(2); - -const blackboxString = "sourceFooter.blackbox"; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const unblackboxString = "sourceFooter.unblackbox"; - -function formatMenuElement(labelString, click, disabled = false) { - const label = L10N.getStr(labelString); - const accesskey = L10N.getStr(`${labelString}.accesskey`); - const id = `node-menu-${(0, _lodash.kebabCase)(label)}`; - return { - id, - label, - accesskey, - disabled, - click - }; -} - -function copySourceElement(url) { - return formatMenuElement("copySourceUri2", () => (0, _clipboard.copyToTheClipboard)(url)); -} - -function copyStackTraceElement(copyStackTrace) { - return formatMenuElement("copyStackTrace", () => copyStackTrace()); -} - -function toggleFrameworkGroupingElement(toggleFrameworkGrouping, frameworkGroupingOn) { - const actionType = frameworkGroupingOn ? "framework.disableGrouping" : "framework.enableGrouping"; - - return formatMenuElement(actionType, () => toggleFrameworkGrouping()); -} - -function blackBoxSource(source, toggleBlackBox) { - const toggleBlackBoxString = source.isBlackBoxed ? unblackboxString : blackboxString; - - return formatMenuElement(toggleBlackBoxString, () => toggleBlackBox(source)); -} - -function FrameMenu(frame, frameworkGroupingOn, callbacks, event) { - event.stopPropagation(); - event.preventDefault(); - - const menuOptions = []; - - const source = frame.source; - - const toggleFrameworkElement = toggleFrameworkGroupingElement(callbacks.toggleFrameworkGrouping, frameworkGroupingOn); - menuOptions.push(toggleFrameworkElement); - - if (source) { - const copySourceUri2 = copySourceElement(source.url); - menuOptions.push(copySourceUri2); - menuOptions.push(blackBoxSource(source, callbacks.toggleBlackBox)); - } - - const copyStackTraceItem = copyStackTraceElement(callbacks.copyStackTrace); - - menuOptions.push(copyStackTraceItem); - - (0, _devtoolsContextmenu.showMenu)(event, menuOptions); -} - -/***/ }), - -/***/ 1459: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _devtoolsEnvironment = __webpack_require__(3721); - -var _client = __webpack_require__(1499); - -var _bootstrap = __webpack_require__(1430); - -var _sourceQueue = __webpack_require__(1795); - -var _sourceQueue2 = _interopRequireDefault(_sourceQueue); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function unmountRoot() { - const mount = document.querySelector("#mount .launchpad-root"); - _reactDom2.default.unmountComponentAtNode(mount); -} - -if ((0, _devtoolsEnvironment.isFirefoxPanel)()) { - module.exports = { - bootstrap: ({ - threadClient, - tabTarget, - debuggerClient, - sourceMaps, - toolboxActions - }) => { - return (0, _client.onConnect)({ - tab: { clientType: "firefox" }, - tabConnection: { - tabTarget, - threadClient, - debuggerClient - } - }, { - services: { sourceMaps }, - toolboxActions - }); - }, - destroy: () => { - unmountRoot(); - _sourceQueue2.default.clear(); - (0, _bootstrap.teardownWorkers)(); - } - }; -} else { - const { bootstrap, L10N } = __webpack_require__(52); - - window.L10N = L10N; - // $FlowIgnore: - window.L10N.setBundle(__webpack_require__(52)); - - bootstrap(_react2.default, _reactDom2.default).then(connection => { - (0, _client.onConnect)(connection, { - services: { sourceMaps: __webpack_require__(3646) }, - toolboxActions: {} - }); - }); -} - -/***/ }), - -/***/ 1464: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const EventEmitter = __webpack_require__(1382); - -function inToolbox() { - return window.parent.document.documentURI == "about:devtools-toolbox"; -} - -/** - * A partial implementation of the Menu API provided by electron: - * https://github.com/electron/electron/blob/master/docs/api/menu.md. - * - * Extra features: - * - Emits an 'open' and 'close' event when the menu is opened/closed - - * @param String id (non standard) - * Needed so tests can confirm the XUL implementation is working - */ -function Menu({ id = null } = {}) { - this.menuitems = []; - this.id = id; - - Object.defineProperty(this, "items", { - get() { - return this.menuitems; - } - }); - - EventEmitter.decorate(this); -} - -/** - * Add an item to the end of the Menu - * - * @param {MenuItem} menuItem - */ -Menu.prototype.append = function (menuItem) { - this.menuitems.push(menuItem); -}; - -/** - * Add an item to a specified position in the menu - * - * @param {int} pos - * @param {MenuItem} menuItem - */ -Menu.prototype.insert = function (pos, menuItem) { - throw Error("Not implemented"); -}; - -/** - * Show the Menu at a specified location on the screen - * - * Missing features: - * - browserWindow - BrowserWindow (optional) - Default is null. - * - positioningItem Number - (optional) OS X - * - * @param {int} screenX - * @param {int} screenY - * @param Toolbox toolbox (non standard) - * Needed so we in which window to inject XUL - */ -Menu.prototype.popup = function (screenX, screenY, toolbox) { - let doc = toolbox.doc; - let popupset = doc.querySelector("popupset"); - // See bug 1285229, on Windows, opening the same popup multiple times in a - // row ends up duplicating the popup. The newly inserted popup doesn't - // dismiss the old one. So remove any previously displayed popup before - // opening a new one. - let popup = popupset.querySelector("menupopup[menu-api=\"true\"]"); - if (popup) { - popup.hidePopup(); - } - - popup = this.createPopup(doc); - popup.setAttribute("menu-api", "true"); - - if (this.id) { - popup.id = this.id; - } - this._createMenuItems(popup); - - // Remove the menu from the DOM once it's hidden. - popup.addEventListener("popuphidden", e => { - if (e.target === popup) { - popup.remove(); - this.emit("close", popup); - } - }); - - popup.addEventListener("popupshown", e => { - if (e.target === popup) { - this.emit("open", popup); - } - }); - - popupset.appendChild(popup); - popup.openPopupAtScreen(screenX, screenY, true); -}; - -Menu.prototype.createPopup = function (doc) { - return doc.createElement("menupopup"); -}; - -Menu.prototype._createMenuItems = function (parent) { - let doc = parent.ownerDocument; - this.menuitems.forEach(item => { - if (!item.visible) { - return; - } - - if (item.submenu) { - let menupopup = doc.createElement("menupopup"); - item.submenu._createMenuItems(menupopup); - - let menuitem = doc.createElement("menuitem"); - menuitem.setAttribute("label", item.label); - if (!inToolbox()) { - menuitem.textContent = item.label; - } - - let menu = doc.createElement("menu"); - menu.appendChild(menuitem); - menu.appendChild(menupopup); - if (item.disabled) { - menu.setAttribute("disabled", "true"); - } - if (item.accesskey) { - menu.setAttribute("accesskey", item.accesskey); - } - if (item.id) { - menu.id = item.id; - } - parent.appendChild(menu); - } else if (item.type === "separator") { - let menusep = doc.createElement("menuseparator"); - parent.appendChild(menusep); - } else { - let menuitem = doc.createElement("menuitem"); - menuitem.setAttribute("label", item.label); - - if (!inToolbox()) { - menuitem.textContent = item.label; - } - - menuitem.addEventListener("command", () => item.click()); - - if (item.type === "checkbox") { - menuitem.setAttribute("type", "checkbox"); - } - if (item.type === "radio") { - menuitem.setAttribute("type", "radio"); - } - if (item.disabled) { - menuitem.setAttribute("disabled", "true"); - } - if (item.checked) { - menuitem.setAttribute("checked", "true"); - } - if (item.accesskey) { - menuitem.setAttribute("accesskey", item.accesskey); - } - if (item.id) { - menuitem.id = item.id; - } - - parent.appendChild(menuitem); - } - }); -}; - -Menu.setApplicationMenu = () => { - throw Error("Not implemented"); -}; - -Menu.sendActionToFirstResponder = () => { - throw Error("Not implemented"); -}; - -Menu.buildFromTemplate = () => { - throw Error("Not implemented"); -}; - -module.exports = Menu; - -/***/ }), - -/***/ 1465: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/Promise.jsm - */ - -/** - * Promise.jsm is mostly the Promise web API with a `defer` method. Just drop this in here, - * and use the native web API (although building with webpack/babel, it may replace this - * with it's own version if we want to target environments that do not have `Promise`. - */ - -let p = typeof window != "undefined" ? window.Promise : Promise; -p.defer = function defer() { - var resolve, reject; - var promise = new Promise(function () { - resolve = arguments[0]; - reject = arguments[1]; - }); - return { - resolve: resolve, - reject: reject, - promise: promise - }; -}; - -module.exports = p; - -/***/ }), - -/***/ 1466: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * A partial implementation of the MenuItem API provided by electron: - * https://github.com/electron/electron/blob/master/docs/api/menu-item.md. - * - * Missing features: - * - id String - Unique within a single menu. If defined then it can be used - * as a reference to this item by the position attribute. - * - role String - Define the action of the menu item; when specified the - * click property will be ignored - * - sublabel String - * - accelerator Accelerator - * - icon NativeImage - * - position String - This field allows fine-grained definition of the - * specific location within a given menu. - * - * Implemented features: - * @param Object options - * Function click - * Will be called with click(menuItem, browserWindow) when the menu item - * is clicked - * String type - * Can be normal, separator, submenu, checkbox or radio - * String label - * Boolean enabled - * If false, the menu item will be greyed out and unclickable. - * Boolean checked - * Should only be specified for checkbox or radio type menu items. - * Menu submenu - * Should be specified for submenu type menu items. If submenu is specified, - * the type: 'submenu' can be omitted. If the value is not a Menu then it - * will be automatically converted to one using Menu.buildFromTemplate. - * Boolean visible - * If false, the menu item will be entirely hidden. - */ -function MenuItem({ - accesskey = null, - checked = false, - click = () => {}, - disabled = false, - label = "", - id = null, - submenu = null, - type = "normal", - visible = true -} = {}) { - this.accesskey = accesskey; - this.checked = checked; - this.click = click; - this.disabled = disabled; - this.id = id; - this.label = label; - this.submenu = submenu; - this.type = type; - this.visible = visible; -} - -module.exports = MenuItem; - -/***/ }), - -/***/ 1467: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const Services = __webpack_require__(22); -const EventEmitter = __webpack_require__(1382); - -/** - * Shortcuts for lazily accessing and setting various preferences. - * Usage: - * let prefs = new Prefs("root.path.to.branch", { - * myIntPref: ["Int", "leaf.path.to.my-int-pref"], - * myCharPref: ["Char", "leaf.path.to.my-char-pref"], - * myJsonPref: ["Json", "leaf.path.to.my-json-pref"], - * myFloatPref: ["Float", "leaf.path.to.my-float-pref"] - * ... - * }); - * - * Get/set: - * prefs.myCharPref = "foo"; - * let aux = prefs.myCharPref; - * - * Observe: - * prefs.registerObserver(); - * prefs.on("pref-changed", (prefName, prefValue) => { - * ... - * }); - * - * @param string prefsRoot - * The root path to the required preferences branch. - * @param object prefsBlueprint - * An object containing { accessorName: [prefType, prefName, prefDefault] } keys. - */ -function PrefsHelper(prefsRoot = "", prefsBlueprint = {}) { - EventEmitter.decorate(this); - - let cache = new Map(); - - for (let accessorName in prefsBlueprint) { - let [prefType, prefName, prefDefault] = prefsBlueprint[accessorName]; - map(this, cache, accessorName, prefType, prefsRoot, prefName, prefDefault); - } - - let observer = makeObserver(this, cache, prefsRoot, prefsBlueprint); - this.registerObserver = () => observer.register(); - this.unregisterObserver = () => observer.unregister(); -} - -/** - * Helper method for getting a pref value. - * - * @param Map cache - * @param string prefType - * @param string prefsRoot - * @param string prefName - * @return any - */ -function get(cache, prefType, prefsRoot, prefName) { - let cachedPref = cache.get(prefName); - if (cachedPref !== undefined) { - return cachedPref; - } - let value = Services.prefs["get" + prefType + "Pref"]([prefsRoot, prefName].join(".")); - cache.set(prefName, value); - return value; -} - -/** - * Helper method for setting a pref value. - * - * @param Map cache - * @param string prefType - * @param string prefsRoot - * @param string prefName - * @param any value - */ -function set(cache, prefType, prefsRoot, prefName, value) { - Services.prefs["set" + prefType + "Pref"]([prefsRoot, prefName].join("."), value); - cache.set(prefName, value); -} - -/** - * Maps a property name to a pref, defining lazy getters and setters. - * Supported types are "Bool", "Char", "Int", "Float" (sugar around "Char" - * type and casting), and "Json" (which is basically just sugar for "Char" - * using the standard JSON serializer). - * - * @param PrefsHelper self - * @param Map cache - * @param string accessorName - * @param string prefType - * @param string prefsRoot - * @param string prefName - * @param string prefDefault - * @param array serializer [optional] - */ -function map(self, cache, accessorName, prefType, prefsRoot, prefName, prefDefault, serializer = { in: e => e, out: e => e }) { - if (prefName in self) { - throw new Error(`Can't use ${prefName} because it overrides a property` + "on the instance."); - } - if (prefType == "Json") { - map(self, cache, accessorName, "String", prefsRoot, prefName, prefDefault, { - in: JSON.parse, - out: JSON.stringify - }); - return; - } - if (prefType == "Float") { - map(self, cache, accessorName, "Char", prefsRoot, prefName, prefDefault, { - in: Number.parseFloat, - out: n => n + "" - }); - return; - } - - Object.defineProperty(self, accessorName, { - get: () => { - try { - return serializer.in(get(cache, prefType, prefsRoot, prefName)); - } catch (e) { - if (typeof prefDefault !== 'undefined') { - return prefDefault; - } - throw e; - } - }, - set: e => set(cache, prefType, prefsRoot, prefName, serializer.out(e)) - }); -} - -/** - * Finds the accessor for the provided pref, based on the blueprint object - * used in the constructor. - * - * @param PrefsHelper self - * @param object prefsBlueprint - * @return string - */ -function accessorNameForPref(somePrefName, prefsBlueprint) { - for (let accessorName in prefsBlueprint) { - let [, prefName] = prefsBlueprint[accessorName]; - if (somePrefName == prefName) { - return accessorName; - } - } - return ""; -} - -/** - * Creates a pref observer for `self`. - * - * @param PrefsHelper self - * @param Map cache - * @param string prefsRoot - * @param object prefsBlueprint - * @return object - */ -function makeObserver(self, cache, prefsRoot, prefsBlueprint) { - return { - register: function () { - this._branch = Services.prefs.getBranch(prefsRoot + "."); - this._branch.addObserver("", this); - }, - unregister: function () { - this._branch.removeObserver("", this); - }, - observe: function (subject, topic, prefName) { - // If this particular pref isn't handled by the blueprint object, - // even though it's in the specified branch, ignore it. - let accessorName = accessorNameForPref(prefName, prefsBlueprint); - if (!(accessorName in self)) { - return; - } - cache.delete(prefName); - self.emit("pref-changed", accessorName, self[accessorName]); - } - }; -} - -exports.PrefsHelper = PrefsHelper; - -/***/ }), - -/***/ 1468: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const { appinfo } = __webpack_require__(22); -const EventEmitter = __webpack_require__(1382); -const isOSX = appinfo.OS === "Darwin"; - -// List of electron keys mapped to DOM API (DOM_VK_*) key code -const ElectronKeysMapping = { - "F1": "DOM_VK_F1", - "F2": "DOM_VK_F2", - "F3": "DOM_VK_F3", - "F4": "DOM_VK_F4", - "F5": "DOM_VK_F5", - "F6": "DOM_VK_F6", - "F7": "DOM_VK_F7", - "F8": "DOM_VK_F8", - "F9": "DOM_VK_F9", - "F10": "DOM_VK_F10", - "F11": "DOM_VK_F11", - "F12": "DOM_VK_F12", - "F13": "DOM_VK_F13", - "F14": "DOM_VK_F14", - "F15": "DOM_VK_F15", - "F16": "DOM_VK_F16", - "F17": "DOM_VK_F17", - "F18": "DOM_VK_F18", - "F19": "DOM_VK_F19", - "F20": "DOM_VK_F20", - "F21": "DOM_VK_F21", - "F22": "DOM_VK_F22", - "F23": "DOM_VK_F23", - "F24": "DOM_VK_F24", - "Space": "DOM_VK_SPACE", - "Backspace": "DOM_VK_BACK_SPACE", - "Delete": "DOM_VK_DELETE", - "Insert": "DOM_VK_INSERT", - "Return": "DOM_VK_RETURN", - "Enter": "DOM_VK_RETURN", - "Up": "DOM_VK_UP", - "Down": "DOM_VK_DOWN", - "Left": "DOM_VK_LEFT", - "Right": "DOM_VK_RIGHT", - "Home": "DOM_VK_HOME", - "End": "DOM_VK_END", - "PageUp": "DOM_VK_PAGE_UP", - "PageDown": "DOM_VK_PAGE_DOWN", - "Escape": "DOM_VK_ESCAPE", - "Esc": "DOM_VK_ESCAPE", - "Tab": "DOM_VK_TAB", - "VolumeUp": "DOM_VK_VOLUME_UP", - "VolumeDown": "DOM_VK_VOLUME_DOWN", - "VolumeMute": "DOM_VK_VOLUME_MUTE", - "PrintScreen": "DOM_VK_PRINTSCREEN" -}; - -/** - * Helper to listen for keyboard events decribed in .properties file. - * - * let shortcuts = new KeyShortcuts({ - * window - * }); - * shortcuts.on("Ctrl+F", event => { - * // `event` is the KeyboardEvent which relates to the key shortcuts - * }); - * - * @param DOMWindow window - * The window object of the document to listen events from. - * @param DOMElement target - * Optional DOM Element on which we should listen events from. - * If omitted, we listen for all events fired on `window`. - */ -function KeyShortcuts({ window, target }) { - this.window = window; - this.target = target || window; - this.keys = new Map(); - this.eventEmitter = new EventEmitter(); - this.target.addEventListener("keydown", this); -} - -/* - * Parse an electron-like key string and return a normalized object which - * allow efficient match on DOM key event. The normalized object matches DOM - * API. - * - * @param DOMWindow window - * Any DOM Window object, just to fetch its `KeyboardEvent` object - * @param String str - * The shortcut string to parse, following this document: - * https://github.com/electron/electron/blob/master/docs/api/accelerator.md - */ -KeyShortcuts.parseElectronKey = function (window, str) { - let modifiers = str.split("+"); - let key = modifiers.pop(); - - let shortcut = { - ctrl: false, - meta: false, - alt: false, - shift: false, - // Set for character keys - key: undefined, - // Set for non-character keys - keyCode: undefined - }; - for (let mod of modifiers) { - if (mod === "Alt") { - shortcut.alt = true; - } else if (["Command", "Cmd"].includes(mod)) { - shortcut.meta = true; - } else if (["CommandOrControl", "CmdOrCtrl"].includes(mod)) { - if (isOSX) { - shortcut.meta = true; - } else { - shortcut.ctrl = true; - } - } else if (["Control", "Ctrl"].includes(mod)) { - shortcut.ctrl = true; - } else if (mod === "Shift") { - shortcut.shift = true; - } else { - console.error("Unsupported modifier:", mod, "from key:", str); - return null; - } - } - - // Plus is a special case. It's a character key and shouldn't be matched - // against a keycode as it is only accessible via Shift/Capslock - if (key === "Plus") { - key = "+"; - } - - if (typeof key === "string" && key.length === 1) { - // Match any single character - shortcut.key = key.toLowerCase(); - } else if (key in ElectronKeysMapping) { - // Maps the others manually to DOM API DOM_VK_* - key = ElectronKeysMapping[key]; - shortcut.keyCode = window.KeyboardEvent[key]; - // Used only to stringify the shortcut - shortcut.keyCodeString = key; - shortcut.key = key; - } else { - console.error("Unsupported key:", key); - return null; - } - - return shortcut; -}; - -KeyShortcuts.stringify = function (shortcut) { - let list = []; - if (shortcut.alt) { - list.push("Alt"); - } - if (shortcut.ctrl) { - list.push("Ctrl"); - } - if (shortcut.meta) { - list.push("Cmd"); - } - if (shortcut.shift) { - list.push("Shift"); - } - let key; - if (shortcut.key) { - key = shortcut.key.toUpperCase(); - } else { - key = shortcut.keyCodeString; - } - list.push(key); - return list.join("+"); -}; - -KeyShortcuts.prototype = { - destroy() { - this.target.removeEventListener("keydown", this); - this.keys.clear(); - }, - - doesEventMatchShortcut(event, shortcut) { - if (shortcut.meta != event.metaKey) { - return false; - } - if (shortcut.ctrl != event.ctrlKey) { - return false; - } - if (shortcut.alt != event.altKey) { - return false; - } - // Shift is a special modifier, it may implicitely be required if the - // expected key is a special character accessible via shift. - if (shortcut.shift != event.shiftKey && event.key && event.key.match(/[a-zA-Z]/)) { - return false; - } - if (shortcut.keyCode) { - return event.keyCode == shortcut.keyCode; - } else if (event.key in ElectronKeysMapping) { - return ElectronKeysMapping[event.key] === shortcut.key; - } - - // get the key from the keyCode if key is not provided. - let key = event.key || String.fromCharCode(event.keyCode); - - // For character keys, we match if the final character is the expected one. - // But for digits we also accept indirect match to please azerty keyboard, - // which requires Shift to be pressed to get digits. - return key.toLowerCase() == shortcut.key || shortcut.key.match(/^[0-9]$/) && event.keyCode == shortcut.key.charCodeAt(0); - }, - - handleEvent(event) { - for (let [key, shortcut] of this.keys) { - if (this.doesEventMatchShortcut(event, shortcut)) { - this.eventEmitter.emit(key, event); - } - } - }, - - on(key, listener) { - if (typeof listener !== "function") { - throw new Error("KeyShortcuts.on() expects a function as " + "second argument"); - } - if (!this.keys.has(key)) { - let shortcut = KeyShortcuts.parseElectronKey(this.window, key); - // The key string is wrong and we were unable to compute the key shortcut - if (!shortcut) { - return; - } - this.keys.set(key, shortcut); - } - this.eventEmitter.on(key, listener); - }, - - off(key, listener) { - this.eventEmitter.off(key, listener); - } -}; -module.exports = KeyShortcuts; - -/***/ }), - -/***/ 1469: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - - -/** - * Empty shim for "devtools/client/shared/zoom-keys" module - * - * Based on nsIMarkupDocumentViewer.fullZoom API - * https://developer.mozilla.org/en-US/Firefox/Releases/3/Full_page_zoom - */ - -exports.register = function (window) {}; - -/***/ }), - -/***/ 1499: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.onConnect = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _firefox = __webpack_require__(1500); - -var firefox = _interopRequireWildcard(_firefox); - -var _prefs = __webpack_require__(226); - -var _dbg = __webpack_require__(2246); - -var _bootstrap = __webpack_require__(1430); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function loadFromPrefs(actions) { - const { pauseOnExceptions, pauseOnCaughtExceptions } = _prefs.prefs; - if (pauseOnExceptions || pauseOnCaughtExceptions) { - return actions.pauseOnExceptions(pauseOnExceptions, pauseOnCaughtExceptions); - } -} - -async function onConnect(connection, { services, toolboxActions }) { - // NOTE: the landing page does not connect to a JS process - if (!connection) { - return; - } - - const commands = firefox.clientCommands; - const { store, actions, selectors } = (0, _bootstrap.bootstrapStore)(commands, { - services, - toolboxActions - }); - - const workers = (0, _bootstrap.bootstrapWorkers)(); - await firefox.onConnect(connection, actions); - await loadFromPrefs(actions); - - (0, _dbg.setupHelper)({ - store, - actions, - selectors, - workers: _extends({}, workers, services), - connection, - client: firefox.clientCommands - }); - - (0, _bootstrap.bootstrapApp)(store); - return { store, actions, selectors, client: commands }; -} - -exports.onConnect = onConnect; - -/***/ }), - -/***/ 1500: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.clientEvents = exports.clientCommands = exports.createObjectClient = undefined; -exports.onConnect = onConnect; - -var _commands = __webpack_require__(1501); - -var _events = __webpack_require__(1506); - -var _prefs = __webpack_require__(226); - -let DebuggerClient; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function createObjectClient(grip) { - return DebuggerClient.createObjectClient(grip); -} - -async function onConnect(connection, actions) { - const { - tabConnection: { tabTarget, threadClient, debuggerClient } - } = connection; - - DebuggerClient = debuggerClient; - - if (!tabTarget || !threadClient || !debuggerClient) { - return { bpClients: {} }; - } - - const supportsWasm = _prefs.features.wasm && !!debuggerClient.mainRoot.traits.wasmBinarySource; - - const { bpClients } = (0, _commands.setupCommands)({ - threadClient, - tabTarget, - debuggerClient, - supportsWasm - }); - - if (actions) { - (0, _events.setupEvents)({ threadClient, actions, supportsWasm }); - } - - tabTarget.on("will-navigate", actions.willNavigate); - tabTarget.on("navigate", actions.navigated); - - await threadClient.reconfigure({ - observeAsmJS: true, - wasmBinarySource: supportsWasm - }); - - // In Firefox, we need to initially request all of the sources. This - // usually fires off individual `newSource` notifications as the - // debugger finds them, but there may be existing sources already in - // the debugger (if it's paused already, or if loading the page from - // bfcache) so explicity fire `newSource` events for all returned - // sources. - const sources = await _commands.clientCommands.fetchSources(); - const traits = tabTarget.activeTab ? tabTarget.activeTab.traits : null; - await actions.connect(tabTarget.url, traits && traits.canRewind); - await actions.newSources(sources); - - // If the threadClient is already paused, make sure to show a - // paused state. - const pausedPacket = threadClient.getLastPausePacket(); - if (pausedPacket) { - _events.clientEvents.paused("paused", pausedPacket); - } - - return { bpClients }; -} - -exports.createObjectClient = createObjectClient; -exports.clientCommands = _commands.clientCommands; -exports.clientEvents = _events.clientEvents; - -/***/ }), - -/***/ 1501: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.clientCommands = exports.setupCommands = undefined; - -var _breakpoint = __webpack_require__(1364); - -var _create = __webpack_require__(1428); - -var _frontsDevice = __webpack_require__(3626); - -var _devtoolsModules = __webpack_require__(1376); - -let bpClients; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -let threadClient; -let tabTarget; -let debuggerClient; -let supportsWasm; - -function setupCommands(dependencies) { - threadClient = dependencies.threadClient; - tabTarget = dependencies.tabTarget; - debuggerClient = dependencies.debuggerClient; - supportsWasm = dependencies.supportsWasm; - bpClients = {}; - - return { bpClients }; -} - -function sendPacket(packet, callback = r => r) { - return debuggerClient.request(packet).then(callback); -} - -function resume() { - return new Promise(resolve => { - threadClient.resume(resolve); - }); -} - -function stepIn() { - return new Promise(resolve => { - threadClient.stepIn(resolve); - }); -} - -function stepOver() { - return new Promise(resolve => { - threadClient.stepOver(resolve); - }); -} - -function stepOut() { - return new Promise(resolve => { - threadClient.stepOut(resolve); - }); -} - -function rewind() { - return new Promise(resolve => { - threadClient.rewind(resolve); - }); -} - -function reverseStepIn() { - return new Promise(resolve => { - threadClient.reverseStepIn(resolve); - }); -} - -function reverseStepOver() { - return new Promise(resolve => { - threadClient.reverseStepOver(resolve); - }); -} - -function reverseStepOut() { - return new Promise(resolve => { - threadClient.reverseStepOut(resolve); - }); -} - -function breakOnNext() { - return threadClient.breakOnNext(); -} - -function sourceContents(sourceId) { - const sourceClient = threadClient.source({ actor: sourceId }); - return sourceClient.source(); -} - -function getBreakpointByLocation(location) { - const id = (0, _breakpoint.makePendingLocationId)(location); - const bpClient = bpClients[id]; - - if (bpClient) { - const { actor, url, line, column, condition } = bpClient.location; - return { - id: bpClient.actor, - condition, - actualLocation: { - line, - column, - sourceId: actor, - sourceUrl: url - } - }; - } - return null; -} - -function setBreakpoint(location, condition, noSliding) { - const sourceClient = threadClient.source({ actor: location.sourceId }); - - return sourceClient.setBreakpoint({ - line: location.line, - column: location.column, - condition, - noSliding - }).then(([{ actualLocation }, bpClient]) => { - actualLocation = (0, _create.createBreakpointLocation)(location, actualLocation); - const id = (0, _breakpoint.makePendingLocationId)(actualLocation); - bpClients[id] = bpClient; - bpClient.location.line = actualLocation.line; - bpClient.location.column = actualLocation.column; - bpClient.location.url = actualLocation.sourceUrl || ""; - - return { id, actualLocation }; - }); -} - -function removeBreakpoint(generatedLocation) { - try { - const id = (0, _breakpoint.makePendingLocationId)(generatedLocation); - const bpClient = bpClients[id]; - if (!bpClient) { - console.warn("No breakpoint to delete on server"); - return Promise.resolve(); - } - delete bpClients[id]; - return bpClient.remove(); - } catch (_error) { - console.warn("No breakpoint to delete on server"); - } -} - -function setBreakpointCondition(breakpointId, location, condition, noSliding) { - const bpClient = bpClients[breakpointId]; - delete bpClients[breakpointId]; - - return bpClient.setCondition(threadClient, condition, noSliding).then(_bpClient => { - bpClients[breakpointId] = _bpClient; - return { id: breakpointId }; - }); -} - -async function evaluateInFrame(script, frameId) { - return evaluate(script, { frameId }); -} - -async function evaluateExpressions(scripts, frameId) { - return Promise.all(scripts.map(script => evaluate(script, { frameId }))); -} - -function evaluate(script, { frameId } = {}) { - const params = frameId ? { frameActor: frameId } : {}; - if (!tabTarget || !tabTarget.activeConsole || !script) { - return Promise.resolve({}); - } - - return new Promise(resolve => { - tabTarget.activeConsole.evaluateJSAsync(script, result => resolve(result), params); - }); -} - -function autocomplete(input, cursor, frameId) { - if (!tabTarget || !tabTarget.activeConsole || !input) { - return Promise.resolve({}); - } - return new Promise(resolve => { - tabTarget.activeConsole.autocomplete(input, cursor, result => resolve(result), frameId); - }); -} - -function debuggeeCommand(script) { - tabTarget.activeConsole.evaluateJS(script, () => {}, {}); - - if (!debuggerClient) { - return; - } - - const consoleActor = tabTarget.form.consoleActor; - const request = debuggerClient._activeRequests.get(consoleActor); - request.emit("json-reply", {}); - debuggerClient._activeRequests.delete(consoleActor); - - return Promise.resolve(); -} - -function navigate(url) { - return tabTarget.activeTab.navigateTo(url); -} - -function reload() { - return tabTarget.activeTab.reload(); -} - -function getProperties(grip) { - const objClient = threadClient.pauseGrip(grip); - - return objClient.getPrototypeAndProperties().then(resp => { - const { ownProperties, safeGetterValues } = resp; - for (const name in safeGetterValues) { - const { enumerable, writable, getterValue } = safeGetterValues[name]; - ownProperties[name] = { enumerable, writable, value: getterValue }; - } - return resp; - }); -} - -async function getFrameScopes(frame) { - if (frame.scope) { - return frame.scope; - } - - return threadClient.getEnvironment(frame.id); -} - -function pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) { - return threadClient.pauseOnExceptions(shouldPauseOnExceptions, - // Providing opposite value because server - // uses "shouldIgnoreCaughtExceptions" - !shouldPauseOnCaughtExceptions); -} - -function prettyPrint(sourceId, indentSize) { - const sourceClient = threadClient.source({ actor: sourceId }); - return sourceClient.prettyPrint(indentSize); -} - -async function blackBox(sourceId, isBlackBoxed) { - const sourceClient = threadClient.source({ actor: sourceId }); - if (isBlackBoxed) { - await sourceClient.unblackBox(); - } else { - await sourceClient.blackBox(); - } - - return { isBlackBoxed: !isBlackBoxed }; -} - -function disablePrettyPrint(sourceId) { - const sourceClient = threadClient.source({ actor: sourceId }); - return sourceClient.disablePrettyPrint(); -} - -async function setPausePoints(sourceId, pausePoints) { - return sendPacket({ to: sourceId, type: "setPausePoints", pausePoints }); -} - -async function setSkipPausing(shouldSkip) { - return threadClient.request({ - skip: shouldSkip, - to: threadClient.actor, - type: "skipPausing" - }); -} - -function interrupt() { - return threadClient.interrupt(); -} - -function eventListeners() { - return threadClient.eventListeners(); -} - -function pauseGrip(func) { - return threadClient.pauseGrip(func); -} - -async function fetchSources() { - const { sources } = await threadClient.getSources(); - return sources.map(source => (0, _create.createSource)(source, { supportsWasm })); -} - -/** - * Temporary helper to check if the current server will support a call to - * listWorkers. On Fennec 60 or older, the call will silently crash and prevent - * the client from resuming. - * XXX: Remove when FF60 for Android is no longer used or available. - * - * See https://bugzilla.mozilla.org/show_bug.cgi?id=1443550 for more details. - */ -async function checkServerSupportsListWorkers() { - const root = await tabTarget.root; - // root is not available on all debug targets. - if (!root) { - return false; - } - - const deviceFront = await (0, _frontsDevice.getDeviceFront)(debuggerClient, root); - const description = await deviceFront.getDescription(); - - const isFennec = description.apptype === "mobile/android"; - if (!isFennec) { - // Explicitly return true early to avoid calling Services.vs.compare. - // This would force us to extent the Services shim provided by - // devtools-modules, used when this code runs in a tab. - return true; - } - - // We are only interested in Fennec release versions here. - // We assume that the server fix for Bug 1443550 will land in FF61. - const version = description.platformversion; - return _devtoolsModules.Services.vc.compare(version, "61.0") >= 0; -} - -async function fetchWorkers() { - // Temporary workaround for Bug 1443550 - // XXX: Remove when FF60 for Android is no longer used or available. - const supportsListWorkers = await checkServerSupportsListWorkers(); - - // NOTE: The Worker and Browser Content toolboxes do not have a parent - // with a listWorkers function - // TODO: there is a listWorkers property, but it is not a function on the - // parent. Investigate what it is - if (!threadClient._parent || typeof threadClient._parent.listWorkers != "function" || !supportsListWorkers) { - return Promise.resolve({ workers: [] }); - } - - return threadClient._parent.listWorkers(); -} - -const clientCommands = { - autocomplete, - blackBox, - interrupt, - eventListeners, - pauseGrip, - resume, - stepIn, - stepOut, - stepOver, - rewind, - reverseStepIn, - reverseStepOut, - reverseStepOver, - breakOnNext, - sourceContents, - getBreakpointByLocation, - setBreakpoint, - removeBreakpoint, - setBreakpointCondition, - evaluate, - evaluateInFrame, - evaluateExpressions, - debuggeeCommand, - navigate, - reload, - getProperties, - getFrameScopes, - pauseOnExceptions, - prettyPrint, - disablePrettyPrint, - fetchSources, - fetchWorkers, - sendPacket, - setPausePoints, - setSkipPausing -}; - -exports.setupCommands = setupCommands; -exports.clientCommands = clientCommands; - -/***/ }), - -/***/ 1502: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _lodash = __webpack_require__(2); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -// hasOwnProperty is defensive because it is possible that the -// object that we're creating a map for has a `hasOwnProperty` field -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Immutable JS conversion utils - * @deprecated - * @module utils/fromJS - */ - -function hasOwnProperty(value, key) { - if (value.hasOwnProperty && (0, _lodash.isFunction)(value.hasOwnProperty)) { - return value.hasOwnProperty(key); - } - - if (value.prototype && value.prototype.hasOwnProperty) { - return value.prototype.hasOwnProperty(key); - } - - return false; -} - -/* - creates an immutable map, where each of the value's - items are transformed into their own map. - - NOTE: we guard against `length` being a property because - length confuses Immutable's internal algorithm. -*/ -function createMap(value) { - const hasLength = hasOwnProperty(value, "length"); - const length = value.length; - - if (hasLength) { - value.length = `${value.length}`; - } - - let map = I.Seq(value).map(fromJS).toMap(); - - if (hasLength) { - map = map.set("length", length); - value.length = length; - } - - return map; -} - -function createList(value) { - return I.Seq(value).map(fromJS).toList(); -} - -/** - * When our app state is fully typed, we should be able to get rid of - * this function. This is only temporarily necessary to support - * converting typed objects to immutable.js, which usually happens in - * reducers. - * - * @memberof utils/fromJS - * @static - */ -function fromJS(value) { - if (Array.isArray(value)) { - return createList(value); - } - if (value && value.constructor && value.constructor.meta) { - // This adds support for tcomb objects which are native JS objects - // but are not "plain", so the above checks fail. Since they - // behave the same we can use the same constructors, but we need - // special checks for them. - const kind = value.constructor.meta.kind; - if (kind === "struct") { - return createMap(value); - } else if (kind === "list") { - return createList(value); - } - } - - // If it's a primitive type, just return the value. Note `==` check - // for null, which is intentionally used to match either `null` or - // `undefined`. - if (value == null || typeof value !== "object") { - return value; - } - - // Otherwise, treat it like an object. We can't reliably detect if - // it's a plain object because we might be objects from other JS - // contexts so `Object !== Object`. - - return createMap(value); -} - -module.exports = fromJS; - -/***/ }), - -/***/ 1503: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getBreakpointAtLocation = getBreakpointAtLocation; - -var _sources = __webpack_require__(1369); - -var _breakpoints = __webpack_require__(1378); - -var _devtoolsSourceMap = __webpack_require__(3646); - -function isGenerated(selectedSource) { - const sourceId = selectedSource.get("id"); - return (0, _devtoolsSourceMap.isGeneratedId)(sourceId); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getColumn(column, selectedSource) { - if (column) { - return column; - } - - return isGenerated(selectedSource) ? undefined : 0; -} - -function getLocation(bp, selectedSource) { - return isGenerated(selectedSource) ? bp.generatedLocation || bp.location : bp.location; -} - -function getBreakpointsForSource(state, selectedSource) { - const breakpoints = (0, _breakpoints.getBreakpoints)(state); - - return breakpoints.filter(bp => { - const location = getLocation(bp, selectedSource); - return location.sourceId === selectedSource.get("id"); - }); -} - -function findBreakpointAtLocation(breakpoints, selectedSource, { line, column }) { - return breakpoints.find(breakpoint => { - const location = getLocation(breakpoint, selectedSource); - const sameLine = location.line === line; - if (!sameLine) { - return false; - } - - if (column === undefined) { - return true; - } - - return location.column === getColumn(column, selectedSource); - }); -} - -/* - * Finds a breakpoint at a location (line, column) of the - * selected source. - * - * This is useful for finding a breakpoint when the - * user clicks in the gutter or on a token. - */ -function getBreakpointAtLocation(state, location) { - const selectedSource = (0, _sources.getSelectedSource)(state); - const breakpoints = getBreakpointsForSource(state, selectedSource); - - return findBreakpointAtLocation(breakpoints, selectedSource, location); -} - -/***/ }), - -/***/ 1505: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isSelectedFrameVisible = isSelectedFrameVisible; - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _pause = __webpack_require__(1394); - -var _sources = __webpack_require__(1369); - -function getGeneratedId(sourceId) { - if ((0, _devtoolsSourceMap.isOriginalId)(sourceId)) { - return (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId); - } - - return sourceId; -} - -/* - * Checks to if the selected frame's source is currently - * selected. - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function isSelectedFrameVisible(state) { - const selectedLocation = (0, _sources.getSelectedLocation)(state); - const selectedFrame = (0, _pause.getSelectedFrame)(state); - - if (!selectedFrame || !selectedLocation) { - return false; - } - - if ((0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId)) { - return selectedLocation.sourceId === selectedFrame.location.sourceId; - } - - return selectedLocation.sourceId === getGeneratedId(selectedFrame.location.sourceId); -} - -/***/ }), - -/***/ 1506: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.clientEvents = exports.setupEvents = undefined; - -var _create = __webpack_require__(1428); - -var _sourceQueue = __webpack_require__(1795); - -var _sourceQueue2 = _interopRequireDefault(_sourceQueue); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const CALL_STACK_PAGE_SIZE = 1000; - -let threadClient; -let actions; -let supportsWasm; -let isInterrupted; - -function setupEvents(dependencies) { - threadClient = dependencies.threadClient; - actions = dependencies.actions; - supportsWasm = dependencies.supportsWasm; - _sourceQueue2.default.initialize({ actions, supportsWasm, createSource: _create.createSource }); - - if (threadClient) { - Object.keys(clientEvents).forEach(eventName => { - threadClient.addListener(eventName, clientEvents[eventName]); - }); - - if (threadClient._parent) { - threadClient._parent.addListener("workerListChanged", workerListChanged); - } - } -} - -async function paused(_, packet) { - // If paused by an explicit interrupt, which are generated by the - // slow script dialog and internal events such as setting - // breakpoints, ignore the event. - const { why } = packet; - if (why.type === "interrupted" && !packet.why.onNext) { - isInterrupted = true; - return; - } - - // Eagerly fetch the frames - const response = await threadClient.getFrames(0, CALL_STACK_PAGE_SIZE); - - if (why.type != "alreadyPaused") { - const pause = (0, _create.createPause)(packet, response); - await _sourceQueue2.default.flush(); - actions.paused(pause); - } -} - -function resumed(_, packet) { - // NOTE: the client suppresses resumed events while interrupted - // to prevent unintentional behavior. - // see [client docs](../README.md#interrupted) for more information. - if (isInterrupted) { - isInterrupted = false; - return; - } - - actions.resumed(packet); -} - -function newSource(_, { source }) { - _sourceQueue2.default.queue(source); - - if (_prefs.features.eventListeners) { - actions.fetchEventListeners(); - } -} - -function workerListChanged() { - actions.updateWorkers(); -} - -const clientEvents = { - paused, - resumed, - newSource -}; - -exports.setupEvents = setupEvents; -exports.clientEvents = clientEvents; - -/***/ }), - -/***/ 1516: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _expressions = __webpack_require__(1417); - -var _expressions2 = _interopRequireDefault(_expressions); - -var _eventListeners = __webpack_require__(1420); - -var _eventListeners2 = _interopRequireDefault(_eventListeners); - -var _sources = __webpack_require__(1369); - -var _sources2 = _interopRequireDefault(_sources); - -var _breakpoints = __webpack_require__(1378); - -var _breakpoints2 = _interopRequireDefault(_breakpoints); - -var _pendingBreakpoints = __webpack_require__(1419); - -var _pendingBreakpoints2 = _interopRequireDefault(_pendingBreakpoints); - -var _asyncRequests = __webpack_require__(1517); - -var _asyncRequests2 = _interopRequireDefault(_asyncRequests); - -var _pause = __webpack_require__(1394); - -var _pause2 = _interopRequireDefault(_pause); - -var _ui = __webpack_require__(1421); - -var _ui2 = _interopRequireDefault(_ui); - -var _fileSearch = __webpack_require__(1422); - -var _fileSearch2 = _interopRequireDefault(_fileSearch); - -var _ast = __webpack_require__(1383); - -var _ast2 = _interopRequireDefault(_ast); - -var _coverage = __webpack_require__(1423); - -var _coverage2 = _interopRequireDefault(_coverage); - -var _projectTextSearch = __webpack_require__(1424); - -var _projectTextSearch2 = _interopRequireDefault(_projectTextSearch); - -var _replay = __webpack_require__(2342); - -var _replay2 = _interopRequireDefault(_replay); - -var _quickOpen = __webpack_require__(1635); - -var _quickOpen2 = _interopRequireDefault(_quickOpen); - -var _sourceTree = __webpack_require__(1426); - -var _sourceTree2 = _interopRequireDefault(_sourceTree); - -var _debuggee = __webpack_require__(1418); - -var _debuggee2 = _interopRequireDefault(_debuggee); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Reducer index - * @module reducers/index - */ - -exports.default = { - expressions: _expressions2.default, - eventListeners: _eventListeners2.default, - sources: _sources2.default, - breakpoints: _breakpoints2.default, - pendingBreakpoints: _pendingBreakpoints2.default, - asyncRequests: _asyncRequests2.default, - pause: _pause2.default, - ui: _ui2.default, - fileSearch: _fileSearch2.default, - ast: _ast2.default, - coverage: _coverage2.default, - projectTextSearch: _projectTextSearch2.default, - replay: _replay2.default, - quickOpen: _quickOpen2.default, - sourceTree: _sourceTree2.default, - debuggee: _debuggee2.default -}; - -/***/ }), - -/***/ 1517: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Async request reducer - * @module reducers/async-request - */ - -const initialAsyncRequestState = []; - -function update(state = initialAsyncRequestState, action) { - const { seqId } = action; - - if (action.type === "NAVIGATE") { - return initialAsyncRequestState; - } else if (seqId) { - let newState; - if (action.status === "start") { - newState = [...state, seqId]; - } else if (action.status === "error" || action.status === "done") { - newState = state.filter(id => id !== seqId); - } - - return newState; - } - - return state; -} - -exports.default = update; - -/***/ }), - -/***/ 1518: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _prefs = __webpack_require__(226); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _ShortcutsModal = __webpack_require__(1535); - -var _selectors = __webpack_require__(3590); - -var _devtoolsModules = __webpack_require__(1376); - -__webpack_require__(1305); - -__webpack_require__(1306); - -__webpack_require__(1302); - -__webpack_require__(1307); - -__webpack_require__(1308); - -var _devtoolsSplitter = __webpack_require__(1440); - -var _devtoolsSplitter2 = _interopRequireDefault(_devtoolsSplitter); - -var _ProjectSearch = __webpack_require__(2009); - -var _ProjectSearch2 = _interopRequireDefault(_ProjectSearch); - -var _PrimaryPanes = __webpack_require__(1551); - -var _PrimaryPanes2 = _interopRequireDefault(_PrimaryPanes); - -var _Editor = __webpack_require__(1554); - -var _Editor2 = _interopRequireDefault(_Editor); - -var _SecondaryPanes = __webpack_require__(1599); - -var _SecondaryPanes2 = _interopRequireDefault(_SecondaryPanes); - -var _WelcomeBox = __webpack_require__(1613); - -var _WelcomeBox2 = _interopRequireDefault(_WelcomeBox); - -var _Tabs = __webpack_require__(1614); - -var _Tabs2 = _interopRequireDefault(_Tabs); - -var _QuickOpenModal = __webpack_require__(1652); - -var _QuickOpenModal2 = _interopRequireDefault(_QuickOpenModal); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const shortcuts = new _devtoolsModules.KeyShortcuts({ window }); - -const { appinfo } = _devtoolsModules.Services; - -const isMacOS = appinfo.OS === "Darwin"; - -const horizontalLayoutBreakpoint = window.matchMedia("(min-width: 800px)"); -const verticalLayoutBreakpoint = window.matchMedia("(min-width: 10px) and (max-width: 800px)"); - -class App extends _react.Component { - - constructor(props) { - super(props); - - this.getChildContext = () => { - return { shortcuts }; - }; - - this.onEscape = (_, e) => { - const { - activeSearch, - closeActiveSearch, - closeQuickOpen, - quickOpenEnabled - } = this.props; - - if (activeSearch) { - e.preventDefault(); - closeActiveSearch(); - } - - if (quickOpenEnabled) { - e.preventDefault(); - closeQuickOpen(); - } - }; - - this.onCommandSlash = () => { - this.toggleShortcutsModal(); - }; - - this.toggleQuickOpenModal = (_, e, query) => { - const { quickOpenEnabled, openQuickOpen, closeQuickOpen } = this.props; - - e.preventDefault(); - e.stopPropagation(); - - if (quickOpenEnabled === true) { - closeQuickOpen(); - return; - } - - if (query != null) { - openQuickOpen(query); - return; - } - openQuickOpen(); - return; - }; - - this.onLayoutChange = () => { - this.setOrientation(); - }; - - this.renderEditorPane = () => { - const { startPanelCollapsed, endPanelCollapsed } = this.props; - const { endPanelSize, startPanelSize } = this.state; - const horizontal = this.isHorizontal(); - - return _react2.default.createElement( - "div", - { className: "editor-pane" }, - _react2.default.createElement( - "div", - { className: "editor-container" }, - _react2.default.createElement(_Tabs2.default, { - startPanelCollapsed: startPanelCollapsed, - endPanelCollapsed: endPanelCollapsed, - horizontal: horizontal, - startPanelSize: startPanelSize, - endPanelSize: endPanelSize - }), - _react2.default.createElement(_Editor2.default, { - horizontal: horizontal, - startPanelSize: startPanelSize, - endPanelSize: endPanelSize - }), - !this.props.selectedSource ? _react2.default.createElement(_WelcomeBox2.default, { horizontal: horizontal }) : null, - _react2.default.createElement(_ProjectSearch2.default, null) - ) - ); - }; - - this.renderLayout = () => { - const { startPanelCollapsed, endPanelCollapsed } = this.props; - const horizontal = this.isHorizontal(); - - const maxSize = horizontal ? "70%" : "95%"; - const primaryInitialSize = horizontal ? "250px" : "150px"; - - return _react2.default.createElement(_devtoolsSplitter2.default, { - style: { width: "100vw" }, - initialHeight: 400, - initialWidth: 300, - minSize: 30, - maxSize: maxSize, - splitterSize: 1, - vert: horizontal, - startPanel: _react2.default.createElement(_devtoolsSplitter2.default, { - style: { width: "100vw" }, - initialSize: primaryInitialSize, - minSize: 30, - maxSize: "85%", - splitterSize: 1, - startPanelCollapsed: startPanelCollapsed, - startPanel: _react2.default.createElement(_PrimaryPanes2.default, { horizontal: horizontal }), - endPanel: this.renderEditorPane() - }), - endPanelControl: true, - endPanel: _react2.default.createElement(_SecondaryPanes2.default, { - horizontal: horizontal, - toggleShortcutsModal: () => this.toggleShortcutsModal() - }), - endPanelCollapsed: endPanelCollapsed - }); - }; - - this.state = { - shortcutsModalEnabled: false, - startPanelSize: 0, - endPanelSize: 0 - }; - } - - componentDidMount() { - horizontalLayoutBreakpoint.addListener(this.onLayoutChange); - verticalLayoutBreakpoint.addListener(this.onLayoutChange); - this.setOrientation(); - - shortcuts.on(L10N.getStr("symbolSearch.search.key2"), (_, e) => this.toggleQuickOpenModal(_, e, "@")); - - const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")]; - searchKeys.forEach(key => shortcuts.on(key, this.toggleQuickOpenModal)); - - shortcuts.on(L10N.getStr("gotoLineModal.key2"), (_, e) => this.toggleQuickOpenModal(_, e, ":")); - - shortcuts.on("Escape", this.onEscape); - shortcuts.on("Cmd+/", this.onCommandSlash); - } - - componentWillUnmount() { - horizontalLayoutBreakpoint.removeListener(this.onLayoutChange); - verticalLayoutBreakpoint.removeListener(this.onLayoutChange); - shortcuts.off(L10N.getStr("symbolSearch.search.key2"), this.toggleQuickOpenModal); - - const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")]; - searchKeys.forEach(key => shortcuts.off(key, this.toggleQuickOpenModal)); - - shortcuts.off(L10N.getStr("gotoLineModal.key2"), this.toggleQuickOpenModal); - - shortcuts.off("Escape", this.onEscape); - } - - isHorizontal() { - return this.props.orientation === "horizontal"; - } - - setOrientation() { - // If the orientation does not match (if it is not visible) it will - // not setOrientation, or if it is the same as before, calling - // setOrientation will not cause a rerender. - if (horizontalLayoutBreakpoint.matches) { - this.props.setOrientation("horizontal"); - } else if (verticalLayoutBreakpoint.matches) { - this.props.setOrientation("vertical"); - } - } - - toggleShortcutsModal() { - this.setState(prevState => ({ - shortcutsModalEnabled: !prevState.shortcutsModalEnabled - })); - } - - renderShortcutsModal() { - const additionalClass = isMacOS ? "mac" : ""; - - if (!_prefs.features.shortcuts) { - return; - } - - return _react2.default.createElement(_ShortcutsModal.ShortcutsModal, { - additionalClass: additionalClass, - enabled: this.state.shortcutsModalEnabled, - handleClose: () => this.toggleShortcutsModal() - }); - } - - render() { - const { quickOpenEnabled } = this.props; - return _react2.default.createElement( - "div", - { className: "debugger" }, - this.renderLayout(), - quickOpenEnabled === true && _react2.default.createElement(_QuickOpenModal2.default, { - shortcutsModalEnabled: this.state.shortcutsModalEnabled, - toggleShortcutsModal: () => this.toggleShortcutsModal() - }), - this.renderShortcutsModal() - ); - } -} - -App.childContextTypes = { shortcuts: _propTypes2.default.object }; - -const mapStateToProps = state => ({ - selectedSource: (0, _selectors.getSelectedSource)(state), - startPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "start"), - endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end"), - activeSearch: (0, _selectors.getActiveSearch)(state), - quickOpenEnabled: (0, _selectors.getQuickOpenEnabled)(state), - orientation: (0, _selectors.getOrientation)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(App); - -/***/ }), - -/***/ 1519: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _breakpoint = __webpack_require__(1364); - -var _selectors = __webpack_require__(3590); - -var _sourceMaps = __webpack_require__(1397); - -var _source = __webpack_require__(1356); - -exports.default = async function addBreakpoint(getState, client, sourceMaps, breakpoint) { - const state = getState(); - const source = (0, _selectors.getSource)(state, breakpoint.location.sourceId); - - const location = _extends({}, breakpoint.location, { sourceUrl: source.url }); - const generatedLocation = await (0, _sourceMaps.getGeneratedLocation)(state, source, location, sourceMaps); - - const generatedSource = (0, _selectors.getSource)(state, generatedLocation.sourceId); - - (0, _breakpoint.assertLocation)(location); - (0, _breakpoint.assertLocation)(generatedLocation); - - if ((0, _breakpoint.breakpointExists)(state, location)) { - const newBreakpoint = _extends({}, breakpoint, { location, generatedLocation }); - (0, _breakpoint.assertBreakpoint)(newBreakpoint); - return { breakpoint: newBreakpoint }; - } - - const { id, hitCount, actualLocation } = await client.setBreakpoint(generatedLocation, breakpoint.condition, sourceMaps.isOriginalId(location.sourceId)); - - const newGeneratedLocation = actualLocation || generatedLocation; - const newLocation = await sourceMaps.getOriginalLocation(newGeneratedLocation); - - const symbols = (0, _selectors.getSymbols)(getState(), source); - const astLocation = await (0, _breakpoint.getASTLocation)(source, symbols, newLocation); - - const originalText = (0, _source.getTextAtPosition)(source, location); - const text = (0, _source.getTextAtPosition)(generatedSource, actualLocation); - - const newBreakpoint = { - id, - disabled: false, - hidden: breakpoint.hidden, - loading: false, - condition: breakpoint.condition, - location: newLocation, - astLocation, - hitCount, - generatedLocation: newGeneratedLocation, - text, - originalText - }; - - (0, _breakpoint.assertBreakpoint)(newBreakpoint); - - const previousLocation = (0, _breakpoint.locationMoved)(location, newLocation) ? location : null; - - return { - breakpoint: newBreakpoint, - previousLocation - }; -}; - -/***/ }), - -/***/ 1520: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -exports.default = remapLocations; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function remapLocations(breakpoints, sourceId, sourceMaps) { - const sourceBreakpoints = breakpoints.map(async breakpoint => { - if (breakpoint.location.sourceId !== sourceId) { - return breakpoint; - } - const location = await sourceMaps.getOriginalLocation(breakpoint.location); - return _extends({}, breakpoint, { location }); - }); - - return Promise.all(sourceBreakpoints.valueSeq()); -} - -/***/ }), - -/***/ 1521: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.syncClientBreakpoint = syncClientBreakpoint; - -var _breakpoint = __webpack_require__(1364); - -var _sourceMaps = __webpack_require__(1397); - -var _source = __webpack_require__(1356); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _selectors = __webpack_require__(3590); - -async function makeScopedLocation({ name, offset }, location, source) { - const scope = await (0, _breakpoint.findScopeByName)(source, name); - // fallback onto the location line, if the scope is not found - // note: we may at some point want to delete the breakpoint if the scope - // disappears - const line = scope ? scope.location.start.line + offset.line : location.line; - return { - line, - column: location.column, - sourceUrl: source.url, - sourceId: source.id - }; -} - -function createSyncData(id, pendingBreakpoint, location, generatedLocation, previousLocation, text, originalText) { - const overrides = _extends({}, pendingBreakpoint, { - generatedLocation, - id, - text, - originalText - }); - const breakpoint = (0, _breakpoint.createBreakpoint)(location, overrides); - - (0, _breakpoint.assertBreakpoint)(breakpoint); - return { breakpoint, previousLocation }; -} - -// we have three forms of syncing: disabled syncing, existing server syncing -// and adding a new breakpoint -async function syncClientBreakpoint(getState, client, sourceMaps, sourceId, pendingBreakpoint) { - (0, _breakpoint.assertPendingBreakpoint)(pendingBreakpoint); - - const source = (0, _selectors.getSource)(getState(), sourceId); - - const generatedSourceId = sourceMaps.isOriginalId(sourceId) ? (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId) : sourceId; - - const generatedSource = (0, _selectors.getSource)(getState(), generatedSourceId); - - const { location, astLocation } = pendingBreakpoint; - const previousLocation = _extends({}, location, { sourceId }); - - const scopedLocation = await makeScopedLocation(astLocation, previousLocation, source); - - const scopedGeneratedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source, scopedLocation, sourceMaps); - - // this is the generatedLocation of the pending breakpoint, with - // the source id updated to reflect the new connection - const generatedLocation = _extends({}, pendingBreakpoint.generatedLocation, { - sourceId: generatedSourceId - }); - - const isSameLocation = !(0, _breakpoint.locationMoved)(generatedLocation, scopedGeneratedLocation); - - const existingClient = client.getBreakpointByLocation(generatedLocation); - - /** ******* CASE 1: No server change ***********/ - // early return if breakpoint is disabled or we are in the sameLocation - // send update only to redux - if (pendingBreakpoint.disabled || existingClient && isSameLocation) { - const id = pendingBreakpoint.disabled ? "" : existingClient.id; - const originalText = (0, _source.getTextAtPosition)(source, previousLocation); - const text = (0, _source.getTextAtPosition)(generatedSource, generatedLocation); - - return createSyncData(id, pendingBreakpoint, scopedLocation, scopedGeneratedLocation, previousLocation, text, originalText); - } - - // clear server breakpoints if they exist and we have moved - if (existingClient) { - await client.removeBreakpoint(generatedLocation); - } - - /** ******* Case 2: Add New Breakpoint ***********/ - // If we are not disabled, set the breakpoint on the server and get - // that info so we can set it on our breakpoints. - - if (!scopedGeneratedLocation.line) { - return { previousLocation, breakpoint: null }; - } - - const { id, actualLocation } = await client.setBreakpoint(scopedGeneratedLocation, pendingBreakpoint.condition, sourceMaps.isOriginalId(sourceId)); - - // the breakpoint might have slid server side, so we want to get the location - // based on the server's return value - const newGeneratedLocation = actualLocation; - const newLocation = await sourceMaps.getOriginalLocation(newGeneratedLocation); - - const originalText = (0, _source.getTextAtPosition)(source, newLocation); - const text = (0, _source.getTextAtPosition)(generatedSource, newGeneratedLocation); - - return createSyncData(id, pendingBreakpoint, newLocation, newGeneratedLocation, previousLocation, text, originalText); -} - -/***/ }), - -/***/ 1526: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.buildQuery = undefined; -exports.getMatchIndex = getMatchIndex; -exports.searchSourceForHighlight = searchSourceForHighlight; -exports.removeOverlay = removeOverlay; -exports.find = find; -exports.findNext = findNext; -exports.findPrev = findPrev; - -var _buildQuery = __webpack_require__(1402); - -var _buildQuery2 = _interopRequireDefault(_buildQuery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @memberof utils/source-search - * @static - */ -function getSearchCursor(cm, query, pos, modifiers) { - const regexQuery = (0, _buildQuery2.default)(query, modifiers, { isGlobal: true }); - return cm.getSearchCursor(regexQuery, pos); -} - -/** - * @memberof utils/source-search - * @static - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function SearchState() { - this.posFrom = this.posTo = this.query = null; - this.overlay = null; - this.results = []; -} - -/** - * @memberof utils/source-search - * @static - */ -function getSearchState(cm, query) { - const state = cm.state.search || (cm.state.search = new SearchState()); - return state; -} - -function isWhitespace(query) { - return !query.match(/\S/); -} - -/** - * This returns a mode object used by CoeMirror's addOverlay function - * to parse and style tokens in the file. - * The mode object contains a tokenizer function (token) which takes - * a character stream as input, advances it a character at a time, - * and returns style(s) for that token. For more details see - * https://codemirror.net/doc/manual.html#modeapi - * - * Also the token function code is mainly based of work done - * by the chrome devtools team. Thanks guys! :) - * - * @memberof utils/source-search - * @static - */ -function searchOverlay(query, modifiers) { - const regexQuery = (0, _buildQuery2.default)(query, modifiers, { - ignoreSpaces: true, - // regex must be global for the overlay - isGlobal: true - }); - - return { - token: function (stream, state) { - // set the last index to be the current stream position - // this acts as an offset - regexQuery.lastIndex = stream.pos; - const match = regexQuery.exec(stream.string); - if (match && match.index === stream.pos) { - // if we have a match at the current stream position - // set the class for a match - stream.pos += match[0].length || 1; - return "highlight highlight-full"; - } else if (match) { - // if we have a match somewhere in the line, go to that point in the - // stream - stream.pos = match.index; - } else { - // if we have no matches in this line, skip to the end of the line - stream.skipToEnd(); - } - } - }; -} - -/** - * @memberof utils/source-search - * @static - */ -function updateOverlay(cm, state, query, modifiers) { - cm.removeOverlay(state.overlay); - state.overlay = searchOverlay(query, modifiers); - cm.addOverlay(state.overlay, { opaque: false }); -} - -function updateCursor(cm, state, keepSelection) { - state.posTo = cm.getCursor("anchor"); - state.posFrom = cm.getCursor("head"); - - if (!keepSelection) { - state.posTo = { line: 0, ch: 0 }; - state.posFrom = { line: 0, ch: 0 }; - } -} - -function getMatchIndex(count, currentIndex, rev) { - if (!rev) { - if (currentIndex == count - 1) { - return 0; - } - - return currentIndex + 1; - } - - if (currentIndex == 0) { - return count - 1; - } - - return currentIndex - 1; -} - -/** - * If there's a saved search, selects the next results. - * Otherwise, creates a new search and selects the first - * result. - * - * @memberof utils/source-search - * @static - */ -function doSearch(ctx, rev, query, keepSelection, modifiers) { - const { cm } = ctx; - if (!cm) { - return; - } - const defaultIndex = { line: -1, ch: -1 }; - - return cm.operation(function () { - if (!query || isWhitespace(query)) { - clearSearch(cm, query); - return; - } - - const state = getSearchState(cm, query); - const isNewQuery = state.query !== query; - state.query = query; - - updateOverlay(cm, state, query, modifiers); - updateCursor(cm, state, keepSelection); - const searchLocation = searchNext(ctx, rev, query, isNewQuery, modifiers); - - return searchLocation ? searchLocation.from : defaultIndex; - }); -} - -function searchSourceForHighlight(ctx, rev, query, keepSelection, modifiers, line, ch) { - const { cm } = ctx; - if (!cm) { - return; - } - - return cm.operation(function () { - const state = getSearchState(cm, query); - const isNewQuery = state.query !== query; - state.query = query; - - updateOverlay(cm, state, query, modifiers); - updateCursor(cm, state, keepSelection); - findNextOnLine(ctx, rev, query, isNewQuery, modifiers, line, ch); - }); -} - -function getCursorPos(newQuery, rev, state) { - if (newQuery) { - return rev ? state.posFrom : state.posTo; - } - - return rev ? state.posTo : state.posFrom; -} - -/** - * Selects the next result of a saved search. - * - * @memberof utils/source-search - * @static - */ -function searchNext(ctx, rev, query, newQuery, modifiers) { - const { cm, ed } = ctx; - let nextMatch; - cm.operation(function () { - const state = getSearchState(cm, query); - const pos = getCursorPos(newQuery, rev, state); - - if (!state.query) { - return; - } - - let cursor = getSearchCursor(cm, state.query, pos, modifiers); - - const location = rev ? { line: cm.lastLine(), ch: null } : { line: cm.firstLine(), ch: 0 }; - - if (!cursor.find(rev) && state.query) { - cursor = getSearchCursor(cm, state.query, location, modifiers); - if (!cursor.find(rev)) { - return; - } - } - - // We don't want to jump the editor - // when we're selecting text - if (!cm.state.selectingText) { - ed.alignLine(cursor.from().line, "center"); - cm.setSelection(cursor.from(), cursor.to()); - } - - nextMatch = { from: cursor.from(), to: cursor.to() }; - }); - - return nextMatch; -} - -function findNextOnLine(ctx, rev, query, newQuery, modifiers, line, ch) { - const { cm, ed } = ctx; - cm.operation(function () { - const pos = { line: line - 1, ch }; - let cursor = getSearchCursor(cm, query, pos, modifiers); - - if (!cursor.find(rev) && query) { - cursor = getSearchCursor(cm, query, pos, modifiers); - if (!cursor.find(rev)) { - return; - } - } - - // We don't want to jump the editor - // when we're selecting text - if (!cm.state.selectingText) { - ed.alignLine(cursor.from().line, "center"); - cm.setSelection(cursor.from(), cursor.to()); - } - }); -} - -/** - * Remove overlay. - * - * @memberof utils/source-search - * @static - */ -function removeOverlay(ctx, query) { - const state = getSearchState(ctx.cm, query); - ctx.cm.removeOverlay(state.overlay); - const { line, ch } = ctx.cm.getCursor(); - ctx.cm.doc.setSelection({ line, ch }, { line, ch }, { scroll: false }); -} - -/** - * Clears the currently saved search. - * - * @memberof utils/source-search - * @static - */ -function clearSearch(cm, query) { - const state = getSearchState(cm, query); - - state.results = []; - - if (!state.query) { - return; - } - cm.removeOverlay(state.overlay); - state.query = null; -} - -/** - * Starts a new search. - * - * @memberof utils/source-search - * @static - */ -function find(ctx, query, keepSelection, modifiers) { - clearSearch(ctx.cm, query); - return doSearch(ctx, false, query, keepSelection, modifiers); -} - -/** - * Finds the next item based on the currently saved search. - * - * @memberof utils/source-search - * @static - */ -function findNext(ctx, query, keepSelection, modifiers) { - return doSearch(ctx, false, query, keepSelection, modifiers); -} - -/** - * Finds the previous item based on the currently saved search. - * - * @memberof utils/source-search - * @static - */ -function findPrev(ctx, query, keepSelection, modifiers) { - return doSearch(ctx, true, query, keepSelection, modifiers); -} - -exports.buildQuery = _buildQuery2.default; - -/***/ }), - -/***/ 1527: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.fetchEventListeners = fetchEventListeners; -exports.updateEventBreakpoints = updateEventBreakpoints; - -var _DevToolsUtils = __webpack_require__(1432); - -var _selectors = __webpack_require__(3590); - -var _waitService = __webpack_require__(1659); - -// delay is in ms -const FETCH_EVENT_LISTENERS_DELAY = 200; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* global window gThreadClient setNamedTimeout EVENTS */ -/* eslint no-shadow: 0 */ - -/** - * Redux actions for the event listeners state - * @module actions/event-listeners - */ - -let fetchListenersTimerID; - -/** - * @memberof utils/utils - * @static - */ -async function asPaused(state, client, func) { - if (!(0, _selectors.isPaused)(state)) { - await client.interrupt(); - let result; - - try { - result = await func(client); - } catch (e) { - // Try to put the debugger back in a working state by resuming - // it - await client.resume(); - throw e; - } - - await client.resume(); - return result; - } - - return func(client); -} - -/** - * @memberof actions/event-listeners - * @static - */ -function fetchEventListeners() { - return ({ dispatch, getState, client }) => { - // Make sure we"re not sending a batch of closely repeated requests. - // This can easily happen whenever new sources are fetched. - if (fetchListenersTimerID) { - clearTimeout(fetchListenersTimerID); - } - - fetchListenersTimerID = setTimeout(() => { - // In case there is still a request of listeners going on (it - // takes several RDP round trips right now), make sure we wait - // on a currently running request - if (getState().eventListeners.fetchingListeners) { - dispatch({ - type: _waitService.NAME, - predicate: action => action.type === "FETCH_EVENT_LISTENERS" && action.status === "done", - run: dispatch => dispatch(fetchEventListeners()) - }); - return; - } - - dispatch({ - type: "FETCH_EVENT_LISTENERS", - status: "begin" - }); - - asPaused(getState(), client, _getEventListeners).then(listeners => { - dispatch({ - type: "FETCH_EVENT_LISTENERS", - status: "done", - listeners: formatListeners(getState(), listeners) - }); - }); - }, FETCH_EVENT_LISTENERS_DELAY); - }; -} - -function formatListeners(state, listeners) { - return listeners.map(l => { - return { - selector: l.node.selector, - type: l.type, - sourceId: (0, _selectors.getSourceByURL)(state, l.function.location.url).get("id"), - line: l.function.location.line - }; - }); -} - -async function _getEventListeners(threadClient) { - const response = await threadClient.eventListeners(); - - // Make sure all the listeners are sorted by the event type, since - // they"re not guaranteed to be clustered together. - response.listeners.sort((a, b) => a.type > b.type ? 1 : -1); - - // Add all the listeners in the debugger view event linsteners container. - const fetchedDefinitions = new Map(); - const listeners = []; - for (const listener of response.listeners) { - let definitionSite; - if (fetchedDefinitions.has(listener.function.actor)) { - definitionSite = fetchedDefinitions.get(listener.function.actor); - } else if (listener.function.class == "Function") { - definitionSite = await _getDefinitionSite(threadClient, listener.function); - if (!definitionSite) { - // We don"t know where this listener comes from so don"t show it in - // the UI as breaking on it doesn"t work (bug 942899). - continue; - } - - fetchedDefinitions.set(listener.function.actor, definitionSite); - } - listener.function.url = definitionSite; - listeners.push(listener); - } - fetchedDefinitions.clear(); - - return listeners; -} - -async function _getDefinitionSite(threadClient, func) { - const grip = threadClient.pauseGrip(func); - let response; - - try { - response = await grip.getDefinitionSite(); - } catch (e) { - // Don't make this error fatal, it would break the entire events pane. - (0, _DevToolsUtils.reportException)("_getDefinitionSite", e); - return null; - } - - return response.source.url; -} - -/** - * @memberof actions/event-listeners - * @static - * @param {string} eventNames - */ -function updateEventBreakpoints(eventNames) { - return dispatch => { - setNamedTimeout("event-breakpoints-update", 0, () => { - gThreadClient.pauseOnDOMEvents(eventNames, () => { - // Notify that event breakpoints were added/removed on the server. - window.emit(EVENTS.EVENT_BREAKPOINTS_UPDATED); - - dispatch({ - type: "UPDATE_EVENT_BREAKPOINTS", - eventNames: eventNames - }); - }); - }); - }; -} - -/***/ }), - -/***/ 1529: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.willNavigate = willNavigate; -exports.navigate = navigate; -exports.connect = connect; -exports.navigated = navigated; - -var _editor = __webpack_require__(1358); - -var _sourceQueue = __webpack_require__(1795); - -var _sourceQueue2 = _interopRequireDefault(_sourceQueue); - -var _sources = __webpack_require__(1369); - -var _utils = __webpack_require__(1366); - -var _sources2 = __webpack_require__(1797); - -var _debuggee = __webpack_require__(1533); - -var _parser = __webpack_require__(1365); - -var _wasm = __webpack_require__(1401); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Redux actions for the navigation state - * @module actions/navigation - */ - -/** - * @memberof actions/navigation - * @static - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function willNavigate(event) { - return async function ({ dispatch, getState, client, sourceMaps }) { - await sourceMaps.clearSourceMaps(); - (0, _wasm.clearWasmStates)(); - (0, _editor.clearDocuments)(); - (0, _editor.removeEditor)(); - (0, _parser.clearSymbols)(); - (0, _parser.clearASTs)(); - (0, _parser.clearScopes)(); - (0, _parser.clearSources)(); - dispatch(navigate(event.url)); - }; -} - -function navigate(url) { - _sourceQueue2.default.clear(); - - return { - type: "NAVIGATE", - url - }; -} - -function connect(url, canRewind) { - return async function ({ dispatch }) { - await dispatch((0, _debuggee.updateWorkers)()); - dispatch({ type: "CONNECT", url, canRewind }); - }; -} - -/** - * @memberof actions/navigation - * @static - */ -function navigated() { - return async function ({ dispatch, getState, client }) { - await (0, _utils.waitForMs)(100); - if ((0, _sources.getSources)(getState()).size == 0) { - const sources = await client.fetchSources(); - dispatch((0, _sources2.newSources)(sources)); - } - }; -} - -/***/ }), - -/***/ 1530: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.doSearch = doSearch; -exports.doSearchForHighlight = doSearchForHighlight; -exports.setFileSearchQuery = setFileSearchQuery; -exports.toggleFileSearchModifier = toggleFileSearchModifier; -exports.updateSearchResults = updateSearchResults; -exports.searchContents = searchContents; -exports.searchContentsForHighlight = searchContentsForHighlight; -exports.traverseResults = traverseResults; -exports.closeFileSearch = closeFileSearch; - -var _editor = __webpack_require__(1358); - -var _search = __webpack_require__(1395); - -var _selectors = __webpack_require__(3590); - -var _ui = __webpack_require__(1385); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function doSearch(query, editor) { - return ({ getState, dispatch }) => { - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - if (!selectedSource || !selectedSource.text) { - return; - } - - dispatch(setFileSearchQuery(query)); - dispatch(searchContents(query, editor)); - }; -} - -function doSearchForHighlight(query, editor, line, ch) { - return async ({ getState, dispatch }) => { - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - if (!selectedSource || !selectedSource.text) { - return; - } - dispatch(searchContentsForHighlight(query, editor, line, ch)); - }; -} - -function setFileSearchQuery(query) { - return { - type: "UPDATE_FILE_SEARCH_QUERY", - query - }; -} - -function toggleFileSearchModifier(modifier) { - return { type: "TOGGLE_FILE_SEARCH_MODIFIER", modifier }; -} - -function updateSearchResults(characterIndex, line, matches) { - const matchIndex = matches.findIndex(elm => elm.line === line && elm.ch === characterIndex); - - return { - type: "UPDATE_SEARCH_RESULTS", - results: { - matches, - matchIndex, - count: matches.length, - index: characterIndex - } - }; -} - -function searchContents(query, editor) { - return async ({ getState, dispatch }) => { - const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - - if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) { - return; - } - - const ctx = { ed: editor, cm: editor.codeMirror }; - const _modifiers = modifiers.toJS(); - const matches = await (0, _search.getMatches)(query, selectedSource.text, _modifiers); - - const res = (0, _editor.find)(ctx, query, true, _modifiers); - if (!res) { - return; - } - - const { ch, line } = res; - - dispatch(updateSearchResults(ch, line, matches)); - }; -} - -function searchContentsForHighlight(query, editor, line, ch) { - return async ({ getState, dispatch }) => { - const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - - if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) { - return; - } - - const ctx = { ed: editor, cm: editor.codeMirror }; - const _modifiers = modifiers.toJS(); - - (0, _editor.searchSourceForHighlight)(ctx, false, query, true, _modifiers, line, ch); - }; -} - -function traverseResults(rev, editor) { - return async ({ getState, dispatch }) => { - if (!editor) { - return; - } - - const ctx = { ed: editor, cm: editor.codeMirror }; - - const query = (0, _selectors.getFileSearchQuery)(getState()); - const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); - const { matches } = (0, _selectors.getFileSearchResults)(getState()); - - if (query === "") { - dispatch((0, _ui.setActiveSearch)("file")); - } - - if (modifiers) { - const matchedLocations = matches || []; - const results = rev ? (0, _editor.findPrev)(ctx, query, true, modifiers.toJS()) : (0, _editor.findNext)(ctx, query, true, modifiers.toJS()); - - if (!results) { - return; - } - const { ch, line } = results; - dispatch(updateSearchResults(ch, line, matchedLocations)); - } - }; -} - -function closeFileSearch(editor) { - return ({ getState, dispatch }) => { - const query = (0, _selectors.getFileSearchQuery)(getState()); - - if (editor) { - const ctx = { ed: editor, cm: editor.codeMirror }; - (0, _editor.removeOverlay)(ctx, query); - } - - dispatch(setFileSearchQuery("")); - dispatch((0, _ui.closeActiveSearch)()); - dispatch((0, _ui.clearHighlightLineRange)()); - }; -} - -/***/ }), - -/***/ 1531: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.recordCoverage = recordCoverage; -function recordCoverage() { - return async function ({ dispatch, getState, client }) { - const { coverage } = await client.recordCoverage(); - - return dispatch({ - type: "RECORD_COVERAGE", - value: { coverage } - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1532: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setExpandedState = setExpandedState; -function setExpandedState(expanded) { - return ({ dispatch, getState }) => { - dispatch({ - type: "SET_EXPANDED_STATE", - expanded - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1533: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.updateWorkers = updateWorkers; -function updateWorkers() { - return async function ({ dispatch, client }) { - const { workers } = await client.fetchWorkers(); - dispatch({ type: "SET_WORKERS", workers }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1534: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.openLink = openLink; -exports.openWorkerToolbox = openWorkerToolbox; -exports.evaluateInConsole = evaluateInConsole; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { isDevelopment } = __webpack_require__(3721); -const { getSelectedFrameId } = __webpack_require__(3590); - -/** - * @memberof actions/toolbox - * @static - */ -function openLink(url) { - return async function ({ openLink: openLinkCommand }) { - if (isDevelopment()) { - const win = window.open(url, "_blank"); - win.focus(); - } else { - openLinkCommand(url); - } - }; -} - -function openWorkerToolbox(worker) { - return async function ({ - getState, - openWorkerToolbox: openWorkerToolboxCommand - }) { - if (isDevelopment()) { - alert(worker.url); - } else { - openWorkerToolboxCommand(worker); - } - }; -} - -function evaluateInConsole(inputString) { - return async ({ client, getState }) => { - const frameId = getSelectedFrameId(getState()); - client.evaluate(`console.log("${inputString}"); console.log(${inputString})`, { frameId }); - }; -} - -/***/ }), - -/***/ 1535: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ShortcutsModal = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _Modal = __webpack_require__(1403); - -var _Modal2 = _interopRequireDefault(_Modal); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _text = __webpack_require__(1387); - -__webpack_require__(1304); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class ShortcutsModal extends _react.Component { - renderPrettyCombos(combo) { - return combo.split(" ").map(c => _react2.default.createElement( - "span", - { key: c, className: "keystroke" }, - c - )).reduce((prev, curr) => [prev, " + ", curr]); - } - - renderShorcutItem(title, combo) { - return _react2.default.createElement( - "li", - null, - _react2.default.createElement( - "span", - null, - title - ), - _react2.default.createElement( - "span", - null, - this.renderPrettyCombos(combo) - ) - ); - } - - renderEditorShortcuts() { - return _react2.default.createElement( - "ul", - { className: "shortcuts-list" }, - this.renderShorcutItem(L10N.getStr("shortcuts.toggleBreakpoint"), (0, _text.formatKeyShortcut)(L10N.getStr("toggleBreakpoint.key"))), - this.renderShorcutItem(L10N.getStr("shortcuts.toggleCondPanel"), (0, _text.formatKeyShortcut)(L10N.getStr("toggleCondPanel.key"))) - ); - } - - renderSteppingShortcuts() { - return _react2.default.createElement( - "ul", - { className: "shortcuts-list" }, - this.renderShorcutItem(L10N.getStr("shortcuts.pauseOrResume"), "F8"), - this.renderShorcutItem(L10N.getStr("shortcuts.stepOver"), "F10"), - this.renderShorcutItem(L10N.getStr("shortcuts.stepIn"), "F11"), - this.renderShorcutItem(L10N.getStr("shortcuts.stepOut"), (0, _text.formatKeyShortcut)(L10N.getStr("stepOut.key"))) - ); - } - - renderSearchShortcuts() { - return _react2.default.createElement( - "ul", - { className: "shortcuts-list" }, - this.renderShorcutItem(L10N.getStr("shortcuts.fileSearch"), (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"))), - this.renderShorcutItem(L10N.getStr("shortcuts.searchAgain"), (0, _text.formatKeyShortcut)(L10N.getStr("sourceSearch.search.again.key2"))), - this.renderShorcutItem(L10N.getStr("shortcuts.projectSearch"), (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key"))), - this.renderShorcutItem(L10N.getStr("shortcuts.functionSearch"), (0, _text.formatKeyShortcut)(L10N.getStr("functionSearch.key"))), - this.renderShorcutItem(L10N.getStr("shortcuts.gotoLine"), (0, _text.formatKeyShortcut)(L10N.getStr("gotoLineModal.key2"))) - ); - } - - renderShortcutsContent() { - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("shortcuts-content", this.props.additionalClass) - }, - _react2.default.createElement( - "div", - { className: "shortcuts-section" }, - _react2.default.createElement( - "h2", - null, - L10N.getStr("shortcuts.header.editor") - ), - this.renderEditorShortcuts() - ), - _react2.default.createElement( - "div", - { className: "shortcuts-section" }, - _react2.default.createElement( - "h2", - null, - L10N.getStr("shortcuts.header.stepping") - ), - this.renderSteppingShortcuts() - ), - _react2.default.createElement( - "div", - { className: "shortcuts-section" }, - _react2.default.createElement( - "h2", - null, - L10N.getStr("shortcuts.header.search") - ), - this.renderSearchShortcuts() - ) - ); - } - - render() { - const { enabled } = this.props; - - if (!enabled) { - return null; - } - - return _react2.default.createElement( - _Modal2.default, - { - "in": enabled, - additionalClass: "shortcuts-modal", - handleClose: this.props.handleClose - }, - this.renderShortcutsContent() - ); - } -} -exports.ShortcutsModal = ShortcutsModal; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1536: -/***/ (function(module, exports, __webpack_require__) { - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const React = __webpack_require__(0); -const ReactDOM = __webpack_require__(4); -const Draggable = React.createFactory(__webpack_require__(1537)); -const { Component } = React; -const PropTypes = __webpack_require__(3642); -const dom = __webpack_require__(3643); - -__webpack_require__(1309); - -/** - * This component represents a Splitter. The splitter supports vertical - * as well as horizontal mode. - */ -class SplitBox extends Component { - static get propTypes() { - return { - // Custom class name. You can use more names separated by a space. - className: PropTypes.string, - // Initial size of controlled panel. - initialSize: PropTypes.any, - // Optional initial width of controlled panel. - initialWidth: PropTypes.number, - // Optional initial height of controlled panel. - initialHeight: PropTypes.number, - // Left/top panel - startPanel: PropTypes.any, - // Left/top panel collapse state. - startPanelCollapsed: PropTypes.bool, - // Min panel size. - minSize: PropTypes.any, - // Max panel size. - maxSize: PropTypes.any, - // Right/bottom panel - endPanel: PropTypes.any, - // Right/bottom panel collapse state. - endPanelCollapsed: PropTypes.bool, - // True if the right/bottom panel should be controlled. - endPanelControl: PropTypes.bool, - // Size of the splitter handle bar. - splitterSize: PropTypes.number, - // True if the splitter bar is vertical (default is vertical). - vert: PropTypes.bool, - // Optional style properties passed into the splitbox - style: PropTypes.object, - // Optional callback when splitbox resize stops - onResizeEnd: PropTypes.func - }; - } - - static get defaultProps() { - return { - splitterSize: 5, - vert: true, - endPanelControl: false, - endPanelCollapsed: false, - startPanelCollapsed: false - }; - } - - constructor(props) { - super(props); - - this.state = { - vert: props.vert, - // We use integers for these properties - width: parseInt(props.initialWidth || props.initialSize, 10), - height: parseInt(props.initialHeight || props.initialSize, 10) - }; - - this.onStartMove = this.onStartMove.bind(this); - this.onStopMove = this.onStopMove.bind(this); - this.onMove = this.onMove.bind(this); - this.preparePanelStyles = this.preparePanelStyles.bind(this); - } - - componentWillReceiveProps(nextProps) { - if (this.props.vert !== nextProps.vert) { - this.setState({ vert: nextProps.vert }); - } - } - - // Dragging Events - - /** - * Set 'resizing' cursor on entire document during splitter dragging. - * This avoids cursor-flickering that happens when the mouse leaves - * the splitter bar area (happens frequently). - */ - onStartMove() { - const splitBox = ReactDOM.findDOMNode(this); - const doc = splitBox.ownerDocument; - let defaultCursor = doc.documentElement.style.cursor; - doc.documentElement.style.cursor = this.state.vert ? "ew-resize" : "ns-resize"; - - splitBox.classList.add("dragging"); - - this.setState({ - defaultCursor: defaultCursor - }); - } - - onStopMove() { - const splitBox = ReactDOM.findDOMNode(this); - const doc = splitBox.ownerDocument; - doc.documentElement.style.cursor = this.state.defaultCursor; - - splitBox.classList.remove("dragging"); - - if (this.props.onResizeEnd) { - this.props.onResizeEnd(this.state.vert ? this.state.width : this.state.height); - } - } - - /** - * Adjust size of the controlled panel. Depending on the current - * orientation we either remember the width or height of - * the splitter box. - */ - onMove({ movementX, movementY }) { - const node = ReactDOM.findDOMNode(this); - const doc = node.ownerDocument; - - if (this.props.endPanelControl) { - // For the end panel we need to increase the width/height when the - // movement is towards the left/top. - movementX = -movementX; - movementY = -movementY; - } - - if (this.state.vert) { - const isRtl = doc.dir === "rtl"; - if (isRtl) { - // In RTL we need to reverse the movement again -- but only for vertical - // splitters - movementX = -movementX; - } - - this.setState((state, props) => ({ - width: state.width + movementX - })); - } else { - this.setState((state, props) => ({ - height: state.height + movementY - })); - } - } - - // Rendering - preparePanelStyles() { - const vert = this.state.vert; - const { - minSize, - maxSize, - startPanelCollapsed, - endPanelControl, - endPanelCollapsed - } = this.props; - let leftPanelStyle, rightPanelStyle; - - // Set proper size for panels depending on the current state. - if (vert) { - let startWidth = endPanelControl ? null : this.state.width, - endWidth = endPanelControl ? this.state.width : null; - - leftPanelStyle = { - maxWidth: endPanelControl ? null : maxSize, - minWidth: endPanelControl ? null : minSize, - width: startPanelCollapsed ? 0 : startWidth - }; - rightPanelStyle = { - maxWidth: endPanelControl ? maxSize : null, - minWidth: endPanelControl ? minSize : null, - width: endPanelCollapsed ? 0 : endWidth - }; - } else { - let startHeight = endPanelControl ? null : this.state.height, - endHeight = endPanelControl ? this.state.height : null; - - leftPanelStyle = { - maxHeight: endPanelControl ? null : maxSize, - minHeight: endPanelControl ? null : minSize, - height: endPanelCollapsed ? maxSize : startHeight - }; - rightPanelStyle = { - maxHeight: endPanelControl ? maxSize : null, - minHeight: endPanelControl ? minSize : null, - height: startPanelCollapsed ? maxSize : endHeight - }; - } - - return { leftPanelStyle, rightPanelStyle }; - } - - render() { - const vert = this.state.vert; - const { - startPanelCollapsed, - startPanel, - endPanel, - endPanelControl, - splitterSize, - endPanelCollapsed - } = this.props; - - let style = Object.assign({}, this.props.style); - - // Calculate class names list. - let classNames = ["split-box"]; - classNames.push(vert ? "vert" : "horz"); - if (this.props.className) { - classNames = classNames.concat(this.props.className.split(" ")); - } - - const { leftPanelStyle, rightPanelStyle } = this.preparePanelStyles(); - - // Calculate splitter size - let splitterStyle = { - flex: `0 0 ${splitterSize}px` - }; - - return dom.div({ - className: classNames.join(" "), - style: style - }, !startPanelCollapsed ? dom.div({ - className: endPanelControl ? "uncontrolled" : "controlled", - style: leftPanelStyle - }, startPanel) : null, Draggable({ - className: "splitter", - style: splitterStyle, - onStart: this.onStartMove, - onStop: this.onStopMove, - onMove: this.onMove - }), !endPanelCollapsed ? dom.div({ - className: endPanelControl ? "controlled" : "uncontrolled", - style: rightPanelStyle - }, endPanel) : null); - } -} - -module.exports = SplitBox; - -/***/ }), - -/***/ 1537: -/***/ (function(module, exports, __webpack_require__) { - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const React = __webpack_require__(0); -const ReactDOM = __webpack_require__(4); -const { Component } = React; -const PropTypes = __webpack_require__(3642); -const dom = __webpack_require__(3643); - -class Draggable extends Component { - static get propTypes() { - return { - onMove: PropTypes.func.isRequired, - onStart: PropTypes.func, - onStop: PropTypes.func, - style: PropTypes.object, - className: PropTypes.string - }; - } - - constructor(props) { - super(props); - this.startDragging = this.startDragging.bind(this); - this.onMove = this.onMove.bind(this); - this.onUp = this.onUp.bind(this); - } - - startDragging(ev) { - ev.preventDefault(); - const doc = ReactDOM.findDOMNode(this).ownerDocument; - doc.addEventListener("mousemove", this.onMove); - doc.addEventListener("mouseup", this.onUp); - this.props.onStart && this.props.onStart(); - } - - onMove(ev) { - ev.preventDefault(); - // We pass the whole event because we don't know which properties - // the callee needs. - this.props.onMove(ev); - } - - onUp(ev) { - ev.preventDefault(); - const doc = ReactDOM.findDOMNode(this).ownerDocument; - doc.removeEventListener("mousemove", this.onMove); - doc.removeEventListener("mouseup", this.onUp); - this.props.onStop && this.props.onStop(); - } - - render() { - return dom.div({ - style: this.props.style, - className: this.props.className, - onMouseDown: this.startDragging - }); - } -} - -module.exports = Draggable; - -/***/ }), - -/***/ 1540: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _svgInlineReact = __webpack_require__(1763); - -var _svgInlineReact2 = _interopRequireDefault(_svgInlineReact); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const React = __webpack_require__(0); - - -const svg = { - "angle-brackets": __webpack_require__(347), - angular: __webpack_require__(247), - arrow: __webpack_require__(348), - babel: __webpack_require__(3595), - backbone: __webpack_require__(997), - blackBox: __webpack_require__(349), - breadcrumb: __webpack_require__(3603), - breakpoint: __webpack_require__(350), - "column-breakpoint": __webpack_require__(998), - "case-match": __webpack_require__(351), - choo: __webpack_require__(1290), - close: __webpack_require__(352), - coffeescript: __webpack_require__(2250), - dojo: __webpack_require__(806), - domain: __webpack_require__(353), - extension: __webpack_require__(3632), - file: __webpack_require__(354), - folder: __webpack_require__(355), - globe: __webpack_require__(356), - home: __webpack_require__(3604), - javascript: __webpack_require__(2251), - jquery: __webpack_require__(999), - underscore: __webpack_require__(1117), - lodash: __webpack_require__(1118), - ember: __webpack_require__(1119), - vuejs: __webpack_require__(1174), - "magnifying-glass": __webpack_require__(357), - "arrow-up": __webpack_require__(919), - "arrow-down": __webpack_require__(920), - pause: __webpack_require__(358), - "pause-exceptions": __webpack_require__(359), - plus: __webpack_require__(360), - preact: __webpack_require__(1233), - aframe: __webpack_require__(1648), - prettyPrint: __webpack_require__(361), - react: __webpack_require__(1000), - "regex-match": __webpack_require__(362), - redux: __webpack_require__(256), - immutable: __webpack_require__(258), - resume: __webpack_require__(363), - settings: __webpack_require__(364), - stepIn: __webpack_require__(365), - stepOut: __webpack_require__(366), - stepOver: __webpack_require__(367), - subSettings: __webpack_require__(368), - tab: __webpack_require__(3631), - toggleBreakpoints: __webpack_require__(369), - togglePanes: __webpack_require__(370), - typescript: __webpack_require__(2252), - "whole-word-match": __webpack_require__(371), - worker: __webpack_require__(372), - "sad-face": __webpack_require__(1347), - refresh: __webpack_require__(1348), - webpack: __webpack_require__(1001), - node: __webpack_require__(1002), - express: __webpack_require__(1003), - pug: __webpack_require__(1004), - extjs: __webpack_require__(1043), - mobx: __webpack_require__(1733), - marko: __webpack_require__(1649), - nextjs: __webpack_require__(1650), - showSources: __webpack_require__(1044), - showOutline: __webpack_require__(1045), - nuxtjs: __webpack_require__(1651), - rxjs: __webpack_require__(1808) -}; - -function Svg({ name, className, onClick, "aria-label": ariaLabel }) { - if (!svg[name]) { - const error = `Unknown SVG: ${name}`; - console.warn(error); - return null; - } - - className = `${name} ${className || ""}`; - if (name === "subSettings") { - className = ""; - } - - const props = { - className, - onClick, - ["aria-label"]: ariaLabel, - src: svg[name] - }; - - return React.createElement(_svgInlineReact2.default, props); -} - -Svg.displayName = "Svg"; - -module.exports = Svg; - -/***/ }), - -/***/ 1542: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.formatTree = formatTree; -function formatTree(tree, depth = 0, str = "") { - const whitespace = new Array(depth * 2).join(" "); - - if (Array.isArray(tree.contents)) { - str += `${whitespace} - ${tree.name} path=${tree.path} \n`; - tree.contents.forEach(t => { - str = formatTree(t, depth + 1, str); - }); - } else { - const id = tree.contents.get("id"); - str += `${whitespace} - ${tree.name} path=${tree.path} source_id=${id} \n`; - } - - return str; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1543: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getDomain = getDomain; -exports.findNodeInContents = findNodeInContents; -exports.createTreeNodeMatcher = createTreeNodeMatcher; - -var _url = __webpack_require__(334); - -var _utils = __webpack_require__(1371); - -/* - * Gets domain from url (without www prefix) - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getDomain(url) { - // TODO: define how files should be ordered on the browser debugger - if (!url) { - return null; - } - const { host } = (0, _url.parse)(url); - if (!host) { - return null; - } - return host.startsWith("www.") ? host.substr("www.".length) : host; -} - -/* - * Checks if node name matches debugger host/domain. - */ -function isExactDomainMatch(part, debuggeeHost) { - return part.startsWith("www.") ? part.substr("www.".length) === debuggeeHost : part === debuggeeHost; -} - -/* - * Function to assist with node search for a defined sorted order, see e.g. - * `createTreeNodeMatcher`. Returns negative number if the node - * stands earlier in sorting order, positive number if the node stands later - * in sorting order, or zero if the node is found. - */ - - -/* - * Performs a binary search to insert a node into contents. Returns positive - * number, index of the found child, or negative number, which can be used - * to calculate a position where a new node can be inserted (`-index - 1`). - * The matcher is a function that returns result of comparision of a node with - * lookup value. - */ -function findNodeInContents(tree, matcher) { - const { contents } = tree; - if (contents.length === 0) { - return { found: false, index: 0 }; - } - let left = 0; - let right = contents.length - 1; - while (left < right) { - const middle = Math.floor((left + right) / 2); - if (matcher(contents[middle]) < 0) { - left = middle + 1; - } else { - right = middle; - } - } - const result = matcher(contents[left]); - if (result === 0) { - return { found: true, index: left }; - } - return { found: false, index: result > 0 ? left : left + 1 }; -} - -const IndexName = "(index)"; - -function createTreeNodeMatcherWithIndex() { - return node => node.name === IndexName ? 0 : 1; -} - -function createTreeNodeMatcherWithDebuggeeHost(debuggeeHost) { - return node => { - if (node.name === IndexName) { - return -1; - } - return isExactDomainMatch(node.name, debuggeeHost) ? 0 : 1; - }; -} - -function createTreeNodeMatcherWithNameAndOther(part, isDir, debuggeeHost) { - return node => { - if (node.name === IndexName) { - return -1; - } - if (debuggeeHost && isExactDomainMatch(node.name, debuggeeHost)) { - return -1; - } - const nodeIsDir = (0, _utils.nodeHasChildren)(node); - if (nodeIsDir && !isDir) { - return -1; - } else if (!nodeIsDir && isDir) { - return 1; - } - return node.name.localeCompare(part); - }; -} - -/* - * Creates a matcher for findNodeInContents. - * The sorting order of nodes during comparison is: - * - "(index)" node - * - root node with the debuggee host/domain - * - hosts/directories (not files) sorted by name - * - files sorted by name - */ -function createTreeNodeMatcher(part, isDir, debuggeeHost) { - if (part === IndexName) { - // Specialied matcher, when we are looking for "(index)" position. - return createTreeNodeMatcherWithIndex(); - } - if (debuggeeHost && isExactDomainMatch(part, debuggeeHost)) { - // Specialied matcher, when we are looking for domain position. - return createTreeNodeMatcherWithDebuggeeHost(debuggeeHost); - } - // Rest of the cases, without mentioned above. - return createTreeNodeMatcherWithNameAndOther(part, isDir, debuggeeHost); -} - -/***/ }), - -/***/ 1544: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.sortEntireTree = sortEntireTree; -exports.sortTree = sortTree; - -var _utils = __webpack_require__(1371); - -/** - * Look at the nodes in the source tree, and determine the index of where to - * insert a new node. The ordering is index -> folder -> file. - * @memberof utils/sources-tree - * @static - */ -function sortEntireTree(tree, debuggeeUrl = "") { - if ((0, _utils.nodeHasChildren)(tree)) { - const contents = sortTree(tree, debuggeeUrl).map(subtree => sortEntireTree(subtree)); - return _extends({}, tree, { contents }); - } - return tree; -} - -/** - * Look at the nodes in the source tree, and determine the index of where to - * insert a new node. The ordering is index -> folder -> file. - * @memberof utils/sources-tree - * @static - */ -function sortTree(tree, debuggeeUrl = "") { - return tree.contents.sort((previousNode, currentNode) => { - const currentNodeIsDir = (0, _utils.nodeHasChildren)(currentNode); - const previousNodeIsDir = (0, _utils.nodeHasChildren)(previousNode); - if (currentNode.name === "(index)") { - return 1; - } else if (previousNode.name === "(index)") { - return -1; - } else if ((0, _utils.isExactUrlMatch)(currentNode.name, debuggeeUrl)) { - return 1; - } else if ((0, _utils.isExactUrlMatch)(previousNode.name, debuggeeUrl)) { - return -1; - // If neither is the case, continue to compare alphabetically - } else if (previousNodeIsDir && !currentNodeIsDir) { - return -1; - } else if (!previousNodeIsDir && currentNodeIsDir) { - return 1; - } - return previousNode.name.localeCompare(currentNode.name); - }); -} - -/***/ }), - -/***/ 1545: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getDirectories = getDirectories; - -var _utils = __webpack_require__(1371); - -var _getURL = __webpack_require__(1405); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function findSource(sourceTree, sourceUrl) { - let returnTarget = null; - function _traverse(subtree) { - if ((0, _utils.nodeHasChildren)(subtree)) { - for (const child of subtree.contents) { - _traverse(child); - } - } else if (!returnTarget) { - if (subtree.path.replace(/http(s)?:\//, "") == sourceUrl) { - returnTarget = subtree; - return; - } - } - } - - sourceTree.contents.forEach(_traverse); - - if (!returnTarget) { - return sourceTree; - } - - return returnTarget; -} - -function getDirectories(sourceUrl, sourceTree) { - const url = (0, _getURL.getURL)(sourceUrl); - const fullUrl = `${url.group}${url.path}`; - const parentMap = (0, _utils.createParentMap)(sourceTree); - const source = findSource(sourceTree, fullUrl); - if (!source) { - return []; - } - - let node = source; - const directories = []; - directories.push(source); - while (true) { - node = parentMap.get(node); - if (!node) { - return directories; - } - directories.push(node); - } -} - -/***/ }), - -/***/ 1546: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createTree = createTree; - -var _addToTree = __webpack_require__(1443); - -var _collapseTree = __webpack_require__(1444); - -var _utils = __webpack_require__(1371); - -function createTree({ sources, debuggeeUrl, projectRoot }) { - const uncollapsedTree = (0, _utils.createNode)("root", "", []); - for (const source of sources.valueSeq()) { - (0, _addToTree.addToTree)(uncollapsedTree, source, debuggeeUrl, projectRoot); - } - - const sourceTree = (0, _collapseTree.collapseTree)(uncollapsedTree); - - return { - uncollapsedTree, - sourceTree, - parentMap: (0, _utils.createParentMap)(sourceTree), - focusedItem: null - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1551: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _text = __webpack_require__(1387); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _prefs = __webpack_require__(226); - -__webpack_require__(1318); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Outline = __webpack_require__(1552); - -var _Outline2 = _interopRequireDefault(_Outline); - -var _SourcesTree = __webpack_require__(1553); - -var _SourcesTree2 = _interopRequireDefault(_SourcesTree); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class PrimaryPanes extends _react.Component { - - constructor(props) { - super(props); - - this.showPane = selectedPane => { - this.props.setPrimaryPaneTab(selectedPane); - }; - - this.onAlphabetizeClick = () => { - const alphabetizeOutline = !_prefs.prefs.alphabetizeOutline; - _prefs.prefs.alphabetizeOutline = alphabetizeOutline; - this.setState({ alphabetizeOutline }); - }; - - this.renderTabs = () => { - return _react2.default.createElement( - "div", - { className: "source-outline-tabs" }, - this.renderOutlineTabs() - ); - }; - - this.renderShortcut = () => { - if (this.props.horizontal) { - const onClick = () => { - if (this.props.sourceSearchOn) { - return this.props.closeActiveSearch(); - } - this.props.setActiveSearch("source"); - }; - return _react2.default.createElement( - "span", - { className: "sources-header-info", dir: "ltr", onClick: onClick }, - L10N.getFormatStr("sources.search", (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"))) - ); - } - }; - - this.state = { - alphabetizeOutline: _prefs.prefs.alphabetizeOutline - }; - } - - renderOutlineTabs() { - if (!_prefs.features.outline) { - return; - } - - const sources = (0, _text.formatKeyShortcut)(L10N.getStr("sources.header")); - - const outline = (0, _text.formatKeyShortcut)(L10N.getStr("outline.header")); - - return [_react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("tab sources-tab", { - active: this.props.selectedTab === "sources" - }), - onClick: () => this.showPane("sources"), - key: "sources-tab" - }, - sources - ), _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("tab outline-tab", { - active: this.props.selectedTab === "outline" - }), - onClick: () => this.showPane("outline"), - key: "outline-tab" - }, - outline - )]; - } - - render() { - const { selectedTab } = this.props; - - return _react2.default.createElement( - "div", - { className: "sources-panel" }, - this.renderTabs(), - selectedTab === "sources" ? _react2.default.createElement(_SourcesTree2.default, null) : _react2.default.createElement(_Outline2.default, { - alphabetizeOutline: this.state.alphabetizeOutline, - onAlphabetizeClick: this.onAlphabetizeClick - }) - ); - } -} - -const mapStateToProps = state => ({ - selectedTab: (0, _selectors.getSelectedPrimaryPaneTab)(state), - sources: (0, _selectors.getSources)(state), - sourceSearchOn: (0, _selectors.getActiveSearch)(state) === "source" -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(PrimaryPanes); - -/***/ }), - -/***/ 1552: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Outline = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _devtoolsContextmenu = __webpack_require__(1413); - -var _reactRedux = __webpack_require__(3592); - -var _clipboard = __webpack_require__(1388); - -var _function = __webpack_require__(1597); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -__webpack_require__(1319); - -var _PreviewFunction = __webpack_require__(1446); - -var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction); - -var _lodash = __webpack_require__(2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Outline extends _react.Component { - selectItem(location) { - const { selectedSource, selectLocation } = this.props; - if (!selectedSource) { - return; - } - const selectedSourceId = selectedSource.get("id"); - const startLine = location.start.line; - selectLocation({ sourceId: selectedSourceId, line: startLine }); - } - - onContextMenu(event, func) { - event.stopPropagation(); - event.preventDefault(); - - const { - selectedSource, - getFunctionText, - flashLineRange, - selectedLocation - } = this.props; - - const copyFunctionKey = L10N.getStr("copyFunction.accesskey"); - const copyFunctionLabel = L10N.getStr("copyFunction.label"); - - if (!selectedSource) { - return; - } - - const sourceLine = func.location.start.line; - const functionText = getFunctionText(sourceLine); - - const copyFunctionItem = { - id: "node-menu-copy-function", - label: copyFunctionLabel, - accesskey: copyFunctionKey, - disabled: !functionText, - click: () => { - flashLineRange({ - start: func.location.start.line, - end: func.location.end.line, - sourceId: selectedLocation.sourceId - }); - return (0, _clipboard.copyToTheClipboard)(functionText); - } - }; - const menuOptions = [copyFunctionItem]; - (0, _devtoolsContextmenu.showMenu)(event, menuOptions); - } - - renderPlaceholder() { - const placeholderMessage = this.props.selectedSource ? L10N.getStr("outline.noFunctions") : L10N.getStr("outline.noFileSelected"); - - return _react2.default.createElement( - "div", - { className: "outline-pane-info" }, - placeholderMessage - ); - } - - renderLoading() { - return _react2.default.createElement( - "div", - { className: "outline-pane-info" }, - L10N.getStr("loadingText") - ); - } - - renderFunction(func) { - const { name, location, parameterNames } = func; - - return _react2.default.createElement( - "li", - { - key: `${name}:${location.start.line}:${location.start.column}`, - className: "outline-list__element", - onClick: () => this.selectItem(location), - onContextMenu: e => this.onContextMenu(e, func) - }, - _react2.default.createElement( - "span", - { className: "outline-list__element-icon" }, - "\u03BB" - ), - _react2.default.createElement(_PreviewFunction2.default, { func: { name, parameterNames } }) - ); - } - - renderClassFunctions(klass, functions) { - if (klass == null || functions.length == 0) { - return null; - } - - const classFunc = functions.find(func => func.name === klass); - const classFunctions = functions.filter(func => func.klass === klass); - const classInfo = this.props.symbols.classes.find(c => c.name === klass); - - const heading = classFunc ? _react2.default.createElement( - "h2", - null, - this.renderFunction(classFunc) - ) : _react2.default.createElement( - "h2", - { - onClick: classInfo ? () => this.selectItem(classInfo.location) : null - }, - _react2.default.createElement( - "span", - { className: "keyword" }, - "class" - ), - " ", - klass - ); - - return _react2.default.createElement( - "div", - { className: "outline-list__class", key: klass }, - heading, - _react2.default.createElement( - "ul", - { className: "outline-list__class-list" }, - classFunctions.map(func => this.renderFunction(func)) - ) - ); - } - - renderFunctions(functions) { - let classes = (0, _lodash.uniq)(functions.map(func => func.klass)); - let namedFunctions = functions.filter(func => func.name != "anonymous" && !func.klass && !classes.includes(func.name)); - - let classFunctions = functions.filter(func => func.name != "anonymous" && !!func.klass); - - if (this.props.alphabetizeOutline) { - namedFunctions = (0, _lodash.sortBy)(namedFunctions, "name"); - classes = (0, _lodash.sortBy)(classes, "klass"); - classFunctions = (0, _lodash.sortBy)(classFunctions, "name"); - } - - return _react2.default.createElement( - "div", - null, - _react2.default.createElement( - "ul", - { className: "outline-list" }, - namedFunctions.map(func => this.renderFunction(func)), - classes.map(klass => this.renderClassFunctions(klass, classFunctions)) - ), - _react2.default.createElement( - "div", - { className: "outline-footer bottom" }, - _react2.default.createElement( - "button", - { - onClick: () => { - this.props.onAlphabetizeClick(); - }, - className: this.props.alphabetizeOutline ? "active" : "" - }, - L10N.getStr("outline.sortLabel") - ) - ) - ); - } - - render() { - const { symbols, selectedSource } = this.props; - if (!selectedSource) { - return this.renderPlaceholder(); - } - if (!symbols || symbols.loading) { - return this.renderLoading(); - } - const symbolsToDisplay = symbols.functions.filter(func => func.name != "anonymous"); - return _react2.default.createElement( - "div", - { className: "outline" }, - symbolsToDisplay.length > 0 ? this.renderFunctions(symbols.functions) : this.renderPlaceholder() - ); - } -} - -exports.Outline = Outline; -const mapStateToProps = state => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - const symbols = (0, _selectors.getSymbols)(state, selectedSource); - return { - symbols, - selectedSource, - selectedLocation: (0, _selectors.getSelectedLocation)(state), - getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols) - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Outline); - -/***/ }), - -/***/ 1553: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _devtoolsContextmenu = __webpack_require__(1413); - -var _reactRedux = __webpack_require__(3592); - -var _selectors = __webpack_require__(3590); - -var _sourceTree = __webpack_require__(1532); - -var _sources = __webpack_require__(1797); - -var _ui = __webpack_require__(1385); - -var _ManagedTree = __webpack_require__(1404); - -var _ManagedTree2 = _interopRequireDefault(_ManagedTree); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _sourcesTree = __webpack_require__(1442); - -var _source = __webpack_require__(1356); - -var _clipboard = __webpack_require__(1388); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// Utils - - -// Components - - -// Selectors -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -class SourcesTree extends _react.Component { - - constructor(props) { - super(props); - - _initialiseProps.call(this); - - const { debuggeeUrl, sources, projectRoot } = this.props; - - this.state = (0, _sourcesTree.createTree)({ - projectRoot, - debuggeeUrl, - sources - }); - } - - componentWillReceiveProps(nextProps) { - const { - projectRoot, - debuggeeUrl, - sources, - shownSource, - selectedSource - } = this.props; - - const { uncollapsedTree, sourceTree } = this.state; - - if (projectRoot != nextProps.projectRoot || debuggeeUrl != nextProps.debuggeeUrl || nextProps.sources.size === 0) { - // early recreate tree because of changes - // to project root, debugee url or lack of sources - return this.setState((0, _sourcesTree.createTree)({ - sources: nextProps.sources, - debuggeeUrl: nextProps.debuggeeUrl, - projectRoot: nextProps.projectRoot - })); - } - if (nextProps.shownSource && nextProps.shownSource != shownSource) { - const listItems = (0, _sourcesTree.getDirectories)(nextProps.shownSource, sourceTree); - - if (listItems && listItems[0]) { - this.selectItem(listItems[0]); - } - - return this.setState({ listItems }); - } - - if (nextProps.selectedSource && nextProps.selectedSource != selectedSource) { - const highlightItems = (0, _sourcesTree.getDirectories)((0, _source.getRawSourceURL)(nextProps.selectedSource.get("url")), sourceTree); - - return this.setState({ highlightItems }); - } - - // NOTE: do not run this every time a source is clicked, - // only when a new source is added - if (nextProps.sources != this.props.sources) { - this.setState((0, _sourcesTree.updateTree)({ - newSources: nextProps.sources, - prevSources: sources, - debuggeeUrl, - projectRoot, - uncollapsedTree, - sourceTree - })); - } - } - - renderItemName(name) { - const hosts = { - "ng://": "Angular", - "webpack://": "Webpack", - "moz-extension://": L10N.getStr("extensionsText") - }; - - return hosts[name] || name; - } - - renderEmptyElement(message) { - return _react2.default.createElement( - "div", - { className: "no-sources-message" }, - message - ); - } - - render() { - const { expanded, projectRoot } = this.props; - const { - focusedItem, - highlightItems, - listItems, - parentMap, - sourceTree - } = this.state; - - const onExpand = (item, expandedState) => { - this.props.setExpandedState(expandedState); - }; - - const onCollapse = (item, expandedState) => { - this.props.setExpandedState(expandedState); - }; - - const isEmpty = sourceTree.contents.length === 0; - - const isCustomRoot = projectRoot !== ""; - let roots = () => sourceTree.contents; - - let clearProjectRootButton = null; - - // The "sourceTree.contents[0]" check ensures that there are contents - // A custom root with no existing sources will be ignored - if (isCustomRoot) { - const sourceContents = sourceTree.contents[0]; - let rootLabel = projectRoot.split("/").pop(); - roots = () => sourceContents.contents; - if (sourceContents && sourceContents.name !== rootLabel) { - rootLabel = sourceContents.contents[0].name; - roots = () => sourceContents.contents[0].contents; - } - - clearProjectRootButton = _react2.default.createElement( - "button", - { - className: "sources-clear-root", - onClick: () => this.props.clearProjectDirectoryRoot(), - title: L10N.getStr("removeDirectoryRoot.label") - }, - _react2.default.createElement(_Svg2.default, { name: "home" }), - _react2.default.createElement(_Svg2.default, { name: "breadcrumb", "class": true }), - _react2.default.createElement( - "span", - { className: "sources-clear-root-label" }, - rootLabel - ) - ); - } - - if (isEmpty && !isCustomRoot) { - return this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable")); - } - - const treeProps = { - autoExpandAll: false, - autoExpandDepth: expanded ? 0 : 1, - expanded, - getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [], - getParent: item => parentMap.get(item), - getPath: this.getPath, - getRoots: roots, - highlightItems, - itemHeight: 21, - key: isEmpty ? "empty" : "full", - listItems, - onCollapse, - onExpand, - onFocus: this.focusItem, - renderItem: this.renderItem - }; - - const tree = _react2.default.createElement(_ManagedTree2.default, treeProps); - - const onKeyDown = e => { - if (e.keyCode === 13 && focusedItem) { - this.selectItem(focusedItem); - } - }; - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("sources-pane", { - "sources-list-custom-root": isCustomRoot - }) - }, - isCustomRoot ? _react2.default.createElement( - "div", - { className: "sources-clear-root-container" }, - clearProjectRootButton - ) : null, - isEmpty ? this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailableRoot")) : _react2.default.createElement( - "div", - { className: "sources-list", onKeyDown: onKeyDown }, - tree - ) - ); - } -} - -// Actions - -var _initialiseProps = function () { - this.focusItem = item => { - this.setState({ focusedItem: item }); - }; - - this.selectItem = item => { - if (!(0, _sourcesTree.nodeHasChildren)(item)) { - this.props.selectLocation({ sourceId: item.contents.get("id") }); - } - }; - - this.getPath = item => { - const { sources } = this.props; - const obj = item.contents.get && item.contents.get("id"); - - let blackBoxedPart = ""; - - if (typeof obj !== "undefined" && sources.has(obj) && sources.get(obj).get("isBlackBoxed")) { - blackBoxedPart = "update"; - } - - return `${item.path}/${item.name}/${blackBoxedPart}`; - }; - - this.getIcon = (sources, item, depth) => { - const { debuggeeUrl, projectRoot } = this.props; - - if (item.path === "webpack://") { - return _react2.default.createElement(_Svg2.default, { name: "webpack" }); - } else if (item.path === "ng://") { - return _react2.default.createElement(_Svg2.default, { name: "angular" }); - } else if (item.path === "moz-extension://") { - return _react2.default.createElement("img", { className: "extension" }); - } - - if (depth === 0 && projectRoot === "") { - return _react2.default.createElement("img", { - className: (0, _classnames2.default)("domain", { - debuggee: debuggeeUrl && debuggeeUrl.includes(item.name) - }) - }); - } - - if (!(0, _sourcesTree.nodeHasChildren)(item)) { - const obj = item.contents.get("id"); - const source = sources.get(obj); - const className = (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "source-icon"); - return _react2.default.createElement("img", { className: className }); - } - return _react2.default.createElement("img", { className: "folder" }); - }; - - this.onContextMenu = (event, item) => { - const copySourceUri2Label = L10N.getStr("copySourceUri2"); - const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey"); - const setDirectoryRootLabel = L10N.getStr("setDirectoryRoot.label"); - const setDirectoryRootKey = L10N.getStr("setDirectoryRoot.accesskey"); - const removeDirectoryRootLabel = L10N.getStr("removeDirectoryRoot.label"); - - event.stopPropagation(); - event.preventDefault(); - - const menuOptions = []; - - if (!(0, _sourcesTree.isDirectory)(item)) { - const source = item.contents.get("url"); - const copySourceUri2 = { - id: "node-menu-copy-source", - label: copySourceUri2Label, - accesskey: copySourceUri2Key, - disabled: false, - click: () => (0, _clipboard.copyToTheClipboard)(source) - }; - - menuOptions.push(copySourceUri2); - } - - if ((0, _sourcesTree.isDirectory)(item) && _prefs.features.root) { - const { path } = item; - const { projectRoot } = this.props; - - if (projectRoot.endsWith(path)) { - menuOptions.push({ - id: "node-remove-directory-root", - label: removeDirectoryRootLabel, - disabled: false, - click: () => this.props.clearProjectDirectoryRoot() - }); - } else { - menuOptions.push({ - id: "node-set-directory-root", - label: setDirectoryRootLabel, - accesskey: setDirectoryRootKey, - disabled: false, - click: () => this.props.setProjectDirectoryRoot(path) - }); - } - } - - (0, _devtoolsContextmenu.showMenu)(event, menuOptions); - }; - - this.renderItem = (item, depth, focused, _, expanded, { setExpanded }) => { - const arrow = (0, _sourcesTree.nodeHasChildren)(item) ? _react2.default.createElement("img", { - className: (0, _classnames2.default)("arrow", { - expanded: expanded - }) - }) : _react2.default.createElement("i", { className: "no-arrow" }); - - const { sources } = this.props; - const icon = this.getIcon(sources, item, depth); - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("node", { focused }), - key: item.path, - onClick: e => { - this.focusItem(item); - - if ((0, _sourcesTree.isDirectory)(item)) { - setExpanded(item, !!expanded, e.altKey); - } else { - this.selectItem(item); - } - }, - onContextMenu: e => this.onContextMenu(e, item) - }, - arrow, - icon, - _react2.default.createElement( - "span", - { className: "label" }, - " ", - this.renderItemName(item.name), - " " - ) - ); - }; -}; - -const mapStateToProps = state => { - return { - shownSource: (0, _selectors.getShownSource)(state), - selectedSource: (0, _selectors.getSelectedSource)(state), - debuggeeUrl: (0, _selectors.getDebuggeeUrl)(state), - expanded: (0, _selectors.getExpandedState)(state), - projectRoot: (0, _selectors.getProjectDirectoryRoot)(state), - sources: (0, _selectors.getSources)(state) - }; -}; - -const actionCreators = { - setExpandedState: _sourceTree.setExpandedState, - selectLocation: _sources.selectLocation, - setProjectDirectoryRoot: _ui.setProjectDirectoryRoot, - clearProjectDirectoryRoot: _ui.clearProjectDirectoryRoot -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, actionCreators)(SourcesTree); - -/***/ }), - -/***/ 1554: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _reactRedux = __webpack_require__(3592); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _source = __webpack_require__(1356); - -var _devtoolsEnvironment = __webpack_require__(3721); - -var _prefs = __webpack_require__(226); - -var _indentation = __webpack_require__(1438); - -var _selectors = __webpack_require__(3590); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _Footer = __webpack_require__(1555); - -var _Footer2 = _interopRequireDefault(_Footer); - -var _SearchBar = __webpack_require__(1556); - -var _SearchBar2 = _interopRequireDefault(_SearchBar); - -var _HighlightLines = __webpack_require__(1557); - -var _HighlightLines2 = _interopRequireDefault(_HighlightLines); - -var _Preview = __webpack_require__(1558); - -var _Preview2 = _interopRequireDefault(_Preview); - -var _Breakpoints = __webpack_require__(1588); - -var _Breakpoints2 = _interopRequireDefault(_Breakpoints); - -var _HitMarker = __webpack_require__(1590); - -var _HitMarker2 = _interopRequireDefault(_HitMarker); - -var _CallSites = __webpack_require__(1591); - -var _CallSites2 = _interopRequireDefault(_CallSites); - -var _DebugLine = __webpack_require__(1593); - -var _DebugLine2 = _interopRequireDefault(_DebugLine); - -var _HighlightLine = __webpack_require__(1796); - -var _HighlightLine2 = _interopRequireDefault(_HighlightLine); - -var _EmptyLines = __webpack_require__(1594); - -var _EmptyLines2 = _interopRequireDefault(_EmptyLines); - -var _GutterMenu = __webpack_require__(1595); - -var _GutterMenu2 = _interopRequireDefault(_GutterMenu); - -var _EditorMenu = __webpack_require__(1596); - -var _EditorMenu2 = _interopRequireDefault(_EditorMenu); - -var _ConditionalPanel = __webpack_require__(1598); - -var _ConditionalPanel2 = _interopRequireDefault(_ConditionalPanel); - -var _editor = __webpack_require__(1358); - -var _ui = __webpack_require__(1439); - -__webpack_require__(1332); - -__webpack_require__(1333); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// Redux actions -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const cssVars = { - searchbarHeight: "var(--editor-searchbar-height)", - secondSearchbarHeight: "var(--editor-second-searchbar-height)", - footerHeight: "var(--editor-footer-height)" -}; - -class Editor extends _react.PureComponent { - constructor(props) { - super(props); - - this.onToggleBreakpoint = (key, e) => { - e.preventDefault(); - e.stopPropagation(); - const { selectedSource, conditionalPanelLine } = this.props; - - if (!selectedSource) { - return; - } - - const line = this.getCurrentLine(); - - if (e.shiftKey) { - this.toggleConditionalPanel(line); - } else if (!conditionalPanelLine) { - this.props.toggleBreakpoint(line); - } else { - this.toggleConditionalPanel(line); - this.props.toggleBreakpoint(line); - } - }; - - this.onToggleConditionalPanel = (key, e) => { - e.stopPropagation(); - e.preventDefault(); - const line = this.getCurrentLine(); - this.toggleConditionalPanel(line); - }; - - this.onEscape = (key, e) => { - if (!this.state.editor) { - return; - } - - const { codeMirror } = this.state.editor; - if (codeMirror.listSelections().length > 1) { - codeMirror.execCommand("singleSelection"); - e.preventDefault(); - } - }; - - this.onSearchAgain = (_, e) => { - this.props.traverseResults(e.shiftKey, this.state.editor); - }; - - this.onGutterClick = (cm, line, gutter, ev) => { - const { - selectedSource, - conditionalPanelLine, - closeConditionalPanel, - addOrToggleDisabledBreakpoint, - toggleBreakpoint, - continueToHere - } = this.props; - - // ignore right clicks in the gutter - if (ev.ctrlKey && ev.button === 0 || ev.which === 3 || selectedSource && selectedSource.isBlackBoxed || !selectedSource) { - return; - } - - if (conditionalPanelLine) { - return closeConditionalPanel(); - } - - if (gutter === "CodeMirror-foldgutter") { - return; - } - - const sourceLine = (0, _editor.toSourceLine)(selectedSource.get("id"), line); - - if (ev.altKey) { - return continueToHere(sourceLine); - } - - if (ev.shiftKey) { - return addOrToggleDisabledBreakpoint(sourceLine); - } - - return toggleBreakpoint(sourceLine); - }; - - this.onGutterContextMenu = event => { - event.stopPropagation(); - event.preventDefault(); - return this.props.setContextMenu("Gutter", event); - }; - - this.toggleConditionalPanel = line => { - const { - conditionalPanelLine, - closeConditionalPanel, - openConditionalPanel - } = this.props; - - if (conditionalPanelLine) { - return closeConditionalPanel(); - } - - return openConditionalPanel(line); - }; - - this.closeConditionalPanel = () => { - return this.props.closeConditionalPanel(); - }; - - this.state = { - highlightedLineRange: null, - editor: null - }; - } - - componentWillReceiveProps(nextProps) { - if (!this.state.editor) { - return; - } - - (0, _ui.resizeBreakpointGutter)(this.state.editor.codeMirror); - (0, _ui.resizeToggleButton)(this.state.editor.codeMirror); - } - - componentWillUpdate(nextProps) { - this.setText(nextProps); - this.setSize(nextProps); - this.scrollToLocation(nextProps); - } - - setupEditor() { - const editor = (0, _editor.createEditor)(); - - // disables the default search shortcuts - // $FlowIgnore - editor._initShortcuts = () => {}; - - const node = _reactDom2.default.findDOMNode(this); - if (node instanceof HTMLElement) { - editor.appendToLocalElement(node.querySelector(".editor-mount")); - } - - const { codeMirror } = editor; - const codeMirrorWrapper = codeMirror.getWrapperElement(); - - (0, _ui.resizeBreakpointGutter)(codeMirror); - (0, _ui.resizeToggleButton)(codeMirror); - - codeMirror.on("gutterClick", this.onGutterClick); - - // Set code editor wrapper to be focusable - codeMirrorWrapper.tabIndex = 0; - codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e)); - codeMirrorWrapper.addEventListener("click", e => this.onClick(e)); - - const toggleFoldMarkerVisibility = e => { - if (node instanceof HTMLElement) { - node.querySelectorAll(".CodeMirror-guttermarker-subtle").forEach(elem => { - elem.classList.toggle("visible"); - }); - } - }; - - const codeMirrorGutter = codeMirror.getGutterElement(); - codeMirrorGutter.addEventListener("mouseleave", toggleFoldMarkerVisibility); - codeMirrorGutter.addEventListener("mouseenter", toggleFoldMarkerVisibility); - - if (!(0, _devtoolsEnvironment.isFirefox)()) { - codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => this.onGutterContextMenu(event)); - codeMirror.on("contextmenu", (cm, event) => this.openMenu(event)); - } else { - codeMirrorWrapper.addEventListener("contextmenu", event => this.openMenu(event)); - } - - this.setState({ editor }); - (0, _editor.setEditor)(editor); - return editor; - } - - componentDidMount() { - const { shortcuts } = this.context; - - const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2"); - const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2"); - - shortcuts.on(L10N.getStr("toggleBreakpoint.key"), this.onToggleBreakpoint); - shortcuts.on(L10N.getStr("toggleCondPanel.key"), this.onToggleConditionalPanel); - shortcuts.on("Esc", this.onEscape); - shortcuts.on(searchAgainPrevKey, this.onSearchAgain); - shortcuts.on(searchAgainKey, this.onSearchAgain); - } - - componentWillUnmount() { - if (this.state.editor) { - this.state.editor.destroy(); - this.setState({ editor: null }); - } - - const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2"); - const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2"); - const shortcuts = this.context.shortcuts; - shortcuts.off(L10N.getStr("toggleBreakpoint.key")); - shortcuts.off(L10N.getStr("toggleCondPanel.key")); - shortcuts.off(searchAgainPrevKey); - shortcuts.off(searchAgainKey); - } - - componentDidUpdate(prevProps, prevState) { - const { selectedSource } = this.props; - // NOTE: when devtools are opened, the editor is not set when - // the source loads so we need to wait until the editor is - // set to update the text and size. - if (!prevState.editor && selectedSource) { - if (!this.state.editor) { - const editor = this.setupEditor(); - (0, _editor.updateDocument)(editor, selectedSource); - } else { - this.setText(this.props); - this.setSize(this.props); - } - } - } - - getCurrentLine() { - const { codeMirror } = this.state.editor; - const { selectedSource } = this.props; - const line = (0, _editor.getCursorLine)(codeMirror); - - return (0, _editor.toSourceLine)(selectedSource.get("id"), line); - } - - onKeyDown(e) { - const { codeMirror } = this.state.editor; - const { key, target } = e; - const codeWrapper = codeMirror.getWrapperElement(); - const textArea = codeWrapper.querySelector("textArea"); - - if (key === "Escape" && target == textArea) { - e.stopPropagation(); - e.preventDefault(); - codeWrapper.focus(); - } else if (key === "Enter" && target == codeWrapper) { - e.preventDefault(); - // Focus into editor's text area - textArea.focus(); - } - } - - /* - * The default Esc command is overridden in the CodeMirror keymap to allow - * the Esc keypress event to be catched by the toolbox and trigger the - * split console. Restore it here, but preventDefault if and only if there - * is a multiselection. - */ - - - openMenu(event) { - event.stopPropagation(); - event.preventDefault(); - - const { setContextMenu } = this.props; - if (event.target.classList.contains("CodeMirror-linenumber")) { - return setContextMenu("Gutter", event); - } - - return setContextMenu("Editor", event); - } - - onClick(e) { - const { selectedLocation, jumpToMappedLocation } = this.props; - - if (e.metaKey && e.altKey) { - const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(this.state.editor, selectedLocation, e); - jumpToMappedLocation(sourceLocation); - } - } - - shouldScrollToLocation(nextProps) { - const { selectedLocation, selectedSource } = this.props; - const { editor } = this.state; - - if (!nextProps.selectedSource || !editor || !nextProps.selectedLocation) { - return false; - } - - if (!(0, _source.isLoaded)(nextProps.selectedSource)) { - return false; - } - - if (!nextProps.selectedLocation.line) { - return false; - } - - const isFirstLoad = (!selectedSource || !(0, _source.isLoaded)(selectedSource)) && (0, _source.isLoaded)(nextProps.selectedSource); - - const locationChanged = selectedLocation !== nextProps.selectedLocation; - return isFirstLoad || locationChanged; - } - - scrollToLocation(nextProps) { - const { editor } = this.state; - - if (this.shouldScrollToLocation(nextProps)) { - let { line, column } = (0, _editor.toEditorPosition)(nextProps.selectedLocation); - - if ((0, _editor.hasDocument)(nextProps.selectedSource.get("id"))) { - const doc = (0, _editor.getDocument)(nextProps.selectedSource.get("id")); - const lineText = doc.getLine(line); - column = Math.max(column, (0, _indentation.getIndentation)(lineText)); - } - (0, _editor.scrollToColumn)(editor.codeMirror, line, column); - } - } - - setSize(nextProps) { - if (!this.state.editor) { - return; - } - - if (nextProps.startPanelSize !== this.props.startPanelSize || nextProps.endPanelSize !== this.props.endPanelSize) { - this.state.editor.codeMirror.setSize(); - } - } - - setText(props) { - const { selectedSource, symbols } = props; - - if (!this.state.editor) { - return; - } - - // check if we previously had a selected source - if (!selectedSource) { - return this.clearEditor(); - } - - if (!(0, _source.isLoaded)(selectedSource)) { - return (0, _editor.showLoading)(this.state.editor); - } - - if (selectedSource.get("error")) { - return this.showErrorMessage(selectedSource.get("error")); - } - if (selectedSource) { - return (0, _editor.showSourceText)(this.state.editor, selectedSource.toJS(), symbols); - } - } - - clearEditor() { - const { editor } = this.state; - if (!editor) { - return; - } - - (0, _editor.clearEditor)(editor); - } - - showErrorMessage(msg) { - const { editor } = this.state; - if (!editor) { - return; - } - - (0, _editor.showErrorMessage)(editor, msg); - } - - getInlineEditorStyles() { - const { selectedSource, horizontal, searchOn } = this.props; - - const subtractions = []; - - if ((0, _editor.shouldShowFooter)(selectedSource, horizontal)) { - subtractions.push(cssVars.footerHeight); - } - - if (searchOn) { - subtractions.push(cssVars.searchbarHeight); - subtractions.push(cssVars.secondSearchbarHeight); - } - - return { - height: subtractions.length === 0 ? "100%" : `calc(100% - ${subtractions.join(" - ")})` - }; - } - - renderHitCounts() { - const { hitCount, selectedSource } = this.props; - - if (!selectedSource || !(0, _source.isLoaded)(selectedSource) || !hitCount || !this.state.editor) { - return; - } - - return hitCount.filter(marker => marker.get("count") > 0).map(marker => _react2.default.createElement(_HitMarker2.default, { - key: marker.get("line"), - hitData: marker.toJS(), - editor: this.state.editor.codeMirror - })); - } - - renderItems() { - const { horizontal, selectedSource } = this.props; - const { editor } = this.state; - - if (!editor || !selectedSource) { - return null; - } - - return _react2.default.createElement( - "div", - null, - _react2.default.createElement(_DebugLine2.default, null), - _react2.default.createElement(_HighlightLine2.default, null), - _react2.default.createElement(_EmptyLines2.default, { editor: editor }), - _react2.default.createElement(_Breakpoints2.default, { editor: editor }), - _react2.default.createElement(_Preview2.default, { editor: editor, editorRef: this.$editorWrapper }), - ";", - _react2.default.createElement(_Footer2.default, { editor: editor, horizontal: horizontal }), - _react2.default.createElement(_HighlightLines2.default, { editor: editor }), - _react2.default.createElement(_EditorMenu2.default, { editor: editor }), - _react2.default.createElement(_GutterMenu2.default, { editor: editor }), - _react2.default.createElement(_ConditionalPanel2.default, { editor: editor }), - _prefs.features.columnBreakpoints ? _react2.default.createElement(_CallSites2.default, { editor: editor }) : null, - this.renderHitCounts() - ); - } - - renderSearchBar() { - const { editor } = this.state; - - if (!editor) { - return null; - } - - return _react2.default.createElement(_SearchBar2.default, { editor: editor }); - } - - render() { - const { coverageOn } = this.props; - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("editor-wrapper", { - "coverage-on": coverageOn - }), - ref: c => this.$editorWrapper = c - }, - this.renderSearchBar(), - _react2.default.createElement("div", { - className: "editor-mount devtools-monospace", - style: this.getInlineEditorStyles() - }), - this.renderItems() - ); - } -} - -Editor.contextTypes = { - shortcuts: _propTypes2.default.object -}; - -const mapStateToProps = state => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - const sourceId = selectedSource ? selectedSource.get("id") : ""; - - return { - selectedLocation: (0, _selectors.getSelectedLocation)(state), - selectedSource, - searchOn: (0, _selectors.getActiveSearch)(state) === "file", - hitCount: (0, _selectors.getHitCountForSource)(state, sourceId), - coverageOn: (0, _selectors.getCoverageEnabled)(state), - conditionalPanelLine: (0, _selectors.getConditionalPanelLine)(state), - symbols: (0, _selectors.getSymbols)(state, selectedSource && selectedSource.toJS()) - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Editor); - -/***/ }), - -/***/ 1555: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _prefs = __webpack_require__(226); - -var _source = __webpack_require__(1356); - -var _sources = __webpack_require__(1369); - -var _editor = __webpack_require__(1358); - -var _PaneToggle = __webpack_require__(1407); - -var _PaneToggle2 = _interopRequireDefault(_PaneToggle); - -__webpack_require__(1322); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class SourceFooter extends _react.PureComponent { - prettyPrintButton() { - const { selectedSource, togglePrettyPrint } = this.props; - const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource); - - if (!(0, _editor.shouldShowPrettyPrint)(selectedSource)) { - return; - } - - const tooltip = L10N.getStr("sourceTabs.prettyPrint"); - - const type = "prettyPrint"; - return _react2.default.createElement( - "button", - { - onClick: () => togglePrettyPrint(selectedSource.get("id")), - className: (0, _classnames2.default)("action", type, { - active: sourceLoaded, - pretty: (0, _source.isPretty)(selectedSource) - }), - key: type, - title: tooltip, - "aria-label": tooltip - }, - _react2.default.createElement("img", { className: type }) - ); - } - - blackBoxButton() { - const { selectedSource, toggleBlackBox } = this.props; - const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource); - - if (!sourceLoaded) { - return; - } - - const blackboxed = selectedSource.isBlackBoxed; - - const tooltip = L10N.getStr("sourceFooter.blackbox"); - const type = "black-box"; - - return _react2.default.createElement( - "button", - { - onClick: () => toggleBlackBox(selectedSource.toJS()), - className: (0, _classnames2.default)("action", type, { - active: sourceLoaded, - blackboxed: blackboxed - }), - key: type, - title: tooltip, - "aria-label": tooltip - }, - _react2.default.createElement("img", { className: "blackBox" }) - ); - } - - blackBoxSummary() { - const { selectedSource } = this.props; - - if (!selectedSource || !selectedSource.isBlackBoxed) { - return; - } - - return _react2.default.createElement( - "span", - { className: "blackbox-summary" }, - L10N.getStr("sourceFooter.blackboxed") - ); - } - - coverageButton() { - const { recordCoverage } = this.props; - - if (!_prefs.features.codeCoverage) { - return; - } - - return _react2.default.createElement( - "button", - { - className: "coverage action", - title: L10N.getStr("sourceFooter.codeCoverage"), - onClick: () => recordCoverage(), - "aria-label": L10N.getStr("sourceFooter.codeCoverage") - }, - "C" - ); - } - - renderToggleButton() { - if (this.props.horizontal) { - return; - } - - return _react2.default.createElement(_PaneToggle2.default, { - position: "end", - collapsed: !this.props.endPanelCollapsed, - horizontal: this.props.horizontal, - handleClick: this.props.togglePaneCollapse - }); - } - - renderCommands() { - return _react2.default.createElement( - "div", - { className: "commands" }, - this.prettyPrintButton(), - this.blackBoxButton(), - this.blackBoxSummary(), - this.coverageButton() - ); - } - - renderSourceSummary() { - const { mappedSource, jumpToMappedLocation, selectedSource } = this.props; - if (mappedSource) { - const bundleSource = mappedSource.toJS(); - const filename = (0, _source.getFilename)(bundleSource); - const tooltip = L10N.getFormatStr("sourceFooter.mappedSourceTooltip", filename); - const title = L10N.getFormatStr("sourceFooter.mappedSource", filename); - const mappedSourceLocation = { - sourceId: selectedSource.get("id"), - line: 1, - column: 1 - }; - return _react2.default.createElement( - "button", - { - className: "mapped-source", - onClick: () => jumpToMappedLocation(mappedSourceLocation), - title: tooltip - }, - _react2.default.createElement( - "span", - null, - title - ) - ); - } - return null; - } - - render() { - const { selectedSource, horizontal } = this.props; - - if (!(0, _editor.shouldShowFooter)(selectedSource, horizontal)) { - return null; - } - - return _react2.default.createElement( - "div", - { className: "source-footer" }, - this.renderCommands(), - this.renderSourceSummary(), - this.renderToggleButton() - ); - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const mapStateToProps = state => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - const selectedId = selectedSource.get("id"); - const source = selectedSource.toJS(); - - return { - selectedSource, - mappedSource: (0, _sources.getGeneratedSource)(state, source), - prettySource: (0, _selectors.getPrettySource)(state, selectedId), - endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end") - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SourceFooter); - -/***/ }), - -/***/ 1556: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _editor = __webpack_require__(1358); - -var _resultList = __webpack_require__(1406); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _SearchInput = __webpack_require__(1379); - -var _SearchInput2 = _interopRequireDefault(_SearchInput); - -var _lodash = __webpack_require__(2); - -__webpack_require__(1323); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getShortcuts() { - const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2"); - const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2"); - const searchKey = L10N.getStr("sourceSearch.search.key2"); - - return { - shiftSearchAgainShortcut: searchAgainPrevKey, - searchAgainShortcut: searchAgainKey, - searchShortcut: searchKey - }; -} - -class SearchBar extends _react.Component { - constructor(props) { - super(props); - - this.onEscape = e => { - this.closeSearch(e); - }; - - this.clearSearch = () => { - const { editor: ed, query } = this.props; - if (ed) { - const ctx = { ed, cm: ed.codeMirror }; - (0, _editor.removeOverlay)(ctx, query); - } - }; - - this.closeSearch = e => { - const { closeFileSearch, editor, searchOn } = this.props; - if (editor && searchOn) { - this.clearSearch(); - closeFileSearch(editor); - e.stopPropagation(); - e.preventDefault(); - } - this.setState({ query: "", inputFocused: false }); - }; - - this.toggleSearch = e => { - e.stopPropagation(); - e.preventDefault(); - const { editor, searchOn, setActiveSearch } = this.props; - - if (!searchOn) { - setActiveSearch("file"); - } - - if (searchOn && editor) { - const query = editor.codeMirror.getSelection() || this.state.query; - - if (query !== "") { - this.setState({ query, inputFocused: true }); - this.doSearch(query); - } else { - this.setState({ query: "", inputFocused: true }); - } - } - }; - - this.doSearch = query => { - const { selectedSource } = this.props; - if (!selectedSource || !selectedSource.get("text")) { - return; - } - - this.props.doSearch(query, this.props.editor); - }; - - this.updateSearchResults = (characterIndex, line, matches) => { - const matchIndex = matches.findIndex(elm => elm.line === line && elm.ch === characterIndex); - this.props.updateSearchResults({ - matches, - matchIndex, - count: matches.length, - index: characterIndex - }); - }; - - this.traverseResults = (e, rev) => { - e.stopPropagation(); - e.preventDefault(); - const editor = this.props.editor; - - if (!editor) { - return; - } - this.props.traverseResults(rev, editor); - }; - - this.onChange = e => { - this.setState({ query: e.target.value }); - - return this.doSearch(e.target.value); - }; - - this.onBlur = e => { - this.setState({ inputFocused: false }); - }; - - this.onKeyDown = e => { - if (e.key !== "Enter" && e.key !== "F3") { - return; - } - - this.traverseResults(e, e.shiftKey); - e.preventDefault(); - }; - - this.renderSearchModifiers = () => { - const { modifiers, toggleFileSearchModifier, query } = this.props; - const { doSearch } = this; - - function SearchModBtn({ modVal, className, svgName, tooltip }) { - const preppedClass = (0, _classnames2.default)(className, { - active: modifiers && modifiers.get(modVal) - }); - return _react2.default.createElement( - "button", - { - className: preppedClass, - onClick: () => { - toggleFileSearchModifier(modVal); - doSearch(query); - }, - title: tooltip - }, - _react2.default.createElement(_Svg2.default, { name: svgName }) - ); - } - - return _react2.default.createElement( - "div", - { className: "search-modifiers" }, - _react2.default.createElement( - "span", - { className: "search-type-name" }, - L10N.getStr("symbolSearch.searchModifier.modifiersLabel") - ), - _react2.default.createElement(SearchModBtn, { - modVal: "regexMatch", - className: "regex-match-btn", - svgName: "regex-match", - tooltip: L10N.getStr("symbolSearch.searchModifier.regex") - }), - _react2.default.createElement(SearchModBtn, { - modVal: "caseSensitive", - className: "case-sensitive-btn", - svgName: "case-match", - tooltip: L10N.getStr("symbolSearch.searchModifier.caseSensitive") - }), - _react2.default.createElement(SearchModBtn, { - modVal: "wholeWord", - className: "whole-word-btn", - svgName: "whole-word-match", - tooltip: L10N.getStr("symbolSearch.searchModifier.wholeWord") - }) - ); - }; - - this.state = { - query: props.query, - selectedResultIndex: 0, - count: 0, - index: -1, - inputFocused: false - }; - } - - componentWillUnmount() { - const shortcuts = this.context.shortcuts; - const { - searchShortcut, - searchAgainShortcut, - shiftSearchAgainShortcut - } = getShortcuts(); - - shortcuts.off(searchShortcut); - shortcuts.off("Escape"); - shortcuts.off(searchAgainShortcut); - shortcuts.off(shiftSearchAgainShortcut); - } - - componentDidMount() { - // overwrite this.doSearch with debounced version to - // reduce frequency of queries - this.doSearch = (0, _lodash.debounce)(this.doSearch, 100); - const shortcuts = this.context.shortcuts; - const { - searchShortcut, - searchAgainShortcut, - shiftSearchAgainShortcut - } = getShortcuts(); - - shortcuts.on(searchShortcut, (_, e) => this.toggleSearch(e)); - shortcuts.on("Escape", (_, e) => this.onEscape(e)); - - shortcuts.on(shiftSearchAgainShortcut, (_, e) => this.traverseResults(e, true)); - - shortcuts.on(searchAgainShortcut, (_, e) => this.traverseResults(e, false)); - } - - componentDidUpdate(prevProps, prevState) { - if (this.refs.resultList && this.refs.resultList.refs) { - (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedResultIndex); - } - } - - // Handlers - - // Renderers - buildSummaryMsg() { - const { searchResults: { matchIndex, count, index }, query } = this.props; - - if (query.trim() == "") { - return ""; - } - - if (count == 0) { - return L10N.getStr("editor.noResults"); - } - - if (index == -1) { - return L10N.getFormatStr("sourceSearch.resultsSummary1", count); - } - - return L10N.getFormatStr("editor.searchResults", matchIndex + 1, count); - } - - shouldShowErrorEmoji() { - const { query, searchResults: { count } } = this.props; - return !!query && !count; - } - - render() { - const { searchResults: { count }, searchOn } = this.props; - - if (!searchOn) { - return _react2.default.createElement("div", null); - } - return _react2.default.createElement( - "div", - { className: "search-bar" }, - _react2.default.createElement(_SearchInput2.default, { - query: this.state.query, - count: count, - placeholder: L10N.getStr("sourceSearch.search.placeholder"), - summaryMsg: this.buildSummaryMsg(), - onChange: this.onChange, - onBlur: this.onBlur, - showErrorEmoji: this.shouldShowErrorEmoji(), - onKeyDown: this.onKeyDown, - handleNext: e => this.traverseResults(e, false), - handlePrev: e => this.traverseResults(e, true), - handleClose: this.closeSearch, - shouldFocus: this.state.inputFocused - }), - _react2.default.createElement( - "div", - { className: "search-bottom-bar" }, - this.renderSearchModifiers() - ) - ); - } -} - -SearchBar.contextTypes = { - shortcuts: _propTypes2.default.object -}; - -const mapStateToProps = state => ({ - searchOn: (0, _selectors.getActiveSearch)(state) === "file", - selectedSource: (0, _selectors.getSelectedSource)(state), - selectedLocation: (0, _selectors.getSelectedLocation)(state), - query: (0, _selectors.getFileSearchQuery)(state), - modifiers: (0, _selectors.getFileSearchModifiers)(state), - highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state), - searchResults: (0, _selectors.getFileSearchResults)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SearchBar); - -/***/ }), - -/***/ 1557: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _lodash = __webpack_require__(2); - -var _reactRedux = __webpack_require__(3592); - -var _selectors = __webpack_require__(3590); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class HighlightLines extends _react.Component { - - constructor() { - super(); - - this.highlightLineRange = () => { - const { highlightedLineRange, editor } = this.props; - - const { codeMirror } = editor; - - if ((0, _lodash.isEmpty)(highlightedLineRange) || !codeMirror) { - return; - } - - const { start, end } = highlightedLineRange; - - codeMirror.operation(() => { - editor.alignLine(start); - - (0, _lodash.range)(start - 1, end).forEach(line => { - codeMirror.addLineClass(line, "line", "highlight-lines"); - }); - }); - }; - } - - componentDidMount() { - this.highlightLineRange(); - } - - componentWillUpdate() { - this.clearHighlightRange(); - } - - componentDidUpdate() { - this.highlightLineRange(); - } - - componentWillUnmount() { - this.clearHighlightRange(); - } - - clearHighlightRange() { - const { highlightedLineRange, editor } = this.props; - - const { codeMirror } = editor; - - if ((0, _lodash.isEmpty)(highlightedLineRange) || !codeMirror) { - return; - } - - const { start, end } = highlightedLineRange; - codeMirror.operation(() => { - (0, _lodash.range)(start - 1, end).forEach(line => { - codeMirror.removeLineClass(line, "line", "highlight-lines"); - }); - }); - } - - render() { - return null; - } -} - -exports.default = (0, _reactRedux.connect)(state => ({ - highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state) -}))(HighlightLines); - -/***/ }), - -/***/ 1558: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _Popup = __webpack_require__(1559); - -var _Popup2 = _interopRequireDefault(_Popup); - -var _selectors = __webpack_require__(3590); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _editor = __webpack_require__(1358); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Preview extends _react.PureComponent { - constructor(props) { - super(props); - - this.onMouseOver = e => { - const { target } = e; - this.props.updatePreview(target, this.props.editor); - }; - - this.onMouseUp = () => { - this.setState({ selecting: false }); - return true; - }; - - this.onMouseDown = () => { - this.setState({ selecting: true }); - return true; - }; - - this.onMouseLeave = e => { - const target = e.target; - if (target.classList.contains("CodeMirror")) { - return; - } - - this.props.clearPreview(); - }; - - this.onClose = () => { - this.props.clearPreview(); - }; - - this.state = { selecting: false }; - } - - componentDidMount() { - const { codeMirror } = this.props.editor; - const codeMirrorWrapper = codeMirror.getWrapperElement(); - - codeMirrorWrapper.addEventListener("mouseover", this.onMouseOver); - codeMirrorWrapper.addEventListener("mouseup", this.onMouseUp); - codeMirrorWrapper.addEventListener("mousedown", this.onMouseDown); - codeMirrorWrapper.addEventListener("mouseleave", this.onMouseLeave); - if (document.body) { - document.body.addEventListener("mouseleave", this.onMouseLeave); - } - } - - componentWillUnmount() { - const codeMirror = this.props.editor.codeMirror; - const codeMirrorWrapper = codeMirror.getWrapperElement(); - codeMirrorWrapper.removeEventListener("mouseover", this.onMouseOver); - codeMirrorWrapper.removeEventListener("mouseup", this.onMouseUp); - codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown); - codeMirrorWrapper.removeEventListener("mouseleave", this.onMouseLeave); - if (document.body) { - document.body.removeEventListener("mouseleave", this.onMouseLeave); - } - } - - render() { - const { selectedSource, preview } = this.props; - - if (!this.props.editor || !selectedSource || this.state.selecting) { - return null; - } - - if (!preview || preview.updating) { - return null; - } - - const { result, expression, location, cursorPos, extra } = preview; - const value = result; - if (typeof value == "undefined" || value.optimizedOut) { - return null; - } - - const editorRange = (0, _editor.toEditorRange)(selectedSource.get("id"), location); - - return _react2.default.createElement(_Popup2.default, { - value: value, - editor: this.props.editor, - editorRef: this.props.editorRef, - range: editorRange, - expression: expression, - popoverPos: cursorPos, - extra: extra, - onClose: this.onClose - }); - } -} - -const mapStateToProps = state => ({ - preview: (0, _selectors.getPreview)(state), - selectedSource: (0, _selectors.getSelectedSource)(state) -}); - -const { - addExpression, - setPopupObjectProperties, - updatePreview, - clearPreview -} = _actions2.default; - -const mapDispatchToProps = { - addExpression, - setPopupObjectProperties, - updatePreview, - clearPreview -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Preview); - -/***/ }), - -/***/ 1559: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Popup = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _devtoolsReps = __webpack_require__(3655); - -var _devtoolsReps2 = _interopRequireDefault(_devtoolsReps); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _Popover = __webpack_require__(1586); - -var _Popover2 = _interopRequireDefault(_Popover); - -var _PreviewFunction = __webpack_require__(1446); - -var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction); - -var _editor = __webpack_require__(1358); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _firefox = __webpack_require__(1500); - -__webpack_require__(1328); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { REPS: { Rep }, MODE, ObjectInspector, ObjectInspectorUtils } = _devtoolsReps2.default; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { - createNode, - getChildren, - getValue, - nodeIsPrimitive, - NODE_TYPES -} = ObjectInspectorUtils.node; -const { loadItemProperties } = ObjectInspectorUtils.loadProperties; - -class Popup extends _react.Component { - constructor(...args) { - var _temp; - - return _temp = super(...args), this.onMouseLeave = e => { - const relatedTarget = e.relatedTarget; - - if (relatedTarget && (relatedTarget.classList.contains("popover") || relatedTarget.classList.contains("debug-expression") || relatedTarget.classList.contains("editor-mount"))) { - return; - } - - this.props.onClose(); - }, _temp; - } - - async componentWillMount() { - const { - value, - setPopupObjectProperties, - popupObjectProperties - } = this.props; - - const root = this.getRoot(); - - if (!nodeIsPrimitive(root) && value && value.actor && !popupObjectProperties[value.actor]) { - const onLoadItemProperties = loadItemProperties(root, _firefox.createObjectClient); - if (onLoadItemProperties !== null) { - const properties = await onLoadItemProperties; - setPopupObjectProperties(root.contents.value, properties); - } - } - } - - componentDidMount() { - const { value, editor, range } = this.props; - - if (!value || !value.type == "object") { - return; - } - - this.marker = (0, _editor.markText)(editor, "preview-selection", range); - } - - componentWillUnmount() { - if (this.marker) { - this.marker.clear(); - } - } - - getRoot() { - const { expression, value, extra } = this.props; - - let rootValue = value; - if (extra.immutable) { - rootValue = extra.immutable.entries; - } - - return createNode({ - name: expression, - path: expression, - contents: { value: rootValue } - }); - } - - getChildren() { - const { popupObjectProperties } = this.props; - - const root = this.getRoot(); - const value = getValue(root); - const actor = value ? value.actor : null; - const loadedRootProperties = popupObjectProperties[actor]; - if (!loadedRootProperties) { - return null; - } - - const children = getChildren({ - item: root, - loadedProperties: new Map([[root.path, loadedRootProperties]]) - }); - - if (children.length > 0) { - return children; - } - - return null; - } - - renderFunctionPreview() { - const { selectSourceURL, value } = this.props; - - if (!value) { - return null; - } - - const { location } = value; - return _react2.default.createElement( - "div", - { - className: "preview-popup", - onClick: () => selectSourceURL(location.url, { line: location.line }) - }, - _react2.default.createElement(_PreviewFunction2.default, { func: value }) - ); - } - - renderReact(react, roots) { - const reactHeader = react.displayName || "React Component"; - - return _react2.default.createElement( - "div", - { className: "header-container" }, - _react2.default.createElement(_Svg2.default, { name: "react", className: "logo" }), - _react2.default.createElement( - "h3", - null, - reactHeader - ) - ); - } - - renderImmutable(immutable) { - const immutableHeader = immutable.type || "Immutable"; - - return _react2.default.createElement( - "div", - { className: "header-container" }, - _react2.default.createElement(_Svg2.default, { name: "immutable", className: "logo" }), - _react2.default.createElement( - "h3", - null, - immutableHeader - ) - ); - } - - renderObjectPreview() { - const { extra } = this.props; - const root = this.getRoot(); - - if (nodeIsPrimitive(root)) { - return null; - } - - let roots = this.getChildren(); - if (!Array.isArray(roots) || roots.length === 0) { - return null; - } - - let header = null; - if (extra.immutable) { - header = this.renderImmutable(extra.immutable); - roots = roots.filter(r => r.type != NODE_TYPES.PROTOTYPE); - } - - if (extra.react) { - header = this.renderReact(extra.react); - roots = roots.filter(r => ["state", "props"].includes(r.name)); - } - - return _react2.default.createElement( - "div", - { className: "preview-popup" }, - header, - this.renderObjectInspector(roots) - ); - } - - renderSimplePreview(value) { - const { openLink } = this.props; - return _react2.default.createElement( - "div", - { className: "preview-popup" }, - Rep({ - object: value, - mode: MODE.LONG, - openLink - }) - ); - } - - renderObjectInspector(roots) { - const { openLink } = this.props; - - return _react2.default.createElement(ObjectInspector, { - roots: roots, - autoExpandDepth: 0, - disableWrap: true, - focusable: false, - openLink: openLink, - createObjectClient: grip => (0, _firefox.createObjectClient)(grip) - }); - } - - renderPreview() { - const { value } = this.props; - if (!value) { - return null; - } - - if (value.class === "Function") { - return this.renderFunctionPreview(); - } - - if (value.type === "object") { - return _react2.default.createElement( - "div", - null, - this.renderObjectPreview() - ); - } - - return this.renderSimplePreview(value); - } - - getPreviewType(value) { - if (typeof value == "number" || typeof value == "boolean" || typeof value == "string" && value.length < 10 || typeof value == "number" && value.toString().length < 10 || value.type == "null" || value.type == "undefined" || value.class === "Function") { - return "tooltip"; - } - - return "popover"; - } - - render() { - const { popoverPos, value, editorRef } = this.props; - const type = this.getPreviewType(value); - - if (value && value.type === "object" && !this.getChildren()) { - return null; - } - - return _react2.default.createElement( - _Popover2.default, - { - targetPosition: popoverPos, - onMouseLeave: this.onMouseLeave, - type: type, - editorRef: editorRef - }, - this.renderPreview() - ); - } -} - -exports.Popup = Popup; -const mapStateToProps = state => ({ - popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state) -}); - -const { - addExpression, - selectSourceURL, - selectLocation, - setPopupObjectProperties, - openLink -} = _actions2.default; - -const mapDispatchToProps = { - addExpression, - selectSourceURL, - selectLocation, - setPopupObjectProperties, - openLink -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Popup); - -/***/ }), - -/***/ 1586: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _BracketArrow = __webpack_require__(1587); - -var _BracketArrow2 = _interopRequireDefault(_BracketArrow); - -__webpack_require__(1327); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Popover extends _react.Component { - constructor(props) { - super(props); - - this.calculateTopForRightOrientation = (target, editor, popover) => { - if (popover.height < editor.height) { - const rightOrientationTop = target.top - popover.height / 2; - if (rightOrientationTop < editor.top) { - return editor.top; - } - const rightOrientationBottom = rightOrientationTop + popover.height; - if (rightOrientationBottom > editor.bottom) { - return editor.bottom - popover.height; - } - return rightOrientationTop; - } - return 0; - }; - - this.calculateTop = (target, editor, popover, orientation) => { - if (orientation === "down") { - return target.bottom; - } - if (orientation === "up") { - return target.top - popover.height; - } - - return this.calculateTopForRightOrientation(target, editor, popover); - }; - - this.onMouseLeave = e => { - const { onMouseLeave } = this.props; - if (/^(bracket-arrow|gap)$/.test(e.currentTarget.className)) { - return; - } - - onMouseLeave(e); - }; - - this.state = { - left: 0, - top: 0, - targetMid: { x: 0, y: 0 }, - orientation: "up" - }; - } - - componentDidMount() { - const { type } = this.props; - const { left, top, orientation, targetMid } = type == "popover" ? this.getPopoverCoords() : this.getTooltipCoords(); - - // eslint-disable-next-line react/no-did-mount-set-state - this.setState({ - left, - top, - orientation, - targetMid - }); - } - - calculateLeft(target, editor, popover, orientation) { - const estimatedLeft = target.left; - const estimatedRight = estimatedLeft + popover.width; - const isOverflowingRight = estimatedRight > editor.right; - if (orientation === "right") { - return target.left + target.width + 10; - } - if (isOverflowingRight) { - const adjustedLeft = editor.right - popover.width - 8; - return adjustedLeft; - } - return estimatedLeft; - } - - calculateOrientation(target, editor, popover) { - const estimatedBottom = target.bottom + popover.height; - if (editor.bottom > estimatedBottom) { - return "down"; - } - const upOrientationTop = target.top - popover.height; - if (upOrientationTop > editor.top) { - return "up"; - } - - return "right"; - } - - getPopoverCoords() { - if (this.$popover && this.props.editorRef) { - const popover = this.$popover; - const editor = this.props.editorRef; - const popoverRect = popover.getBoundingClientRect(); - const editorRect = editor.getBoundingClientRect(); - const targetRect = this.props.targetPosition; - const orientation = this.calculateOrientation(targetRect, editorRect, popoverRect); - const top = this.calculateTop(targetRect, editorRect, popoverRect, orientation); - const popoverLeft = this.calculateLeft(targetRect, editorRect, popoverRect, orientation); - let targetMid; - if (orientation === "right") { - targetMid = { - x: -14, - y: targetRect.top - top - 2 - }; - } else { - targetMid = { - x: targetRect.left - popoverLeft + targetRect.width / 2 - 8, - y: 0 - }; - } - - return { - left: popoverLeft, - top, - orientation, - targetMid - }; - } - return { - left: 0, - top: 0, - orientation: "down", - targetMid: { x: 0, y: 0 } - }; - } - - getTooltipCoords() { - if (this.$tooltip && this.props.editorRef) { - const tooltip = this.$tooltip; - const editor = this.props.editorRef; - const tooltipRect = tooltip.getBoundingClientRect(); - const editorRect = editor.getBoundingClientRect(); - const targetRect = this.props.targetPosition; - const left = this.calculateLeft(targetRect, editorRect, tooltipRect); - const top = targetRect.top - tooltipRect.height; - - return { - left, - top, - orientation: "up", - targetMid: { x: 0, y: 0 } - }; - } - return { - left: 0, - top: 0, - orientation: "up", - targetMid: { x: 0, y: 0 } - }; - } - - getChildren() { - const { children } = this.props; - const { orientation } = this.state; - const gap = _react2.default.createElement("div", { className: "gap", key: "gap" }); - return orientation === "up" ? [children, gap] : [gap, children]; - } - - getPopoverArrow(orientation, left, top) { - const arrowProps = {}; - if (orientation === "up") { - Object.assign(arrowProps, { orientation: "down", bottom: 5, left }); - } else if (orientation === "down") { - Object.assign(arrowProps, { orientation: "up", top: -7, left }); - } else { - Object.assign(arrowProps, { orientation: "left", top, left: -14 }); - } - - return _react2.default.createElement(_BracketArrow2.default, arrowProps); - } - - renderPopover() { - const { top, left, orientation, targetMid } = this.state; - const arrow = this.getPopoverArrow(orientation, targetMid.x, targetMid.y); - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("popover", `orientation-${orientation}`, { - up: orientation === "up" - }), - onMouseLeave: this.onMouseLeave, - style: { top, left }, - ref: c => this.$popover = c - }, - arrow, - this.getChildren() - ); - } - - renderTooltip() { - const { onMouseLeave } = this.props; - const { top, left } = this.state; - - return _react2.default.createElement( - "div", - { - className: "tooltip", - onMouseLeave: onMouseLeave, - style: { top, left }, - ref: c => this.$tooltip = c - }, - this.getChildren() - ); - } - - render() { - const { type } = this.props; - - if (type === "tooltip") { - return this.renderTooltip(); - } - - return this.renderPopover(); - } -} - -Popover.defaultProps = { - onMouseLeave: () => {}, - type: "popover" -}; -exports.default = Popover; - -/***/ }), - -/***/ 1587: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -__webpack_require__(1326); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const BracketArrow = ({ - orientation, - left, - top, - bottom -}) => { - return _react2.default.createElement("div", { - className: (0, _classnames2.default)("bracket-arrow", orientation || "up"), - style: { left, top, bottom } - }); -}; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.default = BracketArrow; - -/***/ }), - -/***/ 1588: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _reactRedux = __webpack_require__(3592); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _Breakpoint = __webpack_require__(1589); - -var _Breakpoint2 = _interopRequireDefault(_Breakpoint); - -var _selectors = __webpack_require__(3590); - -var _breakpoint = __webpack_require__(1364); - -var _source = __webpack_require__(1356); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Breakpoints extends _react.Component { - shouldComponentUpdate(nextProps) { - if (nextProps.selectedSource && !(0, _source.isLoaded)(nextProps.selectedSource)) { - return false; - } - - return true; - } - - render() { - const { breakpoints, selectedSource, editor } = this.props; - - if (!selectedSource || !breakpoints || selectedSource.get("isBlackBoxed")) { - return null; - } - - return _react2.default.createElement( - "div", - null, - breakpoints.valueSeq().map(bp => { - return _react2.default.createElement(_Breakpoint2.default, { - key: (0, _breakpoint.makeLocationId)(bp.location), - breakpoint: bp, - selectedSource: selectedSource, - editor: editor - }); - }) - ); - } -} - -exports.default = (0, _reactRedux.connect)(state => ({ - breakpoints: (0, _selectors.getVisibleBreakpoints)(state), - selectedSource: (0, _selectors.getSelectedSource)(state) -}))(Breakpoints); - -/***/ }), - -/***/ 1589: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _editor = __webpack_require__(1358); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const breakpointSvg = document.createElement("div"); -_reactDom2.default.render(_react2.default.createElement(_Svg2.default, { name: "breakpoint" }), breakpointSvg); - -function makeMarker(isDisabled) { - const bp = breakpointSvg.cloneNode(true); - bp.className = (0, _classnames2.default)("editor new-breakpoint", { - "breakpoint-disabled": isDisabled, - "folding-enabled": _prefs.features.codeFolding - }); - - return bp; -} - -class Breakpoint extends _react.Component { - - constructor() { - super(); - - this.addBreakpoint = () => { - const { breakpoint, editor, selectedSource } = this.props; - - // Hidden Breakpoints are never rendered on the client - if (breakpoint.hidden) { - return; - } - - // NOTE: we need to wait for the breakpoint to be loaded - // to get the generated location - if (!selectedSource || breakpoint.loading) { - return; - } - - const sourceId = selectedSource.id; - const line = (0, _editor.toEditorLine)(sourceId, breakpoint.location.line); - - editor.codeMirror.setGutterMarker(line, "breakpoints", makeMarker(breakpoint.disabled)); - - editor.codeMirror.addLineClass(line, "line", "new-breakpoint"); - if (breakpoint.condition) { - editor.codeMirror.addLineClass(line, "line", "has-condition"); - } else { - editor.codeMirror.removeLineClass(line, "line", "has-condition"); - } - }; - } - - shouldComponentUpdate(nextProps) { - const { editor, breakpoint, selectedSource } = this.props; - return editor !== nextProps.editor || breakpoint.disabled !== nextProps.breakpoint.disabled || breakpoint.hidden !== nextProps.breakpoint.hidden || breakpoint.condition !== nextProps.breakpoint.condition || breakpoint.loading !== nextProps.breakpoint.loading || selectedSource !== nextProps.selectedSource; - } - - componentDidMount() { - this.addBreakpoint(); - } - - componentDidUpdate() { - this.addBreakpoint(); - } - - componentWillUnmount() { - const { editor, breakpoint, selectedSource } = this.props; - - if (!selectedSource) { - return; - } - - if (breakpoint.loading) { - return; - } - - const sourceId = selectedSource.id; - const doc = (0, _editor.getDocument)(sourceId); - if (!doc) { - return; - } - - const line = (0, _editor.toEditorLine)(sourceId, breakpoint.location.line); - - // NOTE: when we upgrade codemirror we can use `doc.setGutterMarker` - if (doc.setGutterMarker) { - doc.setGutterMarker(line, "breakpoints", null); - } else { - editor.codeMirror.setGutterMarker(line, "breakpoints", null); - } - - doc.removeLineClass(line, "line", "new-breakpoint"); - doc.removeLineClass(line, "line", "has-condition"); - } - - render() { - return null; - } -} - -exports.default = Breakpoint; - -/***/ }), - -/***/ 1590: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -const markerEl = document.createElement("div"); /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function makeMarker() { - const marker = markerEl.cloneNode(true); - marker.className = "editor hit-marker"; - return marker; -} - -class HitMarker extends _react.Component { - addMarker() { - const hitData = this.props.hitData; - const line = hitData.line - 1; - - this.props.editor.setGutterMarker(line, "hit-markers", makeMarker()); - - this.props.editor.addLineClass(line, "line", "hit-marker"); - } - - shouldComponentUpdate(nextProps) { - return this.props.editor !== nextProps.editor || this.props.hitData !== nextProps.hitData; - } - - componentDidMount() { - this.addMarker(); - } - - componentDidUpdate() { - this.addMarker(); - } - - componentWillUnmount() { - const hitData = this.props.hitData; - const line = hitData.line - 1; - - this.props.editor.setGutterMarker(line, "hit-markers", null); - this.props.editor.removeLineClass(line, "line", "hit-marker"); - } - - render() { - return null; - } -} - -exports.default = HitMarker; - -/***/ }), - -/***/ 1591: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _lodash = __webpack_require__(2); - -var _CallSite = __webpack_require__(1592); - -var _CallSite2 = _interopRequireDefault(_CallSite); - -var _selectors = __webpack_require__(3590); - -var _editor = __webpack_require__(1358); - -var _wasm = __webpack_require__(1401); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function getCallSiteAtLocation(callSites, location) { - return callSites.find(callSite => (0, _lodash.isEqualWith)(callSite.location, location, (cloc, loc) => { - return loc.line === cloc.start.line && loc.column >= cloc.start.column && loc.column <= cloc.end.column; - })); -} - -class CallSites extends _react.Component { - - constructor(props) { - super(props); - - this.onKeyUp = e => { - if (e.key === "Alt") { - e.preventDefault(); - this.setState({ showCallSites: false }); - } - }; - - this.onKeyDown = e => { - if (e.key === "Alt") { - e.preventDefault(); - this.setState({ showCallSites: true }); - } - }; - - this.state = { - showCallSites: false - }; - } - - componentDidMount() { - const { editor } = this.props; - const codeMirrorWrapper = editor.codeMirror.getWrapperElement(); - - codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e)); - document.body.addEventListener("keydown", this.onKeyDown); - document.body.addEventListener("keyup", this.onKeyUp); - } - - componentWillUnmount() { - const { editor } = this.props; - const codeMirrorWrapper = editor.codeMirror.getWrapperElement(); - - codeMirrorWrapper.removeEventListener("click", e => this.onTokenClick(e)); - document.body.removeEventListener("keydown", this.onKeyDown); - document.body.removeEventListener("keyup", this.onKeyUp); - } - - onTokenClick(e) { - const { target } = e; - const { editor, selectedLocation } = this.props; - - if (!e.altKey && !target.classList.contains("call-site-bp") || !target.classList.contains("call-site") && !target.classList.contains("call-site-bp")) { - return; - } - - const { sourceId } = selectedLocation; - const { line, column } = (0, _editor.getTokenLocation)(editor.codeMirror, target); - - this.toggleBreakpoint(line, (0, _wasm.isWasm)(sourceId) ? undefined : column); - } - - toggleBreakpoint(line, column = undefined) { - const { - selectedSource, - selectedLocation, - addBreakpoint, - removeBreakpoint, - callSites - } = this.props; - - const callSite = getCallSiteAtLocation(callSites, { line, column }); - - if (!callSite) { - return; - } - - const bp = callSite.breakpoint; - - if (bp && bp.loading || !selectedLocation || !selectedSource) { - return; - } - - const { sourceId } = selectedLocation; - - if (bp) { - // NOTE: it's possible the breakpoint has slid to a column - column = column || bp.location.column; - removeBreakpoint({ - sourceId: sourceId, - line: line, - column - }); - } else { - addBreakpoint({ - sourceId: sourceId, - sourceUrl: selectedSource.get("url"), - line: line, - column: column - }); - } - } - - render() { - const { editor, callSites, selectedSource } = this.props; - const { showCallSites } = this.state; - let sites; - if (!callSites) { - return null; - } - - editor.codeMirror.operation(() => { - const childCallSites = callSites.map((callSite, index) => { - const props = { - key: index, - callSite, - editor, - source: selectedSource, - breakpoint: callSite.breakpoint, - showCallSite: showCallSites - }; - return _react2.default.createElement(_CallSite2.default, props); - }); - sites = _react2.default.createElement( - "div", - null, - childCallSites - ); - }); - return sites; - } -} - -function getCallSites(symbols, breakpoints) { - if (!symbols || !symbols.callExpressions) { - return; - } - - const callSites = symbols.callExpressions; - - // NOTE: we create a breakpoint map keyed on location - // to speed up the lookups. Hopefully we'll fix the - // inconsistency with column offsets so that we can expect - // a breakpoint to be added at the beginning of a call expression. - const bpLocationMap = (0, _lodash.keyBy)(breakpoints.valueSeq().toJS(), ({ location }) => locationKey(location)); - - function locationKey({ line, column }) { - return `${line}/${column}`; - } - - function findBreakpoint(callSite) { - const { location: { start, end } } = callSite; - - const breakpointId = (0, _lodash.range)(start.column - 1, end.column).map(column => locationKey({ line: start.line, column })).find(key => bpLocationMap[key]); - - if (breakpointId) { - return bpLocationMap[breakpointId]; - } - } - - return callSites.filter(({ location }) => location.start.line === location.end.line).map(callSite => _extends({}, callSite, { breakpoint: findBreakpoint(callSite) })); -} - -const mapStateToProps = state => { - const selectedLocation = (0, _selectors.getSelectedLocation)(state); - const selectedSource = (0, _selectors.getSelectedSource)(state); - const sourceId = selectedLocation && selectedLocation.sourceId; - const symbols = (0, _selectors.getSymbols)(state, selectedSource); - const breakpoints = (0, _selectors.getBreakpointsForSource)(state, sourceId); - - return { - selectedLocation, - selectedSource, - callSites: getCallSites(symbols, breakpoints), - breakpoints: breakpoints - }; -}; - -const { addBreakpoint, removeBreakpoint } = _actions2.default; -const mapDispatchToProps = { addBreakpoint, removeBreakpoint }; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(CallSites); - -/***/ }), - -/***/ 1592: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _editor = __webpack_require__(1358); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -__webpack_require__(1329); - -class CallSite extends _react.Component { - - constructor() { - super(); - - this.addCallSite = nextProps => { - const { editor, callSite, breakpoint, source } = nextProps || this.props; - const className = !breakpoint ? "call-site" : "call-site-bp"; - const sourceId = source.get("id"); - const editorRange = (0, _editor.toEditorRange)(sourceId, callSite.location); - this.marker = (0, _editor.markText)(editor, className, editorRange); - }; - - this.clearCallSite = () => { - if (this.marker) { - this.marker.clear(); - this.marker = null; - } - }; - - this.marker = undefined; - } - - shouldComponentUpdate(nextProps) { - return this.props.editor !== nextProps.editor; - } - - componentDidMount() { - const { breakpoint, showCallSite } = this.props; - - if (!breakpoint && !showCallSite) { - return; - } - - this.addCallSite(); - } - - componentWillReceiveProps(nextProps) { - const { breakpoint, showCallSite } = this.props; - - if (nextProps.breakpoint !== breakpoint) { - if (this.marker) { - this.clearCallSite(); - } - if (nextProps.showCallSite) { - this.addCallSite(nextProps); - } - } - - if (nextProps.showCallSite !== showCallSite) { - if (nextProps.showCallSite) { - if (!this.marker) { - this.addCallSite(); - } - } else if (!nextProps.breakpoint) { - this.clearCallSite(); - } - } - } - - componentWillUnmount() { - if (!this.marker) { - return; - } - this.marker.clear(); - } - - render() { - return null; - } -} -exports.default = CallSite; - -/***/ }), - -/***/ 1593: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DebugLine = undefined; - -var _react = __webpack_require__(0); - -var _editor = __webpack_require__(1358); - -var _source = __webpack_require__(1356); - -var _pause = __webpack_require__(2419); - -var _indentation = __webpack_require__(1438); - -var _reactRedux = __webpack_require__(3592); - -var _selectors = __webpack_require__(3590); - -function isDocumentReady(selectedSource, selectedFrame) { - return selectedFrame && (0, _source.isLoaded)(selectedSource) && (0, _editor.hasDocument)(selectedFrame.location.sourceId); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class DebugLine extends _react.Component { - - componentDidUpdate(prevProps) { - const { why, selectedFrame, selectedSource } = this.props; - this.setDebugLine(why, selectedFrame, selectedSource); - } - - componentWillUpdate() { - const { why, selectedFrame, selectedSource } = this.props; - this.clearDebugLine(selectedFrame, selectedSource, why); - } - - componentDidMount() { - const { why, selectedFrame, selectedSource } = this.props; - this.setDebugLine(why, selectedFrame, selectedSource); - } - - setDebugLine(why, selectedFrame, selectedSource) { - if (!isDocumentReady(selectedSource, selectedFrame)) { - return; - } - const sourceId = selectedFrame.location.sourceId; - const doc = (0, _editor.getDocument)(sourceId); - - let { line, column } = (0, _editor.toEditorPosition)(selectedFrame.location); - const { markTextClass, lineClass } = this.getTextClasses(why); - doc.addLineClass(line, "line", lineClass); - - const lineText = doc.getLine(line); - column = Math.max(column, (0, _indentation.getIndentation)(lineText)); - - this.debugExpression = doc.markText({ ch: column, line }, { ch: null, line }, { className: markTextClass }); - } - - clearDebugLine(selectedFrame, selectedSource, why) { - if (!isDocumentReady(selectedSource, selectedFrame)) { - return; - } - - if (this.debugExpression) { - this.debugExpression.clear(); - } - - const sourceId = selectedFrame.location.sourceId; - const { line } = (0, _editor.toEditorPosition)(selectedFrame.location); - const doc = (0, _editor.getDocument)(sourceId); - const { lineClass } = this.getTextClasses(why); - doc.removeLineClass(line, "line", lineClass); - } - - getTextClasses(why) { - if ((0, _pause.isException)(why)) { - return { - markTextClass: "debug-expression-error", - lineClass: "new-debug-line-error" - }; - } - - return { markTextClass: "debug-expression", lineClass: "new-debug-line" }; - } - - render() { - return null; - } -} - -exports.DebugLine = DebugLine; -const mapStateToProps = state => ({ - selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state), - selectedSource: (0, _selectors.getSelectedSource)(state), - why: (0, _selectors.getPauseReason)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps)(DebugLine); - -/***/ }), - -/***/ 1594: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _reactRedux = __webpack_require__(3592); - -var _react = __webpack_require__(0); - -var _selectors = __webpack_require__(3590); - -var _editor = __webpack_require__(1358); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class EmptyLines extends _react.Component { - - componentDidMount() { - this.disableEmptyLines(); - } - - componentDidUpdate() { - this.disableEmptyLines(); - } - - componentWillUnmount() { - const { emptyLines, selectedSource, editor } = this.props; - - if (!emptyLines) { - return; - } - - editor.codeMirror.operation(() => { - emptyLines.forEach(emptyLine => { - const line = (0, _editor.toEditorLine)(selectedSource.get("id"), emptyLine); - editor.codeMirror.removeLineClass(line, "line", "empty-line"); - }); - }); - } - - disableEmptyLines() { - const { emptyLines, selectedSource, editor } = this.props; - - if (!emptyLines) { - return; - } - editor.codeMirror.operation(() => { - emptyLines.forEach(emptyLine => { - const line = (0, _editor.toEditorLine)(selectedSource.get("id"), emptyLine); - editor.codeMirror.addLineClass(line, "line", "empty-line"); - }); - }); - } - - render() { - return null; - } -} - -const mapStateToProps = state => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS()); - - return { - selectedSource, - emptyLines: selectedSource ? foundEmptyLines : [] - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps)(EmptyLines); - -/***/ }), - -/***/ 1595: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.gutterMenu = gutterMenu; - -var _react = __webpack_require__(0); - -var _devtoolsContextmenu = __webpack_require__(1413); - -var _reactRedux = __webpack_require__(3592); - -var _editor = __webpack_require__(1358); - -var _selectors = __webpack_require__(3590); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -function gutterMenu({ - breakpoint, - line, - event, - isPaused, - toggleBreakpoint, - openConditionalPanel, - toggleDisabledBreakpoint, - isCbPanelOpen, - closeConditionalPanel, - continueToHere -}) { - event.stopPropagation(); - event.preventDefault(); - - const gutterItems = { - addBreakpoint: { - id: "node-menu-add-breakpoint", - label: L10N.getStr("editor.addBreakpoint") - }, - addConditional: { - id: "node-menu-add-conditional-breakpoint", - label: L10N.getStr("editor.addConditionalBreakpoint") - }, - removeBreakpoint: { - id: "node-menu-remove-breakpoint", - label: L10N.getStr("editor.removeBreakpoint") - }, - editConditional: { - id: "node-menu-edit-conditional-breakpoint", - label: L10N.getStr("editor.editBreakpoint") - }, - enableBreakpoint: { - id: "node-menu-enable-breakpoint", - label: L10N.getStr("editor.enableBreakpoint") - }, - disableBreakpoint: { - id: "node-menu-disable-breakpoint", - label: L10N.getStr("editor.disableBreakpoint") - }, - continueToHere: { - id: "node-menu-continue-to-here", - label: L10N.getStr("editor.continueToHere.label") - } - }; - - const toggleBreakpointItem = _extends({ - accesskey: L10N.getStr("shortcuts.toggleBreakpoint.accesskey"), - disabled: false, - click: () => { - toggleBreakpoint(line); - if (isCbPanelOpen) { - closeConditionalPanel(); - } - } - }, breakpoint ? gutterItems.removeBreakpoint : gutterItems.addBreakpoint); - - const conditionalBreakpoint = _extends({ - accesskey: L10N.getStr("editor.addConditionalBreakpoint.accesskey"), - disabled: false, - click: () => openConditionalPanel(line) - }, breakpoint && breakpoint.condition ? gutterItems.editConditional : gutterItems.addConditional); - - const items = [toggleBreakpointItem, conditionalBreakpoint]; - - if (isPaused) { - const continueToHereItem = _extends({ - accesskey: L10N.getStr("editor.continueToHere.accesskey"), - disabled: false, - click: () => continueToHere(line) - }, gutterItems.continueToHere); - items.push(continueToHereItem); - } - - if (breakpoint) { - const disableBreakpoint = _extends({ - accesskey: L10N.getStr("editor.disableBreakpoint.accesskey"), - disabled: false, - click: () => toggleDisabledBreakpoint(line) - }, breakpoint.disabled ? gutterItems.enableBreakpoint : gutterItems.disableBreakpoint); - items.push(disableBreakpoint); - } - - (0, _devtoolsContextmenu.showMenu)(event, items); -} - -class GutterContextMenuComponent extends _react.Component { - - constructor() { - super(); - } - - shouldComponentUpdate(nextProps) { - return nextProps.contextMenu.type === "Gutter"; - } - - componentWillUpdate(nextProps) { - // clear the context menu since it is open - this.props.setContextMenu("", null); - return this.showMenu(nextProps); - } - - showMenu(nextProps) { - const { contextMenu } = nextProps, - props = _objectWithoutProperties(nextProps, ["contextMenu"]); - const { event } = contextMenu; - const sourceId = props.selectedSource ? props.selectedSource.get("id") : ""; - const line = (0, _editor.lineAtHeight)(props.editor, sourceId, event); - const breakpoint = nextProps.breakpoints.find(bp => bp.location.line === line); - - if (props.emptyLines && props.emptyLines.includes(line)) { - return; - } - - gutterMenu(_extends({ event, sourceId, line, breakpoint }, props)); - } - - render() { - return null; - } -} - -const mapStateToProps = state => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - - return { - selectedLocation: (0, _selectors.getSelectedLocation)(state), - selectedSource: selectedSource, - breakpoints: (0, _selectors.getVisibleBreakpoints)(state), - isPaused: (0, _selectors.isPaused)(state), - contextMenu: (0, _selectors.getContextMenu)(state), - emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.toJS()) - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(GutterContextMenuComponent); - -/***/ }), - -/***/ 1596: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _reactRedux = __webpack_require__(3592); - -var _devtoolsContextmenu = __webpack_require__(1413); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _clipboard = __webpack_require__(1388); - -var _function = __webpack_require__(1597); - -var _ast = __webpack_require__(1638); - -var _editor = __webpack_require__(1358); - -var _source = __webpack_require__(1356); - -var _selectors = __webpack_require__(3590); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getMenuItems(event, { - addExpression, - editor, - evaluateInConsole, - flashLineRange, - getFunctionLocation, - getFunctionText, - hasPrettyPrint, - jumpToMappedLocation, - onGutterContextMenu, - selectedLocation, - selectedSource, - showSource, - toggleBlackBox -}) { - // variables - const hasSourceMap = !!selectedSource.get("sourceMapURL"); - const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId); - const isPrettyPrinted = (0, _source.isPretty)(selectedSource); - const isPrettified = isPrettyPrinted || hasPrettyPrint; - const isMapped = isOriginal || hasSourceMap; - const { line } = editor.codeMirror.coordsChar({ - left: event.clientX, - top: event.clientY - }); - const selectionText = editor.codeMirror.getSelection().trim(); - const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(editor, selectedLocation, event); - const isTextSelected = editor.codeMirror.somethingSelected(); - - // localizations - const blackboxKey = L10N.getStr("sourceFooter.blackbox.accesskey"); - const blackboxLabel = L10N.getStr("sourceFooter.blackbox"); - const unblackboxLabel = L10N.getStr("sourceFooter.unblackbox"); - const toggleBlackBoxLabel = selectedSource.isBlackBoxed ? unblackboxLabel : blackboxLabel; - const copyFunctionKey = L10N.getStr("copyFunction.accesskey"); - const copyFunctionLabel = L10N.getStr("copyFunction.label"); - const copySourceKey = L10N.getStr("copySource.accesskey"); - const copySourceLabel = L10N.getStr("copySource"); - const copyToClipboardKey = L10N.getStr("copyToClipboard.accesskey"); - const copyToClipboardLabel = L10N.getStr("copyToClipboard.label"); - const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey"); - const copySourceUri2Label = L10N.getStr("copySourceUri2"); - const evaluateInConsoleLabel = L10N.getStr("evaluateInConsole.label"); - const jumpToMappedLocKey = L10N.getStr("editor.jumpToMappedLocation1.accesskey"); - const jumpToMappedLocLabel = L10N.getFormatStr("editor.jumpToMappedLocation1", isOriginal ? L10N.getStr("generated") : L10N.getStr("original")); - const revealInTreeKey = L10N.getStr("sourceTabs.revealInTree.accesskey"); - const revealInTreeLabel = L10N.getStr("sourceTabs.revealInTree"); - const watchExpressionKey = L10N.getStr("expressions.accesskey"); - const watchExpressionLabel = L10N.getStr("expressions.label"); - - // menu items - - const copyToClipboardItem = { - id: "node-menu-copy-to-clipboard", - label: copyToClipboardLabel, - accesskey: copyToClipboardKey, - disabled: false, - click: () => (0, _clipboard.copyToTheClipboard)(selectedSource.text) - }; - - const copySourceItem = { - id: "node-menu-copy-source", - label: copySourceLabel, - accesskey: copySourceKey, - disabled: selectionText.length === 0, - click: () => (0, _clipboard.copyToTheClipboard)(selectionText) - }; - - const copySourceUri2Item = { - id: "node-menu-copy-source-url", - label: copySourceUri2Label, - accesskey: copySourceUri2Key, - disabled: false, - click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(selectedSource.url)) - }; - - const sourceId = selectedSource.get("id"); - const sourceLine = (0, _editor.toSourceLine)(sourceId, line); - - const functionText = getFunctionText(sourceLine); - const copyFunctionItem = { - id: "node-menu-copy-function", - label: copyFunctionLabel, - accesskey: copyFunctionKey, - disabled: !functionText, - click: () => { - const { location: { start, end } } = getFunctionLocation(sourceLine); - flashLineRange({ - start: start.line, - end: end.line, - sourceId: selectedLocation.sourceId - }); - return (0, _clipboard.copyToTheClipboard)(functionText); - } - }; - - const jumpToMappedLocationItem = { - id: "node-menu-jump", - label: jumpToMappedLocLabel, - accesskey: jumpToMappedLocKey, - disabled: !isMapped && !isPrettified, - click: () => jumpToMappedLocation(sourceLocation) - }; - - const showSourceMenuItem = { - id: "node-menu-show-source", - label: revealInTreeLabel, - accesskey: revealInTreeKey, - disabled: false, - click: () => showSource(sourceId) - }; - - const blackBoxMenuItem = { - id: "node-menu-blackbox", - label: toggleBlackBoxLabel, - accesskey: blackboxKey, - disabled: isOriginal || isPrettyPrinted || hasSourceMap, - click: () => toggleBlackBox(selectedSource.toJS()) - }; - - const watchExpressionItem = { - id: "node-menu-add-watch-expression", - label: watchExpressionLabel, - accesskey: watchExpressionKey, - click: () => addExpression(editor.codeMirror.getSelection()) - }; - - const evaluateInConsoleItem = { - id: "node-menu-evaluate-in-console", - label: evaluateInConsoleLabel, - click: () => evaluateInConsole(selectionText) - }; - - // construct menu - const menuItems = [copyToClipboardItem, copySourceItem, copySourceUri2Item, copyFunctionItem, { type: "separator" }, jumpToMappedLocationItem, showSourceMenuItem, blackBoxMenuItem]; - - // conditionally added items - // TODO: Find a new way to only add this for mapped sources? - if (isTextSelected) { - menuItems.push(watchExpressionItem, evaluateInConsoleItem); - } - - return menuItems; -} - -class EditorMenu extends _react.Component { - - constructor() { - super(); - } - - shouldComponentUpdate(nextProps) { - return nextProps.contextMenu.type === "Editor"; - } - - componentWillUpdate(nextProps) { - // clear the context menu since it is open - this.props.setContextMenu("", null); - return this.showMenu(nextProps); - } - - showMenu(nextProps) { - const { contextMenu } = nextProps, - options = _objectWithoutProperties(nextProps, ["contextMenu"]); - const { event } = contextMenu; - (0, _devtoolsContextmenu.showMenu)(event, getMenuItems(event, options)); - } - - render() { - return null; - } -} - -const mapStateToProps = state => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - const symbols = (0, _selectors.getSymbols)(state, selectedSource); - - return { - selectedLocation: (0, _selectors.getSelectedLocation)(state), - selectedSource, - hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")), - contextMenu: (0, _selectors.getContextMenu)(state), - getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), symbols), - getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, { - line, - column: Infinity - }) - }; -}; - -const { - addExpression, - evaluateInConsole, - flashLineRange, - jumpToMappedLocation, - setContextMenu, - showSource, - toggleBlackBox -} = _actions2.default; - -const mapDispatchToProps = { - addExpression, - evaluateInConsole, - flashLineRange, - jumpToMappedLocation, - setContextMenu, - showSource, - toggleBlackBox -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(EditorMenu); - -/***/ }), - -/***/ 1597: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.findFunctionText = findFunctionText; - -var _ast = __webpack_require__(1638); - -var _indentation = __webpack_require__(1438); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function findFunctionText(line, source, symbols) { - const func = (0, _ast.findClosestFunction)(symbols, { - sourceId: source.id, - line, - column: Infinity - }); - - if (!func || !source.text) { - return null; - } - - const { location: { start, end } } = func; - const lines = source.text.split("\n"); - const firstLine = lines[start.line - 1].slice(start.column); - const lastLine = lines[end.line - 1].slice(0, end.column); - const middle = lines.slice(start.line, end.line - 1); - const functionText = [firstLine, ...middle, lastLine].join("\n"); - const indentedFunctionText = (0, _indentation.correctIndentation)(functionText); - - return indentedFunctionText; -} - -/***/ }), - -/***/ 1598: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ConditionalPanel = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _reactRedux = __webpack_require__(3592); - -__webpack_require__(1331); - -var _editor = __webpack_require__(1358); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class ConditionalPanel extends _react.PureComponent { - - constructor() { - super(); - - this.saveAndClose = () => { - if (this.input) { - this.setBreakpoint(this.input.value); - } - - this.props.closeConditionalPanel(); - }; - - this.onKey = e => { - if (e.key === "Enter") { - this.saveAndClose(); - } else if (e.key === "Escape") { - this.props.closeConditionalPanel(); - } - }; - - this.repositionOnScroll = () => { - if (this.panelNode && this.scrollParent) { - const { scrollLeft } = this.scrollParent; - this.panelNode.style.transform = `translateX(${scrollLeft}px)`; - } - }; - - this.cbPanel = null; - } - - keepFocusOnInput() { - if (this.input) { - this.input.focus(); - } - } - - setBreakpoint(condition) { - const { selectedLocation, line } = this.props; - const sourceId = selectedLocation ? selectedLocation.sourceId : ""; - const location = { sourceId, line }; - return this.props.setBreakpointCondition(location, { condition }); - } - - clearConditionalPanel() { - if (this.cbPanel) { - this.cbPanel.clear(); - this.cbPanel = null; - } - if (this.scrollParent) { - this.scrollParent.removeEventListener("scroll", this.repositionOnScroll); - } - } - - componentWillMount() { - if (this.props.line) { - return this.renderToWidget(this.props); - } - } - - componentWillUpdate(nextProps) { - if (nextProps.line) { - return this.renderToWidget(nextProps); - } - return this.clearConditionalPanel(); - } - - componentWillUnmount() { - // This is called if CodeMirror is re-initializing itself before the - // user closes the conditional panel. Clear the widget, and re-render it - // as soon as this component gets remounted - return this.clearConditionalPanel(); - } - - renderToWidget(props) { - if (this.cbPanel) { - if (this.props.line && this.props.line == props.line) { - return props.closeConditionalPanel(); - } - this.clearConditionalPanel(); - } - - const { selectedLocation, line, editor } = props; - const sourceId = selectedLocation ? selectedLocation.sourceId : ""; - - const editorLine = (0, _editor.toEditorLine)(sourceId, line); - this.cbPanel = editor.codeMirror.addLineWidget(editorLine, this.renderConditionalPanel(props), { - coverGutter: true, - noHScroll: false - }); - if (this.input) { - let parent = this.input.parentNode; - while (parent) { - if (parent instanceof HTMLElement && parent.classList.contains("CodeMirror-scroll")) { - this.scrollParent = parent; - break; - } - parent = parent.parentNode; - } - - if (this.scrollParent) { - this.scrollParent.addEventListener("scroll", this.repositionOnScroll); - this.repositionOnScroll(); - } - - this.input.focus(); - } - } - - renderConditionalPanel(props) { - const { breakpoint } = props; - const condition = breakpoint ? breakpoint.condition : ""; - const panel = document.createElement("div"); - _reactDom2.default.render(_react2.default.createElement( - "div", - { - className: "conditional-breakpoint-panel", - onClick: () => this.keepFocusOnInput(), - onBlur: this.props.closeConditionalPanel, - ref: node => this.panelNode = node - }, - _react2.default.createElement( - "div", - { className: "prompt" }, - "\xBB" - ), - _react2.default.createElement("input", { - defaultValue: condition, - placeholder: L10N.getStr("editor.conditionalPanel.placeholder"), - onKeyDown: this.onKey, - ref: input => { - this.input = input; - this.keepFocusOnInput(); - } - }) - ), panel); - return panel; - } - - render() { - return null; - } -} - -exports.ConditionalPanel = ConditionalPanel; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const mapStateToProps = state => { - const line = (0, _selectors.getConditionalPanelLine)(state); - const selectedLocation = (0, _selectors.getSelectedLocation)(state); - - return { - selectedLocation, - breakpoint: (0, _selectors.getBreakpointForLine)(state, selectedLocation.sourceId, line), - line - }; -}; - -const { - setBreakpointCondition, - openConditionalPanel, - closeConditionalPanel -} = _actions2.default; - -const mapDispatchToProps = { - setBreakpointCondition, - openConditionalPanel, - closeConditionalPanel -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(ConditionalPanel); - -/***/ }), - -/***/ 1599: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _immutable = __webpack_require__(3594); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _prefs = __webpack_require__(226); - -var _Breakpoints = __webpack_require__(1600); - -var _Breakpoints2 = _interopRequireDefault(_Breakpoints); - -var _Expressions = __webpack_require__(1601); - -var _Expressions2 = _interopRequireDefault(_Expressions); - -var _devtoolsSplitter = __webpack_require__(1440); - -var _devtoolsSplitter2 = _interopRequireDefault(_devtoolsSplitter); - -var _Frames = __webpack_require__(1602); - -var _Frames2 = _interopRequireDefault(_Frames); - -var _EventListeners = __webpack_require__(1605); - -var _EventListeners2 = _interopRequireDefault(_EventListeners); - -var _Workers = __webpack_require__(1606); - -var _Workers2 = _interopRequireDefault(_Workers); - -var _Accordion = __webpack_require__(1607); - -var _Accordion2 = _interopRequireDefault(_Accordion); - -var _CommandBar = __webpack_require__(1608); - -var _CommandBar2 = _interopRequireDefault(_CommandBar); - -var _UtilsBar = __webpack_require__(1609); - -var _UtilsBar2 = _interopRequireDefault(_UtilsBar); - -var _FrameworkComponent = __webpack_require__(3623); - -var _FrameworkComponent2 = _interopRequireDefault(_FrameworkComponent); - -var _ReactComponentStack = __webpack_require__(3639); - -var _ReactComponentStack2 = _interopRequireDefault(_ReactComponentStack); - -var _Scopes = __webpack_require__(1611); - -var _Scopes2 = _interopRequireDefault(_Scopes); - -__webpack_require__(1342); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function debugBtn(onClick, type, className, tooltip) { - return _react2.default.createElement( - "button", - { - onClick: onClick, - className: `${type} ${className}`, - key: type, - title: tooltip - }, - _react2.default.createElement(_Svg2.default, { name: type, title: tooltip, "aria-label": tooltip }) - ); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class SecondaryPanes extends _react.Component { - constructor(props) { - super(props); - - this.onExpressionAdded = () => { - this.setState({ showExpressionsInput: false }); - }; - - this.state = { - showExpressionsInput: false - }; - } - - renderBreakpointsToggle() { - const { - toggleAllBreakpoints, - breakpoints, - breakpointsDisabled, - breakpointsLoading - } = this.props; - const isIndeterminate = !breakpointsDisabled && breakpoints.some(x => x.disabled); - - if (_prefs.features.skipPausing || breakpoints.size == 0) { - return null; - } - - const inputProps = { - type: "checkbox", - "aria-label": breakpointsDisabled ? L10N.getStr("breakpoints.enable") : L10N.getStr("breakpoints.disable"), - className: "breakpoints-toggle", - disabled: breakpointsLoading, - key: "breakpoints-toggle", - onChange: e => { - e.stopPropagation(); - toggleAllBreakpoints(!breakpointsDisabled); - }, - onClick: e => e.stopPropagation(), - checked: !breakpointsDisabled && !isIndeterminate, - ref: input => { - if (input) { - input.indeterminate = isIndeterminate; - } - }, - title: breakpointsDisabled ? L10N.getStr("breakpoints.enable") : L10N.getStr("breakpoints.disable") - }; - - return _react2.default.createElement("input", inputProps); - } - - watchExpressionHeaderButtons() { - const { expressions } = this.props; - - const buttons = []; - - if (expressions.size) { - buttons.push(debugBtn(evt => { - evt.stopPropagation(); - this.props.evaluateExpressions(); - }, "refresh", "refresh", L10N.getStr("watchExpressions.refreshButton"))); - } - - buttons.push(debugBtn(evt => { - if (_prefs.prefs.expressionsVisible) { - evt.stopPropagation(); - } - this.setState({ showExpressionsInput: true }); - }, "plus", "plus", L10N.getStr("expressions.placeholder"))); - - return buttons; - } - - getScopeItem() { - return { - header: L10N.getStr("scopes.header"), - className: "scopes-pane", - component: _react2.default.createElement(_Scopes2.default, null), - opened: _prefs.prefs.scopesVisible, - onToggle: opened => { - _prefs.prefs.scopesVisible = opened; - } - }; - } - - getComponentStackItem() { - return { - header: L10N.getStr("components.header"), - component: _react2.default.createElement(_ReactComponentStack2.default, null), - opened: _prefs.prefs.componentStackVisible, - onToggle: opened => { - _prefs.prefs.componentStackVisible = opened; - } - }; - } - - getComponentItem() { - const { extra: { react } } = this.props; - - return { - header: react.displayName, - className: "component-pane", - component: _react2.default.createElement(_FrameworkComponent2.default, null), - opened: _prefs.prefs.componentVisible, - onToggle: opened => { - _prefs.prefs.componentVisible = opened; - } - }; - } - - getWatchItem() { - return { - header: L10N.getStr("watchExpressions.header"), - className: "watch-expressions-pane", - buttons: this.watchExpressionHeaderButtons(), - component: _react2.default.createElement(_Expressions2.default, { - showInput: this.state.showExpressionsInput, - onExpressionAdded: this.onExpressionAdded - }), - opened: _prefs.prefs.expressionsVisible, - onToggle: opened => { - _prefs.prefs.expressionsVisible = opened; - } - }; - } - - getCallStackItem() { - return { - header: L10N.getStr("callStack.header"), - className: "call-stack-pane", - component: _react2.default.createElement(_Frames2.default, null), - opened: _prefs.prefs.callStackVisible, - onToggle: opened => { - _prefs.prefs.callStackVisible = opened; - } - }; - } - - getWorkersItem() { - return { - header: L10N.getStr("workersHeader"), - className: "workers-pane", - component: _react2.default.createElement(_Workers2.default, null), - opened: _prefs.prefs.workersVisible, - onToggle: opened => { - _prefs.prefs.workersVisible = opened; - } - }; - } - - getBreakpointsItem() { - const { - shouldPauseOnExceptions, - shouldPauseOnCaughtExceptions, - pauseOnExceptions - } = this.props; - - return { - header: L10N.getStr("breakpoints.header"), - className: "breakpoints-pane", - buttons: [this.renderBreakpointsToggle()], - component: _react2.default.createElement(_Breakpoints2.default, { - shouldPauseOnExceptions: shouldPauseOnExceptions, - shouldPauseOnCaughtExceptions: shouldPauseOnCaughtExceptions, - pauseOnExceptions: pauseOnExceptions - }), - opened: _prefs.prefs.breakpointsVisible, - onToggle: opened => { - _prefs.prefs.breakpointsVisible = opened; - } - }; - } - - getStartItems() { - const { extra, workers } = this.props; - - const items = []; - if (this.props.horizontal) { - if (_prefs.features.workers && workers.size > 0) { - items.push(this.getWorkersItem()); - } - - items.push(this.getWatchItem()); - } - - items.push(this.getBreakpointsItem()); - - if (this.props.hasFrames) { - items.push(this.getCallStackItem()); - - if (this.props.horizontal) { - if (extra && extra.react) { - if (_prefs.features.componentStack && extra.react.componentStack.length > 1) { - items.push(this.getComponentStackItem()); - } - items.push(this.getComponentItem()); - } - - items.push(this.getScopeItem()); - } - } - - if (_prefs.features.eventListeners) { - items.push({ - header: L10N.getStr("eventListenersHeader"), - className: "event-listeners-pane", - component: _react2.default.createElement(_EventListeners2.default, null) - }); - } - - return items.filter(item => item); - } - - renderHorizontalLayout() { - return _react2.default.createElement(_Accordion2.default, { items: this.getItems() }); - } - - getEndItems() { - const { extra, workers } = this.props; - - let items = []; - - if (this.props.horizontal) { - return []; - } - - if (_prefs.features.workers && workers.size > 0) { - items.push(this.getWorkersItem()); - } - - items.push(this.getWatchItem()); - - if (extra && extra.react) { - items.push(this.getComponentItem()); - } - - if (this.props.hasFrames) { - items = [...items, this.getScopeItem()]; - } - - return items; - } - - getItems() { - return [...this.getStartItems(), ...this.getEndItems()]; - } - - renderVerticalLayout() { - return _react2.default.createElement(_devtoolsSplitter2.default, { - initialSize: "300px", - minSize: 10, - maxSize: "50%", - splitterSize: 1, - startPanel: _react2.default.createElement(_Accordion2.default, { items: this.getStartItems() }), - endPanel: _react2.default.createElement(_Accordion2.default, { items: this.getEndItems() }) - }); - } - - renderUtilsBar() { - if (!_prefs.features.shortcuts) { - return; - } - - return _react2.default.createElement(_UtilsBar2.default, { - horizontal: this.props.horizontal, - toggleShortcutsModal: this.props.toggleShortcutsModal - }); - } - - render() { - return _react2.default.createElement( - "div", - { className: "secondary-panes-wrapper" }, - _react2.default.createElement(_CommandBar2.default, { horizontal: this.props.horizontal }), - _react2.default.createElement( - "div", - { className: "secondary-panes" }, - this.props.horizontal ? this.renderHorizontalLayout() : this.renderVerticalLayout() - ), - this.renderUtilsBar() - ); - } -} - -SecondaryPanes.contextTypes = { - shortcuts: _propTypes2.default.object -}; - -const mapStateToProps = state => ({ - expressions: (0, _selectors.getExpressions)(state), - extra: (0, _selectors.getExtra)(state), - hasFrames: !!(0, _selectors.getTopFrame)(state), - breakpoints: (0, _selectors.getBreakpoints)(state), - breakpointsDisabled: (0, _selectors.getBreakpointsDisabled)(state), - breakpointsLoading: (0, _selectors.getBreakpointsLoading)(state), - isWaitingOnBreak: (0, _selectors.getIsWaitingOnBreak)(state), - shouldPauseOnExceptions: (0, _selectors.getShouldPauseOnExceptions)(state), - shouldPauseOnCaughtExceptions: (0, _selectors.getShouldPauseOnCaughtExceptions)(state), - workers: (0, _selectors.getWorkers)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SecondaryPanes); - -/***/ }), - -/***/ 1600: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _reactRedux = __webpack_require__(3592); - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _reselect = __webpack_require__(993); - -var _lodash = __webpack_require__(2); - -var _Breakpoint = __webpack_require__(3634); - -var _Breakpoint2 = _interopRequireDefault(_Breakpoint); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _source = __webpack_require__(1356); - -var _selectors = __webpack_require__(3590); - -var _pause = __webpack_require__(2419); - -var _breakpoint = __webpack_require__(1364); - -var _BreakpointsContextMenu = __webpack_require__(1805); - -var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu); - -__webpack_require__(1334); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function isCurrentlyPausedAtBreakpoint(frame, why, breakpoint) { - if (!frame || !(0, _pause.isInterrupted)(why)) { - return false; - } - - const bpId = (0, _breakpoint.makeLocationId)(breakpoint.location); - const pausedId = (0, _breakpoint.makeLocationId)(frame.location); - return bpId === pausedId; -} - -function createExceptionOption(label, value, onChange, className) { - return _react2.default.createElement( - "div", - { className: className, onClick: onChange }, - _react2.default.createElement("input", { - type: "checkbox", - checked: value ? "checked" : "", - onChange: e => e.stopPropagation() && onChange() - }), - _react2.default.createElement( - "div", - { className: "breakpoint-exceptions-label" }, - label - ) - ); -} - -function sortFilenames(urlA, urlB) { - const filenameA = (0, _source.getFilenameFromURL)(urlA); - const filenameB = (0, _source.getFilenameFromURL)(urlB); - - if (filenameA > filenameB) { - return 1; - } - if (filenameA < filenameB) { - return -1; - } - - return 0; -} - -class Breakpoints extends _react.Component { - handleBreakpointCheckbox(breakpoint) { - if (breakpoint.loading) { - return; - } - - if (breakpoint.disabled) { - this.props.enableBreakpoint(breakpoint.location); - } else { - this.props.disableBreakpoint(breakpoint.location); - } - } - - selectBreakpoint(breakpoint) { - this.props.selectLocation(breakpoint.location); - } - - removeBreakpoint(event, breakpoint) { - event.stopPropagation(); - this.props.removeBreakpoint(breakpoint.location); - } - - renderBreakpoint(breakpoint) { - const { selectedSource } = this.props; - - return _react2.default.createElement(_Breakpoint2.default, { - key: breakpoint.locationId, - breakpoint: breakpoint, - selectedSource: selectedSource, - onClick: () => this.selectBreakpoint(breakpoint), - onContextMenu: e => (0, _BreakpointsContextMenu2.default)(_extends({}, this.props, { breakpoint, contextMenuEvent: e })), - onChange: () => this.handleBreakpointCheckbox(breakpoint), - onCloseClick: ev => this.removeBreakpoint(ev, breakpoint) - }); - } - - renderExceptionsOptions() { - const { - breakpoints, - shouldPauseOnExceptions, - shouldPauseOnCaughtExceptions, - pauseOnExceptions - } = this.props; - - const isEmpty = breakpoints.size == 0; - - const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions"); - - const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught"); - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("breakpoints-exceptions-options", { - empty: isEmpty - }) - }, - exceptionsBox, - shouldPauseOnExceptions ? ignoreCaughtBox : null - ); - } - - renderBreakpoints() { - const { breakpoints } = this.props; - if (breakpoints.size == 0) { - return; - } - - const groupedBreakpoints = (0, _lodash.groupBy)((0, _lodash.sortBy)([...breakpoints.valueSeq()], bp => bp.location.line), bp => (0, _source.getRawSourceURL)(bp.source.url)); - - return [...Object.keys(groupedBreakpoints).sort(sortFilenames).map(url => { - const file = (0, _source.getFilenameFromURL)(url); - const groupBreakpoints = groupedBreakpoints[url].filter(bp => !bp.hidden && (bp.text || bp.originalText)); - - if (!groupBreakpoints.length) { - return null; - } - - return [_react2.default.createElement( - "div", - { - className: "breakpoint-heading", - title: url, - key: url, - onClick: () => this.props.selectSource(groupBreakpoints[0].source.id) - }, - file - ), ...groupBreakpoints.map(bp => this.renderBreakpoint(bp))]; - })]; - } - - render() { - return _react2.default.createElement( - "div", - { className: "pane breakpoints-list" }, - this.renderExceptionsOptions(), - this.renderBreakpoints() - ); - } -} - -function updateLocation(sources, frame, why, bp) { - const source = (0, _selectors.getSourceInSources)(sources, bp.location.sourceId); - const isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(frame, why, bp); - const locationId = (0, _breakpoint.makeLocationId)(bp.location); - const localBP = _extends({}, bp, { locationId, isCurrentlyPaused, source }); - - return localBP; -} - -const _getBreakpoints = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _selectors.getTopFrame, _selectors.getPauseReason, (breakpoints, sources, frame, why) => breakpoints.map(bp => updateLocation(sources, frame, why, bp)).filter(bp => bp.source && !bp.source.isBlackBoxed)); - -const mapStateToProps = state => ({ - breakpoints: _getBreakpoints(state), - selectedSource: (0, _selectors.getSelectedSource)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints); - -/***/ }), - -/***/ 1601: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _devtoolsReps = __webpack_require__(3655); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _expressions = __webpack_require__(1437); - -var _firefox = __webpack_require__(1500); - -var _Close = __webpack_require__(1374); - -var _Close2 = _interopRequireDefault(_Close); - -__webpack_require__(1335); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Expressions extends _react.Component { - - constructor(props) { - super(props); - - this.clear = () => { - this.setState(() => { - this.props.clearExpressionError(); - return { editing: false, editIndex: -1, inputValue: "" }; - }); - }; - - this.handleChange = e => { - this.setState({ inputValue: e.target.value }); - }; - - this.handleKeyDown = e => { - if (e.key === "Escape") { - this.clear(); - } - }; - - this.hideInput = () => { - this.setState({ focused: false }); - this.props.onExpressionAdded(); - }; - - this.onFocus = () => { - this.setState({ focused: true }); - }; - - this.handleExistingSubmit = async (e, expression) => { - e.preventDefault(); - e.stopPropagation(); - - this.props.updateExpression(this.state.inputValue, expression); - this.hideInput(); - }; - - this.handleNewSubmit = async e => { - const { inputValue } = this.state; - e.preventDefault(); - e.stopPropagation(); - - this.props.clearExpressionError(); - await this.props.addExpression(this.state.inputValue); - this.setState({ - editing: false, - editIndex: -1, - inputValue: this.props.expressionError ? inputValue : "" - }); - - if (!this.props.expressionError) { - this.hideInput(); - } - }; - - this.renderExpression = (expression, index) => { - const { expressionError, openLink } = this.props; - const { editing, editIndex } = this.state; - const { input, updating } = expression; - const isEditingExpr = editing && editIndex === index; - if (isEditingExpr || isEditingExpr && expressionError) { - return this.renderExpressionEditInput(expression); - } - - if (updating) { - return; - } - - const { value } = (0, _expressions.getValue)(expression); - - const root = { - name: expression.input, - path: input, - contents: { value } - }; - - return _react2.default.createElement( - "li", - { - className: "expression-container", - key: input, - onDoubleClick: (items, options) => this.editExpression(expression, index) - }, - _react2.default.createElement( - "div", - { className: "expression-content" }, - _react2.default.createElement(_devtoolsReps.ObjectInspector, { - roots: [root], - autoExpandDepth: 0, - disableWrap: true, - focusable: false, - openLink: openLink, - createObjectClient: grip => (0, _firefox.createObjectClient)(grip) - }), - _react2.default.createElement( - "div", - { className: "expression-container__close-btn" }, - _react2.default.createElement(_Close2.default, { - handleClick: e => this.deleteExpression(e, expression) - }) - ) - ) - ); - }; - - this.state = { - editing: false, - editIndex: -1, - inputValue: "", - focused: false - }; - } - - componentDidMount() { - const { expressions, evaluateExpressions } = this.props; - if (expressions.size > 0) { - evaluateExpressions(); - } - } - - componentWillReceiveProps(nextProps) { - if (this.state.editing && !nextProps.expressionError) { - this.clear(); - } - } - - shouldComponentUpdate(nextProps, nextState) { - const { editing, inputValue, focused } = this.state; - const { expressions, expressionError, showInput } = this.props; - - return expressions !== nextProps.expressions || expressionError !== nextProps.expressionError || editing !== nextState.editing || inputValue !== nextState.inputValue || nextProps.showInput !== showInput || focused !== nextState.focused; - } - - componentDidUpdate(prevProps, prevState) { - const input = this._input; - - if (!input) { - return; - } - - if (!prevState.editing && this.state.editing) { - input.setSelectionRange(0, input.value.length); - input.focus(); - } else if (this.props.showInput && !this.state.focused) { - input.focus(); - } - } - - editExpression(expression, index) { - this.setState({ - inputValue: expression.input, - editing: true, - editIndex: index - }); - } - - deleteExpression(e, expression) { - e.stopPropagation(); - const { deleteExpression } = this.props; - deleteExpression(expression); - } - - onBlur() { - this.clear(); - this.hideInput(); - } - - renderNewExpressionInput() { - const { expressionError, showInput } = this.props; - const { editing, inputValue, focused } = this.state; - const error = editing === false && expressionError === true; - const placeholder = error ? L10N.getStr("expressions.errorMsg") : L10N.getStr("expressions.placeholder"); - - return _react2.default.createElement( - "li", - { - className: (0, _classnames2.default)("expression-input-container", { focused, error }) - }, - _react2.default.createElement( - "form", - { className: "expression-input-form", onSubmit: this.handleNewSubmit }, - _react2.default.createElement("input", { - className: "input-expression", - type: "text", - placeholder: placeholder, - onChange: this.handleChange, - onBlur: this.hideInput, - onKeyDown: this.handleKeyDown, - onFocus: this.onFocus, - autoFocus: showInput, - value: !editing ? inputValue : "", - ref: c => this._input = c - }), - _react2.default.createElement("input", { type: "submit", style: { display: "none" } }) - ) - ); - } - - renderExpressionEditInput(expression) { - const { expressionError } = this.props; - const { inputValue, editing, focused } = this.state; - const error = editing === true && expressionError === true; - - return _react2.default.createElement( - "span", - { - className: (0, _classnames2.default)("expression-input-container", { focused, error }), - key: expression.input - }, - _react2.default.createElement( - "form", - { - className: "expression-input-form", - onSubmit: e => this.handleExistingSubmit(e, expression) - }, - _react2.default.createElement("input", { - className: (0, _classnames2.default)("input-expression", { error }), - type: "text", - onChange: this.handleChange, - onBlur: this.clear, - onKeyDown: this.handleKeyDown, - onFocus: this.onFocus, - value: editing ? inputValue : expression.input, - ref: c => this._input = c - }), - _react2.default.createElement("input", { type: "submit", style: { display: "none" } }) - ) - ); - } - - render() { - const { expressions, showInput } = this.props; - - return _react2.default.createElement( - "ul", - { className: "pane expressions-list" }, - expressions.map(this.renderExpression), - (showInput || !expressions.size) && this.renderNewExpressionInput() - ); - } -} - -const mapStateToProps = state => ({ - expressions: (0, _selectors.getExpressions)(state), - expressionError: (0, _selectors.getExpressionError)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Expressions); - -/***/ }), - -/***/ 1602: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _Frame = __webpack_require__(1453); - -var _Frame2 = _interopRequireDefault(_Frame); - -var _Group = __webpack_require__(1603); - -var _Group2 = _interopRequireDefault(_Group); - -var _WhyPaused = __webpack_require__(1604); - -var _WhyPaused2 = _interopRequireDefault(_WhyPaused); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _frames = __webpack_require__(3605); - -var _clipboard = __webpack_require__(1388); - -var _selectors = __webpack_require__(3590); - -__webpack_require__(1338); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const NUM_FRAMES_SHOWN = 7; - -class Frames extends _react.Component { - - constructor(props) { - super(props); - - this.toggleFramesDisplay = () => { - this.setState(prevState => ({ - showAllFrames: !prevState.showAllFrames - })); - }; - - this.copyStackTrace = () => { - const { frames } = this.props; - const framesToCopy = frames.map(f => (0, _frames.formatCopyName)(f)).join("\n"); - (0, _clipboard.copyToTheClipboard)(framesToCopy); - }; - - this.toggleFrameworkGrouping = () => { - const { toggleFrameworkGrouping, frameworkGroupingOn } = this.props; - toggleFrameworkGrouping(!frameworkGroupingOn); - }; - - this.state = { - showAllFrames: !!props.disableFrameTruncate - }; - } - - shouldComponentUpdate(nextProps, nextState) { - const { frames, selectedFrame, frameworkGroupingOn } = this.props; - const { showAllFrames } = this.state; - return frames !== nextProps.frames || selectedFrame !== nextProps.selectedFrame || showAllFrames !== nextState.showAllFrames || frameworkGroupingOn !== nextProps.frameworkGroupingOn; - } - - collapseFrames(frames) { - const { frameworkGroupingOn } = this.props; - if (!frameworkGroupingOn) { - return frames; - } - - return (0, _frames.collapseFrames)(frames); - } - - truncateFrames(frames) { - const numFramesToShow = this.state.showAllFrames ? frames.length : NUM_FRAMES_SHOWN; - - return frames.slice(0, numFramesToShow); - } - - renderFrames(frames) { - const { - selectFrame, - selectedFrame, - toggleBlackBox, - frameworkGroupingOn - } = this.props; - - const framesOrGroups = this.truncateFrames(this.collapseFrames(frames)); - - - return _react2.default.createElement( - "ul", - null, - framesOrGroups.map(frameOrGroup => frameOrGroup.id ? _react2.default.createElement(_Frame2.default, { - frame: frameOrGroup, - toggleFrameworkGrouping: this.toggleFrameworkGrouping, - copyStackTrace: this.copyStackTrace, - frameworkGroupingOn: frameworkGroupingOn, - selectFrame: selectFrame, - selectedFrame: selectedFrame, - toggleBlackBox: toggleBlackBox, - key: String(frameOrGroup.id) - }) : _react2.default.createElement(_Group2.default, { - group: frameOrGroup, - toggleFrameworkGrouping: this.toggleFrameworkGrouping, - copyStackTrace: this.copyStackTrace, - frameworkGroupingOn: frameworkGroupingOn, - selectFrame: selectFrame, - selectedFrame: selectedFrame, - toggleBlackBox: toggleBlackBox, - key: frameOrGroup[0].id - })) - ); - } - - renderToggleButton(frames) { - const buttonMessage = this.state.showAllFrames ? L10N.getStr("callStack.collapse") : L10N.getStr("callStack.expand"); - - frames = this.collapseFrames(frames); - if (frames.length <= NUM_FRAMES_SHOWN) { - return null; - } - - return _react2.default.createElement( - "div", - { className: "show-more-container" }, - _react2.default.createElement( - "button", - { className: "show-more", onClick: this.toggleFramesDisplay }, - buttonMessage - ) - ); - } - - render() { - const { frames, disableFrameTruncate, why } = this.props; - - if (!frames) { - return _react2.default.createElement( - "div", - { className: "pane frames" }, - _react2.default.createElement( - "div", - { className: "pane-info empty" }, - L10N.getStr("callStack.notPaused") - ) - ); - } - - return _react2.default.createElement( - "div", - { className: "pane frames" }, - this.renderFrames(frames), - (0, _WhyPaused2.default)(why), - disableFrameTruncate ? null : this.renderToggleButton(frames) - ); - } -} - -const mapStateToProps = state => ({ - frames: (0, _selectors.getCallStackFrames)(state), - why: (0, _selectors.getPauseReason)(state), - frameworkGroupingOn: (0, _selectors.getFrameworkGroupingState)(state), - selectedFrame: (0, _selectors.getSelectedFrame)(state), - pause: (0, _selectors.isPaused)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Frames); - -/***/ }), - -/***/ 1603: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _frames = __webpack_require__(3605); - -var _FrameMenu = __webpack_require__(1454); - -var _FrameMenu2 = _interopRequireDefault(_FrameMenu); - -__webpack_require__(1336); - -var _Frame = __webpack_require__(1453); - -var _Frame2 = _interopRequireDefault(_Frame); - -var _Badge = __webpack_require__(1704); - -var _Badge2 = _interopRequireDefault(_Badge); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function FrameLocation({ frame }) { - const library = frame.library || (0, _frames.getLibraryFromUrl)(frame); - if (!library) { - return null; - } - - return _react2.default.createElement( - "div", - { className: "location" }, - library, - _react2.default.createElement(_Svg2.default, { name: library.toLowerCase(), className: "annotation-logo" }) - ); -} - -FrameLocation.displayName = "FrameLocation"; - -class Group extends _react.Component { - - constructor(...args) { - super(...args); - - this.toggleFrames = () => { - this.setState(prevState => ({ expanded: !prevState.expanded })); - }; - - this.state = { expanded: false }; - } - - onContextMenu(event) { - const { - group, - copyStackTrace, - toggleFrameworkGrouping, - toggleBlackBox, - frameworkGroupingOn - } = this.props; - const frame = group[0]; - (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { copyStackTrace, toggleFrameworkGrouping, toggleBlackBox }, event); - } - - renderFrames() { - const { - group, - selectFrame, - selectedFrame, - toggleFrameworkGrouping, - frameworkGroupingOn, - toggleBlackBox, - copyStackTrace - } = this.props; - - const { expanded } = this.state; - if (!expanded) { - return null; - } - - return _react2.default.createElement( - "div", - { className: "frames-list" }, - group.map(frame => _react2.default.createElement(_Frame2.default, { - copyStackTrace: copyStackTrace, - frame: frame, - frameworkGroupingOn: frameworkGroupingOn, - hideLocation: true, - key: frame.id, - selectedFrame: selectedFrame, - selectFrame: selectFrame, - shouldMapDisplayName: false, - toggleBlackBox: toggleBlackBox, - toggleFrameworkGrouping: toggleFrameworkGrouping - })) - ); - } - - renderDescription() { - const frame = this.props.group[0]; - const displayName = (0, _frames.formatDisplayName)(frame); - return _react2.default.createElement( - "li", - { - key: frame.id, - className: (0, _classnames2.default)("group"), - onClick: this.toggleFrames, - tabIndex: 0 - }, - _react2.default.createElement( - "div", - { className: "d-flex align-items-center min-width-0" }, - _react2.default.createElement( - "div", - { className: "title" }, - displayName - ), - _react2.default.createElement( - _Badge2.default, - null, - this.props.group.length - ) - ), - _react2.default.createElement(FrameLocation, { frame: frame }) - ); - } - - render() { - const { expanded } = this.state; - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("frames-group", { expanded }), - onContextMenu: e => this.onContextMenu(e) - }, - this.renderDescription(), - this.renderFrames() - ); - } -} - -exports.default = Group; -Group.displayName = "Group"; - -/***/ }), - -/***/ 1604: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = renderWhyPaused; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _pause = __webpack_require__(2419); - -__webpack_require__(1337); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function renderExceptionSummary(exception) { - if (typeof exception === "string") { - return exception; - } - - const preview = exception.preview; - if (!preview) { - return; - } - - return `${preview.name}: ${preview.message}`; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function renderMessage(why) { - if (why.type == "exception" && why.exception) { - return _react2.default.createElement( - "div", - { className: "message warning" }, - renderExceptionSummary(why.exception) - ); - } - - if (typeof why.message == "string") { - return _react2.default.createElement( - "div", - { className: "message" }, - why.message - ); - } - - return null; -} - -function renderWhyPaused(why) { - const reason = (0, _pause.getPauseReason)(why); - - if (!reason) { - return null; - } - - return _react2.default.createElement( - "div", - { className: "pane why-paused" }, - _react2.default.createElement( - "div", - null, - L10N.getStr(reason) - ), - renderMessage(why) - ); -} -renderWhyPaused.displayName = "whyPaused"; - -/***/ }), - -/***/ 1605: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _Close = __webpack_require__(1374); - -var _Close2 = _interopRequireDefault(_Close); - -__webpack_require__(1339); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class EventListeners extends _react.Component { - - constructor(...args) { - super(...args); - - this.renderListener = ({ type, selector, line, sourceId, breakpoint }) => { - const checked = breakpoint && !breakpoint.disabled; - const location = { sourceId, line }; - - return _react2.default.createElement( - "div", - { - className: "listener", - onClick: () => this.props.selectLocation({ sourceId, line }), - key: `${type}.${selector}.${sourceId}.${line}` - }, - _react2.default.createElement("input", { - type: "checkbox", - className: "listener-checkbox", - checked: checked, - onChange: () => this.handleCheckbox(breakpoint, location) - }), - _react2.default.createElement( - "span", - { className: "type" }, - type - ), - _react2.default.createElement( - "span", - { className: "selector" }, - selector - ), - breakpoint ? _react2.default.createElement(_Close2.default, { - handleClick: ev => this.removeBreakpoint(ev, breakpoint) - }) : "" - ); - }; - } - - handleCheckbox(breakpoint, location) { - if (!breakpoint) { - return this.props.addBreakpoint(location); - } - - if (breakpoint.loading) { - return; - } - - if (breakpoint.disabled) { - this.props.enableBreakpoint(breakpoint.location); - } else { - this.props.disableBreakpoint(breakpoint.location); - } - } - - removeBreakpoint(event, breakpoint) { - event.stopPropagation(); - if (breakpoint) { - this.props.removeBreakpoint(breakpoint.location); - } - } - - render() { - const { listeners } = this.props; - return _react2.default.createElement( - "div", - { className: "pane event-listeners" }, - listeners.map(this.renderListener) - ); - } -} - -const mapStateToProps = state => { - const listeners = (0, _selectors.getEventListeners)(state).map(listener => { - return _extends({}, listener, { - breakpoint: (0, _selectors.getBreakpoint)(state, { - sourceId: listener.sourceId, - line: listener.line, - column: null - }) - }); - }); - - return { listeners }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(EventListeners); - -/***/ }), - -/***/ 1606: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Workers = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -__webpack_require__(1340); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _path = __webpack_require__(1393); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Workers extends _react.PureComponent { - - renderWorkers(workers) { - const { openWorkerToolbox } = this.props; - return workers.map(worker => _react2.default.createElement( - "div", - { - className: "worker", - key: worker.actor, - onClick: () => openWorkerToolbox(worker) - }, - _react2.default.createElement("img", { className: "domain" }), - (0, _path.basename)(worker.url) - )); - } - - renderNoWorkersPlaceholder() { - return _react2.default.createElement( - "div", - { className: "pane-info" }, - L10N.getStr("noWorkersText") - ); - } - - render() { - const { workers } = this.props; - return _react2.default.createElement( - "div", - { className: "pane workers-list" }, - workers && workers.size > 0 ? this.renderWorkers(workers) : this.renderNoWorkersPlaceholder() - ); - } -} - -exports.Workers = Workers; -const mapStateToProps = state => ({ - workers: (0, _selectors.getWorkers)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Workers); - -/***/ }), - -/***/ 1607: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -__webpack_require__(1341); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class Accordion extends _react.Component { - constructor(props) { - super(props); - - this.renderContainer = (item, i) => { - const { opened } = item; - - return _react2.default.createElement( - "li", - { role: "listitem", className: item.className, key: i }, - _react2.default.createElement( - "h2", - { - className: "_header", - tabIndex: "0", - onClick: () => this.handleHeaderClick(i) - }, - _react2.default.createElement(_Svg2.default, { name: "arrow", className: opened ? "expanded" : "" }), - item.header, - item.buttons ? _react2.default.createElement( - "div", - { className: "header-buttons", tabIndex: "-1" }, - item.buttons - ) : null - ), - opened && _react2.default.createElement( - "div", - { className: "_content" }, - (0, _react.cloneElement)(item.component, item.componentProps || {}) - ) - ); - }; - - this.state = { - opened: props.items.map(item => item.opened), - created: [] - }; - } - - handleHeaderClick(i) { - const item = this.props.items[i]; - const opened = !item.opened; - item.opened = opened; - - if (item.onToggle) { - item.onToggle(opened); - } - - // We force an update because otherwise the accordion - // would not re-render - this.forceUpdate(); - } - - render() { - return _react2.default.createElement( - "ul", - { role: "list", className: "accordion" }, - this.props.items.map(this.renderContainer) - ); - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.default = Accordion; - -/***/ }), - -/***/ 1608: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _prefs = __webpack_require__(226); - -var _selectors = __webpack_require__(3590); - -var _text = __webpack_require__(1387); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _CommandBarButton = __webpack_require__(1764); - -__webpack_require__(1295); - -var _devtoolsModules = __webpack_require__(1376); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { appinfo } = _devtoolsModules.Services; /* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const isMacOS = appinfo.OS === "Darwin"; - -const COMMANDS = ["resume", "stepOver", "stepIn", "stepOut"]; - -const KEYS = { - WINNT: { - resume: "F8", - pause: "F8", - stepOver: "F10", - stepIn: "F11", - stepOut: "Shift+F11" - }, - Darwin: { - resume: "Cmd+\\", - pause: "Cmd+\\", - stepOver: "Cmd+'", - stepIn: "Cmd+;", - stepOut: "Cmd+Shift+:", - stepOutDisplay: "Cmd+Shift+;" - }, - Linux: { - resume: "F8", - pause: "F8", - stepOver: "F10", - stepIn: "Ctrl+F11", - stepOut: "Ctrl+Shift+F11" - } -}; - -function getKey(action) { - return getKeyForOS(appinfo.OS, action); -} - -function getKeyForOS(os, action) { - const osActions = KEYS[os] || KEYS.Linux; - return osActions[action]; -} - -function formatKey(action) { - const key = getKey(`${action}Display`) || getKey(action); - if (isMacOS) { - const winKey = getKeyForOS("WINNT", `${action}Display`) || getKeyForOS("WINNT", action); - // display both Windows type and Mac specific keys - return (0, _text.formatKeyShortcut)([key, winKey].join(" ")); - } - return (0, _text.formatKeyShortcut)(key); -} - -class CommandBar extends _react.Component { - componentWillUnmount() { - const shortcuts = this.context.shortcuts; - COMMANDS.forEach(action => shortcuts.off(getKey(action))); - if (isMacOS) { - COMMANDS.forEach(action => shortcuts.off(getKeyForOS("WINNT", action))); - } - } - - componentDidMount() { - const shortcuts = this.context.shortcuts; - - COMMANDS.forEach(action => shortcuts.on(getKey(action), (_, e) => this.handleEvent(e, action))); - - if (isMacOS) { - // The Mac supports both the Windows Function keys - // as well as the Mac non-Function keys - COMMANDS.forEach(action => shortcuts.on(getKeyForOS("WINNT", action), (_, e) => this.handleEvent(e, action))); - } - } - - handleEvent(e, action) { - e.preventDefault(); - e.stopPropagation(); - - this.props[action](); - } - - setHistory(offset) { - this.props.timeTravelTo(this.props.historyPosition + offset); - } - - renderStepButtons() { - const { isPaused, canRewind } = this.props; - const className = isPaused ? "active" : "disabled"; - const isDisabled = !isPaused; - - if (canRewind || !isPaused && _prefs.features.removeCommandBarOptions) { - return; - } - - return [(0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", className, L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled)]; - } - - resume() { - this.props.resume(); - this.props.clearHistory(); - } - - renderPauseButton() { - const { isPaused, breakOnNext, isWaitingOnBreak, canRewind } = this.props; - - if (canRewind) { - return; - } - - if (isPaused) { - return (0, _CommandBarButton.debugBtn)(() => this.resume(), "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))); - } - - if (_prefs.features.removeCommandBarOptions && !this.props.canRewind) { - return; - } - - if (isWaitingOnBreak) { - return (0, _CommandBarButton.debugBtn)(null, "pause", "disabled", L10N.getStr("pausePendingButtonTooltip"), true); - } - - return (0, _CommandBarButton.debugBtn)(breakOnNext, "pause", "active", L10N.getFormatStr("pauseButtonTooltip", formatKey("pause"))); - } - - renderTimeTravelButtons() { - const { isPaused, canRewind } = this.props; - - if (!canRewind || !isPaused) { - return null; - } - - const isDisabled = !isPaused; - - return [(0, _CommandBarButton.debugBtn)(this.props.rewind, "rewind", "active", "Rewind Execution"), (0, _CommandBarButton.debugBtn)(() => this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", { className: "divider" }), (0, _CommandBarButton.debugBtn)(this.props.reverseStepOver, "reverseStepOver", "active", "Reverse step over"), (0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", "active", L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), _react2.default.createElement("div", { className: "divider" }), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", "active", L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", "active", L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled)]; - } - - replayPreviousButton() { - const { history, historyPosition, canRewind } = this.props; - const historyLength = history.length; - - if (canRewind || !historyLength || historyLength <= 1 || !_prefs.features.replay) { - return null; - } - - const enabled = historyPosition === 0; - const activeClass = enabled ? "replay-inactive" : ""; - return (0, _CommandBarButton.debugBtn)(() => this.setHistory(-1), `replay-previous ${activeClass}`, "active", L10N.getStr("replayPrevious"), enabled); - } - - replayNextButton() { - const { history, historyPosition, canRewind } = this.props; - const historyLength = history.length; - - if (canRewind || !historyLength || historyLength <= 1 || !_prefs.features.replay) { - return null; - } - - const enabled = historyPosition + 1 === historyLength; - const activeClass = enabled ? "replay-inactive" : ""; - return (0, _CommandBarButton.debugBtn)(() => this.setHistory(1), `replay-next ${activeClass}`, "active", L10N.getStr("replayNext"), enabled); - } - - renderStepPosition() { - const { history, historyPosition, canRewind } = this.props; - const historyLength = history.length; - - if (canRewind || !historyLength || !_prefs.features.replay) { - return null; - } - - const position = historyPosition + 1; - const total = historyLength; - const activePrev = position > 1 ? "replay-active" : "replay-inactive"; - const activeNext = position < total ? "replay-active" : "replay-inactive"; - return _react2.default.createElement( - "div", - { className: "step-position" }, - _react2.default.createElement( - "span", - { className: activePrev }, - position - ), - _react2.default.createElement( - "span", - null, - " | " - ), - _react2.default.createElement( - "span", - { className: activeNext }, - total - ) - ); - } - - renderSkipPausingButton() { - const { skipPausing, toggleSkipPausing } = this.props; - - if (!_prefs.features.skipPausing) { - return null; - } - - return _react2.default.createElement( - "button", - { - className: (0, _classnames2.default)("command-bar-button", { - active: skipPausing - }), - title: L10N.getStr("skipPausingTooltip"), - onClick: toggleSkipPausing - }, - _react2.default.createElement("img", { className: "skipPausing" }) - ); - } - - render() { - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("command-bar", { - vertical: !this.props.horizontal - }) - }, - this.renderPauseButton(), - this.renderStepButtons(), - this.renderTimeTravelButtons(), - _react2.default.createElement("div", { className: "filler" }), - this.replayPreviousButton(), - this.renderStepPosition(), - this.replayNextButton(), - this.renderSkipPausingButton() - ); - } -} - -CommandBar.contextTypes = { - shortcuts: _propTypes2.default.object -}; - -const mapStateToProps = state => ({ - isPaused: (0, _selectors.isPaused)(state), - history: (0, _selectors.getHistory)(state), - historyPosition: (0, _selectors.getHistoryPosition)(state), - isWaitingOnBreak: (0, _selectors.getIsWaitingOnBreak)(state), - canRewind: (0, _selectors.getCanRewind)(state), - skipPausing: (0, _selectors.getSkipPausing)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(CommandBar); - -/***/ }), - -/***/ 1609: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _CommandBarButton = __webpack_require__(1764); - -__webpack_require__(1295); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class UtilsBar extends _react.Component { - renderUtilButtons() { - return [(0, _CommandBarButton.debugBtn)(this.props.toggleShortcutsModal, "shortcuts", "active", L10N.getStr("shortcuts.buttonName"), false)]; - } - - render() { - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("command-bar bottom", { - vertical: !this.props.horizontal - }) - }, - this.renderUtilButtons() - ); - } -} - -exports.default = UtilsBar; - -/***/ }), - -/***/ 161: -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(process) {(function() { - var Query, defaultPathSeparator, filter, matcher, parseOptions, pathScorer, preparedQueryCache, scorer; - - filter = __webpack_require__(162); - - matcher = __webpack_require__(166); - - scorer = __webpack_require__(163); - - pathScorer = __webpack_require__(164); - - Query = __webpack_require__(165); - - preparedQueryCache = null; - - defaultPathSeparator = (typeof process !== "undefined" && process !== null ? process.platform : void 0) === "win32" ? '\\' : '/'; - - module.exports = { - filter: function(candidates, query, options) { - if (options == null) { - options = {}; - } - if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) { - return []; - } - options = parseOptions(options, query); - return filter(candidates, query, options); - }, - score: function(string, query, options) { - if (options == null) { - options = {}; - } - if (!((string != null ? string.length : void 0) && (query != null ? query.length : void 0))) { - return 0; - } - options = parseOptions(options, query); - if (options.usePathScoring) { - return pathScorer.score(string, query, options); - } else { - return scorer.score(string, query, options); - } - }, - match: function(string, query, options) { - var _i, _ref, _results; - if (options == null) { - options = {}; - } - if (!string) { - return []; - } - if (!query) { - return []; - } - if (string === query) { - return (function() { - _results = []; - for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } - return _results; - }).apply(this); - } - options = parseOptions(options, query); - return matcher.match(string, query, options); - }, - wrap: function(string, query, options) { - if (options == null) { - options = {}; - } - if (!string) { - return []; - } - if (!query) { - return []; - } - options = parseOptions(options, query); - return matcher.wrap(string, query, options); - }, - prepareQuery: function(query, options) { - if (options == null) { - options = {}; - } - options = parseOptions(options, query); - return options.preparedQuery; - } - }; - - parseOptions = function(options, query) { - if (options.allowErrors == null) { - options.allowErrors = false; - } - if (options.usePathScoring == null) { - options.usePathScoring = true; - } - if (options.useExtensionBonus == null) { - options.useExtensionBonus = false; - } - if (options.pathSeparator == null) { - options.pathSeparator = defaultPathSeparator; - } - if (options.optCharRegEx == null) { - options.optCharRegEx = null; - } - if (options.wrap == null) { - options.wrap = null; - } - if (options.preparedQuery == null) { - options.preparedQuery = preparedQueryCache && preparedQueryCache.query === query ? preparedQueryCache : (preparedQueryCache = new Query(query, options)); - } - return options; - }; - -}).call(this); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120))) - -/***/ }), - -/***/ 1611: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _firefox = __webpack_require__(1500); - -var _selectors = __webpack_require__(3590); - -var _scopes = __webpack_require__(1792); - -var _devtoolsReps = __webpack_require__(3655); - -__webpack_require__(1296); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Scopes extends _react.PureComponent { - constructor(props, ...args) { - const { - why, - selectedFrame, - originalFrameScopes, - generatedFrameScopes - } = props; - - super(props, ...args); - - this.state = { - originalScopes: (0, _scopes.getScopes)(why, selectedFrame, originalFrameScopes), - generatedScopes: (0, _scopes.getScopes)(why, selectedFrame, generatedFrameScopes), - showOriginal: true - }; - } - - componentWillReceiveProps(nextProps) { - const { - isPaused, - selectedFrame, - originalFrameScopes, - generatedFrameScopes - } = this.props; - const isPausedChanged = isPaused !== nextProps.isPaused; - const selectedFrameChanged = selectedFrame !== nextProps.selectedFrame; - const originalFrameScopesChanged = originalFrameScopes !== nextProps.originalFrameScopes; - const generatedFrameScopesChanged = generatedFrameScopes !== nextProps.generatedFrameScopes; - - if (isPausedChanged || selectedFrameChanged || originalFrameScopesChanged || generatedFrameScopesChanged) { - this.setState({ - originalScopes: (0, _scopes.getScopes)(nextProps.why, nextProps.selectedFrame, nextProps.originalFrameScopes), - generatedScopes: (0, _scopes.getScopes)(nextProps.why, nextProps.selectedFrame, nextProps.generatedFrameScopes) - }); - } - } - - render() { - const { isPaused, isLoading } = this.props; - const { originalScopes, generatedScopes, showOriginal } = this.state; - - const scopes = showOriginal && originalScopes || generatedScopes; - - if (scopes && !isLoading) { - return _react2.default.createElement( - "div", - { className: "pane scopes-list" }, - _react2.default.createElement(_devtoolsReps.ObjectInspector, { - roots: scopes, - autoExpandAll: false, - autoExpandDepth: 1, - disableWrap: true, - focusable: false, - dimTopLevelWindow: true, - createObjectClient: grip => (0, _firefox.createObjectClient)(grip) - }), - originalScopes ? _react2.default.createElement( - "div", - { className: "scope-type-toggle" }, - _react2.default.createElement( - "a", - { - href: "", - onClick: e => { - e.preventDefault(); - this.setState({ showOriginal: !showOriginal }); - } - }, - showOriginal ? L10N.getStr("scopes.toggleToGenerated") : L10N.getStr("scopes.toggleToOriginal") - ) - ) : null - ); - } - - let stateText = L10N.getStr("scopes.notPaused"); - if (isPaused) { - if (isLoading) { - stateText = L10N.getStr("loadingText"); - } else { - stateText = L10N.getStr("scopes.notAvailable"); - } - } - - return _react2.default.createElement( - "div", - { className: "pane scopes-list" }, - _react2.default.createElement( - "div", - { className: "pane-info" }, - stateText - ) - ); - } -} - -const mapStateToProps = state => { - const selectedFrame = (0, _selectors.getSelectedFrame)(state); - const selectedSource = (0, _selectors.getSelectedSource)(state); - - const { - scope: originalFrameScopes, - pending: originalPending - } = (0, _selectors.getOriginalFrameScope)(state, selectedSource && selectedSource.get("id"), selectedFrame && selectedFrame.id) || { scope: null, pending: false }; - - const { - scope: generatedFrameScopes, - pending: generatedPending - } = (0, _selectors.getGeneratedFrameScope)(state, selectedFrame && selectedFrame.id) || { - scope: null, - pending: false - }; - - return { - selectedFrame, - isPaused: (0, _selectors.isPaused)(state), - isLoading: generatedPending || originalPending, - why: (0, _selectors.getPauseReason)(state), - originalFrameScopes, - generatedFrameScopes - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Scopes); - -/***/ }), - -/***/ 1613: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WelcomeBox = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _text = __webpack_require__(1387); - -var _PaneToggle = __webpack_require__(1407); - -var _PaneToggle2 = _interopRequireDefault(_PaneToggle); - -__webpack_require__(1343); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class WelcomeBox extends _react.Component { - renderToggleButton() { - const { horizontal, endPanelCollapsed, togglePaneCollapse } = this.props; - if (horizontal) { - return; - } - - return _react2.default.createElement(_PaneToggle2.default, { - position: "end", - collapsed: !endPanelCollapsed, - horizontal: horizontal, - handleClick: togglePaneCollapse - }); - } - - render() { - const searchSourcesShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2")); - - const searchProjectShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key")); - - const searchSourcesLabel = L10N.getStr("welcome.search").substring(2); - const searchProjectLabel = L10N.getStr("welcome.findInFiles").substring(2); - const { setActiveSearch, openQuickOpen } = this.props; - - return _react2.default.createElement( - "div", - { className: "welcomebox" }, - _react2.default.createElement( - "div", - { className: "alignlabel" }, - _react2.default.createElement( - "div", - { className: "shortcutFunction" }, - _react2.default.createElement( - "p", - { - className: "welcomebox__searchSources", - onClick: () => openQuickOpen() - }, - _react2.default.createElement( - "span", - { className: "shortcutKey" }, - searchSourcesShortcut - ), - _react2.default.createElement( - "span", - { className: "shortcutLabel" }, - searchSourcesLabel - ) - ), - _react2.default.createElement( - "p", - { - className: "welcomebox__searchProject", - onClick: setActiveSearch.bind(null, "project") - }, - _react2.default.createElement( - "span", - { className: "shortcutKey" }, - searchProjectShortcut - ), - _react2.default.createElement( - "span", - { className: "shortcutLabel" }, - searchProjectLabel - ) - ) - ), - this.renderToggleButton() - ) - ); - } -} - -exports.WelcomeBox = WelcomeBox; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const mapStateToProps = state => ({ - endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end") -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(WelcomeBox); - -/***/ }), - -/***/ 1614: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _immutable = __webpack_require__(3594); - -var I = _interopRequireWildcard(_immutable); - -var _selectors = __webpack_require__(3590); - -var _ui = __webpack_require__(1439); - -var _tabs = __webpack_require__(1941); - -var _source = __webpack_require__(1356); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _lodash = __webpack_require__(2); - -__webpack_require__(1344); - -var _Tab = __webpack_require__(2018); - -var _Tab2 = _interopRequireDefault(_Tab); - -var _PaneToggle = __webpack_require__(1407); - -var _PaneToggle2 = _interopRequireDefault(_PaneToggle); - -var _Dropdown = __webpack_require__(1615); - -var _Dropdown2 = _interopRequireDefault(_Dropdown); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class Tabs extends _react.PureComponent { - - constructor(props) { - super(props); - - this.updateHiddenTabs = () => { - if (!this.refs.sourceTabs) { - return; - } - const { selectedSource, tabSources, moveTab } = this.props; - const sourceTabEls = this.refs.sourceTabs.children; - const hiddenTabs = (0, _tabs.getHiddenTabs)(tabSources, sourceTabEls); - - if ((0, _ui.isVisible)() && hiddenTabs.indexOf(selectedSource) !== -1) { - return moveTab(selectedSource.url, 0); - } - - this.setState({ hiddenTabs }); - }; - - this.renderDropdownSource = source => { - const { selectSpecificSource } = this.props; - const filename = (0, _source.getFilename)(source.toJS()); - - const onClick = () => selectSpecificSource(source.id); - return _react2.default.createElement( - "li", - { key: source.id, onClick: onClick }, - _react2.default.createElement("img", { className: `dropdown-icon ${this.getIconClass(source)}` }), - filename - ); - }; - - this.state = { - dropdownShown: false, - hiddenTabs: I.List() - }; - - this.onResize = (0, _lodash.debounce)(() => { - this.updateHiddenTabs(); - }); - } - - componentDidUpdate(prevProps) { - if (!(prevProps === this.props)) { - this.updateHiddenTabs(); - } - } - - componentDidMount() { - window.requestIdleCallback(this.updateHiddenTabs); - window.addEventListener("resize", this.onResize); - } - - componentWillUnmount() { - window.removeEventListener("resize", this.onResize); - } - - /* - * Updates the hiddenSourceTabs state, by - * finding the source tabs which are wrapped and are not on the top row. - */ - - - toggleSourcesDropdown(e) { - this.setState(prevState => ({ - dropdownShown: !prevState.dropdownShown - })); - } - - getIconClass(source) { - if ((0, _source.isPretty)(source)) { - return "prettyPrint"; - } - if (source.isBlackBoxed) { - return "blackBox"; - } - return "file"; - } - - renderTabs() { - const { tabSources } = this.props; - if (!tabSources) { - return; - } - - return _react2.default.createElement( - "div", - { className: "source-tabs", ref: "sourceTabs" }, - tabSources.map((source, index) => _react2.default.createElement(_Tab2.default, { key: index, source: source })) - ); - } - - renderDropdown() { - const hiddenTabs = this.state.hiddenTabs; - if (!hiddenTabs || hiddenTabs.size == 0) { - return null; - } - - const Panel = _react2.default.createElement( - "ul", - null, - hiddenTabs.map(this.renderDropdownSource) - ); - const icon = _react2.default.createElement("img", { className: "moreTabs" }); - - return _react2.default.createElement(_Dropdown2.default, { panel: Panel, icon: icon }); - } - - renderStartPanelToggleButton() { - return _react2.default.createElement(_PaneToggle2.default, { - position: "start", - collapsed: !this.props.startPanelCollapsed, - handleClick: this.props.togglePaneCollapse - }); - } - - renderEndPanelToggleButton() { - const { horizontal, endPanelCollapsed, togglePaneCollapse } = this.props; - if (!horizontal) { - return; - } - - return _react2.default.createElement(_PaneToggle2.default, { - position: "end", - collapsed: !endPanelCollapsed, - handleClick: togglePaneCollapse, - horizontal: horizontal - }); - } - - render() { - return _react2.default.createElement( - "div", - { className: "source-header" }, - this.renderStartPanelToggleButton(), - this.renderTabs(), - this.renderDropdown(), - this.renderEndPanelToggleButton() - ); - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const mapStateToProps = state => ({ - selectedSource: (0, _selectors.getSelectedSource)(state), - tabSources: (0, _selectors.getSourcesForTabs)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tabs); - -/***/ }), - -/***/ 1615: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Dropdown = undefined; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -__webpack_require__(1345); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -class Dropdown extends _react.Component { - constructor(props) { - super(props); - - this.toggleDropdown = e => { - this.setState(prevState => ({ - dropdownShown: !prevState.dropdownShown - })); - }; - - this.state = { - dropdownShown: false - }; - } - - renderPanel() { - return _react2.default.createElement( - "div", - { - className: "dropdown", - onClick: this.toggleDropdown, - style: { display: this.state.dropdownShown ? "block" : "none" } - }, - this.props.panel - ); - } - - renderButton() { - return _react2.default.createElement( - "button", - { className: "dropdown-button", onClick: this.toggleDropdown }, - this.props.icon - ); - } - - renderMask() { - return _react2.default.createElement("div", { - className: "dropdown-mask", - onClick: this.toggleDropdown, - style: { display: this.state.dropdownShown ? "block" : "none" } - }); - } - - render() { - return _react2.default.createElement( - "div", - { className: "dropdown-block" }, - this.renderPanel(), - this.renderButton(), - this.renderMask() - ); - } -} - -exports.Dropdown = Dropdown; -exports.default = Dropdown; - -/***/ }), - -/***/ 162: -/***/ (function(module, exports, __webpack_require__) { - -(function() { - var Query, pathScorer, pluckCandidates, scorer, sortCandidates; - - scorer = __webpack_require__(163); - - pathScorer = __webpack_require__(164); - - Query = __webpack_require__(165); - - pluckCandidates = function(a) { - return a.candidate; - }; - - sortCandidates = function(a, b) { - return b.score - a.score; - }; - - module.exports = function(candidates, query, options) { - var bKey, candidate, key, maxInners, maxResults, score, scoreProvider, scoredCandidates, spotLeft, string, usePathScoring, _i, _len; - scoredCandidates = []; - key = options.key, maxResults = options.maxResults, maxInners = options.maxInners, usePathScoring = options.usePathScoring; - spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : candidates.length + 1; - bKey = key != null; - scoreProvider = usePathScoring ? pathScorer : scorer; - for (_i = 0, _len = candidates.length; _i < _len; _i++) { - candidate = candidates[_i]; - string = bKey ? candidate[key] : candidate; - if (!string) { - continue; - } - score = scoreProvider.score(string, query, options); - if (score > 0) { - scoredCandidates.push({ - candidate: candidate, - score: score - }); - if (!--spotLeft) { - break; - } - } - } - scoredCandidates.sort(sortCandidates); - candidates = scoredCandidates.map(pluckCandidates); - if (maxResults != null) { - candidates = candidates.slice(0, maxResults); - } - return candidates; - }; - -}).call(this); - - -/***/ }), - -/***/ 163: -/***/ (function(module, exports) { - -(function() { - var AcronymResult, computeScore, emptyAcronymResult, isAcronymFullWord, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_size, wm; - - wm = 150; - - pos_bonus = 20; - - tau_size = 150; - - miss_coeff = 0.75; - - exports.score = function(string, query, options) { - var allowErrors, preparedQuery, score, string_lw; - preparedQuery = options.preparedQuery, allowErrors = options.allowErrors; - if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) { - return 0; - } - string_lw = string.toLowerCase(); - score = computeScore(string, string_lw, preparedQuery); - return Math.ceil(score); - }; - - exports.isMatch = isMatch = function(subject, query_lw, query_up) { - var i, j, m, n, qj_lw, qj_up, si; - m = subject.length; - n = query_lw.length; - if (!m || n > m) { - return false; - } - i = -1; - j = -1; - while (++j < n) { - qj_lw = query_lw.charCodeAt(j); - qj_up = query_up.charCodeAt(j); - while (++i < m) { - si = subject.charCodeAt(i); - if (si === qj_lw || si === qj_up) { - break; - } - } - if (i === m) { - return false; - } - } - return true; - }; - - exports.computeScore = computeScore = function(subject, subject_lw, preparedQuery) { - var acro, acro_score, align, csc_diag, csc_row, csc_score, csc_should_rebuild, i, j, m, miss_budget, miss_left, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz; - query = preparedQuery.query; - query_lw = preparedQuery.query_lw; - m = subject.length; - n = query.length; - acro = scoreAcronyms(subject, subject_lw, query, query_lw); - acro_score = acro.score; - if (acro.count === n) { - return scoreExact(n, m, acro_score, acro.pos); - } - pos = subject_lw.indexOf(query_lw); - if (pos > -1) { - return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m); - } - score_row = new Array(n); - csc_row = new Array(n); - sz = scoreSize(n, m); - miss_budget = Math.ceil(miss_coeff * n) + 5; - miss_left = miss_budget; - csc_should_rebuild = true; - j = -1; - while (++j < n) { - score_row[j] = 0; - csc_row[j] = 0; - } - i = -1; - while (++i < m) { - si_lw = subject_lw[i]; - if (!si_lw.charCodeAt(0) in preparedQuery.charCodes) { - if (csc_should_rebuild) { - j = -1; - while (++j < n) { - csc_row[j] = 0; - } - csc_should_rebuild = false; - } - continue; - } - score = 0; - score_diag = 0; - csc_diag = 0; - record_miss = true; - csc_should_rebuild = true; - j = -1; - while (++j < n) { - score_up = score_row[j]; - if (score_up > score) { - score = score_up; - } - csc_score = 0; - if (query_lw[j] === si_lw) { - start = isWordStart(i, subject, subject_lw); - csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); - align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score); - if (align > score) { - score = align; - miss_left = miss_budget; - } else { - if (record_miss && --miss_left <= 0) { - return Math.max(score, score_row[n - 1]) * sz; - } - record_miss = false; - } - } - score_diag = score_up; - csc_diag = csc_row[j]; - csc_row[j] = csc_score; - score_row[j] = score; - } - } - score = score_row[n - 1]; - return score * sz; - }; - - exports.isWordStart = isWordStart = function(pos, subject, subject_lw) { - var curr_s, prev_s; - if (pos === 0) { - return true; - } - curr_s = subject[pos]; - prev_s = subject[pos - 1]; - return isSeparator(prev_s) || (curr_s !== subject_lw[pos] && prev_s === subject_lw[pos - 1]); - }; - - exports.isWordEnd = isWordEnd = function(pos, subject, subject_lw, len) { - var curr_s, next_s; - if (pos === len - 1) { - return true; - } - curr_s = subject[pos]; - next_s = subject[pos + 1]; - return isSeparator(next_s) || (curr_s === subject_lw[pos] && next_s !== subject_lw[pos + 1]); - }; - - isSeparator = function(c) { - return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c === '\\'; - }; - - scorePosition = function(pos) { - var sc; - if (pos < pos_bonus) { - sc = pos_bonus - pos; - return 100 + sc * sc; - } else { - return Math.max(100 + pos_bonus - pos, 0); - } - }; - - exports.scoreSize = scoreSize = function(n, m) { - return tau_size / (tau_size + Math.abs(m - n)); - }; - - scoreExact = function(n, m, quality, pos) { - return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m); - }; - - exports.scorePattern = scorePattern = function(count, len, sameCase, start, end) { - var bonus, sz; - sz = count; - bonus = 6; - if (sameCase === count) { - bonus += 2; - } - if (start) { - bonus += 3; - } - if (end) { - bonus += 1; - } - if (count === len) { - if (start) { - if (sameCase === len) { - sz += 2; - } else { - sz += 1; - } - } - if (end) { - bonus += 1; - } - } - return sameCase + sz * (sz + bonus); - }; - - exports.scoreCharacter = scoreCharacter = function(i, j, start, acro_score, csc_score) { - var posBonus; - posBonus = scorePosition(i); - if (start) { - return posBonus + wm * ((acro_score > csc_score ? acro_score : csc_score) + 10); - } - return posBonus + wm * csc_score; - }; - - exports.scoreConsecutives = scoreConsecutives = function(subject, subject_lw, query, query_lw, i, j, startOfWord) { - var k, m, mi, n, nj, sameCase, sz; - m = subject.length; - n = query.length; - mi = m - i; - nj = n - j; - k = mi < nj ? mi : nj; - sameCase = 0; - sz = 0; - if (query[j] === subject[i]) { - sameCase++; - } - while (++sz < k && query_lw[++j] === subject_lw[++i]) { - if (query[j] === subject[i]) { - sameCase++; - } - } - if (sz < k) { - i--; - } - if (sz === 1) { - return 1 + 2 * sameCase; - } - return scorePattern(sz, n, sameCase, startOfWord, isWordEnd(i, subject, subject_lw, m)); - }; - - exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, query, query_lw, pos, n, m) { - var end, i, pos2, sameCase, start; - start = isWordStart(pos, subject, subject_lw); - if (!start) { - pos2 = subject_lw.indexOf(query_lw, pos + 1); - if (pos2 > -1) { - start = isWordStart(pos2, subject, subject_lw); - if (start) { - pos = pos2; - } - } - } - i = -1; - sameCase = 0; - while (++i < n) { - if (query[pos + i] === subject[i]) { - sameCase++; - } - } - end = isWordEnd(pos + n - 1, subject, subject_lw, m); - return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos); - }; - - AcronymResult = (function() { - function AcronymResult(score, pos, count) { - this.score = score; - this.pos = pos; - this.count = count; - } - - return AcronymResult; - - })(); - - emptyAcronymResult = new AcronymResult(0, 0.1, 0); - - exports.scoreAcronyms = scoreAcronyms = function(subject, subject_lw, query, query_lw) { - var count, fullWord, i, j, m, n, qj_lw, sameCase, score, sepCount, sumPos; - m = subject.length; - n = query.length; - if (!(m > 1 && n > 1)) { - return emptyAcronymResult; - } - count = 0; - sepCount = 0; - sumPos = 0; - sameCase = 0; - i = -1; - j = -1; - while (++j < n) { - qj_lw = query_lw[j]; - if (isSeparator(qj_lw)) { - i = subject_lw.indexOf(qj_lw, i + 1); - if (i > -1) { - sepCount++; - continue; - } else { - break; - } - } - while (++i < m) { - if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) { - if (query[j] === subject[i]) { - sameCase++; - } - sumPos += i; - count++; - break; - } - } - if (i === m) { - break; - } - } - if (count < 2) { - return emptyAcronymResult; - } - fullWord = count === n ? isAcronymFullWord(subject, subject_lw, query, count) : false; - score = scorePattern(count, n, sameCase, true, fullWord); - return new AcronymResult(score, sumPos / count, count + sepCount); - }; - - isAcronymFullWord = function(subject, subject_lw, query, nbAcronymInQuery) { - var count, i, m, n; - m = subject.length; - n = query.length; - count = 0; - if (m > 12 * n) { - return false; - } - i = -1; - while (++i < m) { - if (isWordStart(i, subject, subject_lw) && ++count > nbAcronymInQuery) { - return false; - } - } - return true; - }; - -}).call(this); - - -/***/ }), - -/***/ 1634: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.mapScopes = mapScopes; - -var _selectors = __webpack_require__(3590); - -var _loadSourceText = __webpack_require__(1435); - -var _promise = __webpack_require__(1653); - -var _prefs = __webpack_require__(226); - -var _log = __webpack_require__(2359); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _mapScopes = __webpack_require__(3723); - -function mapScopes(scopes, frame) { - return async function ({ dispatch, getState, client, sourceMaps }) { - const generatedSourceRecord = (0, _selectors.getSource)(getState(), frame.generatedLocation.sourceId); - - const sourceRecord = (0, _selectors.getSource)(getState(), frame.location.sourceId); - - const shouldMapScopes = _prefs.features.mapScopes && !generatedSourceRecord.isWasm && !sourceRecord.isPrettyPrinted && !(0, _devtoolsSourceMap.isGeneratedId)(frame.location.sourceId); - - await dispatch({ - type: "MAP_SCOPES", - frame, - [_promise.PROMISE]: async function () { - if (!shouldMapScopes) { - return null; - } - - await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord)); - - try { - return await (0, _mapScopes.buildMappedScopes)(sourceRecord.toJS(), frame, (await scopes), sourceMaps, client); - } catch (e) { - (0, _log.log)(e); - return null; - } - }() - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1635: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createQuickOpenState = undefined; -exports.default = update; -exports.getQuickOpenEnabled = getQuickOpenEnabled; -exports.getQuickOpenQuery = getQuickOpenQuery; -exports.getQuickOpenType = getQuickOpenType; - -var _makeRecord = __webpack_require__(1361); - -var _makeRecord2 = _interopRequireDefault(_makeRecord); - -var _quickOpen = __webpack_require__(1636); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Quick Open reducer - * @module reducers/quick-open - */ - -const createQuickOpenState = exports.createQuickOpenState = (0, _makeRecord2.default)({ - enabled: false, - query: "", - searchType: "sources" -}); - -function update(state = createQuickOpenState(), action) { - switch (action.type) { - case "OPEN_QUICK_OPEN": - if (action.query != null) { - return state.merge({ - enabled: true, - query: action.query, - searchType: (0, _quickOpen.parseQuickOpenQuery)(action.query) - }); - } - return state.set("enabled", true); - case "CLOSE_QUICK_OPEN": - return createQuickOpenState(); - case "SET_QUICK_OPEN_QUERY": - return state.merge({ - query: action.query, - searchType: (0, _quickOpen.parseQuickOpenQuery)(action.query) - }); - default: - return state; - } -} - -function getQuickOpenEnabled(state) { - return state.quickOpen.get("enabled"); -} - -function getQuickOpenQuery(state) { - return state.quickOpen.get("query"); -} - -function getQuickOpenType(state) { - return state.quickOpen.get("searchType"); -} - -/***/ }), - -/***/ 1636: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.MODIFIERS = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.parseQuickOpenQuery = parseQuickOpenQuery; -exports.parseLineColumn = parseLineColumn; -exports.formatSourcesForList = formatSourcesForList; -exports.formatSymbol = formatSymbol; -exports.formatSymbols = formatSymbols; -exports.formatShortcutResults = formatShortcutResults; -exports.formatSources = formatSources; - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _utils = __webpack_require__(1366); - -var _source = __webpack_require__(1356); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const MODIFIERS = exports.MODIFIERS = { - "@": "functions", - "#": "variables", - ":": "goto", - "?": "shortcuts" -}; - -function parseQuickOpenQuery(query) { - const modifierPattern = /^@|#|:|\?$/; - const gotoSourcePattern = /^(\w+)\:/; - const startsWithModifier = modifierPattern.test(query[0]); - const isGotoSource = gotoSourcePattern.test(query); - - if (startsWithModifier) { - const modifier = query[0]; - return MODIFIERS[modifier]; - } - - if (isGotoSource) { - return "gotoSource"; - } - - return "sources"; -} - -function parseLineColumn(query) { - const [, line, column] = query.split(":"); - const lineNumber = parseInt(line, 10); - const columnNumber = parseInt(column, 10); - if (!isNaN(lineNumber)) { - return _extends({ - line: lineNumber - }, !isNaN(columnNumber) ? { column: columnNumber } : null); - } -} - -function formatSourcesForList(source, tabs) { - const title = (0, _source.getFilename)(source); - const subtitle = (0, _utils.endTruncateStr)(source.relativeUrl, 100); - return { - value: source.relativeUrl, - title, - subtitle, - icon: tabs.includes(source.url) ? "tab result-item-icon" : (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "result-item-icon"), - id: source.id, - url: source.url - }; -} - -function formatSymbol(symbol) { - return { - id: `${symbol.name}:${symbol.location.start.line}`, - title: symbol.name, - subtitle: `${symbol.location.start.line}`, - value: symbol.name, - location: symbol.location - }; -} - -function formatSymbols(symbols) { - if (!symbols || symbols.loading) { - return { variables: [], functions: [] }; - } - - const { variables, functions } = symbols; - - return { - variables: variables.map(formatSymbol), - functions: functions.map(formatSymbol) - }; -} - -function formatShortcutResults() { - return [{ - value: L10N.getStr("symbolSearch.search.functionsPlaceholder.title"), - title: `@ ${L10N.getStr("symbolSearch.search.functionsPlaceholder")}`, - id: "@" - }, { - value: L10N.getStr("symbolSearch.search.variablesPlaceholder.title"), - title: `# ${L10N.getStr("symbolSearch.search.variablesPlaceholder")}`, - id: "#" - }, { - value: L10N.getStr("gotoLineModal.title"), - title: `: ${L10N.getStr("gotoLineModal.placeholder")}`, - id: ":" - }]; -} - -function formatSources(sources, tabs) { - return sources.filter(source => !(0, _source.isPretty)(source)).map(source => formatSourcesForList(source, tabs)).filter(({ value }) => value != ""); -} - -/***/ }), - -/***/ 1637: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.command = command; -exports.stepIn = stepIn; -exports.stepOver = stepOver; -exports.stepOut = stepOut; -exports.resume = resume; -exports.rewind = rewind; -exports.reverseStepIn = reverseStepIn; -exports.reverseStepOver = reverseStepOver; -exports.reverseStepOut = reverseStepOut; -exports.astCommand = astCommand; - -var _selectors = __webpack_require__(3590); - -var _promise = __webpack_require__(1653); - -var _parser = __webpack_require__(1365); - -var _breakpoints = __webpack_require__(1396); - -var _prefs = __webpack_require__(226); - -/** - * Debugger commands like stepOver, stepIn, stepUp - * - * @param string $0.type - * @memberof actions/pause - * @static - */ -function command(type) { - return async ({ dispatch, client }) => { - return dispatch({ - type: "COMMAND", - command: type, - [_promise.PROMISE]: client[type]() - }); - }; -} - -/** - * StepIn - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function stepIn() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(command("stepIn")); - } - }; -} - -/** - * stepOver - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function stepOver() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(astCommand("stepOver")); - } - }; -} - -/** - * stepOut - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function stepOut() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(command("stepOut")); - } - }; -} - -/** - * resume - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function resume() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(command("resume")); - } - }; -} - -/** - * rewind - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function rewind() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(command("rewind")); - } - }; -} - -/** - * reverseStepIn - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function reverseStepIn() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(command("reverseStepIn")); - } - }; -} - -/** - * reverseStepOver - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function reverseStepOver() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(astCommand("reverseStepOver")); - } - }; -} - -/** - * reverseStepOut - * @memberof actions/pause - * @static - * @returns {Function} {@link command} - */ -function reverseStepOut() { - return ({ dispatch, getState }) => { - if ((0, _selectors.isPaused)(getState())) { - return dispatch(command("reverseStepOut")); - } - }; -} - -/* - * Checks for await or yield calls on the paused line - * This avoids potentially expensive parser calls when we are likely - * not at an async expression. - */ -function hasAwait(source, pauseLocation) { - const { line, column } = pauseLocation; - if (!source.text) { - return false; - } - - const lineText = source.text.split("\n")[line - 1]; - - if (!lineText) { - return false; - } - - const snippet = lineText.slice(column - 50, column + 50); - - return !!snippet.match(/(yield|await)/); -} - -/** - * @memberOf actions/pause - * @static - * @param stepType - * @returns {function(ThunkArgs)} - */ -function astCommand(stepType) { - return async ({ dispatch, getState, sourceMaps }) => { - if (!_prefs.features.asyncStepping) { - return dispatch(command(stepType)); - } - - if (stepType == "stepOver") { - // This type definition is ambiguous: - const frame = (0, _selectors.getTopFrame)(getState()); - const source = (0, _selectors.getSource)(getState(), frame.location.sourceId); - - if (source && hasAwait(source, frame.location)) { - const nextLocation = await (0, _parser.getNextStep)(source.id, frame.location); - if (nextLocation) { - await dispatch((0, _breakpoints.addHiddenBreakpoint)(nextLocation)); - return dispatch(command("resume")); - } - } - } - - return dispatch(command(stepType)); - }; -} - -/***/ }), - -/***/ 1638: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.findBestMatchExpression = findBestMatchExpression; -exports.findEmptyLines = findEmptyLines; -exports.containsPosition = containsPosition; -exports.findClosestFunction = findClosestFunction; -exports.findClosestClass = findClosestClass; - -var _lodash = __webpack_require__(2); - -var _pausePoints = __webpack_require__(3622); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function findBestMatchExpression(symbols, tokenPos) { - if (symbols.loading) { - return null; - } - - const { line, column } = tokenPos; - const { memberExpressions, identifiers, literals } = symbols; - const members = memberExpressions.filter(({ computed }) => !computed); - - return [].concat(identifiers, members, literals).reduce((found, expression) => { - const overlaps = expression.location.start.line == line && expression.location.start.column <= column && expression.location.end.column >= column; - - if (overlaps) { - return expression; - } - - return found; - }, null); -} - -function findEmptyLines(selectedSource, pausePoints) { - if (!pausePoints || !selectedSource) { - return []; - } - - const pausePointsList = (0, _pausePoints.convertToList)(pausePoints); - - const breakpoints = pausePointsList.filter(point => point.types.break); - const breakpointLines = breakpoints.map(point => point.location.line); - - if (!selectedSource.text || breakpointLines.length == 0) { - return []; - } - - const lineCount = selectedSource.text.split("\n").length; - const sourceLines = (0, _lodash.range)(1, lineCount + 1); - return (0, _lodash.xor)(sourceLines, breakpointLines); -} - -function containsPosition(a, b) { - const startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column; - const endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column; - - return startsBefore && endsAfter; -} - -function findClosestofSymbol(declarations, location) { - if (!declarations) { - return null; - } - - return declarations.reduce((found, currNode) => { - if (currNode.name === "anonymous" || !containsPosition(currNode.location, { - line: location.line, - column: location.column || 0 - })) { - return found; - } - - if (!found) { - return currNode; - } - - if (found.location.start.line > currNode.location.start.line) { - return found; - } - if (found.location.start.line === currNode.location.start.line && found.location.start.column > currNode.location.start.column) { - return found; - } - - return currNode; - }, null); -} - -function findClosestFunction(symbols, location) { - if (!symbols || symbols.loading) { - return null; - } - - return findClosestofSymbol(symbols.functions, location); -} - -function findClosestClass(symbols, location) { - if (!symbols || symbols.loading) { - return null; - } - - return findClosestofSymbol(symbols.functions, location); -} - -/***/ }), - -/***/ 1639: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commands = __webpack_require__(1637); - -Object.defineProperty(exports, "stepIn", { - enumerable: true, - get: function () { - return _commands.stepIn; - } -}); -Object.defineProperty(exports, "stepOver", { - enumerable: true, - get: function () { - return _commands.stepOver; - } -}); -Object.defineProperty(exports, "stepOut", { - enumerable: true, - get: function () { - return _commands.stepOut; - } -}); -Object.defineProperty(exports, "resume", { - enumerable: true, - get: function () { - return _commands.resume; - } -}); -Object.defineProperty(exports, "rewind", { - enumerable: true, - get: function () { - return _commands.rewind; - } -}); -Object.defineProperty(exports, "reverseStepIn", { - enumerable: true, - get: function () { - return _commands.reverseStepIn; - } -}); -Object.defineProperty(exports, "reverseStepOver", { - enumerable: true, - get: function () { - return _commands.reverseStepOver; - } -}); -Object.defineProperty(exports, "reverseStepOut", { - enumerable: true, - get: function () { - return _commands.reverseStepOut; - } -}); - -var _fetchScopes = __webpack_require__(1655); - -Object.defineProperty(exports, "fetchScopes", { - enumerable: true, - get: function () { - return _fetchScopes.fetchScopes; - } -}); - -var _paused = __webpack_require__(1640); - -Object.defineProperty(exports, "paused", { - enumerable: true, - get: function () { - return _paused.paused; - } -}); - -var _resumed = __webpack_require__(1641); - -Object.defineProperty(exports, "resumed", { - enumerable: true, - get: function () { - return _resumed.resumed; - } -}); - -var _continueToHere = __webpack_require__(1642); - -Object.defineProperty(exports, "continueToHere", { - enumerable: true, - get: function () { - return _continueToHere.continueToHere; - } -}); - -var _breakOnNext = __webpack_require__(1643); - -Object.defineProperty(exports, "breakOnNext", { - enumerable: true, - get: function () { - return _breakOnNext.breakOnNext; - } -}); - -var _mapFrames = __webpack_require__(1804); - -Object.defineProperty(exports, "mapFrames", { - enumerable: true, - get: function () { - return _mapFrames.mapFrames; - } -}); - -var _extra = __webpack_require__(3636); - -Object.defineProperty(exports, "fetchExtra", { - enumerable: true, - get: function () { - return _extra.fetchExtra; - } -}); -Object.defineProperty(exports, "getExtra", { - enumerable: true, - get: function () { - return _extra.getExtra; - } -}); - -var _setPopupObjectProperties = __webpack_require__(2008); - -Object.defineProperty(exports, "setPopupObjectProperties", { - enumerable: true, - get: function () { - return _setPopupObjectProperties.setPopupObjectProperties; - } -}); - -var _pauseOnExceptions = __webpack_require__(1645); - -Object.defineProperty(exports, "pauseOnExceptions", { - enumerable: true, - get: function () { - return _pauseOnExceptions.pauseOnExceptions; - } -}); - -var _selectFrame = __webpack_require__(1646); - -Object.defineProperty(exports, "selectFrame", { - enumerable: true, - get: function () { - return _selectFrame.selectFrame; - } -}); - -var _skipPausing = __webpack_require__(3640); - -Object.defineProperty(exports, "toggleSkipPausing", { - enumerable: true, - get: function () { - return _skipPausing.toggleSkipPausing; - } -}); - -/***/ }), - -/***/ 164: -/***/ (function(module, exports, __webpack_require__) { - -(function() { - var computeScore, countDir, file_coeff, getExtension, getExtensionScore, isMatch, scorePath, scoreSize, tau_depth, _ref; - - _ref = __webpack_require__(163), isMatch = _ref.isMatch, computeScore = _ref.computeScore, scoreSize = _ref.scoreSize; - - tau_depth = 20; - - file_coeff = 2.5; - - exports.score = function(string, query, options) { - var allowErrors, preparedQuery, score, string_lw; - preparedQuery = options.preparedQuery, allowErrors = options.allowErrors; - if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) { - return 0; - } - string_lw = string.toLowerCase(); - score = computeScore(string, string_lw, preparedQuery); - score = scorePath(string, string_lw, score, options); - return Math.ceil(score); - }; - - scorePath = function(subject, subject_lw, fullPathScore, options) { - var alpha, basePathScore, basePos, depth, end, extAdjust, fileLength, pathSeparator, preparedQuery, useExtensionBonus; - if (fullPathScore === 0) { - return 0; - } - preparedQuery = options.preparedQuery, useExtensionBonus = options.useExtensionBonus, pathSeparator = options.pathSeparator; - end = subject.length - 1; - while (subject[end] === pathSeparator) { - end--; - } - basePos = subject.lastIndexOf(pathSeparator, end); - fileLength = end - basePos; - extAdjust = 1.0; - if (useExtensionBonus) { - extAdjust += getExtensionScore(subject_lw, preparedQuery.ext, basePos, end, 2); - fullPathScore *= extAdjust; - } - if (basePos === -1) { - return fullPathScore; - } - depth = preparedQuery.depth; - while (basePos > -1 && depth-- > 0) { - basePos = subject.lastIndexOf(pathSeparator, basePos - 1); - } - basePathScore = basePos === -1 ? fullPathScore : extAdjust * computeScore(subject.slice(basePos + 1, end + 1), subject_lw.slice(basePos + 1, end + 1), preparedQuery); - alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1, pathSeparator)); - return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, file_coeff * fileLength); - }; - - exports.countDir = countDir = function(path, end, pathSeparator) { - var count, i; - if (end < 1) { - return 0; - } - count = 0; - i = -1; - while (++i < end && path[i] === pathSeparator) { - continue; - } - while (++i < end) { - if (path[i] === pathSeparator) { - count++; - while (++i < end && path[i] === pathSeparator) { - continue; - } - } - } - return count; - }; - - exports.getExtension = getExtension = function(str) { - var pos; - pos = str.lastIndexOf("."); - if (pos < 0) { - return ""; - } else { - return str.substr(pos + 1); - } - }; - - getExtensionScore = function(candidate, ext, startPos, endPos, maxDepth) { - var m, matched, n, pos; - if (!ext.length) { - return 0; - } - pos = candidate.lastIndexOf(".", endPos); - if (!(pos > startPos)) { - return 0; - } - n = ext.length; - m = endPos - pos; - if (m < n) { - n = m; - m = ext.length; - } - pos++; - matched = -1; - while (++matched < n) { - if (candidate[pos + matched] !== ext[matched]) { - break; - } - } - if (matched === 0 && maxDepth > 0) { - return 0.9 * getExtensionScore(candidate, ext, startPos, pos - 2, maxDepth - 1); - } - return matched / m; - }; - -}).call(this); - - -/***/ }), - -/***/ 1640: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.paused = paused; - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _selectors = __webpack_require__(3590); - -var _ = __webpack_require__(1639); - -var _breakpoints = __webpack_require__(1396); - -var _expressions = __webpack_require__(1398); - -var _sources = __webpack_require__(1797); - -var _loadSourceText = __webpack_require__(1435); - -var _ui = __webpack_require__(1385); - -var _commands = __webpack_require__(1637); - -var _pause = __webpack_require__(2419); - -var _mapFrames = __webpack_require__(1804); - -var _fetchScopes = __webpack_require__(1655); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -async function getOriginalSourceForFrame(state, frame) { - return (0, _selectors.getSources)(state).get(frame.location.sourceId); -} -/** - * Debugger has just paused - * - * @param {object} pauseInfo - * @memberof actions/pause - * @static - */ -function paused(pauseInfo) { - return async function ({ dispatch, getState, client, sourceMaps }) { - const { frames, why, loadedObjects } = pauseInfo; - const rootFrame = frames.length > 0 ? frames[0] : null; - - if (rootFrame) { - const mappedFrame = await (0, _mapFrames.updateFrameLocation)(rootFrame, sourceMaps); - const source = await getOriginalSourceForFrame(getState(), mappedFrame); - - // Ensure that the original file has loaded if there is one. - await dispatch((0, _loadSourceText.loadSourceText)(source)); - - if ((0, _pause.shouldStep)(mappedFrame, getState(), sourceMaps)) { - dispatch((0, _commands.command)("stepOver")); - return; - } - } - - dispatch({ - type: "PAUSED", - why, - frames, - selectedFrameId: rootFrame ? rootFrame.id : undefined, - loadedObjects: loadedObjects || [] - }); - - const hiddenBreakpointLocation = (0, _selectors.getHiddenBreakpointLocation)(getState()); - if (hiddenBreakpointLocation) { - dispatch((0, _breakpoints.removeBreakpoint)(hiddenBreakpointLocation)); - } - - await dispatch((0, _.mapFrames)()); - const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); - - if (selectedFrame) { - const visibleFrame = (0, _selectors.getVisibleSelectedFrame)(getState()); - const location = (0, _devtoolsSourceMap.isGeneratedId)(visibleFrame.location.sourceId) ? selectedFrame.generatedLocation : selectedFrame.location; - await dispatch((0, _sources.selectLocation)(location)); - } - - dispatch((0, _ui.togglePaneCollapse)("end", false)); - await dispatch((0, _fetchScopes.fetchScopes)()); - - // Run after fetching scoping data so that it may make use of the sourcemap - // expression mappings for local variables. - const atException = why.type == "exception"; - if (!atException || !(0, _selectors.isEvaluatingExpression)(getState())) { - await dispatch((0, _expressions.evaluateExpressions)()); - } - }; -} - -/***/ }), - -/***/ 1641: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.resumed = resumed; - -var _selectors = __webpack_require__(3590); - -var _expressions = __webpack_require__(1398); - -var _pause = __webpack_require__(2419); - -/** - * Debugger has just resumed - * - * @memberof actions/pause - * @static - */ -function resumed() { - return async ({ dispatch, client, getState }) => { - const why = (0, _selectors.getPauseReason)(getState()); - const wasPausedInEval = (0, _pause.inDebuggerEval)(why); - const wasStepping = (0, _selectors.isStepping)(getState()); - - dispatch({ type: "RESUME" }); - - if (!wasStepping && !wasPausedInEval) { - await dispatch((0, _expressions.evaluateExpressions)()); - } - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1642: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.continueToHere = continueToHere; - -var _selectors = __webpack_require__(3590); - -var _breakpoints = __webpack_require__(1396); - -var _commands = __webpack_require__(1637); - -function continueToHere(line) { - return async function ({ dispatch, getState }) { - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - - if (!(0, _selectors.isPaused)(getState()) || !selectedSource) { - return; - } - - const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); - const debugLine = selectedFrame.location.line; - if (debugLine == line) { - return; - } - - const action = (0, _selectors.getCanRewind)(getState()) && line < debugLine ? _commands.rewind : _commands.resume; - - await dispatch((0, _breakpoints.addHiddenBreakpoint)({ - line, - column: undefined, - sourceId: selectedSource.id - })); - - dispatch(action()); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1643: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.breakOnNext = breakOnNext; - - -/** - * Debugger breakOnNext command. - * It's different from the comand action because we also want to - * highlight the pause icon. - * - * @memberof actions/pause - * @static - */ -function breakOnNext() { - return ({ dispatch, client }) => { - client.breakOnNext(); - - return dispatch({ - type: "BREAK_ON_NEXT", - value: true - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1645: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.pauseOnExceptions = pauseOnExceptions; - -var _promise = __webpack_require__(1653); - -/** - * - * @memberof actions/pause - * @static - */ -function pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) { - return ({ dispatch, client }) => { - return dispatch({ - type: "PAUSE_ON_EXCEPTIONS", - shouldPauseOnExceptions, - shouldPauseOnCaughtExceptions, - [_promise.PROMISE]: client.pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1646: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.selectFrame = selectFrame; - -var _sources = __webpack_require__(1797); - -var _expressions = __webpack_require__(1398); - -var _fetchScopes = __webpack_require__(1655); - -/** - * @memberof actions/pause - * @static - */ -function selectFrame(frame) { - return async ({ dispatch, client, getState, sourceMaps }) => { - dispatch({ - type: "SELECT_FRAME", - frame - }); - - dispatch((0, _sources.selectLocation)(frame.location)); - - dispatch((0, _expressions.evaluateExpressions)()); - dispatch((0, _fetchScopes.fetchScopes)()); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1647: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setQuickOpenQuery = setQuickOpenQuery; -exports.openQuickOpen = openQuickOpen; -exports.closeQuickOpen = closeQuickOpen; -function setQuickOpenQuery(query) { - return { - type: "SET_QUICK_OPEN_QUERY", - query - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function openQuickOpen(query) { - if (query != null) { - return { type: "OPEN_QUICK_OPEN", query }; - } - return { type: "OPEN_QUICK_OPEN" }; -} - -function closeQuickOpen() { - return { type: "CLOSE_QUICK_OPEN" }; -} - -/***/ }), - -/***/ 1648: -/***/ (function(module, exports) { - -module.exports = "image/svg+xml" - -/***/ }), - -/***/ 1649: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 165: -/***/ (function(module, exports, __webpack_require__) { - -(function() { - var Query, coreChars, countDir, getCharCodes, getExtension, opt_char_re, truncatedUpperCase, _ref; - - _ref = __webpack_require__(164), countDir = _ref.countDir, getExtension = _ref.getExtension; - - module.exports = Query = (function() { - function Query(query, _arg) { - var optCharRegEx, pathSeparator, _ref1; - _ref1 = _arg != null ? _arg : {}, optCharRegEx = _ref1.optCharRegEx, pathSeparator = _ref1.pathSeparator; - if (!(query && query.length)) { - return null; - } - this.query = query; - this.query_lw = query.toLowerCase(); - this.core = coreChars(query, optCharRegEx); - this.core_lw = this.core.toLowerCase(); - this.core_up = truncatedUpperCase(this.core); - this.depth = countDir(query, query.length, pathSeparator); - this.ext = getExtension(this.query_lw); - this.charCodes = getCharCodes(this.query_lw); - } - - return Query; - - })(); - - opt_char_re = /[ _\-:\/\\]/g; - - coreChars = function(query, optCharRegEx) { - if (optCharRegEx == null) { - optCharRegEx = opt_char_re; - } - return query.replace(optCharRegEx, ''); - }; - - truncatedUpperCase = function(str) { - var char, upper, _i, _len; - upper = ""; - for (_i = 0, _len = str.length; _i < _len; _i++) { - char = str[_i]; - upper += char.toUpperCase()[0]; - } - return upper; - }; - - getCharCodes = function(str) { - var charCodes, i, len; - len = str.length; - i = -1; - charCodes = []; - while (++i < len) { - charCodes[str.charCodeAt(i)] = true; - } - return charCodes; - }; - -}).call(this); - - -/***/ }), - -/***/ 1650: -/***/ (function(module, exports) { - -module.exports = "Zeit - Black on white logo" - -/***/ }), - -/***/ 1651: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1652: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.QuickOpenModal = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _fuzzaldrinPlus = __webpack_require__(161); - -var _fuzzaldrinPlus2 = _interopRequireDefault(_fuzzaldrinPlus); - -var _path = __webpack_require__(1393); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -var _resultList = __webpack_require__(1406); - -var _quickOpen = __webpack_require__(1636); - -var _Modal = __webpack_require__(1403); - -var _Modal2 = _interopRequireDefault(_Modal); - -var _SearchInput = __webpack_require__(1379); - -var _SearchInput2 = _interopRequireDefault(_SearchInput); - -var _ResultList = __webpack_require__(1445); - -var _ResultList2 = _interopRequireDefault(_ResultList); - -__webpack_require__(2253); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function filter(values, query) { - return _fuzzaldrinPlus2.default.filter(values, query, { - key: "value", - maxResults: 1000 - }); -} - -class QuickOpenModal extends _react.Component { - constructor(props) { - super(props); - - this.closeModal = () => { - this.props.closeQuickOpen(); - }; - - this.dropGoto = query => { - return query.split(":")[0]; - }; - - this.searchSources = query => { - const { sources } = this.props; - const results = query == "" ? sources : filter(sources, this.dropGoto(query)); - return this.setState({ results }); - }; - - this.searchSymbols = query => { - const { symbols: { functions, variables } } = this.props; - - let results = functions; - if (this.isVariableQuery()) { - results = variables; - } else { - results = results.filter(result => result.title !== "anonymous"); - } - - if (query === "@" || query === "#") { - return this.setState({ results }); - } - - this.setState({ results: filter(results, query.slice(1)) }); - }; - - this.searchShortcuts = query => { - const results = (0, _quickOpen.formatShortcutResults)(); - if (query == "?") { - this.setState({ results }); - } else { - this.setState({ results: filter(results, query.slice(1)) }); - } - }; - - this.showTopSources = () => { - const { tabs, sources } = this.props; - if (tabs.length > 0) { - this.setState({ - results: sources.filter(source => tabs.includes(source.url)) - }); - } else { - this.setState({ results: sources.slice(0, 100) }); - } - }; - - this.updateResults = query => { - if (this.isGotoQuery()) { - return; - } - - if (query == "" && !this.isShortcutQuery()) { - return this.showTopSources(); - } - - if (this.isSymbolSearch()) { - return this.searchSymbols(query); - } - - if (this.isShortcutQuery()) { - return this.searchShortcuts(query); - } - return this.searchSources(query); - }; - - this.setModifier = item => { - if (["@", "#", ":"].includes(item.id)) { - this.props.setQuickOpenQuery(item.id); - } - }; - - this.selectResultItem = (e, item) => { - if (item == null) { - return; - } - - if (this.isShortcutQuery()) { - return this.setModifier(item); - } - - if (this.isGotoSourceQuery()) { - const location = (0, _quickOpen.parseLineColumn)(this.props.query); - return this.gotoLocation(_extends({}, location, { sourceId: item.id })); - } - - if (this.isSymbolSearch()) { - return this.gotoLocation({ - line: item.location && item.location.start ? item.location.start.line : 0 - }); - } - - this.gotoLocation({ sourceId: item.id, line: 0 }); - }; - - this.onSelectResultItem = item => { - const { selectLocation, selectedSource, highlightLineRange } = this.props; - if (!this.isSymbolSearch() || selectedSource == null) { - return; - } - - if (this.isVariableQuery()) { - const line = item.location && item.location.start ? item.location.start.line : 0; - return selectLocation({ - sourceId: selectedSource.get("id"), - line, - column: null - }); - } - - if (this.isFunctionQuery()) { - return highlightLineRange(_extends({}, item.location != null ? { start: item.location.start.line, end: item.location.end.line } : {}, { - sourceId: selectedSource.get("id") - })); - } - }; - - this.traverseResults = e => { - const direction = e.key === "ArrowUp" ? -1 : 1; - const { selectedIndex, results } = this.state; - const resultCount = this.getResultCount(); - const index = selectedIndex + direction; - const nextIndex = (index + resultCount) % resultCount; - - this.setState({ selectedIndex: nextIndex }); - - if (results != null) { - this.onSelectResultItem(results[nextIndex]); - } - }; - - this.gotoLocation = location => { - const { selectLocation, selectedSource } = this.props; - const selectedSourceId = selectedSource ? selectedSource.get("id") : ""; - if (location != null) { - const sourceId = location.sourceId ? location.sourceId : selectedSourceId; - selectLocation({ - sourceId, - line: location.line, - column: location.column || null - }); - this.closeModal(); - } - }; - - this.onChange = e => { - const { selectedSource, setQuickOpenQuery } = this.props; - setQuickOpenQuery(e.target.value); - const noSource = !selectedSource || !selectedSource.get("text"); - if (this.isSymbolSearch() && noSource || this.isGotoQuery()) { - return; - } - this.updateResults(e.target.value); - }; - - this.onKeyDown = e => { - const { enabled, query } = this.props; - const { results, selectedIndex } = this.state; - - if (!this.isGotoQuery() && (!enabled || !results)) { - return; - } - - if (e.key === "Enter") { - if (this.isGotoQuery()) { - const location = (0, _quickOpen.parseLineColumn)(query); - return this.gotoLocation(location); - } - - if (results) { - if (this.isShortcutQuery()) { - return this.setModifier(results[selectedIndex]); - } - - return this.selectResultItem(e, results[selectedIndex]); - } - } - - if (e.key === "Tab") { - return this.closeModal(); - } - - if (["ArrowUp", "ArrowDown"].includes(e.key)) { - e.preventDefault(); - return this.traverseResults(e); - } - }; - - this.getResultCount = () => { - const results = this.state.results; - return results && results.length ? results.length : 0; - }; - - this.isFunctionQuery = () => this.props.searchType === "functions"; - - this.isVariableQuery = () => this.props.searchType === "variables"; - - this.isSymbolSearch = () => this.isFunctionQuery() || this.isVariableQuery(); - - this.isGotoQuery = () => this.props.searchType === "goto"; - - this.isGotoSourceQuery = () => this.props.searchType === "gotoSource"; - - this.isShortcutQuery = () => this.props.searchType === "shortcuts"; - - this.isSourcesQuery = () => this.props.searchType === "sources"; - - this.isSourceSearch = () => this.isSourcesQuery() || this.isGotoSourceQuery(); - - this.renderHighlight = (candidateString, query, name) => { - const options = { - wrap: { - tagOpen: '', - tagClose: "" - } - }; - const html = _fuzzaldrinPlus2.default.wrap(candidateString, query, options); - return _react2.default.createElement("div", { dangerouslySetInnerHTML: { __html: html } }); - }; - - this.highlightMatching = (query, results) => { - let newQuery = query; - if (newQuery === "") { - return results; - } - newQuery = query.replace(/[@:#?]/gi, " "); - - return results.map(result => { - return _extends({}, result, { - title: this.renderHighlight(result.title, (0, _path.basename)(newQuery), "title") - }); - }); - }; - - this.renderLoading = () => { - const { symbolsLoading } = this.props; - - if ((this.isFunctionQuery() || this.isVariableQuery()) && symbolsLoading) { - return _react2.default.createElement( - "div", - { className: "loading-indicator" }, - L10N.getStr("loadingText") - ); - } - }; - - this.state = { results: null, selectedIndex: 0 }; - } - - componentDidMount() { - const { query, shortcutsModalEnabled, toggleShortcutsModal } = this.props; - - this.updateResults(query); - - if (shortcutsModalEnabled) { - toggleShortcutsModal(); - } - } - - componentDidUpdate(prevProps) { - const nowEnabled = !prevProps.enabled && this.props.enabled; - const queryChanged = prevProps.query !== this.props.query; - - if (this.refs.resultList && this.refs.resultList.refs) { - (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedIndex, nowEnabled || !queryChanged); - } - - if (nowEnabled || queryChanged) { - this.updateResults(this.props.query); - } - } - - // Query helpers - - - /* eslint-disable react/no-danger */ - - - shouldShowErrorEmoji() { - const { query } = this.props; - if (this.isGotoQuery()) { - return !/^:\d*$/.test(query); - } - return !this.getResultCount() && !!query; - } - - render() { - const { enabled, query } = this.props; - const { selectedIndex, results } = this.state; - - if (!enabled) { - return null; - } - const newResults = results && results.slice(0, 100); - const items = this.highlightMatching(query, newResults || []); - const expanded = !!items && items.length > 0; - return _react2.default.createElement( - _Modal2.default, - { "in": enabled, handleClose: this.closeModal }, - _react2.default.createElement(_SearchInput2.default, { - query: query, - hasPrefix: true, - count: this.getResultCount(), - placeholder: L10N.getStr("sourceSearch.search"), - summaryMsg: "", - showErrorEmoji: this.shouldShowErrorEmoji(), - onChange: this.onChange, - onKeyDown: this.onKeyDown, - handleClose: this.closeModal, - expanded: expanded, - selectedItemId: expanded && items[selectedIndex] ? items[selectedIndex].id : "" - }), - this.renderLoading(), - newResults && _react2.default.createElement(_ResultList2.default, _extends({ - key: "results", - items: items, - selected: selectedIndex, - selectItem: this.selectResultItem, - ref: "resultList", - expanded: expanded - }, this.isSourceSearch() ? { size: "big" } : {})) - ); - } -} - -exports.QuickOpenModal = QuickOpenModal; /* istanbul ignore next: ignoring testing of redux connection stuff */ - -function mapStateToProps(state) { - const selectedSource = (0, _selectors.getSelectedSource)(state); - - return { - enabled: (0, _selectors.getQuickOpenEnabled)(state), - sources: (0, _quickOpen.formatSources)((0, _selectors.getRelativeSources)(state), (0, _selectors.getTabs)(state).toArray()), - selectedSource, - symbols: (0, _quickOpen.formatSymbols)((0, _selectors.getSymbols)(state, selectedSource)), - symbolsLoading: (0, _selectors.isSymbolsLoading)(state, selectedSource), - query: (0, _selectors.getQuickOpenQuery)(state), - searchType: (0, _selectors.getQuickOpenType)(state), - tabs: (0, _selectors.getTabs)(state).toArray() - }; -} - -/* istanbul ignore next: ignoring testing of redux connection stuff */ -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(QuickOpenModal); - -/***/ }), - -/***/ 1653: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.promise = exports.PROMISE = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _lodash = __webpack_require__(2); - -var _DevToolsUtils = __webpack_require__(1432); - -let seqIdVal = 1; - -function seqIdGen() { - return seqIdVal++; -} - -function filterAction(action) { - return (0, _lodash.fromPairs)((0, _lodash.toPairs)(action).filter(pair => pair[0] !== PROMISE)); -} - -function promiseMiddleware({ - dispatch, - getState -}) { - return next => action => { - if (!(PROMISE in action)) { - return next(action); - } - - const promiseInst = action[PROMISE]; - const seqId = seqIdGen().toString(); - - // Create a new action that doesn't have the promise field and has - // the `seqId` field that represents the sequence id - action = _extends({}, filterAction(action), { seqId }); - - dispatch(_extends({}, action, { status: "start" })); - - // Return the promise so action creators can still compose if they - // want to. - return new Promise((resolve, reject) => { - promiseInst.then(value => { - (0, _DevToolsUtils.executeSoon)(() => { - dispatch(_extends({}, action, { status: "done", value: value })); - resolve(value); - }); - }, error => { - (0, _DevToolsUtils.executeSoon)(() => { - dispatch(_extends({}, action, { - status: "error", - error: error.message || error - })); - reject(error); - }); - }); - }); - }; -} - -const PROMISE = exports.PROMISE = "@@dispatch/promise"; -exports.promise = promiseMiddleware; - -/***/ }), - -/***/ 1655: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.fetchScopes = fetchScopes; - -var _selectors = __webpack_require__(3590); - -var _mapScopes = __webpack_require__(1634); - -var _promise = __webpack_require__(1653); - -var _extra = __webpack_require__(3636); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function fetchScopes() { - return async function ({ dispatch, getState, client, sourceMaps }) { - const frame = (0, _selectors.getSelectedFrame)(getState()); - if (!frame || (0, _selectors.getGeneratedFrameScope)(getState(), frame.id)) { - return; - } - - const scopes = dispatch({ - type: "ADD_SCOPES", - frame, - [_promise.PROMISE]: client.getFrameScopes(frame) - }); - - await dispatch((0, _extra.fetchExtra)()); - await dispatch((0, _mapScopes.mapScopes)(scopes, frame)); - }; -} - -/***/ }), - -/***/ 1657: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getAsyncTimes = getAsyncTimes; -exports.steppingTimings = steppingTimings; - -var _lodash = __webpack_require__(2); - -function getAsyncTimes(name) { - return (0, _lodash.zip)(window.performance.getEntriesByName(`${name}_start`), window.performance.getEntriesByName(`${name}_end`)).map(([start, end]) => +(end.startTime - start.startTime).toPrecision(2)); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getTimes(name) { - return window.performance.getEntriesByName(name).map(time => +time.duration.toPrecision(2)); -} - -function getStats(times) { - if (times.length == 0) { - return { times: [], avg: null, median: null }; - } - const avg = times.reduce((sum, time) => time + sum, 0) / times.length; - const sortedtimings = [...times].sort((a, b) => a - b); - const median = sortedtimings[times.length / 2]; - return { - times, - avg: +avg.toPrecision(2), - median: +median.toPrecision(2) - }; -} - -function steppingTimings() { - const commandTimings = getAsyncTimes("COMMAND"); - const pausedTimings = getTimes("PAUSED"); - - return { - commands: getStats(commandTimings), - paused: getStats(pausedTimings) - }; -} - -// console.log("..", asyncTimes("COMMAND")); - -/***/ }), - -/***/ 1658: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _redux = __webpack_require__(3593); - -var _waitService = __webpack_require__(1659); - -var _log = __webpack_require__(1660); - -var _history = __webpack_require__(1661); - -var _promise = __webpack_require__(1653); - -var _thunk = __webpack_require__(1662); - -var _timing = __webpack_require__(1663); - -/** - * This creates a dispatcher with all the standard middleware in place - * that all code requires. It can also be optionally configured in - * various ways, such as logging and recording. - * - * @param {object} opts: - * - log: log all dispatched actions to console - * - history: an array to store every action in. Should only be - * used in tests. - * - middleware: array of middleware to be included in the redux store - * @memberof utils/create-store - * @static - */ - - -/** - * @memberof utils/create-store - * @static - */ -const configureStore = (opts = {}) => { - const middleware = [(0, _thunk.thunk)(opts.makeThunkArgs), _promise.promise, - - // Order is important: services must go last as they always - // operate on "already transformed" actions. Actions going through - // them shouldn't have any special fields like promises, they - // should just be normal JSON objects. - _waitService.waitUntilService]; - - if (opts.history) { - middleware.push((0, _history.history)(opts.history)); - } - - if (opts.middleware) { - opts.middleware.forEach(fn => middleware.push(fn)); - } - - if (opts.log) { - middleware.push(_log.log); - } - - if (opts.timing) { - middleware.push(_timing.timing); - } - - // Hook in the redux devtools browser extension if it exists - const devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f; - - return (0, _redux.applyMiddleware)(...middleware)(devtoolsExt(_redux.createStore)); -}; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* global window */ - -/** - * Redux store utils - * @module utils/create-store - */ - -exports.default = configureStore; - -/***/ }), - -/***/ 1659: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.waitUntilService = waitUntilService; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* global window */ - -/** - * A middleware which acts like a service, because it is stateful - * and "long-running" in the background. It provides the ability - * for actions to install a function to be run once when a specific - * condition is met by an action coming through the system. Think of - * it as a thunk that blocks until the condition is met. Example: - * - * ```js - * const services = { WAIT_UNTIL: require('wait-service').NAME }; - * - * { type: services.WAIT_UNTIL, - * predicate: action => action.type === "ADD_ITEM", - * run: (dispatch, getState, action) => { - * // Do anything here. You only need to accept the arguments - * // if you need them. `action` is the action that satisfied - * // the predicate. - * } - * } - * ``` - */ -const NAME = exports.NAME = "@@service/waitUntil"; -function waitUntilService({ dispatch, getState }) { - let pending = []; - - function checkPending(action) { - const readyRequests = []; - const stillPending = []; - - // Find the pending requests whose predicates are satisfied with - // this action. Wait to run the requests until after we update the - // pending queue because the request handler may synchronously - // dispatch again and run this service (that use case is - // completely valid). - for (const request of pending) { - if (request.predicate(action)) { - readyRequests.push(request); - } else { - stillPending.push(request); - } - } - - pending = stillPending; - for (const request of readyRequests) { - request.run(dispatch, getState, action); - } - } - - return next => action => { - if (action.type === NAME) { - pending.push(action); - return null; - } - const result = next(action); - checkPending(action); - return result; - }; -} - -/***/ }), - -/***/ 166: -/***/ (function(module, exports, __webpack_require__) { - -(function() { - var basenameMatch, computeMatch, isMatch, isWordStart, match, mergeMatches, scoreAcronyms, scoreCharacter, scoreConsecutives, _ref; - - _ref = __webpack_require__(163), isMatch = _ref.isMatch, isWordStart = _ref.isWordStart, scoreConsecutives = _ref.scoreConsecutives, scoreCharacter = _ref.scoreCharacter, scoreAcronyms = _ref.scoreAcronyms; - - exports.match = match = function(string, query, options) { - var allowErrors, baseMatches, matches, pathSeparator, preparedQuery, string_lw; - allowErrors = options.allowErrors, preparedQuery = options.preparedQuery, pathSeparator = options.pathSeparator; - if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) { - return []; - } - string_lw = string.toLowerCase(); - matches = computeMatch(string, string_lw, preparedQuery); - if (matches.length === 0) { - return matches; - } - if (string.indexOf(pathSeparator) > -1) { - baseMatches = basenameMatch(string, string_lw, preparedQuery, pathSeparator); - matches = mergeMatches(matches, baseMatches); - } - return matches; - }; - - exports.wrap = function(string, query, options) { - var matchIndex, matchPos, matchPositions, output, strPos, tagClass, tagClose, tagOpen, _ref1; - if ((options.wrap != null)) { - _ref1 = options.wrap, tagClass = _ref1.tagClass, tagOpen = _ref1.tagOpen, tagClose = _ref1.tagClose; - } - if (tagClass == null) { - tagClass = 'highlight'; - } - if (tagOpen == null) { - tagOpen = ''; - } - if (tagClose == null) { - tagClose = ''; - } - if (string === query) { - return tagOpen + string + tagClose; - } - matchPositions = match(string, query, options); - if (matchPositions.length === 0) { - return string; - } - output = ''; - matchIndex = -1; - strPos = 0; - while (++matchIndex < matchPositions.length) { - matchPos = matchPositions[matchIndex]; - if (matchPos > strPos) { - output += string.substring(strPos, matchPos); - strPos = matchPos; - } - while (++matchIndex < matchPositions.length) { - if (matchPositions[matchIndex] === matchPos + 1) { - matchPos++; - } else { - matchIndex--; - break; - } - } - matchPos++; - if (matchPos > strPos) { - output += tagOpen; - output += string.substring(strPos, matchPos); - output += tagClose; - strPos = matchPos; - } - } - if (strPos <= string.length - 1) { - output += string.substring(strPos); - } - return output; - }; - - basenameMatch = function(subject, subject_lw, preparedQuery, pathSeparator) { - var basePos, depth, end; - end = subject.length - 1; - while (subject[end] === pathSeparator) { - end--; - } - basePos = subject.lastIndexOf(pathSeparator, end); - if (basePos === -1) { - return []; - } - depth = preparedQuery.depth; - while (depth-- > 0) { - basePos = subject.lastIndexOf(pathSeparator, basePos - 1); - if (basePos === -1) { - return []; - } - } - basePos++; - end++; - return computeMatch(subject.slice(basePos, end), subject_lw.slice(basePos, end), preparedQuery, basePos); - }; - - mergeMatches = function(a, b) { - var ai, bj, i, j, m, n, out; - m = a.length; - n = b.length; - if (n === 0) { - return a.slice(); - } - if (m === 0) { - return b.slice(); - } - i = -1; - j = 0; - bj = b[j]; - out = []; - while (++i < m) { - ai = a[i]; - while (bj <= ai && ++j < n) { - if (bj < ai) { - out.push(bj); - } - bj = b[j]; - } - out.push(ai); - } - while (j < n) { - out.push(b[j++]); - } - return out; - }; - - computeMatch = function(subject, subject_lw, preparedQuery, offset) { - var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, score_diag, score_row, score_up, si_lw, start, trace; - if (offset == null) { - offset = 0; - } - query = preparedQuery.query; - query_lw = preparedQuery.query_lw; - m = subject.length; - n = query.length; - acro_score = scoreAcronyms(subject, subject_lw, query, query_lw).score; - score_row = new Array(n); - csc_row = new Array(n); - STOP = 0; - UP = 1; - LEFT = 2; - DIAGONAL = 3; - trace = new Array(m * n); - pos = -1; - j = -1; - while (++j < n) { - score_row[j] = 0; - csc_row[j] = 0; - } - i = -1; - while (++i < m) { - score = 0; - score_up = 0; - csc_diag = 0; - si_lw = subject_lw[i]; - j = -1; - while (++j < n) { - csc_score = 0; - align = 0; - score_diag = score_up; - if (query_lw[j] === si_lw) { - start = isWordStart(i, subject, subject_lw); - csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); - align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score); - } - score_up = score_row[j]; - csc_diag = csc_row[j]; - if (score > score_up) { - move = LEFT; - } else { - score = score_up; - move = UP; - } - if (align > score) { - score = align; - move = DIAGONAL; - } else { - csc_score = 0; - } - score_row[j] = score; - csc_row[j] = csc_score; - trace[++pos] = score > 0 ? move : STOP; - } - } - i = m - 1; - j = n - 1; - pos = i * n + j; - backtrack = true; - matches = []; - while (backtrack && i >= 0 && j >= 0) { - switch (trace[pos]) { - case UP: - i--; - pos -= n; - break; - case LEFT: - j--; - pos--; - break; - case DIAGONAL: - matches.push(i + offset); - j--; - i--; - pos -= n + 1; - break; - default: - backtrack = false; - } - } - matches.reverse(); - return matches; - }; - -}).call(this); - - -/***/ }), - -/***/ 1660: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ -/* global window */ - -exports.log = log; - -var _devtoolsEnvironment = __webpack_require__(3721); - -const blacklist = ["SET_POPUP_OBJECT_PROPERTIES", "SET_PAUSE_POINTS", "SET_SYMBOLS", "OUT_OF_SCOPE_LOCATIONS", "MAP_SCOPES", "MAP_FRAMES", "ADD_SCOPES", "IN_SCOPE_LINES", "REMOVE_BREAKPOINT", "ADD_BREAKPOINT"]; - -function cloneAction(action) { - action = action || {}; - action = _extends({}, action); - - // ADD_TAB, ... - if (action.source && action.source.text) { - const source = _extends({}, action.source, { text: "" }); - action.source = source; - } - - if (action.sources) { - const sources = action.sources.slice(0, 20).map(source => { - const url = !source.url || source.url.includes("data:") ? "" : source.url; - return _extends({}, source, { url }); - }); - action.sources = sources; - } - - // LOAD_SOURCE_TEXT - if (action.text) { - action.text = ""; - } - - if (action.value && action.value.text) { - const value = _extends({}, action.value, { text: "" }); - action.value = value; - } - - return action; -} - -function formatFrame(frame) { - const { id, location, displayName } = frame; - return { id, location, displayName }; -} - -function formatPause(pause) { - return _extends({}, pause, { - pauseInfo: { why: pause.why }, - scopes: [], - frames: pause.frames.map(formatFrame), - loadedObjects: [] - }); -} - -function serializeAction(action) { - try { - action = cloneAction(action); - if (blacklist.includes(action.type)) { - action = {}; - } - - if (action.type === "PAUSED") { - action = formatPause(action); - } - - // dump(`> ${action.type}...\n ${JSON.stringify(action)}\n`); - return JSON.stringify(action); - } catch (e) { - console.error(e); - } -} - -/** - * A middleware that logs all actions coming through the system - * to the console. - */ -function log({ dispatch, getState }) { - return next => action => { - const asyncMsg = !action.status ? "" : `[${action.status}]`; - - if ((0, _devtoolsEnvironment.isTesting)()) { - dump(`[ACTION] ${action.type} ${asyncMsg} - ${serializeAction(action)}\n`); - } else { - console.log(action, asyncMsg); - } - - next(action); - }; -} - -/***/ }), - -/***/ 1661: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.history = undefined; - -var _devtoolsEnvironment = __webpack_require__(3721); - -/** - * A middleware that stores every action coming through the store in the passed - * in logging object. Should only be used for tests, as it collects all - * action information, which will cause memory bloat. - */ -const history = exports.history = (log = []) => ({ - dispatch, - getState -}) => { - return next => action => { - if ((0, _devtoolsEnvironment.isDevelopment)()) { - log.push(action); - } - - return next(action); - }; -}; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* global window */ - -/***/ }), - -/***/ 1662: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.thunk = thunk; - - -/** - * A middleware that allows thunks (functions) to be dispatched. If - * it's a thunk, it is called with an argument that contains - * `dispatch`, `getState`, and any additional args passed in via the - * middleware constructure. This allows the action to create multiple - * actions (most likely asynchronously). - */ -function thunk(makeArgs) { - return ({ dispatch, getState }) => { - const args = { dispatch, getState }; - - return next => action => { - return typeof action === "function" ? action(makeArgs ? makeArgs(args, getState()) : args) : next(action); - }; - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* global window */ - -/***/ }), - -/***/ 1663: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.timing = timing; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/* global window */ - -/** - * Redux middleware that sets performance markers for all actions such that they - * will appear in performance tooling under the User Timing API - */ - -const mark = window.performance && window.performance.mark ? window.performance.mark.bind(window.performance) : () => {}; - -const measure = window.performance && window.performance.measure ? window.performance.measure.bind(window.performance) : () => {}; - -function timing(store) { - return next => action => { - mark(`${action.type}_start`); - const result = next(action); - mark(`${action.type}_end`); - measure(`${action.type}`, `${action.type}_start`, `${action.type}_end`); - return result; - }; -} - -/***/ }), - -/***/ 1704: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -__webpack_require__(1705); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const Badge = ({ children }) => _react2.default.createElement( - "div", - { className: "badge text-white text-center" }, - children -); - -exports.default = Badge; - -/***/ }), - -/***/ 1705: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1733: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 175: -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - Copyright (c) 2016 Jed Watson. - Licensed under the MIT License (MIT), see - http://jedwatson.github.io/classnames -*/ -/* global define */ - -(function () { - 'use strict'; - - var hasOwn = {}.hasOwnProperty; - - function classNames () { - var classes = []; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - if (!arg) continue; - - var argType = typeof arg; - - if (argType === 'string' || argType === 'number') { - classes.push(arg); - } else if (Array.isArray(arg)) { - classes.push(classNames.apply(null, arg)); - } else if (argType === 'object') { - for (var key in arg) { - if (hasOwn.call(arg, key) && arg[key]) { - classes.push(key); - } - } - } - } - - return classes.join(' '); - } - - if (typeof module !== 'undefined' && module.exports) { - module.exports = classNames; - } else if (true) { - // register as 'classnames', consistent with npm package name - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () { - return classNames; - }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else { - window.classNames = classNames; - } -}()); - - -/***/ }), - -/***/ 1763: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _propTypes = __webpack_require__(3642); - -var _util = __webpack_require__(1777); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var process = process || { env: {} }; - -var InlineSVG = function (_React$Component) { - _inherits(InlineSVG, _React$Component); - - function InlineSVG() { - _classCallCheck(this, InlineSVG); - - return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments)); - } - - _createClass(InlineSVG, [{ - key: 'componentWillReceiveProps', - value: function componentWillReceiveProps(_ref) { - var children = _ref.children; - - if ("production" !== process.env.NODE_ENV && children != null) { - console.info(': `children` prop will be ignored.'); - } - } - }, { - key: 'render', - value: function render() { - var Element = void 0, - __html = void 0, - svgProps = void 0; - - var _props = this.props, - element = _props.element, - raw = _props.raw, - src = _props.src, - otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']); - - if (raw === true) { - Element = 'svg'; - svgProps = (0, _util.extractSVGProps)(src); - __html = (0, _util.getSVGFromSource)(src).innerHTML; - } - __html = __html || src; - Element = Element || element; - svgProps = svgProps || {}; - - return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null, - dangerouslySetInnerHTML: { __html: __html } })); - } - }]); - - return InlineSVG; -}(_react2.default.Component); - -exports.default = InlineSVG; - - -InlineSVG.defaultProps = { - element: 'i', - raw: false, - src: '' -}; - -InlineSVG.propTypes = { - src: _propTypes.string.isRequired, - element: _propTypes.string, - raw: _propTypes.bool -}; - -/***/ }), - -/***/ 1764: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -exports.debugBtn = debugBtn; - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -__webpack_require__(1788); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function debugBtn(onClick, type, className, tooltip, disabled = false, ariaPressed = false) { - return _react2.default.createElement( - CommandBarButton, - { - className: (0, _classnames2.default)(type, className), - disabled: disabled, - key: type, - onClick: onClick, - pressed: ariaPressed, - title: tooltip - }, - _react2.default.createElement("img", { className: type }) - ); -} - -const CommandBarButton = props => { - const { children, className, pressed = false } = props, - rest = _objectWithoutProperties(props, ["children", "className", "pressed"]); - - return _react2.default.createElement( - "button", - _extends({ - "aria-pressed": pressed, - className: (0, _classnames2.default)("command-bar-button", className) - }, rest), - children - ); -}; - -exports.default = CommandBarButton; - -/***/ }), - -/***/ 1765: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getBindingVariables = getBindingVariables; - -var _lodash = __webpack_require__(2); - -// Create the tree nodes representing all the variables and arguments -// for the bindings from a scope. - - -// VarAndBindingsPair actually is [name: string, contents: BindingContents] - - -// Scope's bindings field which holds variables and arguments -function getBindingVariables(bindings, parentName) { - const args = bindings.arguments.map(arg => (0, _lodash.toPairs)(arg)[0]); - const variables = (0, _lodash.toPairs)(bindings.variables); - - return args.concat(variables).map(binding => { - const name = binding[0]; - const contents = binding[1]; - return { - name, - path: `${parentName}/${name}`, - contents - }; - }); -} /* eslint max-nested-callbacks: ["error", 4] */ - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1766: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getFramePopVariables = getFramePopVariables; -exports.getThisVariable = getThisVariable; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getFramePopVariables(why, path) { - const vars = []; - - if (why && why.frameFinished) { - const frameFinished = why.frameFinished; - - // Always display a `throw` property if present, even if it is falsy. - if (Object.prototype.hasOwnProperty.call(frameFinished, "throw")) { - vars.push({ - name: "", - path: `${path}/`, - contents: { value: frameFinished.throw } - }); - } - - if (Object.prototype.hasOwnProperty.call(frameFinished, "return")) { - const returned = frameFinished.return; - - // Do not display undefined. Do display falsy values like 0 and false. The - // protocol grip for undefined is a JSON object: { type: "undefined" }. - if (typeof returned !== "object" || returned.type !== "undefined") { - vars.push({ - name: "", - path: `${path}/`, - contents: { value: returned } - }); - } - } - } - - return vars; -} - -function getThisVariable(this_, path) { - if (!this_) { - return null; - } - - return { - name: "", - path: `${path}/`, - contents: { value: this_ } - }; -} - -/***/ }), - -/***/ 1777: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.convertReactSVGDOMProperty = convertReactSVGDOMProperty; -exports.startsWith = startsWith; -exports.serializeAttrs = serializeAttrs; -exports.getSVGFromSource = getSVGFromSource; -exports.extractSVGProps = extractSVGProps; -// Transform DOM prop/attr names applicable to `` element but react-limited - -function convertReactSVGDOMProperty(str) { - return str.replace(/[-|:]([a-z])/g, function (g) { - return g[1].toUpperCase(); - }); -} - -function startsWith(str, substring) { - return str.indexOf(substring) === 0; -} - -var DataPropPrefix = 'data-'; -// Serialize `Attr` objects in `NamedNodeMap` -function serializeAttrs(map) { - var ret = {}; - for (var prop, i = 0; i < map.length; i++) { - var key = map[i].name; - if (!startsWith(key, DataPropPrefix)) { - prop = convertReactSVGDOMProperty(key); - } - ret[prop] = map[i].value; - } - return ret; -} - -function getSVGFromSource(src) { - var svgContainer = document.createElement('div'); - svgContainer.innerHTML = src; - var svg = svgContainer.firstElementChild; - svg.remove(); // deref from parent element - return svg; -} - -// get element props -function extractSVGProps(src) { - var map = getSVGFromSource(src).attributes; - return map.length > 0 ? serializeAttrs(map) : null; -} - -/***/ }), - -/***/ 1778: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isMinified = isMinified; - - -// Used to detect minification for automatic pretty printing -const SAMPLE_SIZE = 50; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const INDENT_COUNT_THRESHOLD = 5; -const CHARACTER_LIMIT = 250; -const _minifiedCache = new Map(); - -function isMinified(source) { - if (_minifiedCache.has(source.id)) { - return _minifiedCache.get(source.id); - } - - let text = source.get("text"); - if (!text) { - return false; - } - - let lineEndIndex = 0; - let lineStartIndex = 0; - let lines = 0; - let indentCount = 0; - let overCharLimit = false; - - // Strip comments. - text = text.replace(/\/\*[\S\s]*?\*\/|\/\/(.+|\n)/g, ""); - - while (lines++ < SAMPLE_SIZE) { - lineEndIndex = text.indexOf("\n", lineStartIndex); - if (lineEndIndex == -1) { - break; - } - if (/^\s+/.test(text.slice(lineStartIndex, lineEndIndex))) { - indentCount++; - } - // For files with no indents but are not minified. - if (lineEndIndex - lineStartIndex > CHARACTER_LIMIT) { - overCharLimit = true; - break; - } - lineStartIndex = lineEndIndex + 1; - } - - const minified = indentCount / lines * 100 < INDENT_COUNT_THRESHOLD || overCharLimit; - - _minifiedCache.set(source.id, minified); - return minified; -} - -/***/ }), - -/***/ 1779: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getCallStackFrames = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.formatCallStackFrames = formatCallStackFrames; - -var _sources = __webpack_require__(1369); - -var _pause = __webpack_require__(1394); - -var _frames = __webpack_require__(3605); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _lodash = __webpack_require__(2); - -var _reselect = __webpack_require__(993); - -function getLocation(frame, isGeneratedSource) { - return isGeneratedSource ? frame.generatedLocation || frame.location : frame.location; -} - -function getSourceForFrame(sources, frame, isGeneratedSource) { - const sourceId = getLocation(frame, isGeneratedSource).sourceId; - return (0, _sources.getSourceInSources)(sources, sourceId); -} - -function appendSource(sources, frame, selectedSource) { - const isGeneratedSource = selectedSource && !(0, _devtoolsSourceMap.isOriginalId)(selectedSource.get("id")); - return _extends({}, frame, { - location: getLocation(frame, isGeneratedSource), - source: getSourceForFrame(sources, frame, isGeneratedSource).toJS() - }); -} - -function formatCallStackFrames(frames, sources, selectedSource) { - if (!frames) { - return null; - } - - const formattedFrames = frames.filter(frame => getSourceForFrame(sources, frame)).map(frame => appendSource(sources, frame, selectedSource)).filter(frame => !(0, _lodash.get)(frame, "source.isBlackBoxed")); - - return (0, _frames.annotateFrames)(formattedFrames); -} - -const getCallStackFrames = exports.getCallStackFrames = (0, _reselect.createSelector)(_pause.getFrames, _sources.getSources, _sources.getSelectedSource, formatCallStackFrames); - -/***/ }), - -/***/ 1780: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getVisibleSelectedFrame = undefined; - -var _sources = __webpack_require__(1369); - -var _pause = __webpack_require__(1394); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _reselect = __webpack_require__(993); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getLocation(frame, location) { - if (!location) { - return frame.location; - } - - return !(0, _devtoolsSourceMap.isOriginalId)(location.sourceId) ? frame.generatedLocation || frame.location : frame.location; -} - -const getVisibleSelectedFrame = exports.getVisibleSelectedFrame = (0, _reselect.createSelector)(_sources.getSelectedLocation, _pause.getSelectedFrame, (selectedLocation, selectedFrame) => { - if (!selectedFrame) { - return null; - } - - const { id } = selectedFrame; - - return { - id, - location: getLocation(selectedFrame, selectedLocation) - }; -}); - -/***/ }), - -/***/ 1781: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setInScopeLines = setInScopeLines; - -var _selectors = __webpack_require__(3590); - -var _source = __webpack_require__(1356); - -var _lodash = __webpack_require__(2); - -function getOutOfScopeLines(outOfScopeLocations) { - if (!outOfScopeLocations) { - return null; - } - - return (0, _lodash.uniq)((0, _lodash.flatMap)(outOfScopeLocations, location => (0, _lodash.range)(location.start.line, location.end.line))); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function setInScopeLines() { - return ({ dispatch, getState }) => { - const sourceRecord = (0, _selectors.getSelectedSource)(getState()); - const outOfScopeLocations = (0, _selectors.getOutOfScopeLocations)(getState()); - - if (!sourceRecord || !sourceRecord.text) { - return; - } - - const linesOutOfScope = getOutOfScopeLines(outOfScopeLocations); - - const sourceNumLines = (0, _source.getSourceLineCount)(sourceRecord); - const sourceLines = (0, _lodash.range)(1, sourceNumLines + 1); - - const inScopeLines = !linesOutOfScope ? sourceLines : (0, _lodash.without)(sourceLines, ...linesOutOfScope); - - dispatch({ - type: "IN_SCOPE_LINES", - lines: inScopeLines - }); - }; -} - -/***/ }), - -/***/ 1782: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createLocation = createLocation; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function createLocation({ - sourceId, - line, - column, - sourceUrl -}) { - return { - sourceId, - line, - column, - sourceUrl: sourceUrl || null - }; -} - -/***/ }), - -/***/ 1786: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.updatePreview = updatePreview; -exports.setPreview = setPreview; -exports.clearPreview = clearPreview; - -var _preview = __webpack_require__(1807); - -var _ast = __webpack_require__(1638); - -var _editor = __webpack_require__(1358); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _promise = __webpack_require__(1653); - -var _getExpression = __webpack_require__(2360); - -var _selectors = __webpack_require__(3590); - -var _expressions = __webpack_require__(1398); - -var _pause = __webpack_require__(1639); - -var _lodash = __webpack_require__(2); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function isInvalidTarget(target) { - if (!target || !target.innerText) { - return true; - } - - const tokenText = target.innerText.trim(); - const cursorPos = target.getBoundingClientRect(); - - // exclude literal tokens where it does not make sense to show a preview - const invalidType = ["cm-atom", ""].includes(target.className); - - // exclude syntax where the expression would be a syntax error - const invalidToken = tokenText === "" || tokenText.match(/^[(){}\|&%,.;=<>\+-/\*\s](?=)/); - - const isPresentation = target.attributes.role && target.attributes.getNamedItem("role").value == "presentation"; - - // exclude codemirror elements that are not tokens - const invalidTarget = target.parentElement && !target.parentElement.closest(".CodeMirror-line") || cursorPos.top == 0; - - return invalidTarget || invalidToken || invalidType || isPresentation; -} - -function updatePreview(target, editor) { - return ({ dispatch, getState, client, sourceMaps }) => { - const tokenPos = (0, _editor.getTokenLocation)(editor.codeMirror, target); - const cursorPos = target.getBoundingClientRect(); - const preview = (0, _selectors.getPreview)(getState()); - - if ((0, _selectors.getCanRewind)(getState())) { - return; - } - - if (preview) { - // Return early if we are currently showing another preview or - // if we are mousing over the same token as before - if (preview.updating || (0, _lodash.isEqual)(preview.tokenPos, tokenPos)) { - return; - } - - // We are mousing over a new token that is not in the preview - if (!target.classList.contains("debug-expression")) { - dispatch(clearPreview()); - } - } - - if (isInvalidTarget(target)) { - dispatch(clearPreview()); - return; - } - - if (!(0, _selectors.isSelectedFrameVisible)(getState()) || !(0, _selectors.isLineInScope)(getState(), tokenPos.line)) { - return; - } - - const source = (0, _selectors.getSelectedSource)(getState()); - const symbols = (0, _selectors.getSymbols)(getState(), source); - - let match; - if (!symbols || symbols.loading) { - match = (0, _getExpression.getExpressionFromCoords)(editor.codeMirror, tokenPos); - } else { - match = (0, _ast.findBestMatchExpression)(symbols, tokenPos); - } - - if (!match || !match.expression) { - return; - } - - const { expression, location } = match; - - if ((0, _preview.isConsole)(expression)) { - return; - } - - dispatch(setPreview(expression, location, tokenPos, cursorPos)); - }; -} - -function setPreview(expression, location, tokenPos, cursorPos) { - return async ({ dispatch, getState, client, sourceMaps }) => { - await dispatch({ - type: "SET_PREVIEW", - [_promise.PROMISE]: async function () { - const source = (0, _selectors.getSelectedSource)(getState()); - const sourceId = source.id; - const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); - - if (location && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) { - expression = await dispatch((0, _expressions.getMappedExpression)(expression)); - } - - if (!selectedFrame) { - return; - } - - const { result } = await client.evaluateInFrame(expression, selectedFrame.id); - - if (result === undefined) { - return; - } - - const extra = await dispatch((0, _pause.getExtra)(expression, result)); - - return { - expression, - result, - location, - tokenPos, - cursorPos, - extra - }; - }() - }); - }; -} - -function clearPreview() { - return ({ dispatch, getState, client }) => { - const currentSelection = (0, _selectors.getPreview)(getState()); - if (!currentSelection) { - return; - } - - return dispatch({ - type: "CLEAR_SELECTION" - }); - }; -} - -/***/ }), - -/***/ 1788: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 1792: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getScopes = getScopes; - -var _getScope = __webpack_require__(1794); - -function getScopes(why, selectedFrame, frameScopes) { - if (!why || !selectedFrame) { - return null; - } - - if (!frameScopes) { - return null; - } - - const scopes = []; - - let scope = frameScopes; - let scopeIndex = 1; - - while (scope) { - const scopeItem = (0, _getScope.getScope)(scope, selectedFrame, frameScopes, why, scopeIndex); - - if (scopeItem) { - scopes.push(scopeItem); - } - scopeIndex++; - scope = scope.parent; - } - - return scopes; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1794: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.getScope = getScope; - -var _devtoolsReps = __webpack_require__(3655); - -var _getVariables = __webpack_require__(1765); - -var _utils = __webpack_require__(1766); - -var _frames = __webpack_require__(3605); - -function getScopeTitle(type, scope) { - if (type === "block" && scope.block && scope.block.displayName) { - return scope.block.displayName; - } - - if (type === "function" && scope.function) { - return scope.function.displayName ? (0, _frames.simplifyDisplayName)(scope.function.displayName) : L10N.getStr("anonymous"); - } - return L10N.getStr("scopes.block"); -} - -function getScope(scope, selectedFrame, frameScopes, why, scopeIndex) { - const { type, actor } = scope; - - const isLocalScope = scope.actor === frameScopes.actor; - - const key = `${actor}-${scopeIndex}`; - if (type === "function" || type === "block") { - const bindings = scope.bindings; - - let vars = (0, _getVariables.getBindingVariables)(bindings, key); - - // show exception, return, and this variables in innermost scope - if (isLocalScope) { - vars = vars.concat((0, _utils.getFramePopVariables)(why, key)); - - let thisDesc_ = selectedFrame.this; - - if ("this" in bindings) { - // The presence of "this" means we're rendering a "this" binding - // generated from mapScopes and this can override the binding - // provided by the current frame. - thisDesc_ = bindings.this ? bindings.this.value : null; - } - - const this_ = (0, _utils.getThisVariable)(thisDesc_, key); - - if (this_) { - vars.push(this_); - } - } - - if (vars && vars.length) { - const title = getScopeTitle(type, scope); - vars.sort((a, b) => a.name.localeCompare(b.name)); - return { - name: title, - path: key, - contents: vars, - type: _devtoolsReps.ObjectInspectorUtils.node.NODE_TYPES.BLOCK - }; - } - } else if (type === "object" && scope.object) { - let value = scope.object; - // If this is the global window scope, mark it as such so that it will - // preview Window: Global instead of Window: Window - if (value.class === "Window") { - value = _extends({}, scope.object, { displayClass: "Global" }); - } - return { - name: scope.object.class, - path: key, - contents: { value } - }; - } - - return null; -} - -/***/ }), - -/***/ 1795: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _lodash = __webpack_require__(2); - -let newSources; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -let createSource; -let supportsWasm = false; -let queuedSources; -let currentWork; - -async function dispatchNewSources() { - const sources = queuedSources; - queuedSources = []; - - currentWork = await newSources(sources.map(source => createSource(source, { supportsWasm }))); -} - -const queue = (0, _lodash.throttle)(dispatchNewSources, 100); - -exports.default = { - initialize: options => { - newSources = options.actions.newSources; - createSource = options.createSource; - supportsWasm = options.supportsWasm; - queuedSources = []; - }, - queue: source => { - queuedSources.push(source); - queue(); - }, - flush: () => Promise.all([queue.flush(), currentWork]), - clear: () => queue.cancel() -}; - -/***/ }), - -/***/ 1796: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.HighlightLine = undefined; - -var _react = __webpack_require__(0); - -var _editor = __webpack_require__(1358); - -var _sourceDocuments = __webpack_require__(1436); - -var _source = __webpack_require__(1356); - -var _reactRedux = __webpack_require__(3592); - -var _selectors = __webpack_require__(3590); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function isDebugLine(selectedFrame, selectedLocation) { - if (!selectedFrame) { - return; - } - - return selectedFrame.location.sourceId == selectedLocation.sourceId && selectedFrame.location.line == selectedLocation.line; -} - -function isDocumentReady(selectedSource, selectedLocation) { - return selectedLocation && (0, _source.isLoaded)(selectedSource) && (0, _sourceDocuments.hasDocument)(selectedLocation.sourceId); -} - -class HighlightLine extends _react.Component { - constructor(...args) { - var _temp; - - return _temp = super(...args), this.isStepping = false, this.previousEditorLine = null, _temp; - } - - shouldComponentUpdate(nextProps) { - const { selectedLocation, selectedSource } = nextProps; - return this.shouldSetHighlightLine(selectedLocation, selectedSource); - } - - shouldSetHighlightLine(selectedLocation, selectedSource) { - const { sourceId, line } = selectedLocation; - const editorLine = (0, _editor.toEditorLine)(sourceId, line); - - if (!isDocumentReady(selectedSource, selectedLocation)) { - return false; - } - - if (this.isStepping && editorLine === this.previousEditorLine) { - return false; - } - - return true; - } - - componentDidUpdate(prevProps) { - const { - pauseCommand, - selectedLocation, - selectedFrame, - selectedSource - } = this.props; - if (pauseCommand) { - this.isStepping = true; - } - - this.clearHighlightLine(prevProps.selectedLocation, prevProps.selectedSource); - this.setHighlightLine(selectedLocation, selectedFrame, selectedSource); - } - - setHighlightLine(selectedLocation, selectedFrame, selectedSource) { - const { sourceId, line } = selectedLocation; - if (!this.shouldSetHighlightLine(selectedLocation, selectedSource)) { - return; - } - this.isStepping = false; - const editorLine = (0, _editor.toEditorLine)(sourceId, line); - this.previousEditorLine = editorLine; - - if (!line || isDebugLine(selectedFrame, selectedLocation)) { - return; - } - - const doc = (0, _sourceDocuments.getDocument)(sourceId); - doc.addLineClass(editorLine, "line", "highlight-line"); - } - - clearHighlightLine(selectedLocation, selectedSource) { - if (!isDocumentReady(selectedSource, selectedLocation)) { - return; - } - - const { line, sourceId } = selectedLocation; - const editorLine = (0, _editor.toEditorLine)(sourceId, line); - const doc = (0, _sourceDocuments.getDocument)(sourceId); - doc.removeLineClass(editorLine, "line", "highlight-line"); - } - - render() { - return null; - } -} - -exports.HighlightLine = HighlightLine; -exports.default = (0, _reactRedux.connect)(state => ({ - pauseCommand: (0, _selectors.getPauseCommand)(state), - selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state), - selectedLocation: (0, _selectors.getSelectedLocation)(state), - selectedSource: (0, _selectors.getSelectedSource)(state) -}))(HighlightLine); - -/***/ }), - -/***/ 1797: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _loadSourceText = __webpack_require__(1435); - -Object.keys(_loadSourceText).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _loadSourceText[key]; - } - }); -}); - -var _prettyPrint = __webpack_require__(1798); - -Object.keys(_prettyPrint).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _prettyPrint[key]; - } - }); -}); - -var _newSources = __webpack_require__(1801); - -Object.keys(_newSources).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _newSources[key]; - } - }); -}); - -var _blackbox = __webpack_require__(1802); - -Object.keys(_blackbox).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _blackbox[key]; - } - }); -}); - -var _select = __webpack_require__(1803); - -Object.keys(_select).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _select[key]; - } - }); -}); - -var _tabs = __webpack_require__(1799); - -Object.keys(_tabs).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _tabs[key]; - } - }); -}); - -/***/ }), - -/***/ 1798: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.createPrettySource = createPrettySource; -exports.togglePrettyPrint = togglePrettyPrint; - -var _assert = __webpack_require__(1384); - -var _assert2 = _interopRequireDefault(_assert); - -var _breakpoints = __webpack_require__(1396); - -var _ast = __webpack_require__(1399); - -var _prettyPrint = __webpack_require__(1431); - -var _parser = __webpack_require__(1365); - -var _source = __webpack_require__(1356); - -var _loadSourceText = __webpack_require__(1435); - -var _sources = __webpack_require__(1797); - -var _pause = __webpack_require__(1639); - -var _selectors = __webpack_require__(3590); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function createPrettySource(sourceId) { - return async ({ dispatch, getState, sourceMaps }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - const url = (0, _source.getPrettySourceURL)(source.url); - const id = await sourceMaps.generatedToOriginalId(sourceId, url); - - const prettySource = { - url, - id, - isBlackBoxed: false, - isPrettyPrinted: true, - isWasm: false, - contentType: "text/javascript", - loadedState: "loading" - }; - dispatch({ type: "ADD_SOURCE", source: prettySource }); - - const { code, mappings } = await (0, _prettyPrint.prettyPrint)({ source, url }); - await sourceMaps.applySourceMap(source.id, url, code, mappings); - - const loadedPrettySource = _extends({}, prettySource, { - text: code, - loadedState: "loaded" - }); - - (0, _parser.setSource)(loadedPrettySource); - - dispatch({ type: "UPDATE_SOURCE", source: loadedPrettySource }); - - return prettySource; - }; -} - -/** - * Toggle the pretty printing of a source's text. All subsequent calls to - * |getText| will return the pretty-toggled text. Nothing will happen for - * non-javascript files. - * - * @memberof actions/sources - * @static - * @param string id The source form from the RDP. - * @returns Promise - * A promise that resolves to [aSource, prettyText] or rejects to - * [aSource, error]. - */ -function togglePrettyPrint(sourceId) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - if (!source) { - return {}; - } - - if (!(0, _source.isLoaded)(source)) { - await dispatch((0, _loadSourceText.loadSourceText)(source)); - } - - (0, _assert2.default)(sourceMaps.isGeneratedId(sourceId), "Pretty-printing only allowed on generated sources"); - - const selectedLocation = (0, _selectors.getSelectedLocation)(getState()); - const url = (0, _source.getPrettySourceURL)(source.url); - const prettySource = (0, _selectors.getSourceByURL)(getState(), url); - - const options = {}; - if (selectedLocation) { - options.location = await sourceMaps.getOriginalLocation(selectedLocation); - } - - if (prettySource) { - const _sourceId = prettySource.get("id"); - return dispatch((0, _sources.selectLocation)(_extends({}, options.location, { sourceId: _sourceId }))); - } - - const newPrettySource = await dispatch(createPrettySource(sourceId)); - - await dispatch((0, _breakpoints.remapBreakpoints)(sourceId)); - await dispatch((0, _pause.mapFrames)()); - await dispatch((0, _ast.setPausePoints)(newPrettySource.id)); - await dispatch((0, _ast.setSymbols)(newPrettySource.id)); - - return dispatch((0, _sources.selectLocation)(_extends({}, options.location, { sourceId: newPrettySource.id }))); - }; -} - -/***/ }), - -/***/ 1799: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.addTab = addTab; -exports.moveTab = moveTab; -exports.closeTab = closeTab; -exports.closeTabs = closeTabs; - -var _editor = __webpack_require__(1358); - -var _sources = __webpack_require__(1797); - -var _selectors = __webpack_require__(3590); - -function addTab(source, tabIndex) { - return { - type: "ADD_TAB", - source, - tabIndex - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for the sources state - * @module actions/sources - */ - -function moveTab(url, tabIndex) { - return { - type: "MOVE_TAB", - url, - tabIndex - }; -} - -/** - * @memberof actions/sources - * @static - */ -function closeTab(url) { - return ({ dispatch, getState, client }) => { - (0, _editor.removeDocument)(url); - const tabs = (0, _selectors.removeSourceFromTabList)((0, _selectors.getSourceTabs)(getState()), url); - const sourceId = (0, _selectors.getNewSelectedSourceId)(getState(), tabs); - dispatch({ type: "CLOSE_TAB", url, tabs }); - dispatch((0, _sources.selectSource)(sourceId)); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function closeTabs(urls) { - return ({ dispatch, getState, client }) => { - urls.forEach(url => { - const source = (0, _selectors.getSourceByURL)(getState(), url); - if (source) { - (0, _editor.removeDocument)(source.get("id")); - } - }); - - const tabs = (0, _selectors.removeSourcesFromTabList)((0, _selectors.getSourceTabs)(getState()), urls); - dispatch({ type: "CLOSE_TABS", urls, tabs }); - - const sourceId = (0, _selectors.getNewSelectedSourceId)(getState(), tabs); - dispatch((0, _sources.selectSource)(sourceId)); - }; -} - -/***/ }), - -/***/ 1800: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = defer; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function defer() { - let resolve = () => {}; - let reject = () => {}; - const promise = new Promise((_res, _rej) => { - resolve = _res; - reject = _rej; - }); - - return { resolve, reject, promise }; -} - -/***/ }), - -/***/ 1801: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for the sources state - * @module actions/sources - */ - -exports.newSource = newSource; -exports.newSources = newSources; - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _lodash = __webpack_require__(2); - -var _blackbox = __webpack_require__(1802); - -var _breakpoints = __webpack_require__(1396); - -var _loadSourceText = __webpack_require__(1435); - -var _prettyPrint = __webpack_require__(1798); - -var _sources = __webpack_require__(1797); - -var _source = __webpack_require__(1356); - -var _selectors = __webpack_require__(3590); - -function createOriginalSource(originalUrl, generatedSource, sourceMaps) { - return { - url: originalUrl, - id: sourceMaps.generatedToOriginalId(generatedSource.id, originalUrl), - isPrettyPrinted: false, - isWasm: false, - isBlackBoxed: false, - loadedState: "unloaded" - }; -} - -function loadSourceMaps(sources) { - return async function ({ dispatch, sourceMaps }) { - if (!sourceMaps) { - return; - } - - const originalSources = await Promise.all(sources.map(source => dispatch(loadSourceMap(source.id)))); - - await dispatch(newSources((0, _lodash.flatten)(originalSources))); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function loadSourceMap(sourceId) { - return async function ({ dispatch, getState, sourceMaps }) { - const source = (0, _selectors.getSource)(getState(), sourceId).toJS(); - - if (!sourceMaps || !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) || !source.sourceMapURL) { - return; - } - - let urls = null; - try { - urls = await sourceMaps.getOriginalURLs(source); - } catch (e) { - console.error(e); - } - - if (!urls) { - // If this source doesn't have a sourcemap, enable it for pretty printing - dispatch({ - type: "UPDATE_SOURCE", - source: _extends({}, source, { sourceMapURL: "" }) - }); - return; - } - - return urls.map(url => createOriginalSource(url, source, sourceMaps)); - }; -} - -// If a request has been made to show this source, go ahead and -// select it. -function checkSelectedSource(sourceId) { - return async ({ dispatch, getState }) => { - const source = (0, _selectors.getSource)(getState(), sourceId); - - const pendingLocation = (0, _selectors.getPendingSelectedLocation)(getState()); - - if (!pendingLocation || !pendingLocation.url || !source.url) { - return; - } - - const pendingUrl = pendingLocation.url; - const rawPendingUrl = (0, _source.getRawSourceURL)(pendingUrl); - - if (rawPendingUrl === source.url) { - if ((0, _source.isPrettyURL)(pendingUrl)) { - return await dispatch((0, _prettyPrint.togglePrettyPrint)(source.id)); - } - - await dispatch((0, _sources.selectLocation)(_extends({}, pendingLocation, { sourceId: source.id }))); - } - }; -} - -function checkPendingBreakpoints(sourceId) { - return async ({ dispatch, getState }) => { - // source may have been modified by selectLocation - const source = (0, _selectors.getSource)(getState(), sourceId); - - const pendingBreakpoints = (0, _selectors.getPendingBreakpointsForSource)(getState(), source.get("url")); - - if (!pendingBreakpoints.size) { - return; - } - - // load the source text if there is a pending breakpoint for it - await dispatch((0, _loadSourceText.loadSourceText)(source)); - - const pendingBreakpointsArray = pendingBreakpoints.valueSeq().toJS(); - for (const pendingBreakpoint of pendingBreakpointsArray) { - await dispatch((0, _breakpoints.syncBreakpoint)(sourceId, pendingBreakpoint)); - } - }; -} - -function restoreBlackBoxedSources(sources) { - return async ({ dispatch }) => { - const tabs = (0, _selectors.getBlackBoxList)(); - if (tabs.length == 0) { - return; - } - for (const source of sources) { - if (tabs.includes(source.url) && !source.isBlackBoxed) { - dispatch((0, _blackbox.toggleBlackBox)(source)); - } - } - }; -} - -/** - * Handler for the debugger client's unsolicited newSource notification. - * @memberof actions/sources - * @static - */ -function newSource(source) { - return async ({ dispatch }) => { - await dispatch(newSources([source])); - }; -} - -function newSources(sources) { - return async ({ dispatch, getState }) => { - const filteredSources = sources.filter(source => source && !(0, _selectors.getSource)(getState(), source.id)); - - if (filteredSources.length == 0) { - return; - } - - dispatch({ - type: "ADD_SOURCES", - sources: filteredSources - }); - - for (const source of filteredSources) { - dispatch(checkSelectedSource(source.id)); - dispatch(checkPendingBreakpoints(source.id)); - } - - await dispatch(loadSourceMaps(filteredSources)); - - // We would like to restore the blackboxed state - // after loading all states to make sure the correctness. - await dispatch(restoreBlackBoxedSources(filteredSources)); - }; -} - -/***/ }), - -/***/ 1802: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.toggleBlackBox = toggleBlackBox; - -var _promise = __webpack_require__(1653); - -function toggleBlackBox(source) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const { isBlackBoxed, id } = source; - - return dispatch({ - type: "BLACKBOX", - source, - [_promise.PROMISE]: client.blackBox(id, isBlackBoxed) - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for the sources state - * @module actions/sources - */ - -/***/ }), - -/***/ 1803: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for the sources state - * @module actions/sources - */ - -exports.selectSourceURL = selectSourceURL; -exports.selectSource = selectSource; -exports.selectLocation = selectLocation; -exports.selectSpecificLocation = selectSpecificLocation; -exports.selectSpecificSource = selectSpecificSource; -exports.jumpToMappedLocation = jumpToMappedLocation; -exports.jumpToMappedSelectedLocation = jumpToMappedSelectedLocation; - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _ast = __webpack_require__(1399); - -var _ui = __webpack_require__(1385); - -var _prettyPrint = __webpack_require__(1798); - -var _tabs = __webpack_require__(1799); - -var _loadSourceText = __webpack_require__(1435); - -var _prefs = __webpack_require__(226); - -var _source = __webpack_require__(1356); - -var _location = __webpack_require__(1782); - -var _sourceMaps = __webpack_require__(1397); - -var _selectors = __webpack_require__(3590); - -/** - * Deterministically select a source that has a given URL. This will - * work regardless of the connection status or if the source exists - * yet. This exists mostly for external things to interact with the - * debugger. - * - * @memberof actions/sources - * @static - */ -function selectSourceURL(url, options = {}) { - return async ({ dispatch, getState }) => { - const source = (0, _selectors.getSourceByURL)(getState(), url); - if (source) { - const sourceId = source.id; - const location = (0, _location.createLocation)(_extends({}, options.location, { sourceId })); - await dispatch(selectLocation(location)); - } else { - dispatch({ - type: "SELECT_SOURCE_URL", - url: url, - line: options.location ? options.location.line : null - }); - } - }; -} - -/** - * @memberof actions/sources - * @static - */ -function selectSource(sourceId) { - return async ({ dispatch }) => { - const location = (0, _location.createLocation)({ sourceId }); - return await dispatch(selectLocation(location)); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function selectLocation(location) { - return async ({ dispatch, getState, client }) => { - if (!client) { - // No connection, do nothing. This happens when the debugger is - // shut down too fast and it tries to display a default source. - return; - } - - const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId); - if (!sourceRecord) { - // If there is no source we deselect the current selected source - return dispatch({ type: "CLEAR_SELECTED_SOURCE" }); - } - - const activeSearch = (0, _selectors.getActiveSearch)(getState()); - if (activeSearch !== "file") { - dispatch((0, _ui.closeActiveSearch)()); - } - - const source = sourceRecord.toJS(); - - dispatch((0, _tabs.addTab)(source, 0)); - dispatch({ - type: "SELECT_SOURCE", - source, - location - }); - - await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord)); - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - if (!selectedSource) { - return; - } - - const sourceId = selectedSource.id; - - if (_prefs.prefs.autoPrettyPrint && !(0, _selectors.getPrettySource)(getState(), sourceId) && (0, _source.shouldPrettyPrint)(selectedSource) && (0, _source.isMinified)(selectedSource)) { - await dispatch((0, _prettyPrint.togglePrettyPrint)(sourceId)); - dispatch((0, _tabs.closeTab)(source.url)); - } - - dispatch((0, _ast.setSymbols)(sourceId)); - dispatch((0, _ast.setOutOfScopeLocations)()); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function selectSpecificLocation(location) { - return async ({ dispatch, getState, client }) => { - if (!client) { - // No connection, do nothing. This happens when the debugger is - // shut down too fast and it tries to display a default source. - return; - } - - const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId); - if (!sourceRecord) { - // If there is no source we deselect the current selected source - return dispatch({ type: "CLEAR_SELECTED_SOURCE" }); - } - - const activeSearch = (0, _selectors.getActiveSearch)(getState()); - if (activeSearch !== "file") { - dispatch((0, _ui.closeActiveSearch)()); - } - - const source = sourceRecord.toJS(); - - dispatch((0, _tabs.addTab)(source, 0)); - dispatch({ - type: "SELECT_SOURCE", - source, - location - }); - - await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord)); - const selectedSource = (0, _selectors.getSelectedSource)(getState()); - if (!selectedSource) { - return; - } - - const sourceId = selectedSource.id; - dispatch((0, _ast.setSymbols)(sourceId)); - dispatch((0, _ast.setOutOfScopeLocations)()); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function selectSpecificSource(sourceId) { - return async ({ dispatch }) => { - const location = (0, _location.createLocation)({ sourceId }); - return await dispatch(selectSpecificLocation(location)); - }; -} - -/** - * @memberof actions/sources - * @static - */ -function jumpToMappedLocation(location) { - return async function ({ dispatch, getState, client, sourceMaps }) { - if (!client) { - return; - } - - const source = (0, _selectors.getSource)(getState(), location.sourceId); - let pairedLocation; - if ((0, _devtoolsSourceMap.isOriginalId)(location.sourceId)) { - pairedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source, location, sourceMaps); - } else { - pairedLocation = await sourceMaps.getOriginalLocation(location, source.toJS()); - } - - return dispatch(selectLocation(_extends({}, pairedLocation))); - }; -} - -function jumpToMappedSelectedLocation() { - return async function ({ dispatch, getState }) { - const location = (0, _selectors.getSelectedLocation)(getState()); - await dispatch(jumpToMappedLocation(location)); - }; -} - -/***/ }), - -/***/ 1804: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.updateFrameLocation = updateFrameLocation; -exports.mapDisplayNames = mapDisplayNames; -exports.mapFrames = mapFrames; - -var _selectors = __webpack_require__(3590); - -var _ast = __webpack_require__(1638); - -function updateFrameLocation(frame, sourceMaps) { - return sourceMaps.getOriginalLocation(frame.location).then(loc => _extends({}, frame, { - location: loc, - generatedLocation: frame.generatedLocation || frame.location - })); -} - -function updateFrameLocations(frames, sourceMaps) { - if (!frames || frames.length == 0) { - return Promise.resolve(frames); - } - - return Promise.all(frames.map(frame => updateFrameLocation(frame, sourceMaps))); -} - -function mapDisplayNames(frames, getState) { - return frames.map(frame => { - const source = (0, _selectors.getSource)(getState(), frame.location.sourceId); - const symbols = (0, _selectors.getSymbols)(getState(), source); - - if (!symbols || !symbols.functions) { - return frame; - } - - const originalFunction = (0, _ast.findClosestFunction)(symbols, frame.location); - - if (!originalFunction) { - return frame; - } - - const originalDisplayName = originalFunction.name; - return _extends({}, frame, { originalDisplayName }); - }); -} - -/** - * Map call stack frame locations and display names to originals. - * e.g. - * 1. When the debuggee pauses - * 2. When a source is pretty printed - * 3. When symbols are loaded - * @memberof actions/pause - * @static - */ -function mapFrames() { - return async function ({ dispatch, getState, sourceMaps }) { - const frames = (0, _selectors.getFrames)(getState()); - if (!frames) { - return; - } - - let mappedFrames = await updateFrameLocations(frames, sourceMaps); - mappedFrames = mapDisplayNames(mappedFrames, getState); - - dispatch({ - type: "MAP_FRAMES", - frames: mappedFrames - }); - }; -} - -/***/ }), - -/***/ 1805: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = showContextMenu; - -var _devtoolsContextmenu = __webpack_require__(1413); - -function showContextMenu(props) { - const { - removeBreakpoint, - removeBreakpoints, - removeAllBreakpoints, - toggleBreakpoints, - toggleAllBreakpoints, - toggleDisabledBreakpoint, - selectLocation, - setBreakpointCondition, - openConditionalPanel, - breakpoints, - breakpoint, - contextMenuEvent - } = props; - - contextMenuEvent.preventDefault(); - - const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label"); - const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label"); - const deleteOthersLabel = L10N.getStr("breakpointMenuItem.deleteOthers2.label"); - const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label"); - const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label"); - const enableOthersLabel = L10N.getStr("breakpointMenuItem.enableOthers2.label"); - const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label"); - const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label"); - const disableOthersLabel = L10N.getStr("breakpointMenuItem.disableOthers2.label"); - const removeConditionLabel = L10N.getStr("breakpointMenuItem.removeCondition2.label"); - const addConditionLabel = L10N.getStr("breakpointMenuItem.addCondition2.label"); - const editConditionLabel = L10N.getStr("breakpointMenuItem.editCondition2.label"); - - const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey"); - const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey"); - const deleteOthersKey = L10N.getStr("breakpointMenuItem.deleteOthers2.accesskey"); - const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey"); - const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey"); - const enableOthersKey = L10N.getStr("breakpointMenuItem.enableOthers2.accesskey"); - const disableSelfKey = L10N.getStr("breakpointMenuItem.disableSelf2.accesskey"); - const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey"); - const disableOthersKey = L10N.getStr("breakpointMenuItem.disableOthers2.accesskey"); - const removeConditionKey = L10N.getStr("breakpointMenuItem.removeCondition2.accesskey"); - const editConditionKey = L10N.getStr("breakpointMenuItem.editCondition2.accesskey"); - const addConditionKey = L10N.getStr("breakpointMenuItem.addCondition2.accesskey"); - - const otherBreakpoints = breakpoints.filter(b => b !== breakpoint); - const enabledBreakpoints = breakpoints.filter(b => !b.disabled); - const disabledBreakpoints = breakpoints.filter(b => b.disabled); - const otherEnabledBreakpoints = breakpoints.filter(b => !b.disabled && b !== breakpoint); - const otherDisabledBreakpoints = breakpoints.filter(b => b.disabled && b !== breakpoint); - - const deleteSelfItem = { - id: "node-menu-delete-self", - label: deleteSelfLabel, - accesskey: deleteSelfKey, - disabled: false, - click: () => removeBreakpoint(breakpoint.location) - }; - - const deleteAllItem = { - id: "node-menu-delete-all", - label: deleteAllLabel, - accesskey: deleteAllKey, - disabled: false, - click: () => removeAllBreakpoints() - }; - - const deleteOthersItem = { - id: "node-menu-delete-other", - label: deleteOthersLabel, - accesskey: deleteOthersKey, - disabled: false, - click: () => removeBreakpoints(otherBreakpoints) - }; - - const enableSelfItem = { - id: "node-menu-enable-self", - label: enableSelfLabel, - accesskey: enableSelfKey, - disabled: false, - click: () => toggleDisabledBreakpoint(breakpoint.location.line) - }; - - const enableAllItem = { - id: "node-menu-enable-all", - label: enableAllLabel, - accesskey: enableAllKey, - disabled: false, - click: () => toggleAllBreakpoints(false) - }; - - const enableOthersItem = { - id: "node-menu-enable-others", - label: enableOthersLabel, - accesskey: enableOthersKey, - disabled: false, - click: () => toggleBreakpoints(false, otherDisabledBreakpoints) - }; - - const disableSelfItem = { - id: "node-menu-disable-self", - label: disableSelfLabel, - accesskey: disableSelfKey, - disabled: false, - click: () => toggleDisabledBreakpoint(breakpoint.location.line) - }; - - const disableAllItem = { - id: "node-menu-disable-all", - label: disableAllLabel, - accesskey: disableAllKey, - disabled: false, - click: () => toggleAllBreakpoints(true) - }; - - const disableOthersItem = { - id: "node-menu-disable-others", - label: disableOthersLabel, - accesskey: disableOthersKey, - click: () => toggleBreakpoints(true, otherEnabledBreakpoints) - }; - - const removeConditionItem = { - id: "node-menu-remove-condition", - label: removeConditionLabel, - accesskey: removeConditionKey, - disabled: false, - click: () => setBreakpointCondition(breakpoint.location) - }; - - const addConditionItem = { - id: "node-menu-add-condition", - label: addConditionLabel, - accesskey: addConditionKey, - click: () => { - selectLocation(breakpoint.location); - openConditionalPanel(breakpoint.location.line); - } - }; - - const editConditionItem = { - id: "node-menu-edit-condition", - label: editConditionLabel, - accesskey: editConditionKey, - click: () => { - selectLocation(breakpoint.location); - openConditionalPanel(breakpoint.location.line); - } - }; - - const hideEnableSelfItem = !breakpoint.disabled; - const hideEnableAllItem = disabledBreakpoints.size === 0; - const hideEnableOthersItem = otherDisabledBreakpoints.size === 0; - const hideDisableAllItem = enabledBreakpoints.size === 0; - const hideDisableOthersItem = otherEnabledBreakpoints.size === 0; - const hideDisableSelfItem = breakpoint.disabled; - - const items = [{ item: enableSelfItem, hidden: () => hideEnableSelfItem }, { item: enableAllItem, hidden: () => hideEnableAllItem }, { item: enableOthersItem, hidden: () => hideEnableOthersItem }, { - item: { type: "separator" }, - hidden: () => hideEnableSelfItem && hideEnableAllItem && hideEnableOthersItem - }, { item: deleteSelfItem }, { item: deleteAllItem }, { item: deleteOthersItem, hidden: () => breakpoints.size === 1 }, { - item: { type: "separator" }, - hidden: () => hideDisableSelfItem && hideDisableAllItem && hideDisableOthersItem - }, { item: disableSelfItem, hidden: () => hideDisableSelfItem }, { item: disableAllItem, hidden: () => hideDisableAllItem }, { item: disableOthersItem, hidden: () => hideDisableOthersItem }, { - item: { type: "separator" } - }, { - item: addConditionItem, - hidden: () => breakpoint.condition - }, { - item: editConditionItem, - hidden: () => !breakpoint.condition - }, { - item: removeConditionItem, - hidden: () => !breakpoint.condition - }]; - - (0, _devtoolsContextmenu.showMenu)(contextMenuEvent, (0, _devtoolsContextmenu.buildMenu)(items)); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 1806: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createEditor = createEditor; - -var _sourceEditor = __webpack_require__(197); - -var _sourceEditor2 = _interopRequireDefault(_sourceEditor); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function createEditor() { - const gutters = ["breakpoints", "hit-markers", "CodeMirror-linenumbers"]; - - if (_prefs.features.codeFolding) { - gutters.push("CodeMirror-foldgutter"); - } - - return new _sourceEditor2.default({ - mode: "javascript", - foldGutter: _prefs.features.codeFolding, - enableCodeFolding: _prefs.features.codeFolding, - readOnly: true, - lineNumbers: true, - theme: "mozilla", - styleActiveLine: false, - lineWrapping: false, - matchBrackets: true, - showAnnotationRuler: true, - gutters, - value: " ", - extraKeys: { - // Override code mirror keymap to avoid conflicts with split console. - Esc: false, - "Cmd-F": false, - "Ctrl-F": false, - "Cmd-G": false, - "Ctrl-G": false - } - }); -} - -/***/ }), - -/***/ 1807: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isImmutable = isImmutable; -exports.isReactComponent = isReactComponent; -exports.isConsole = isConsole; - - -const IMMUTABLE_FIELDS = ["_root", "__ownerID", "__altered", "__hash"]; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function isImmutable(result) { - if (!result || !result.preview) { - return; - } - - const ownProperties = result.preview.ownProperties; - if (!ownProperties) { - return; - } - - return IMMUTABLE_FIELDS.every(field => Object.keys(ownProperties).includes(field)); -} - -function isReactComponent(result) { - if (!result || !result.preview) { - return; - } - - const ownProperties = result.preview.ownProperties; - if (!ownProperties) { - return; - } - - return Object.keys(ownProperties).includes("_reactInternalInstance") || Object.keys(ownProperties).includes("_reactInternalFiber"); -} - -function isConsole(expression) { - return (/^console/.test(expression) - ); -} - -/***/ }), - -/***/ 1808: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 1941: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getHiddenTabs = getHiddenTabs; -exports.getSourceAnnotation = getSourceAnnotation; -exports.getTabMenuItems = getTabMenuItems; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _source = __webpack_require__(1356); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* - * Finds the hidden tabs by comparing the tabs' top offset. - * hidden tabs will have a great top offset. - * - * @param sourceTabs Immutable.list - * @param sourceTabEls HTMLCollection - * - * @returns Immutable.list - */ - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getHiddenTabs(sourceTabs, sourceTabEls) { - sourceTabEls = [].slice.call(sourceTabEls); - function getTopOffset() { - const topOffsets = sourceTabEls.map(t => t.getBoundingClientRect().top); - return Math.min(...topOffsets); - } - - function hasTopOffset(el) { - // adding 10px helps account for cases where the tab might be offset by - // styling such as selected tabs which don't have a border. - const tabTopOffset = getTopOffset(); - return el.getBoundingClientRect().top > tabTopOffset + 10; - } - - return sourceTabs.filter((tab, index) => { - const element = sourceTabEls[index]; - return element && hasTopOffset(element); - }); -} - -function getSourceAnnotation(source, sourceMetaData) { - const framework = sourceMetaData && sourceMetaData.framework ? sourceMetaData.framework : false; - - if (framework) { - return _react2.default.createElement("img", { className: framework.toLowerCase() }); - } - - if ((0, _source.isPretty)(source)) { - return _react2.default.createElement("img", { className: "prettyPrint" }); - } - if (source.isBlackBoxed) { - return _react2.default.createElement("img", { className: "blackBox" }); - } -} - -function getTabMenuItems() { - return { - closeTab: { - id: "node-menu-close-tab", - label: L10N.getStr("sourceTabs.closeTab"), - accesskey: L10N.getStr("sourceTabs.closeTab.accesskey"), - disabled: false - }, - closeOtherTabs: { - id: "node-menu-close-other-tabs", - label: L10N.getStr("sourceTabs.closeOtherTabs"), - accesskey: L10N.getStr("sourceTabs.closeOtherTabs.accesskey"), - disabled: false - }, - closeTabsToEnd: { - id: "node-menu-close-tabs-to-end", - label: L10N.getStr("sourceTabs.closeTabsToEnd"), - accesskey: L10N.getStr("sourceTabs.closeTabsToEnd.accesskey"), - disabled: false - }, - closeAllTabs: { - id: "node-menu-close-all-tabs", - label: L10N.getStr("sourceTabs.closeAllTabs"), - accesskey: L10N.getStr("sourceTabs.closeAllTabs.accesskey"), - disabled: false - }, - showSource: { - id: "node-menu-show-source", - label: L10N.getStr("sourceTabs.revealInTree"), - accesskey: L10N.getStr("sourceTabs.revealInTree.accesskey"), - disabled: false - }, - copyToClipboard: { - id: "node-menu-copy-to-clipboard", - label: L10N.getStr("copyToClipboard.label"), - accesskey: L10N.getStr("copyToClipboard.accesskey"), - disabled: false - }, - copySourceUri2: { - id: "node-menu-copy-source-url", - label: L10N.getStr("copySourceUri2"), - accesskey: L10N.getStr("copySourceUri2.accesskey"), - disabled: false - }, - prettyPrint: { - id: "node-menu-pretty-print", - label: L10N.getStr("sourceTabs.prettyPrint"), - accesskey: L10N.getStr("sourceTabs.prettyPrint.accesskey"), - disabled: false - } - }; -} - -/***/ }), - -/***/ 197: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_197__; - -/***/ }), - -/***/ 2: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_2__; - -/***/ }), - -/***/ 2008: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setPopupObjectProperties = setPopupObjectProperties; - -var _selectors = __webpack_require__(3590); - -/** - * @memberof actions/pause - * @static - */ -function setPopupObjectProperties(object, properties) { - return ({ dispatch, client, getState }) => { - const objectId = object.actor || object.objectId; - - if ((0, _selectors.getPopupObjectProperties)(getState(), object.actor)) { - return; - } - - dispatch({ - type: "SET_POPUP_OBJECT_PROPERTIES", - objectId, - properties - }); - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 2009: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ProjectSearch = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _editor = __webpack_require__(1358); - -var _projectSearch = __webpack_require__(2010); - -var _projectTextSearch = __webpack_require__(1424); - -var _sourcesTree = __webpack_require__(1442); - -var _selectors = __webpack_require__(3590); - -var _Svg = __webpack_require__(1359); - -var _Svg2 = _interopRequireDefault(_Svg); - -var _ManagedTree = __webpack_require__(1404); - -var _ManagedTree2 = _interopRequireDefault(_ManagedTree); - -var _SearchInput = __webpack_require__(1379); - -var _SearchInput2 = _interopRequireDefault(_SearchInput); - -__webpack_require__(2011); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function getFilePath(item, index) { - return item.type === "RESULT" ? `${item.sourceId}-${index || "$"}` : `${item.sourceId}-${item.line}-${item.column}-${index || "$"}`; -} - -function sanitizeQuery(query) { - // no '\' at end of query - return query.replace(/\\$/, ""); -} - -class ProjectSearch extends _react.Component { - constructor(props) { - super(props); - - this.toggleProjectTextSearch = (key, e) => { - const { closeProjectSearch, setActiveSearch } = this.props; - if (e) { - e.preventDefault(); - } - - if (this.isProjectSearchEnabled()) { - return closeProjectSearch(); - } - - return setActiveSearch("project"); - }; - - this.isProjectSearchEnabled = () => this.props.activeSearch === "project"; - - this.selectMatchItem = matchItem => { - this.props.selectLocation(_extends({}, matchItem)); - this.props.doSearchForHighlight(this.state.inputValue, (0, _editor.getEditor)(), matchItem.line, matchItem.column); - }; - - this.getResults = () => { - const { results } = this.props; - return results.toJS().map(result => _extends({ - type: "RESULT" - }, result, { - matches: result.matches.map(m => _extends({ type: "MATCH" }, m)) - })).filter(result => result.filepath && result.matches.length > 0); - }; - - this.getResultCount = () => this.getResults().reduce((count, file) => count + file.matches.length, 0); - - this.onKeyDown = e => { - if (e.key === "Escape") { - return; - } - - e.stopPropagation(); - - if (e.key !== "Enter") { - return; - } - this.focusedItem = null; - const query = sanitizeQuery(this.state.inputValue); - if (query) { - this.props.searchSources(query); - } - }; - - this.onEnterPress = () => { - if (this.focusedItem && !this.state.inputFocused) { - const { setExpanded, file, expanded, match } = this.focusedItem; - if (setExpanded) { - setExpanded(file, !expanded); - } else if (match) { - this.selectMatchItem(match); - } - } - }; - - this.inputOnChange = e => { - const inputValue = e.target.value; - const { clearSearch } = this.props; - this.setState({ inputValue }); - if (inputValue === "") { - clearSearch(); - } - }; - - this.renderFile = (file, focused, expanded, setExpanded) => { - if (focused) { - this.focusedItem = { setExpanded, file, expanded }; - } - - const matchesLength = file.matches.length; - const matches = ` (${matchesLength} match${matchesLength > 1 ? "es" : ""})`; - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("file-result", { focused }), - key: file.sourceId, - onClick: e => setExpanded(file, !expanded) - }, - _react2.default.createElement(_Svg2.default, { name: "arrow", className: (0, _classnames2.default)({ expanded }) }), - _react2.default.createElement("img", { className: "file" }), - _react2.default.createElement( - "span", - { className: "file-path" }, - (0, _sourcesTree.getRelativePath)(file.filepath) - ), - _react2.default.createElement( - "span", - { className: "matches-summary" }, - matches - ) - ); - }; - - this.renderMatch = (match, focused) => { - if (focused) { - this.focusedItem = { match }; - } - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)("result", { focused }), - onClick: () => setTimeout(() => this.selectMatchItem(match), 50) - }, - _react2.default.createElement( - "span", - { className: "line-number", key: match.line }, - match.line - ), - (0, _projectSearch.highlightMatches)(match) - ); - }; - - this.renderItem = (item, depth, focused, _, expanded, { setExpanded }) => { - if (item.type === "RESULT") { - return this.renderFile(item, focused, expanded, setExpanded); - } - return this.renderMatch(item, focused); - }; - - this.renderResults = () => { - const results = this.getResults(); - const { status } = this.props; - if (!this.props.query) { - return; - } - if (results.length && status === _projectTextSearch.statusType.done) { - return _react2.default.createElement(_ManagedTree2.default, { - getRoots: () => results, - getChildren: file => file.matches || [], - itemHeight: 24, - autoExpandAll: true, - autoExpandDepth: 1, - getParent: item => null, - getPath: getFilePath, - renderItem: this.renderItem - }); - } - const msg = status === _projectTextSearch.statusType.fetching ? L10N.getStr("loadingText") : L10N.getStr("projectTextSearch.noResults"); - return _react2.default.createElement( - "div", - { className: "no-result-msg absolute-center" }, - msg - ); - }; - - this.renderSummary = () => { - return this.props.query !== "" ? L10N.getFormatStr("sourceSearch.resultsSummary1", this.getResultCount()) : ""; - }; - - this.state = { - inputValue: this.props.query || "", - inputFocused: false - }; - } - - componentDidMount() { - const { shortcuts } = this.context; - - shortcuts.on(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch); - shortcuts.on("Enter", this.onEnterPress); - } - - componentWillUnmount() { - const { shortcuts } = this.context; - shortcuts.off(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch); - shortcuts.off("Enter", this.onEnterPress); - } - - shouldShowErrorEmoji() { - return !this.getResultCount() && this.props.status === _projectTextSearch.statusType.done; - } - - renderInput() { - return _react2.default.createElement(_SearchInput2.default, { - query: this.state.inputValue, - count: this.getResultCount(), - placeholder: L10N.getStr("projectTextSearch.placeholder"), - size: "big", - showErrorEmoji: this.shouldShowErrorEmoji(), - summaryMsg: this.renderSummary(), - onChange: this.inputOnChange, - onFocus: () => this.setState({ inputFocused: true }), - onBlur: () => this.setState({ inputFocused: false }), - onKeyDown: this.onKeyDown, - handleClose: this.props.closeProjectSearch, - ref: "searchInput" - }); - } - - render() { - if (!this.isProjectSearchEnabled()) { - return null; - } - - return _react2.default.createElement( - "div", - { className: "search-container" }, - _react2.default.createElement( - "div", - { className: "project-text-search" }, - _react2.default.createElement( - "div", - { className: "header" }, - this.renderInput() - ), - this.renderResults() - ) - ); - } -} -exports.ProjectSearch = ProjectSearch; -ProjectSearch.contextTypes = { - shortcuts: _propTypes2.default.object -}; - -const mapStateToProps = state => ({ - sources: (0, _selectors.getSources)(state), - activeSearch: (0, _selectors.getActiveSearch)(state), - results: (0, _selectors.getTextSearchResults)(state), - query: (0, _selectors.getTextSearchQuery)(state), - status: (0, _selectors.getTextSearchStatus)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ProjectSearch); - -/***/ }), - -/***/ 2010: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.highlightMatches = highlightMatches; - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function highlightMatches(lineMatch) { - const { value, column, match } = lineMatch; - const len = match.length; - - return _react2.default.createElement( - "span", - { className: "line-value" }, - _react2.default.createElement( - "span", - { className: "line-match", key: 0 }, - value.slice(0, column) - ), - _react2.default.createElement( - "span", - { className: "query-match", key: 1 }, - value.substr(column, len) - ), - _react2.default.createElement( - "span", - { className: "line-match", key: 2 }, - value.slice(column + len, value.length) - ) - ); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Maybe reuse file search's functions? - -/***/ }), - -/***/ 2011: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 2018: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _devtoolsContextmenu = __webpack_require__(1413); - -var _Close = __webpack_require__(1374); - -var _Close2 = _interopRequireDefault(_Close); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _source = __webpack_require__(1356); - -var _clipboard = __webpack_require__(1388); - -var _tabs = __webpack_require__(1941); - -var _selectors = __webpack_require__(3590); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class Tab extends _react.PureComponent { - constructor(...args) { - var _temp; - - return _temp = super(...args), this.onTabContextMenu = (event, tab) => { - event.preventDefault(); - this.showContextMenu(event, tab); - }, _temp; - } - - showContextMenu(e, tab) { - const { - closeTab, - closeTabs, - tabSources, - showSource, - togglePrettyPrint, - selectedSource - } = this.props; - - const otherTabs = tabSources.filter(t => t.get("id") !== tab); - const sourceTab = tabSources.find(t => t.get("id") == tab); - const tabURLs = tabSources.map(t => t.get("url")); - const otherTabURLs = otherTabs.map(t => t.get("url")); - - if (!sourceTab) { - return; - } - - const isPrettySource = (0, _source.isPretty)(sourceTab); - const tabMenuItems = (0, _tabs.getTabMenuItems)(); - const items = [{ - item: _extends({}, tabMenuItems.closeTab, { - click: () => closeTab(sourceTab.get("url")) - }) - }, { - item: _extends({}, tabMenuItems.closeOtherTabs, { - click: () => closeTabs(otherTabURLs) - }), - hidden: () => tabSources.size === 1 - }, { - item: _extends({}, tabMenuItems.closeTabsToEnd, { - click: () => { - const tabIndex = tabSources.findIndex(t => t.get("id") == tab); - closeTabs(tabURLs.filter((t, i) => i > tabIndex)); - } - }), - hidden: () => tabSources.size === 1 || tabSources.some((t, i) => t === tab && tabSources.size - 1 === i) - }, { - item: _extends({}, tabMenuItems.closeAllTabs, { click: () => closeTabs(tabURLs) }) - }, { item: { type: "separator" } }, { - item: _extends({}, tabMenuItems.copyToClipboard, { - disabled: selectedSource.get("id") !== tab, - click: () => (0, _clipboard.copyToTheClipboard)(sourceTab.text) - }) - }, { - item: _extends({}, tabMenuItems.copySourceUri2, { - click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(sourceTab.get("url"))) - }) - }]; - - items.push({ - item: _extends({}, tabMenuItems.showSource, { click: () => showSource(tab) }) - }); - - if (!isPrettySource) { - items.push({ - item: _extends({}, tabMenuItems.prettyPrint, { - click: () => togglePrettyPrint(tab) - }) - }); - } - - (0, _devtoolsContextmenu.showMenu)(e, (0, _devtoolsContextmenu.buildMenu)(items)); - } - - isProjectSearchEnabled() { - return this.props.activeSearch === "project"; - } - - isSourceSearchEnabled() { - return this.props.activeSearch === "source"; - } - - render() { - const { - selectedSource, - selectSpecificSource, - closeTab, - source, - sourceMetaData - } = this.props; - const src = source.toJS(); - const filename = (0, _source.getFilename)(src); - const sourceId = source.id; - const active = selectedSource && sourceId == selectedSource.get("id") && !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled(); - const isPrettyCode = (0, _source.isPretty)(source); - const sourceAnnotation = (0, _tabs.getSourceAnnotation)(source, sourceMetaData); - - function onClickClose(e) { - e.stopPropagation(); - closeTab(source.url); - } - - function handleTabClick(e) { - e.preventDefault(); - e.stopPropagation(); - - // Accommodate middle click to close tab - if (e.button === 1) { - return closeTab(source.url); - } - - return selectSpecificSource(sourceId); - } - - const className = (0, _classnames2.default)("source-tab", { - active, - pretty: isPrettyCode - }); - - return _react2.default.createElement( - "div", - { - className: className, - key: sourceId, - onMouseUp: handleTabClick, - onContextMenu: e => this.onTabContextMenu(e, sourceId), - title: (0, _source.getFileURL)(src) - }, - sourceAnnotation, - _react2.default.createElement( - "div", - { className: "filename" }, - filename - ), - _react2.default.createElement(_Close2.default, { - handleClick: onClickClose, - tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip") - }) - ); - } -} - -const mapStateToProps = (state, { source }) => { - const selectedSource = (0, _selectors.getSelectedSource)(state); - - return { - tabSources: (0, _selectors.getSourcesForTabs)(state), - selectedSource: selectedSource, - sourceMetaData: (0, _selectors.getSourceMetaData)(state, source.id), - activeSearch: (0, _selectors.getActiveSearch)(state) - }; -}; - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tab); - -/***/ }), - -/***/ 22: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_22__; - -/***/ }), - -/***/ 2244: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getTokenLocation = getTokenLocation; -function getTokenLocation(codeMirror, tokenEl) { - const { left, top, width, height } = tokenEl.getBoundingClientRect(); - const { line, ch } = codeMirror.coordsChar({ - left: left + width / 2, - top: top + height / 2 - }); - - return { - line: line + 1, - column: ch - }; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 2245: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.updateTree = updateTree; - -var _addToTree = __webpack_require__(1443); - -var _collapseTree = __webpack_require__(1444); - -var _utils = __webpack_require__(1371); - -function newSourcesSet(newSources, prevSources) { - const next = newSources.toSet(); - const prev = prevSources.toSet(); - return next.subtract(prev); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function updateTree({ - newSources, - prevSources, - debuggeeUrl, - projectRoot, - uncollapsedTree, - sourceTree -}) { - const newSet = newSourcesSet(newSources, prevSources); - - for (const source of newSet) { - (0, _addToTree.addToTree)(uncollapsedTree, source, debuggeeUrl, projectRoot); - } - - const newSourceTree = (0, _collapseTree.collapseTree)(uncollapsedTree); - - return { - uncollapsedTree, - sourceTree: newSourceTree, - parentMap: (0, _utils.createParentMap)(sourceTree), - focusedItem: null - }; -} - -/***/ }), - -/***/ 2246: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.setupHelper = setupHelper; - -var _timings = __webpack_require__(1657); - -var timings = _interopRequireWildcard(_timings); - -var _prefs = __webpack_require__(226); - -var _devtoolsEnvironment = __webpack_require__(3721); - -var _pausePoints = __webpack_require__(3622); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function findSource(dbg, url) { - const sources = dbg.selectors.getSources(); - const source = sources.find(s => (s.get("url") || "").includes(url)); - - if (!source) { - return; - } - - return source.toJS(); -} - -function sendPacket(dbg, packet, callback) { - dbg.client.sendPacket(packet, callback || console.log); -} - -function sendPacketToThread(dbg, packet, callback) { - sendPacket(dbg, _extends({ to: dbg.connection.tabConnection.threadClient.actor }, packet), callback); -} - -function evaluate(dbg, expression, callback) { - dbg.client.evaluate(expression).then(callback || console.log); -} - -function bindSelectors(obj) { - return Object.keys(obj.selectors).reduce((bound, selector) => { - bound[selector] = (a, b, c) => obj.selectors[selector](obj.store.getState(), a, b, c); - return bound; - }, {}); -} - -function getCM() { - const cm = document.querySelector(".CodeMirror"); - return cm && cm.CodeMirror; -} - -function _formatPausePoints(dbg, url) { - const source = dbg.helpers.findSource(url); - const pausePoints = dbg.selectors.getPausePoints(source); - console.log((0, _pausePoints.formatPausePoints)(source.text, pausePoints)); -} - -function setupHelper(obj) { - const selectors = bindSelectors(obj); - const dbg = _extends({}, obj, { - selectors, - prefs: _prefs.prefs, - features: _prefs.features, - timings, - getCM, - helpers: { - findSource: url => findSource(dbg, url), - evaluate: (expression, cbk) => evaluate(dbg, expression, cbk), - sendPacketToThread: (packet, cbk) => sendPacketToThread(dbg, packet, cbk), - sendPacket: (packet, cbk) => sendPacket(dbg, packet, cbk) - }, - formatters: { - pausePoints: url => _formatPausePoints(dbg, url) - } - }); - - window.dbg = dbg; - - if ((0, _devtoolsEnvironment.isDevelopment)()) { - console.group("Development Notes"); - const baseUrl = "https://devtools-html.github.io/debugger.html"; - const localDevelopmentUrl = `${baseUrl}/docs/dbg.html`; - console.log("Debugging Tips", localDevelopmentUrl); - console.log("dbg", window.dbg); - console.groupEnd(); - } -} - -/***/ }), - -/***/ 2250: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 2251: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 2252: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 2253: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 226: -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// @flow - -const { isDevelopment } = __webpack_require__(3721); -const { Services, PrefsHelper } = __webpack_require__(1376); - -const prefsSchemaVersion = "1.0.3"; - -const pref = Services.pref; - -if (isDevelopment()) { - pref("devtools.debugger.alphabetize-outline", false); - pref("devtools.debugger.auto-pretty-print", false); - pref("devtools.source-map.client-service.enabled", true); - pref("devtools.debugger.pause-on-exceptions", false); - pref("devtools.debugger.pause-on-caught-exceptions", false); - pref("devtools.debugger.ignore-caught-exceptions", true); - pref("devtools.debugger.call-stack-visible", true); - pref("devtools.debugger.scopes-visible", true); - pref("devtools.debugger.component-visible", true); - pref("devtools.debugger.component-stack-visible", false); - pref("devtools.debugger.workers-visible", true); - pref("devtools.debugger.expressions-visible", true); - pref("devtools.debugger.breakpoints-visible", true); - pref("devtools.debugger.start-panel-collapsed", false); - pref("devtools.debugger.end-panel-collapsed", false); - pref("devtools.debugger.tabs", "[]"); - pref("devtools.debugger.tabsBlackBoxed", "[]"); - pref("devtools.debugger.ui.framework-grouping-on", true); - pref("devtools.debugger.pending-selected-location", "{}"); - pref("devtools.debugger.pending-breakpoints", "{}"); - pref("devtools.debugger.expressions", "[]"); - pref("devtools.debugger.file-search-case-sensitive", false); - pref("devtools.debugger.file-search-whole-word", false); - pref("devtools.debugger.file-search-regex-match", false); - pref("devtools.debugger.project-directory-root", ""); - pref("devtools.debugger.prefs-schema-version", "1.0.1"); - pref("devtools.debugger.skip-pausing", false); - pref("devtools.debugger.features.workers", true); - pref("devtools.debugger.features.async-stepping", true); - pref("devtools.debugger.features.wasm", true); - pref("devtools.debugger.features.shortcuts", true); - pref("devtools.debugger.features.root", true); - pref("devtools.debugger.features.column-breakpoints", false); - pref("devtools.debugger.features.map-scopes", true); - pref("devtools.debugger.features.remove-command-bar-options", true); - pref("devtools.debugger.features.code-coverage", false); - pref("devtools.debugger.features.event-listeners", false); - pref("devtools.debugger.features.code-folding", false); - pref("devtools.debugger.features.outline", true); - pref("devtools.debugger.features.column-breakpoints", true); - pref("devtools.debugger.features.replay", true); - pref("devtools.debugger.features.pause-points", true); - pref("devtools.debugger.features.component-stack", true); - pref("devtools.debugger.features.skip-pausing", false); -} - -const prefs = new PrefsHelper("devtools", { - alphabetizeOutline: ["Bool", "debugger.alphabetize-outline"], - autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"], - clientSourceMapsEnabled: ["Bool", "source-map.client-service.enabled"], - pauseOnExceptions: ["Bool", "debugger.pause-on-exceptions"], - pauseOnCaughtExceptions: ["Bool", "debugger.pause-on-caught-exceptions"], - ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"], - callStackVisible: ["Bool", "debugger.call-stack-visible"], - scopesVisible: ["Bool", "debugger.scopes-visible"], - componentVisible: ["Bool", "debugger.component-visible"], - componentStackVisible: ["Bool", "debugger.component-stack-visible"], - workersVisible: ["Bool", "debugger.workers-visible"], - breakpointsVisible: ["Bool", "debugger.breakpoints-visible"], - expressionsVisible: ["Bool", "debugger.expressions-visible"], - startPanelCollapsed: ["Bool", "debugger.start-panel-collapsed"], - endPanelCollapsed: ["Bool", "debugger.end-panel-collapsed"], - frameworkGroupingOn: ["Bool", "debugger.ui.framework-grouping-on"], - tabs: ["Json", "debugger.tabs", []], - tabsBlackBoxed: ["Json", "debugger.tabsBlackBoxed", []], - pendingSelectedLocation: ["Json", "debugger.pending-selected-location", {}], - pendingBreakpoints: ["Json", "debugger.pending-breakpoints", {}], - expressions: ["Json", "debugger.expressions", []], - fileSearchCaseSensitive: ["Bool", "debugger.file-search-case-sensitive"], - fileSearchWholeWord: ["Bool", "debugger.file-search-whole-word"], - fileSearchRegexMatch: ["Bool", "debugger.file-search-regex-match"], - debuggerPrefsSchemaVersion: ["Char", "debugger.prefs-schema-version"], - projectDirectoryRoot: ["Char", "debugger.project-directory-root", ""], - skipPausing: ["Bool", "debugger.skip-pausing"] -}); -/* harmony export (immutable) */ __webpack_exports__["prefs"] = prefs; - - -const features = new PrefsHelper("devtools.debugger.features", { - asyncStepping: ["Bool", "async-stepping"], - wasm: ["Bool", "wasm"], - shortcuts: ["Bool", "shortcuts"], - root: ["Bool", "root"], - columnBreakpoints: ["Bool", "column-breakpoints"], - mapScopes: ["Bool", "map-scopes"], - removeCommandBarOptions: ["Bool", "remove-command-bar-options"], - workers: ["Bool", "workers"], - codeCoverage: ["Bool", "code-coverage"], - eventListeners: ["Bool", "event-listeners"], - outline: ["Bool", "outline"], - codeFolding: ["Bool", "code-folding"], - replay: ["Bool", "replay"], - pausePoints: ["Bool", "pause-points"], - componentStack: ["Bool", "component-stack"], - skipPausing: ["Bool", "skip-pausing"] -}); -/* harmony export (immutable) */ __webpack_exports__["features"] = features; - - -if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) { - // clear pending Breakpoints - prefs.pendingBreakpoints = {}; - prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion; -} - - -/***/ }), - -/***/ 2342: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.initialState = initialState; -exports.getHistory = getHistory; -exports.getHistoryFrame = getHistoryFrame; -exports.getHistoryPosition = getHistoryPosition; - -var _prefs = __webpack_require__(226); - -/** - * Breakpoints reducer - * @module reducers/replay - */ -function initialState() { - return { - history: [], - position: -1 - }; -} - -const defaultFrameScopes = { - original: {}, - generated: {} -}; - -function update(state = initialState(), action) { - if (!_prefs.features.replay) { - return state; - } - - switch (action.type) { - case "TRAVEL_TO": - { - return _extends({}, state, { position: action.position }); - } - - case "ADD_SCOPES": - { - return addScopes(state, action); - } - - case "MAP_SCOPES": - { - return mapScopes(state, action); - } - - case "CLEAR_HISTORY": - { - return { history: [], position: -1 }; - } - - case "PAUSED": - { - return paused(state, action); - } - - case "EVALUATE_EXPRESSION": - { - return evaluateExpression(state, action); - } - } - - return state; -} - -function addScopes(state, action) { - const { frame, status, value } = action; - const selectedFrameId = frame.id; - const instance = state.history[state.position]; - - if (!instance) { - return state; - } - - const pausedInst = instance.paused; - - const generated = _extends({}, pausedInst.frameScopes.generated, { - [selectedFrameId]: { - pending: status !== "done", - scope: value - } - }); - - const newPaused = _extends({}, pausedInst, { - frameScopes: _extends({}, pausedInst.frameScopes, { - generated - }) - }); - - const history = [...state.history]; - history[state.position] = _extends({}, instance, { paused: newPaused }); - return _extends({}, state, { history }); -} - -function mapScopes(state, action) { - const { frame, status, value } = action; - const selectedFrameId = frame.id; - const instance = state.history[state.position]; - - if (!instance) { - return state; - } - - const pausedInst = instance.paused; - - const original = _extends({}, pausedInst.frameScopes.original, { - [selectedFrameId]: { - pending: status !== "done", - scope: value - } - }); - - const newPaused = _extends({}, pausedInst, { - frameScopes: _extends({}, pausedInst.frameScopes, { - original - }) - }); - - const history = [...state.history]; - history[state.position] = _extends({}, instance, { paused: newPaused }); - return _extends({}, state, { history }); -} - -function evaluateExpression(state, action) { - const { input, value } = action; - const instance = state.history[state.position]; - if (!instance) { - return state; - } - - const prevExpressions = instance.expressions || []; - const expression = { input, value }; - const expressions = [...prevExpressions, expression]; - - const history = [...state.history]; - history[state.position] = _extends({}, instance, { expressions }); - return _extends({}, state, { history }); -} - -function paused(state, action) { - const { selectedFrameId, frames, loadedObjects, why } = action; - - // turn this into an object keyed by object id - const objectMap = {}; - loadedObjects.forEach(obj => { - objectMap[obj.value.objectId] = obj; - }); - - const pausedInfo = { - isWaitingOnBreak: false, - selectedFrameId, - frames, - frameScopes: defaultFrameScopes, - loadedObjects: objectMap, - why - }; - - const history = [...state.history, { paused: pausedInfo }]; - const position = state.position + 1; - return _extends({}, state, { history, position }); -} - -function getHistory(state) { - return state.replay.history; -} - -function getHistoryFrame(state, position) { - return state.replay.history[position]; -} - -function getHistoryPosition(state) { - return state.replay.position; -} - -exports.default = update; - -/***/ }), - -/***/ 2343: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.timeTravelTo = timeTravelTo; -exports.clearHistory = clearHistory; - -var _selectors = __webpack_require__(3590); - -var _sources = __webpack_require__(1797); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * Redux actions for replay - * @module actions/replay - */ - -function timeTravelTo(position) { - return ({ dispatch, getState }) => { - const data = (0, _selectors.getHistoryFrame)(getState(), position); - dispatch({ - type: "TRAVEL_TO", - data, - position - }); - dispatch((0, _sources.selectLocation)(data.paused.frames[0].location)); - }; -} - -function clearHistory() { - return ({ dispatch, getState }) => { - dispatch({ - type: "CLEAR_HISTORY" - }); - }; -} - -/***/ }), - -/***/ 2349: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.locColumn = locColumn; -function locColumn(loc) { - if (typeof loc.column !== "number") { - // This shouldn't really happen with locations from the AST, but - // the datatype we are using allows null/undefined column. - return 0; - } - - return loc.column; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 2358: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.findGeneratedBindingForStandardBinding = findGeneratedBindingForStandardBinding; -exports.findGeneratedBindingForImportBinding = findGeneratedBindingForImportBinding; -exports.findGeneratedBindingForNormalDeclaration = findGeneratedBindingForNormalDeclaration; -exports.findGeneratedBindingForImportDeclaration = findGeneratedBindingForImportDeclaration; - -var _locColumn = __webpack_require__(2349); - -var _mappingContains = __webpack_require__(3722); - -var _getGeneratedLocationRanges = __webpack_require__(3724); - -var _firefox = __webpack_require__(1500); - -/** - * Find a simple 1-1 match of a binding in the original code to a binding - * in the generated code. - */ -async function findGeneratedBindingForStandardBinding(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { - return await findGeneratedReference((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos, bindingType, pos.type, sourceMaps))); -} - -/** - * Find a simple 1-1 match of a binding in the original code to an - * expression in the generated code. - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -async function findGeneratedBindingForImportBinding(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { - return await findGeneratedImportReference((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos, bindingType, pos.type, sourceMaps))); -} - -/** - * Find a simple 1-1 match of a binding's declaration in the original code to a - * binding in the generated code. - */ -async function findGeneratedBindingForNormalDeclaration(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { - return await findGeneratedReference((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos.declaration, bindingType, pos.type, sourceMaps))); -} - -/** - * Find a simple 1-1 match of an import binding's declaration in the original - * code to an expression in the generated code. - */ -async function findGeneratedBindingForImportDeclaration(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { - const importName = pos.importName; - if (typeof importName !== "string") { - // Should never happen, just keeping Flow happy. - return null; - } - - return await findGeneratedImportDeclaration((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos.declaration, bindingType, pos.type, sourceMaps)), importName); -} - -/** - * Given a mapped range over the generated source, attempt to resolve a real - * binding descriptor that can be used to access the value. - */ -async function findGeneratedReference(applicableBindings) { - // We can adjust this number as we go, but these are a decent start as a - // general heuristic to assume the bindings were bad or just map a chunk of - // whole line or something. - if (applicableBindings.length > 4) { - // Babel's for..of generates at least 3 bindings inside one range for - // block-scoped loop variables, so we shouldn't go below that. - applicableBindings = []; - } - - for (const applicable of applicableBindings) { - const result = await mapBindingReferenceToDescriptor(applicable); - if (result) { - return result; - } - } - return null; -} - -async function findGeneratedImportReference(applicableBindings) { - // When wrapped, for instance as `Object(ns.default)`, the `Object` binding - // will be the first in the list. To avoid resolving `Object` as the - // value of the import itself, we potentially skip the first binding. - applicableBindings = applicableBindings.filter((applicable, i) => { - if (!applicable.firstInRange || applicable.binding.loc.type !== "ref" || applicable.binding.loc.meta) { - return true; - } - - const next = i + 1 < applicableBindings.length ? applicableBindings[i + 1] : null; - - return !next || next.binding.loc.type !== "ref" || !next.binding.loc.meta; - }); - - // We can adjust this number as we go, but these are a decent start as a - // general heuristic to assume the bindings were bad or just map a chunk of - // whole line or something. - if (applicableBindings.length > 2) { - // Babel's for..of generates at least 3 bindings inside one range for - // block-scoped loop variables, so we shouldn't go below that. - applicableBindings = []; - } - - for (const applicable of applicableBindings) { - const result = await mapImportReferenceToDescriptor(applicable); - if (result) { - return result; - } - } - - return null; -} - -/** - * Given a mapped range over the generated source and the name of the imported - * value that is referenced, attempt to resolve a binding descriptor for - * the import's value. - */ -async function findGeneratedImportDeclaration(applicableBindings, importName) { - // We can adjust this number as we go, but these are a decent start as a - // general heuristic to assume the bindings were bad or just map a chunk of - // whole line or something. - if (applicableBindings.length > 10) { - // Import declarations tend to have a large number of bindings for - // for things like 'require' and 'interop', so this number is larger - // than other binding count checks. - applicableBindings = []; - } - - let result = null; - - for (const _ref of applicableBindings) { - const { binding } = _ref; - - if (binding.loc.type === "ref") { - continue; - } - - const namespaceDesc = await binding.desc(); - if (isPrimitiveValue(namespaceDesc)) { - continue; - } - if (!isObjectValue(namespaceDesc)) { - // We want to handle cases like - // - // var _mod = require(...); - // var _mod2 = _interopRequire(_mod); - // - // where "_mod" is optimized out because it is only referenced once. To - // allow that, we track the optimized-out value as a possible result, - // but allow later binding values to overwrite the result. - result = { - name: binding.name, - desc: namespaceDesc, - expression: binding.name - }; - continue; - } - - const desc = await readDescriptorProperty(namespaceDesc, importName); - const expression = `${binding.name}.${importName}`; - - if (desc) { - result = { - name: binding.name, - desc, - expression - }; - break; - } - } - - return result; -} - -/** - * Given a generated binding, and a range over the generated code, statically - * check if the given binding matches the range. - */ -async function mapBindingReferenceToDescriptor({ - binding, - range, - firstInRange, - firstOnLine -}) { - // Allow the mapping to point anywhere within the generated binding - // location to allow for less than perfect sourcemaps. Since you also - // need at least one character between identifiers, we also give one - // characters of space at the front the generated binding in order - // to increase the probability of finding the right mapping. - if (range.start.line === binding.loc.start.line && ( - // If a binding is the first on a line, Babel will extend the mapping to - // include the whitespace between the newline and the binding. To handle - // that, we skip the range requirement for starting location. - firstInRange || firstOnLine || (0, _locColumn.locColumn)(range.start) >= (0, _locColumn.locColumn)(binding.loc.start)) && (0, _locColumn.locColumn)(range.start) <= (0, _locColumn.locColumn)(binding.loc.end)) { - return { - name: binding.name, - desc: await binding.desc(), - expression: binding.name - }; - } - - return null; -} - -/** - * Given an generated binding, and a range over the generated code, statically - * evaluate accessed properties within the mapped range to resolve the actual - * imported value. - */ -async function mapImportReferenceToDescriptor({ - binding, - range -}) { - if (binding.loc.type !== "ref") { - return null; - } - - // Expression matches require broader searching because sourcemaps usage - // varies in how they map certain things. For instance given - // - // import { bar } from "mod"; - // bar(); - // - // The "bar()" expression is generally expanded into one of two possibly - // forms, both of which map the "bar" identifier in different ways. See - // the "^^" markers below for the ranges. - // - // (0, foo.bar)() // Babel - // ^^^^^^^ // mapping - // ^^^ // binding - // vs - // - // Object(foo.bar)() // Webpack - // ^^^^^^^^^^^^^^^ // mapping - // ^^^ // binding - // - // Unfortunately, Webpack also has a tendancy to over-map past the call - // expression to the start of the next line, at least when there isn't - // anything else on that line that is mapped, e.g. - // - // Object(foo.bar)() - // ^^^^^^^^^^^^^^^^^ - // ^ // wrapped to column 0 of next line - - if (!(0, _mappingContains.mappingContains)(range, binding.loc)) { - return null; - } - - let expression = binding.name; - let desc = await binding.desc(); - - if (binding.loc.type === "ref") { - const { meta } = binding.loc; - - // Limit to 2 simple property or inherits operartions, since it would - // just be more work to search more and it is very unlikely that - // bindings would be mapped to more than a single member + inherits - // wrapper. - for (let op = meta, index = 0; op && (0, _mappingContains.mappingContains)(range, op) && desc && index < 2; index++, op = op && op.parent) { - // Calling could potentially trigger side-effects, which would not - // be ideal for this case. - if (op.type === "call") { - return null; - } - - if (op.type === "inherit") { - continue; - } - - desc = await readDescriptorProperty(desc, op.property); - expression += `.${op.property}`; - } - } - - return desc ? { - name: binding.name, - desc, - expression - } : null; -} - -function isPrimitiveValue(desc) { - return desc && (!desc.value || typeof desc.value !== "object"); -} -function isObjectValue(desc) { - return desc && !isPrimitiveValue(desc) && desc.value.type === "object" && - // Note: The check for `.type` might already cover the optimizedOut case - // but not 100% sure, so just being cautious. - !desc.value.optimizedOut; -} - -async function readDescriptorProperty(desc, property) { - if (!desc) { - return null; - } - - if (typeof desc.value !== "object" || !desc.value) { - // If accessing a property on a primitive type, just return 'undefined' - // as the value. - return { - value: { - type: "undefined" - } - }; - } - - if (!isObjectValue(desc)) { - // If we got a non-primitive descriptor but it isn't an object, then - // it's definitely not the namespace and it is probably an error. - return desc; - } - - const objectClient = (0, _firefox.createObjectClient)(desc.value); - return (await objectClient.getProperty(property)).descriptor; -} - -/***/ }), - -/***/ 2359: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.log = log; - -var _devtoolsEnvironment = __webpack_require__(3721); - -/** - * Produces a formatted console log line by imploding args, prefixed by [log] - * - * function input: log(["hello", "world"]) - * console output: [log] hello world - * - * @memberof utils/log - * @static - */ -function log(...args) { - if (!(0, _devtoolsEnvironment.isDevelopment)()) { - return; - } - - console.log.apply(console, ["[log]", ...args]); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * - * Utils for logging to the console - * Suppresses logging in non-development environment - * - * @module utils/log - */ - -/***/ }), - -/***/ 2360: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.tokenAtTextPosition = tokenAtTextPosition; -exports.getExpressionFromCoords = getExpressionFromCoords; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function tokenAtTextPosition(cm, { line, column }) { - if (line < 0 || line >= cm.lineCount()) { - return null; - } - - const token = cm.getTokenAt({ line: line - 1, ch: column }); - if (!token) { - return null; - } - - return { startColumn: token.start, endColumn: token.end, type: token.type }; -} - -// The strategy of querying codeMirror tokens was borrowed -// from Chrome's inital implementation in JavaScriptSourceFrame.js#L414 -function getExpressionFromCoords(cm, coord) { - const token = tokenAtTextPosition(cm, coord); - if (!token) { - return null; - } - - let startHighlight = token.startColumn; - const endHighlight = token.endColumn; - const lineNumber = coord.line; - const line = cm.doc.getLine(coord.line - 1); - while (startHighlight > 1 && line.charAt(startHighlight - 1) === ".") { - const tokenBefore = tokenAtTextPosition(cm, { - line: coord.line, - column: startHighlight - 2 - }); - - if (!tokenBefore || !tokenBefore.type) { - return null; - } - - startHighlight = tokenBefore.startColumn; - } - - const expression = line.substring(startHighlight, endHighlight) || ""; - - if (!expression) { - return null; - } - - const location = { - start: { line: lineNumber, column: startHighlight }, - end: { line: lineNumber, column: endHighlight } - }; - return { expression, location }; -} - -/***/ }), - -/***/ 2419: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _why = __webpack_require__(2420); - -Object.keys(_why).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _why[key]; - } - }); -}); - -var _stepping = __webpack_require__(2421); - -Object.keys(_stepping).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _stepping[key]; - } - }); -}); - -/***/ }), - -/***/ 2420: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getPauseReason = getPauseReason; -exports.isException = isException; -exports.isInterrupted = isInterrupted; -exports.inDebuggerEval = inDebuggerEval; - - -// Map protocol pause "why" reason to a valid L10N key -// These are the known unhandled reasons: -// "breakpointConditionThrown", "clientEvaluated" -// "interrupted", "attached" -const reasons = { - debuggerStatement: "whyPaused.debuggerStatement", - breakpoint: "whyPaused.breakpoint", - exception: "whyPaused.exception", - resumeLimit: "whyPaused.resumeLimit", - pauseOnDOMEvents: "whyPaused.pauseOnDOMEvents", - breakpointConditionThrown: "whyPaused.breakpointConditionThrown", - - // V8 - DOM: "whyPaused.breakpoint", - EventListener: "whyPaused.pauseOnDOMEvents", - XHR: "whyPaused.xhr", - promiseRejection: "whyPaused.promiseRejection", - assert: "whyPaused.assert", - debugCommand: "whyPaused.debugCommand", - other: "whyPaused.other" -}; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getPauseReason(why) { - if (!why) { - return null; - } - - const reasonType = why.type; - if (!reasons[reasonType]) { - console.log("Please file an issue: reasonType=", reasonType); - } - return reasons[reasonType]; -} - -function isException(why) { - return why && why.type && why.type === "exception"; -} - -function isInterrupted(why) { - return why && why.type && why.type === "interrupted"; -} - -function inDebuggerEval(why) { - if (why && why.type === "exception" && why.exception && why.exception.preview && why.exception.preview.fileName) { - return why.exception.preview.fileName === "debugger eval code"; - } - - return false; -} - -/***/ }), - -/***/ 2421: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.shouldStep = shouldStep; - -var _lodash = __webpack_require__(2); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _selectors = __webpack_require__(3590); - -function getFrameLocation(source, frame) { - if (!frame) { - return null; - } - - return (0, _devtoolsSourceMap.isOriginalId)(source.id) ? frame.location : frame.generatedLocation; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function shouldStep(rootFrame, state, sourceMaps) { - const selectedSource = (0, _selectors.getSelectedSource)(state); - const previousFrameInfo = (0, _selectors.getPreviousPauseFrameLocation)(state); - - if (!rootFrame || !selectedSource) { - return false; - } - - const previousFrameLoc = getFrameLocation(selectedSource, previousFrameInfo); - const frameLoc = getFrameLocation(selectedSource, rootFrame); - - const sameLocation = previousFrameLoc && (0, _lodash.isEqual)(previousFrameLoc, frameLoc); - const pausePoint = (0, _selectors.getPausePoint)(state, frameLoc); - const invalidPauseLocation = pausePoint && !pausePoint.step; - - // We always want to pause in generated locations - if (!frameLoc || (0, _devtoolsSourceMap.isGeneratedId)(frameLoc.sourceId)) { - return false; - } - - return sameLocation || invalidPauseLocation; -} - -/***/ }), - -/***/ 247: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 248: -/***/ (function(module, exports, __webpack_require__) { - -(function(){ - var crypt = __webpack_require__(249), - utf8 = __webpack_require__(250).utf8, - isBuffer = __webpack_require__(251), - bin = __webpack_require__(250).bin, - - // The core - md5 = function (message, options) { - // Convert to byte array - if (message.constructor == String) - if (options && options.encoding === 'binary') - message = bin.stringToBytes(message); - else - message = utf8.stringToBytes(message); - else if (isBuffer(message)) - message = Array.prototype.slice.call(message, 0); - else if (!Array.isArray(message)) - message = message.toString(); - // else, assume byte array already - - var m = crypt.bytesToWords(message), - l = message.length * 8, - a = 1732584193, - b = -271733879, - c = -1732584194, - d = 271733878; - - // Swap endian - for (var i = 0; i < m.length; i++) { - m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF | - ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00; - } - - // Padding - m[l >>> 5] |= 0x80 << (l % 32); - m[(((l + 64) >>> 9) << 4) + 14] = l; - - // Method shortcuts - var FF = md5._ff, - GG = md5._gg, - HH = md5._hh, - II = md5._ii; - - for (var i = 0; i < m.length; i += 16) { - - var aa = a, - bb = b, - cc = c, - dd = d; - - a = FF(a, b, c, d, m[i+ 0], 7, -680876936); - d = FF(d, a, b, c, m[i+ 1], 12, -389564586); - c = FF(c, d, a, b, m[i+ 2], 17, 606105819); - b = FF(b, c, d, a, m[i+ 3], 22, -1044525330); - a = FF(a, b, c, d, m[i+ 4], 7, -176418897); - d = FF(d, a, b, c, m[i+ 5], 12, 1200080426); - c = FF(c, d, a, b, m[i+ 6], 17, -1473231341); - b = FF(b, c, d, a, m[i+ 7], 22, -45705983); - a = FF(a, b, c, d, m[i+ 8], 7, 1770035416); - d = FF(d, a, b, c, m[i+ 9], 12, -1958414417); - c = FF(c, d, a, b, m[i+10], 17, -42063); - b = FF(b, c, d, a, m[i+11], 22, -1990404162); - a = FF(a, b, c, d, m[i+12], 7, 1804603682); - d = FF(d, a, b, c, m[i+13], 12, -40341101); - c = FF(c, d, a, b, m[i+14], 17, -1502002290); - b = FF(b, c, d, a, m[i+15], 22, 1236535329); - - a = GG(a, b, c, d, m[i+ 1], 5, -165796510); - d = GG(d, a, b, c, m[i+ 6], 9, -1069501632); - c = GG(c, d, a, b, m[i+11], 14, 643717713); - b = GG(b, c, d, a, m[i+ 0], 20, -373897302); - a = GG(a, b, c, d, m[i+ 5], 5, -701558691); - d = GG(d, a, b, c, m[i+10], 9, 38016083); - c = GG(c, d, a, b, m[i+15], 14, -660478335); - b = GG(b, c, d, a, m[i+ 4], 20, -405537848); - a = GG(a, b, c, d, m[i+ 9], 5, 568446438); - d = GG(d, a, b, c, m[i+14], 9, -1019803690); - c = GG(c, d, a, b, m[i+ 3], 14, -187363961); - b = GG(b, c, d, a, m[i+ 8], 20, 1163531501); - a = GG(a, b, c, d, m[i+13], 5, -1444681467); - d = GG(d, a, b, c, m[i+ 2], 9, -51403784); - c = GG(c, d, a, b, m[i+ 7], 14, 1735328473); - b = GG(b, c, d, a, m[i+12], 20, -1926607734); - - a = HH(a, b, c, d, m[i+ 5], 4, -378558); - d = HH(d, a, b, c, m[i+ 8], 11, -2022574463); - c = HH(c, d, a, b, m[i+11], 16, 1839030562); - b = HH(b, c, d, a, m[i+14], 23, -35309556); - a = HH(a, b, c, d, m[i+ 1], 4, -1530992060); - d = HH(d, a, b, c, m[i+ 4], 11, 1272893353); - c = HH(c, d, a, b, m[i+ 7], 16, -155497632); - b = HH(b, c, d, a, m[i+10], 23, -1094730640); - a = HH(a, b, c, d, m[i+13], 4, 681279174); - d = HH(d, a, b, c, m[i+ 0], 11, -358537222); - c = HH(c, d, a, b, m[i+ 3], 16, -722521979); - b = HH(b, c, d, a, m[i+ 6], 23, 76029189); - a = HH(a, b, c, d, m[i+ 9], 4, -640364487); - d = HH(d, a, b, c, m[i+12], 11, -421815835); - c = HH(c, d, a, b, m[i+15], 16, 530742520); - b = HH(b, c, d, a, m[i+ 2], 23, -995338651); - - a = II(a, b, c, d, m[i+ 0], 6, -198630844); - d = II(d, a, b, c, m[i+ 7], 10, 1126891415); - c = II(c, d, a, b, m[i+14], 15, -1416354905); - b = II(b, c, d, a, m[i+ 5], 21, -57434055); - a = II(a, b, c, d, m[i+12], 6, 1700485571); - d = II(d, a, b, c, m[i+ 3], 10, -1894986606); - c = II(c, d, a, b, m[i+10], 15, -1051523); - b = II(b, c, d, a, m[i+ 1], 21, -2054922799); - a = II(a, b, c, d, m[i+ 8], 6, 1873313359); - d = II(d, a, b, c, m[i+15], 10, -30611744); - c = II(c, d, a, b, m[i+ 6], 15, -1560198380); - b = II(b, c, d, a, m[i+13], 21, 1309151649); - a = II(a, b, c, d, m[i+ 4], 6, -145523070); - d = II(d, a, b, c, m[i+11], 10, -1120210379); - c = II(c, d, a, b, m[i+ 2], 15, 718787259); - b = II(b, c, d, a, m[i+ 9], 21, -343485551); - - a = (a + aa) >>> 0; - b = (b + bb) >>> 0; - c = (c + cc) >>> 0; - d = (d + dd) >>> 0; - } - - return crypt.endian([a, b, c, d]); - }; - - // Auxiliary functions - md5._ff = function (a, b, c, d, x, s, t) { - var n = a + (b & c | ~b & d) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - md5._gg = function (a, b, c, d, x, s, t) { - var n = a + (b & d | c & ~d) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - md5._hh = function (a, b, c, d, x, s, t) { - var n = a + (b ^ c ^ d) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - md5._ii = function (a, b, c, d, x, s, t) { - var n = a + (c ^ (b | ~d)) + (x >>> 0) + t; - return ((n << s) | (n >>> (32 - s))) + b; - }; - - // Package private blocksize - md5._blocksize = 16; - md5._digestsize = 16; - - module.exports = function (message, options) { - if (message === undefined || message === null) - throw new Error('Illegal argument ' + message); - - var digestbytes = crypt.wordsToBytes(md5(message, options)); - return options && options.asBytes ? digestbytes : - options && options.asString ? bin.bytesToString(digestbytes) : - crypt.bytesToHex(digestbytes); - }; - -})(); - - -/***/ }), - -/***/ 249: -/***/ (function(module, exports) { - -(function() { - var base64map - = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', - - crypt = { - // Bit-wise rotation left - rotl: function(n, b) { - return (n << b) | (n >>> (32 - b)); - }, - - // Bit-wise rotation right - rotr: function(n, b) { - return (n << (32 - b)) | (n >>> b); - }, - - // Swap big-endian to little-endian and vice versa - endian: function(n) { - // If number given, swap endian - if (n.constructor == Number) { - return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00; - } - - // Else, assume array and swap all items - for (var i = 0; i < n.length; i++) - n[i] = crypt.endian(n[i]); - return n; - }, - - // Generate an array of any length of random bytes - randomBytes: function(n) { - for (var bytes = []; n > 0; n--) - bytes.push(Math.floor(Math.random() * 256)); - return bytes; - }, - - // Convert a byte array to big-endian 32-bit words - bytesToWords: function(bytes) { - for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) - words[b >>> 5] |= bytes[i] << (24 - b % 32); - return words; - }, - - // Convert big-endian 32-bit words to a byte array - wordsToBytes: function(words) { - for (var bytes = [], b = 0; b < words.length * 32; b += 8) - bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); - return bytes; - }, - - // Convert a byte array to a hex string - bytesToHex: function(bytes) { - for (var hex = [], i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(''); - }, - - // Convert a hex string to a byte array - hexToBytes: function(hex) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; - }, - - // Convert a byte array to a base-64 string - bytesToBase64: function(bytes) { - for (var base64 = [], i = 0; i < bytes.length; i += 3) { - var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; - for (var j = 0; j < 4; j++) - if (i * 8 + j * 6 <= bytes.length * 8) - base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); - else - base64.push('='); - } - return base64.join(''); - }, - - // Convert a base-64 string to a byte array - base64ToBytes: function(base64) { - // Remove non-base-64 characters - base64 = base64.replace(/[^A-Z0-9+\/]/ig, ''); - - for (var bytes = [], i = 0, imod4 = 0; i < base64.length; - imod4 = ++i % 4) { - if (imod4 == 0) continue; - bytes.push(((base64map.indexOf(base64.charAt(i - 1)) - & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) - | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); - } - return bytes; - } - }; - - module.exports = crypt; -})(); - - -/***/ }), - -/***/ 250: -/***/ (function(module, exports) { - -var charenc = { - // UTF-8 encoding - utf8: { - // Convert a string to a byte array - stringToBytes: function(str) { - return charenc.bin.stringToBytes(unescape(encodeURIComponent(str))); - }, - - // Convert a byte array to a string - bytesToString: function(bytes) { - return decodeURIComponent(escape(charenc.bin.bytesToString(bytes))); - } - }, - - // Binary encoding - bin: { - // Convert a string to a byte array - stringToBytes: function(str) { - for (var bytes = [], i = 0; i < str.length; i++) - bytes.push(str.charCodeAt(i) & 0xFF); - return bytes; - }, - - // Convert a byte array to a string - bytesToString: function(bytes) { - for (var str = [], i = 0; i < bytes.length; i++) - str.push(String.fromCharCode(bytes[i])); - return str.join(''); - } - } -}; - -module.exports = charenc; - - -/***/ }), - -/***/ 251: -/***/ (function(module, exports) { - -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} - -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} - -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} - - -/***/ }), - -/***/ 256: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 258: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 259: -/***/ (function(module, exports, __webpack_require__) { - -var toString = __webpack_require__(108); - -/** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */ -var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, - reHasRegExpChar = RegExp(reRegExpChar.source); - -/** - * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", - * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escapeRegExp('[lodash](https://lodash.com/)'); - * // => '\[lodash\]\(https://lodash\.com/\)' - */ -function escapeRegExp(string) { - string = toString(string); - return (string && reHasRegExpChar.test(string)) - ? string.replace(reRegExpChar, '\\$&') - : string; -} - -module.exports = escapeRegExp; - - -/***/ }), - -/***/ 333: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -exports.__esModule = true; -exports.EXITING = exports.ENTERED = exports.ENTERING = exports.EXITED = exports.UNMOUNTED = undefined; - -var _propTypes = __webpack_require__(3642); - -var PropTypes = _interopRequireWildcard(_propTypes); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _PropTypes = __webpack_require__(335); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var UNMOUNTED = exports.UNMOUNTED = 'unmounted'; -var EXITED = exports.EXITED = 'exited'; -var ENTERING = exports.ENTERING = 'entering'; -var ENTERED = exports.ENTERED = 'entered'; -var EXITING = exports.EXITING = 'exiting'; - -/** - * The Transition component lets you describe a transition from one component - * state to another _over time_ with a simple declarative API. Most commonly - * it's used to animate the mounting and unmounting of a component, but can also - * be used to describe in-place transition states as well. - * - * By default the `Transition` component does not alter the behavior of the - * component it renders, it only tracks "enter" and "exit" states for the components. - * It's up to you to give meaning and effect to those states. For example we can - * add styles to a component when it enters or exits: - * - * ```jsx - * import Transition from 'react-transition-group/Transition'; - * - * const duration = 300; - * - * const defaultStyle = { - * transition: `opacity ${duration}ms ease-in-out`, - * opacity: 0, - * } - * - * const transitionStyles = { - * entering: { opacity: 0 }, - * entered: { opacity: 1 }, - * }; - * - * const Fade = ({ in: inProp }) => ( - * - * {(state) => ( - *
- * I'm a fade Transition! - *
- * )} - * - * ); - * ``` - * - * As noted the `Transition` component doesn't _do_ anything by itself to its child component. - * What it does do is track transition states over time so you can update the - * component (such as by adding styles or classes) when it changes states. - * - * There are 4 main states a Transition can be in: - * - `'entering'` - * - `'entered'` - * - `'exiting'` - * - `'exited'` - * - * Transition state is toggled via the `in` prop. When `true` the component begins the - * "Enter" stage. During this stage, the component will shift from its current transition state, - * to `'entering'` for the duration of the transition and then to the `'entered'` stage once - * it's complete. Let's take the following example: - * - * ```jsx - * state = { in: false }; - * - * toggleEnterState = () => { - * this.setState({ in: true }); - * } - * - * render() { - * return ( - *
- * - * - *
- * ); - * } - * ``` - * - * When the button is clicked the component will shift to the `'entering'` state and - * stay there for 500ms (the value of `timeout`) before it finally switches to `'entered'`. - * - * When `in` is `false` the same thing happens except the state moves from `'exiting'` to `'exited'`. - * - * ## Timing - * - * Timing is often the trickiest part of animation, mistakes can result in slight delays - * that are hard to pin down. A common example is when you want to add an exit transition, - * you should set the desired final styles when the state is `'exiting'`. That's when the - * transition to those styles will start and, if you matched the `timeout` prop with the - * CSS Transition duration, it will end exactly when the state changes to `'exited'`. - * - * > **Note**: For simpler transitions the `Transition` component might be enough, but - * > take into account that it's platform-agnostic, while the `CSSTransition` component - * > [forces reflows](https://github.com/reactjs/react-transition-group/blob/5007303e729a74be66a21c3e2205e4916821524b/src/CSSTransition.js#L208-L215) - * > in order to make more complex transitions more predictable. For example, even though - * > classes `example-enter` and `example-enter-active` are applied immediately one after - * > another, you can still transition from one to the other because of the forced reflow - * > (read [this issue](https://github.com/reactjs/react-transition-group/issues/159#issuecomment-322761171) - * > for more info). Take this into account when choosing between `Transition` and - * > `CSSTransition`. - * - * ## Example - * - * - * - */ - -var Transition = function (_React$Component) { - _inherits(Transition, _React$Component); - - function Transition(props, context) { - _classCallCheck(this, Transition); - - var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context)); - - var parentGroup = context.transitionGroup; - // In the context of a TransitionGroup all enters are really appears - var appear = parentGroup && !parentGroup.isMounting ? props.enter : props.appear; - - var initialStatus = void 0; - _this.nextStatus = null; - - if (props.in) { - if (appear) { - initialStatus = EXITED; - _this.nextStatus = ENTERING; - } else { - initialStatus = ENTERED; - } - } else { - if (props.unmountOnExit || props.mountOnEnter) { - initialStatus = UNMOUNTED; - } else { - initialStatus = EXITED; - } - } - - _this.state = { status: initialStatus }; - - _this.nextCallback = null; - return _this; - } - - Transition.prototype.getChildContext = function getChildContext() { - return { transitionGroup: null }; // allows for nested Transitions - }; - - Transition.prototype.componentDidMount = function componentDidMount() { - this.updateStatus(true); - }; - - Transition.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { - var _ref = this.pendingState || this.state, - status = _ref.status; - - if (nextProps.in) { - if (status === UNMOUNTED) { - this.setState({ status: EXITED }); - } - if (status !== ENTERING && status !== ENTERED) { - this.nextStatus = ENTERING; - } - } else { - if (status === ENTERING || status === ENTERED) { - this.nextStatus = EXITING; - } - } - }; - - Transition.prototype.componentDidUpdate = function componentDidUpdate() { - this.updateStatus(); - }; - - Transition.prototype.componentWillUnmount = function componentWillUnmount() { - this.cancelNextCallback(); - }; - - Transition.prototype.getTimeouts = function getTimeouts() { - var timeout = this.props.timeout; - - var exit = void 0, - enter = void 0, - appear = void 0; - - exit = enter = appear = timeout; - - if (timeout != null && typeof timeout !== 'number') { - exit = timeout.exit; - enter = timeout.enter; - appear = timeout.appear; - } - return { exit: exit, enter: enter, appear: appear }; - }; - - Transition.prototype.updateStatus = function updateStatus() { - var mounting = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - var nextStatus = this.nextStatus; - - if (nextStatus !== null) { - this.nextStatus = null; - // nextStatus will always be ENTERING or EXITING. - this.cancelNextCallback(); - var node = _reactDom2.default.findDOMNode(this); - - if (nextStatus === ENTERING) { - this.performEnter(node, mounting); - } else { - this.performExit(node); - } - } else if (this.props.unmountOnExit && this.state.status === EXITED) { - this.setState({ status: UNMOUNTED }); - } - }; - - Transition.prototype.performEnter = function performEnter(node, mounting) { - var _this2 = this; - - var enter = this.props.enter; - - var appearing = this.context.transitionGroup ? this.context.transitionGroup.isMounting : mounting; - - var timeouts = this.getTimeouts(); - - // no enter animation skip right to ENTERED - // if we are mounting and running this it means appear _must_ be set - if (!mounting && !enter) { - this.safeSetState({ status: ENTERED }, function () { - _this2.props.onEntered(node); - }); - return; - } - - this.props.onEnter(node, appearing); - - this.safeSetState({ status: ENTERING }, function () { - _this2.props.onEntering(node, appearing); - - // FIXME: appear timeout? - _this2.onTransitionEnd(node, timeouts.enter, function () { - _this2.safeSetState({ status: ENTERED }, function () { - _this2.props.onEntered(node, appearing); - }); - }); - }); - }; - - Transition.prototype.performExit = function performExit(node) { - var _this3 = this; - - var exit = this.props.exit; - - var timeouts = this.getTimeouts(); - - // no exit animation skip right to EXITED - if (!exit) { - this.safeSetState({ status: EXITED }, function () { - _this3.props.onExited(node); - }); - return; - } - this.props.onExit(node); - - this.safeSetState({ status: EXITING }, function () { - _this3.props.onExiting(node); - - _this3.onTransitionEnd(node, timeouts.exit, function () { - _this3.safeSetState({ status: EXITED }, function () { - _this3.props.onExited(node); - }); - }); - }); - }; - - Transition.prototype.cancelNextCallback = function cancelNextCallback() { - if (this.nextCallback !== null) { - this.nextCallback.cancel(); - this.nextCallback = null; - } - }; - - Transition.prototype.safeSetState = function safeSetState(nextState, callback) { - var _this4 = this; - - // We need to track pending updates for instances where a cWRP fires quickly - // after cDM and before the state flushes, which would double trigger a - // transition - this.pendingState = nextState; - - // This shouldn't be necessary, but there are weird race conditions with - // setState callbacks and unmounting in testing, so always make sure that - // we can cancel any pending setState callbacks after we unmount. - callback = this.setNextCallback(callback); - this.setState(nextState, function () { - _this4.pendingState = null; - callback(); - }); - }; - - Transition.prototype.setNextCallback = function setNextCallback(callback) { - var _this5 = this; - - var active = true; - - this.nextCallback = function (event) { - if (active) { - active = false; - _this5.nextCallback = null; - - callback(event); - } - }; - - this.nextCallback.cancel = function () { - active = false; - }; - - return this.nextCallback; - }; - - Transition.prototype.onTransitionEnd = function onTransitionEnd(node, timeout, handler) { - this.setNextCallback(handler); - - if (node) { - if (this.props.addEndListener) { - this.props.addEndListener(node, this.nextCallback); - } - if (timeout != null) { - setTimeout(this.nextCallback, timeout); - } - } else { - setTimeout(this.nextCallback, 0); - } - }; - - Transition.prototype.render = function render() { - var status = this.state.status; - if (status === UNMOUNTED) { - return null; - } - - var _props = this.props, - children = _props.children, - childProps = _objectWithoutProperties(_props, ['children']); - // filter props for Transtition - - - delete childProps.in; - delete childProps.mountOnEnter; - delete childProps.unmountOnExit; - delete childProps.appear; - delete childProps.enter; - delete childProps.exit; - delete childProps.timeout; - delete childProps.addEndListener; - delete childProps.onEnter; - delete childProps.onEntering; - delete childProps.onEntered; - delete childProps.onExit; - delete childProps.onExiting; - delete childProps.onExited; - - if (typeof children === 'function') { - return children(status, childProps); - } - - var child = _react2.default.Children.only(children); - return _react2.default.cloneElement(child, childProps); - }; - - return Transition; -}(_react2.default.Component); - -Transition.contextTypes = { - transitionGroup: PropTypes.object -}; -Transition.childContextTypes = { - transitionGroup: function transitionGroup() {} -}; - - -Transition.propTypes = false ? { - /** - * A `function` child can be used instead of a React element. - * This function is called with the current transition status - * ('entering', 'entered', 'exiting', 'exited', 'unmounted'), which can be used - * to apply context specific props to a component. - * - * ```jsx - * - * {(status) => ( - * - * )} - * - * ``` - */ - children: PropTypes.oneOfType([PropTypes.func.isRequired, PropTypes.element.isRequired]).isRequired, - - /** - * Show the component; triggers the enter or exit states - */ - in: PropTypes.bool, - - /** - * By default the child component is mounted immediately along with - * the parent `Transition` component. If you want to "lazy mount" the component on the - * first `in={true}` you can set `mountOnEnter`. After the first enter transition the component will stay - * mounted, even on "exited", unless you also specify `unmountOnExit`. - */ - mountOnEnter: PropTypes.bool, - - /** - * By default the child component stays mounted after it reaches the `'exited'` state. - * Set `unmountOnExit` if you'd prefer to unmount the component after it finishes exiting. - */ - unmountOnExit: PropTypes.bool, - - /** - * Normally a component is not transitioned if it is shown when the `` component mounts. - * If you want to transition on the first mount set `appear` to `true`, and the - * component will transition in as soon as the `` mounts. - * - * > Note: there are no specific "appear" states. `appear` only adds an additional `enter` transition. - */ - appear: PropTypes.bool, - - /** - * Enable or disable enter transitions. - */ - enter: PropTypes.bool, - - /** - * Enable or disable exit transitions. - */ - exit: PropTypes.bool, - - /** - * The duration of the transition, in milliseconds. - * Required unless `addEndListener` is provided - * - * You may specify a single timeout for all transitions like: `timeout={500}`, - * or individually like: - * - * ```jsx - * timeout={{ - * enter: 300, - * exit: 500, - * }} - * ``` - * - * @type {number | { enter?: number, exit?: number }} - */ - timeout: function timeout(props) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - var pt = _PropTypes.timeoutsShape; - if (!props.addEndListener) pt = pt.isRequired; - return pt.apply(undefined, [props].concat(args)); - }, - - /** - * Add a custom transition end trigger. Called with the transitioning - * DOM node and a `done` callback. Allows for more fine grained transition end - * logic. **Note:** Timeouts are still used as a fallback if provided. - * - * ```jsx - * addEndListener={(node, done) => { - * // use the css transitionend event to mark the finish of a transition - * node.addEventListener('transitionend', done, false); - * }} - * ``` - */ - addEndListener: PropTypes.func, - - /** - * Callback fired before the "entering" status is applied. An extra parameter - * `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount - * - * @type Function(node: HtmlElement, isAppearing: bool) -> void - */ - onEnter: PropTypes.func, - - /** - * Callback fired after the "entering" status is applied. An extra parameter - * `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount - * - * @type Function(node: HtmlElement, isAppearing: bool) - */ - onEntering: PropTypes.func, - - /** - * Callback fired after the "entered" status is applied. An extra parameter - * `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount - * - * @type Function(node: HtmlElement, isAppearing: bool) -> void - */ - onEntered: PropTypes.func, - - /** - * Callback fired before the "exiting" status is applied. - * - * @type Function(node: HtmlElement) -> void - */ - onExit: PropTypes.func, - - /** - * Callback fired after the "exiting" status is applied. - * - * @type Function(node: HtmlElement) -> void - */ - onExiting: PropTypes.func, - - /** - * Callback fired after the "exited" status is applied. - * - * @type Function(node: HtmlElement) -> void - */ - onExited: PropTypes.func -} : {}; - -// Name the function so it is clearer in the documentation -function noop() {} - -Transition.defaultProps = { - in: false, - mountOnEnter: false, - unmountOnExit: false, - appear: false, - enter: true, - exit: true, - - onEnter: noop, - onEntering: noop, - onEntered: noop, - - onExit: noop, - onExiting: noop, - onExited: noop -}; - -Transition.UNMOUNTED = 0; -Transition.EXITED = 1; -Transition.ENTERING = 2; -Transition.ENTERED = 3; -Transition.EXITING = 4; - -exports.default = Transition; - -/***/ }), - -/***/ 334: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -var punycode = __webpack_require__(3641); -var util = __webpack_require__(336); - -exports.parse = urlParse; -exports.resolve = urlResolve; -exports.resolveObject = urlResolveObject; -exports.format = urlFormat; - -exports.Url = Url; - -function Url() { - this.protocol = null; - this.slashes = null; - this.auth = null; - this.host = null; - this.port = null; - this.hostname = null; - this.hash = null; - this.search = null; - this.query = null; - this.pathname = null; - this.path = null; - this.href = null; -} - -// Reference: RFC 3986, RFC 1808, RFC 2396 - -// define these here so at least they only have to be -// compiled once on the first module load. -var protocolPattern = /^([a-z0-9.+-]+:)/i, - portPattern = /:[0-9]*$/, - - // Special case for a simple path URL - simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, - - // RFC 2396: characters reserved for delimiting URLs. - // We actually just auto-escape these. - delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = __webpack_require__(66); - -function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && util.isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; -} - -Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!util.isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); - } - - // Copy chrome, IE, opera backslash-handling behavior. - // Back slashes before the query string get converted to forward slashes - // See: https://code.google.com/p/chromium/issues/detail?id=25916 - var queryIndex = url.indexOf('?'), - splitter = - (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', - uSplit = url.split(splitter), - slashRegex = /\\/g; - uSplit[0] = uSplit[0].replace(slashRegex, '/'); - url = uSplit.join(splitter); - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - if (!slashesDenoteHost && url.split('#').length === 1) { - // Try fast path regexp - var simplePath = simplePathPattern.exec(rest); - if (simplePath) { - this.path = rest; - this.href = rest; - this.pathname = simplePath[1]; - if (simplePath[2]) { - this.search = simplePath[2]; - if (parseQueryString) { - this.query = querystring.parse(this.search.substr(1)); - } else { - this.query = this.search.substr(1); - } - } else if (parseQueryString) { - this.search = ''; - this.query = {}; - } - return this; - } - } - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a punycoded representation of "domain". - // It only converts parts of the domain name that - // have non-ASCII characters, i.e. it doesn't matter if - // you call it with a domain that already is ASCII-only. - this.hostname = punycode.toASCII(this.hostname); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - if (rest.indexOf(ae) === -1) - continue; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; -}; - -// format a parsed object into a url string -function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (util.isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); -} - -Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - util.isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; -}; - -function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); -} - -Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); -}; - -function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); -} - -Url.prototype.resolveObject = function(relative) { - if (util.isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - var tkeys = Object.keys(this); - for (var tk = 0; tk < tkeys.length; tk++) { - var tkey = tkeys[tk]; - result[tkey] = this[tkey]; - } - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - var rkeys = Object.keys(relative); - for (var rk = 0; rk < rkeys.length; rk++) { - var rkey = rkeys[rk]; - if (rkey !== 'protocol') - result[rkey] = relative[rkey]; - } - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - var keys = Object.keys(relative); - for (var v = 0; v < keys.length; v++) { - var k = keys[v]; - result[k] = relative[k]; - } - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!util.isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especially happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!util.isNull(result.pathname) || !util.isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host || srcPath.length > 1) && - (last === '.' || last === '..') || last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last === '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especially happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!util.isNull(result.pathname) || !util.isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; -}; - -Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; -}; - - -/***/ }), - -/***/ 335: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -exports.__esModule = true; -exports.classNamesShape = exports.timeoutsShape = undefined; -exports.transitionTimeout = transitionTimeout; - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function transitionTimeout(transitionType) { - var timeoutPropName = 'transition' + transitionType + 'Timeout'; - var enabledPropName = 'transition' + transitionType; - - return function (props) { - // If the transition is enabled - if (props[enabledPropName]) { - // If no timeout duration is provided - if (props[timeoutPropName] == null) { - return new Error(timeoutPropName + ' wasn\'t supplied to CSSTransitionGroup: ' + 'this can cause unreliable animations and won\'t be supported in ' + 'a future version of React. See ' + 'https://fb.me/react-animation-transition-group-timeout for more ' + 'information.'); - - // If the duration isn't a number - } else if (typeof props[timeoutPropName] !== 'number') { - return new Error(timeoutPropName + ' must be a number (in milliseconds)'); - } - } - - return null; - }; -} - -var timeoutsShape = exports.timeoutsShape = _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.shape({ - enter: _propTypes2.default.number, - exit: _propTypes2.default.number -}).isRequired]); - -var classNamesShape = exports.classNamesShape = _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.shape({ - enter: _propTypes2.default.string, - exit: _propTypes2.default.string, - active: _propTypes2.default.string -}), _propTypes2.default.shape({ - enter: _propTypes2.default.string, - enterDone: _propTypes2.default.string, - enterActive: _propTypes2.default.string, - exit: _propTypes2.default.string, - exitDone: _propTypes2.default.string, - exitActive: _propTypes2.default.string -})]); - -/***/ }), - -/***/ 336: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = { - isString: function(arg) { - return typeof(arg) === 'string'; - }, - isObject: function(arg) { - return typeof(arg) === 'object' && arg !== null; - }, - isNull: function(arg) { - return arg === null; - }, - isNullOrUndefined: function(arg) { - return arg == null; - } -}; - - -/***/ }), - -/***/ 347: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 348: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 349: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 350: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 351: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 352: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 353: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 354: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 355: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 356: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 357: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 358: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 359: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3590: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _expressions = __webpack_require__(1417); - -Object.keys(_expressions).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _expressions[key]; - } - }); -}); - -var _sources = __webpack_require__(1369); - -Object.keys(_sources).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _sources[key]; - } - }); -}); - -var _pause = __webpack_require__(1394); - -Object.keys(_pause).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _pause[key]; - } - }); -}); - -var _debuggee = __webpack_require__(1418); - -Object.keys(_debuggee).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _debuggee[key]; - } - }); -}); - -var _breakpoints = __webpack_require__(1378); - -Object.keys(_breakpoints).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _breakpoints[key]; - } - }); -}); - -var _pendingBreakpoints = __webpack_require__(1419); - -Object.keys(_pendingBreakpoints).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _pendingBreakpoints[key]; - } - }); -}); - -var _ui = __webpack_require__(1421); - -Object.keys(_ui).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _ui[key]; - } - }); -}); - -var _fileSearch = __webpack_require__(1422); - -Object.keys(_fileSearch).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _fileSearch[key]; - } - }); -}); - -var _ast = __webpack_require__(1383); - -Object.keys(_ast).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _ast[key]; - } - }); -}); - -var _coverage = __webpack_require__(1423); - -Object.keys(_coverage).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _coverage[key]; - } - }); -}); - -var _projectTextSearch = __webpack_require__(1424); - -Object.keys(_projectTextSearch).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _projectTextSearch[key]; - } - }); -}); - -var _replay = __webpack_require__(2342); - -Object.keys(_replay).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _replay[key]; - } - }); -}); - -var _sourceTree = __webpack_require__(1426); - -Object.keys(_sourceTree).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _sourceTree[key]; - } - }); -}); - -var _eventListeners = __webpack_require__(1420); - -Object.defineProperty(exports, "getEventListeners", { - enumerable: true, - get: function () { - return _eventListeners.getEventListeners; - } -}); - -var _quickOpen = __webpack_require__(1635); - -Object.defineProperty(exports, "getQuickOpenEnabled", { - enumerable: true, - get: function () { - return _quickOpen.getQuickOpenEnabled; - } -}); -Object.defineProperty(exports, "getQuickOpenQuery", { - enumerable: true, - get: function () { - return _quickOpen.getQuickOpenQuery; - } -}); -Object.defineProperty(exports, "getQuickOpenType", { - enumerable: true, - get: function () { - return _quickOpen.getQuickOpenType; - } -}); - -var _breakpointAtLocation = __webpack_require__(1503); - -Object.defineProperty(exports, "getBreakpointAtLocation", { - enumerable: true, - get: function () { - return _breakpointAtLocation.getBreakpointAtLocation; - } -}); - -var _visibleBreakpoints = __webpack_require__(1427); - -Object.defineProperty(exports, "getVisibleBreakpoints", { - enumerable: true, - get: function () { - return _visibleBreakpoints.getVisibleBreakpoints; - } -}); - -var _isSelectedFrameVisible = __webpack_require__(1505); - -Object.defineProperty(exports, "isSelectedFrameVisible", { - enumerable: true, - get: function () { - return _isSelectedFrameVisible.isSelectedFrameVisible; - } -}); - -var _getCallStackFrames = __webpack_require__(1779); - -Object.defineProperty(exports, "getCallStackFrames", { - enumerable: true, - get: function () { - return _getCallStackFrames.getCallStackFrames; - } -}); - -var _visibleSelectedFrame = __webpack_require__(1780); - -Object.defineProperty(exports, "getVisibleSelectedFrame", { - enumerable: true, - get: function () { - return _visibleSelectedFrame.getVisibleSelectedFrame; - } -}); - -var _getRelativeSources = __webpack_require__(3625); - -Object.defineProperty(exports, "getRelativeSources", { - enumerable: true, - get: function () { - return _getRelativeSources.getRelativeSources; - } -}); - -/***/ }), - -/***/ 3592: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_3592__; - -/***/ }), - -/***/ 3593: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_3593__; - -/***/ }), - -/***/ 3594: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_3594__; - -/***/ }), - -/***/ 3595: -/***/ (function(module, exports) { - -module.exports = " Created by potrace 1.11, written by Peter Selinger 2001-2013 " - -/***/ }), - -/***/ 360: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3603: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3604: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3605: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _annotateFrames = __webpack_require__(3608); - -Object.keys(_annotateFrames).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _annotateFrames[key]; - } - }); -}); - -var _collapseFrames = __webpack_require__(3609); - -Object.keys(_collapseFrames).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _collapseFrames[key]; - } - }); -}); - -var _displayName = __webpack_require__(3610); - -Object.keys(_displayName).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _displayName[key]; - } - }); -}); - -var _getFrameUrl = __webpack_require__(3606); - -Object.keys(_getFrameUrl).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _getFrameUrl[key]; - } - }); -}); - -var _getLibraryFromUrl = __webpack_require__(3607); - -Object.keys(_getLibraryFromUrl).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _getLibraryFromUrl[key]; - } - }); -}); - -/***/ }), - -/***/ 3606: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getFrameUrl = getFrameUrl; - -var _lodash = __webpack_require__(2); - -function getFrameUrl(frame) { - return (0, _lodash.get)(frame, "source.url", "") || ""; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 3607: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getLibraryFromUrl = getLibraryFromUrl; - -var _lodash = __webpack_require__(2); - -var _getFrameUrl = __webpack_require__(3606); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const libraryMap = [{ - label: "Backbone", - pattern: /backbone/i -}, { - label: "jQuery", - pattern: /jquery/i -}, { - label: "Preact", - pattern: /preact/i -}, { - label: "React", - pattern: /react/i -}, { - label: "Immutable", - pattern: /immutable/i -}, { - label: "Webpack", - pattern: /webpack\/bootstrap/i -}, { - label: "Node", - pattern: /(^internal\/|^[^.\/]+\.js)/ -}, { - label: "Express", - pattern: /node_modules\/express/ -}, { - label: "Pug", - pattern: /node_modules\/pug/ -}, { - label: "ExtJS", - pattern: /\/ext-all[\.\-]/ -}, { - label: "MobX", - pattern: /mobx/i -}, { - label: "Underscore", - pattern: /underscore/i -}, { - label: "Lodash", - pattern: /lodash/i -}, { - label: "Ember", - pattern: /ember/i -}, { - label: "Choo", - pattern: /choo/i -}, { - label: "VueJS", - pattern: /vue\.js/i -}, { - label: "RxJS", - pattern: /rxjs/i -}, { - label: "Angular", - pattern: /angular/i -}, { - label: "Redux", - pattern: /redux/i -}, { - label: "Dojo", - pattern: /dojo/i -}, { - label: "Marko", - pattern: /marko/i -}, { - label: "NuxtJS", - pattern: /[\._]nuxt/i -}, { - label: "Aframe", - pattern: /aframe/i -}, { - label: "NextJS", - pattern: /[\._]next/i -}]; - -function getLibraryFromUrl(frame) { - // @TODO each of these fns calls getFrameUrl, just call it once - // (assuming there's not more complex logic to identify a lib) - const frameUrl = (0, _getFrameUrl.getFrameUrl)(frame); - const match = (0, _lodash.find)(libraryMap, o => frameUrl.match(o.pattern)); - return match && match.label; -} - -/***/ }), - -/***/ 3608: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.annotateFrames = annotateFrames; - -var _lodash = __webpack_require__(2); - -var _getFrameUrl = __webpack_require__(3606); - -var _getLibraryFromUrl = __webpack_require__(3607); - -function annotateFrames(frames) { - const annotatedFrames = frames.map(annotateFrame); - return annotateBabelAsyncFrames(annotatedFrames); -} - -function annotateFrame(frame) { - const library = (0, _getLibraryFromUrl.getLibraryFromUrl)(frame); - if (library) { - return _extends({}, frame, { library }); - } - - return frame; -} - -function annotateBabelAsyncFrames(frames) { - const babelFrameIndexes = getBabelFrameIndexes(frames); - const isBabelFrame = frameIndex => babelFrameIndexes.includes(frameIndex); - - return frames.map((frame, frameIndex) => isBabelFrame(frameIndex) ? _extends({}, frame, { library: "Babel" }) : frame); -} - -// Receives an array of frames and looks for babel async -// call stack groups. -function getBabelFrameIndexes(frames) { - const startIndexes = frames.reduce((accumulator, frame, index) => { - if ((0, _getFrameUrl.getFrameUrl)(frame).match(/regenerator-runtime/i) && frame.displayName === "tryCatch") { - return [...accumulator, index]; - } - return accumulator; - }, []); - - const endIndexes = frames.reduce((accumulator, frame, index) => { - if ((0, _getFrameUrl.getFrameUrl)(frame).match(/_microtask/i) && frame.displayName === "flush") { - return [...accumulator, index]; - } - if (frame.displayName === "_asyncToGenerator/<") { - return [...accumulator, index + 1]; - } - return accumulator; - }, []); - - if (startIndexes.length != endIndexes.length || startIndexes.length === 0) { - return frames; - } - - // Receives an array of start and end index tuples and returns - // an array of async call stack index ranges. - // e.g. [[1,3], [5,7]] => [[1,2,3], [5,6,7]] - return (0, _lodash.flatMap)((0, _lodash.zip)(startIndexes, endIndexes), ([startIndex, endIndex]) => (0, _lodash.range)(startIndex, endIndex + 1)); -} - -/***/ }), - -/***/ 3609: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.collapseFrames = collapseFrames; - -var _lodash = __webpack_require__(2); - -var _getFrameUrl = __webpack_require__(3606); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function collapseLastFrames(frames) { - const index = (0, _lodash.findIndex)(frames, frame => (0, _getFrameUrl.getFrameUrl)(frame).match(/webpack\/bootstrap/i)); - - if (index == -1) { - return { newFrames: frames, lastGroup: [] }; - } - - const newFrames = frames.slice(0, index); - const lastGroup = frames.slice(index); - return { newFrames, lastGroup }; -} - -// eslint-disable-next-line max-len -function collapseFrames(frames) { - // We collapse groups of one so that user frames - // are not in a group of one - function addGroupToList(group, list) { - if (!group) { - return list; - } - - if (group.length > 1) { - list.push(group); - } else { - list = list.concat(group); - } - - return list; - } - const { newFrames, lastGroup } = collapseLastFrames(frames); - frames = newFrames; - let items = []; - let currentGroup = null; - let prevItem = null; - for (const frame of frames) { - const prevLibrary = (0, _lodash.get)(prevItem, "library"); - - if (!currentGroup) { - currentGroup = [frame]; - } else if (prevLibrary && prevLibrary == frame.library) { - currentGroup.push(frame); - } else { - items = addGroupToList(currentGroup, items); - currentGroup = [frame]; - } - - prevItem = frame; - } - - items = addGroupToList(currentGroup, items); - items = addGroupToList(lastGroup, items); - return items; -} - -/***/ }), - -/***/ 361: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3610: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.simplifyDisplayName = simplifyDisplayName; -exports.formatDisplayName = formatDisplayName; -exports.formatCopyName = formatCopyName; - -var _source = __webpack_require__(1356); - -var _utils = __webpack_require__(1366); - -// Decodes an anonymous naming scheme that -// spider monkey implements based on "Naming Anonymous JavaScript Functions" -// http://johnjbarton.github.io/nonymous/index.html -const objectProperty = /([\w\d]+)$/; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// eslint-disable-next-line max-len - -const arrayProperty = /\[(.*?)\]$/; -const functionProperty = /([\w\d]+)[\/\.<]*?$/; -const annonymousProperty = /([\w\d]+)\(\^\)$/; - -function simplifyDisplayName(displayName) { - // if the display name has a space it has already been mapped - if (/\s/.exec(displayName)) { - return displayName; - } - - const scenarios = [objectProperty, arrayProperty, functionProperty, annonymousProperty]; - - for (const reg of scenarios) { - const match = reg.exec(displayName); - if (match) { - return match[1]; - } - } - - return displayName; -} - -const displayNameMap = { - Babel: { - tryCatch: "Async" - }, - Backbone: { - "extend/child": "Create Class", - ".create": "Create Model" - }, - jQuery: { - "jQuery.event.dispatch": "Dispatch Event" - }, - React: { - // eslint-disable-next-line max-len - "ReactCompositeComponent._renderValidatedComponentWithoutOwnerOrContext/renderedElement<": "Render", - _renderValidatedComponentWithoutOwnerOrContext: "Render" - }, - VueJS: { - "renderMixin/Vue.prototype._render": "Render" - }, - Webpack: { - // eslint-disable-next-line camelcase - __webpack_require__: "Bootstrap" - } -}; - -function mapDisplayNames(frame, library) { - const { displayName } = frame; - return displayNameMap[library] && displayNameMap[library][displayName] || displayName; -} - -function formatDisplayName(frame, { shouldMapDisplayName = true } = {}) { - let { displayName, originalDisplayName, library } = frame; - displayName = originalDisplayName || displayName; - if (library && shouldMapDisplayName) { - displayName = mapDisplayNames(frame, library); - } - - displayName = simplifyDisplayName(displayName); - return (0, _utils.endTruncateStr)(displayName, 25); -} - -function formatCopyName(frame) { - const displayName = formatDisplayName(frame); - const fileName = (0, _source.getFilename)(frame.source); - const frameLocation = frame.location.line; - - return `${displayName} (${fileName}#${frameLocation})`; -} - -/***/ }), - -/***/ 362: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3622: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.convertToList = convertToList; -exports.formatPausePoints = formatPausePoints; - -var _lodash = __webpack_require__(2); - -function insertStrtAt(string, index, newString) { - const start = string.slice(0, index); - const end = string.slice(index); - return `${start}${newString}${end}`; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function convertToList(pausePoints) { - const list = []; - for (const line in pausePoints) { - for (const column in pausePoints[line]) { - const point = pausePoints[line][column]; - list.push({ - location: { line: parseInt(line, 10), column: parseInt(column, 10) }, - types: point - }); - } - } - return list; -} - -function formatPausePoints(text, pausePoints) { - const nodes = (0, _lodash.reverse)(convertToList(pausePoints)); - const lines = text.split("\n"); - nodes.forEach((node, index) => { - const { line, column } = node.location; - const { break: breakPoint, step } = node.types; - const num = nodes.length - index; - const types = `${breakPoint ? "b" : ""}${step ? "s" : ""}`; - const spacer = breakPoint || step ? " " : ""; - lines[line - 1] = insertStrtAt(lines[line - 1], column, `/*${types}${spacer}${num}*/`); - }); - - return lines.join("\n"); -} - -/***/ }), - -/***/ 3623: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _firefox = __webpack_require__(1500); - -var _selectors = __webpack_require__(3590); - -var _devtoolsReps = __webpack_require__(3655); - -var _preview = __webpack_require__(1807); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { createNode, getChildren } = _devtoolsReps.ObjectInspectorUtils.node; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { loadItemProperties } = _devtoolsReps.ObjectInspectorUtils.loadProperties; - -class FrameworkComponent extends _react.PureComponent { - async componentWillMount() { - const expression = "this;"; - const { selectedFrame, setPopupObjectProperties } = this.props; - const value = selectedFrame.this; - - const root = createNode({ name: expression, contents: { value } }); - const properties = await loadItemProperties(root, _firefox.createObjectClient); - if (properties) { - setPopupObjectProperties(value, properties); - } - } - - renderReactComponent() { - const { selectedFrame, popupObjectProperties } = this.props; - const expression = "this;"; - const value = selectedFrame.this; - const root = { - name: expression, - path: expression, - contents: { value } - }; - - const loadedRootProperties = popupObjectProperties[value.actor]; - if (!loadedRootProperties) { - return null; - } - - let roots = getChildren({ - item: root, - loadedProperties: new Map([[root.path, loadedRootProperties]]) - }); - - roots = roots.filter(r => ["state", "props"].includes(r.name)); - - return _react2.default.createElement( - "div", - { className: "pane framework-component" }, - _react2.default.createElement(_devtoolsReps.ObjectInspector, { - roots: roots, - autoExpandAll: false, - autoExpandDepth: 0, - disableWrap: true, - focusable: false, - dimTopLevelWindow: true, - createObjectClient: grip => (0, _firefox.createObjectClient)(grip) - }) - ); - } - - render() { - const { selectedFrame } = this.props; - if (selectedFrame && (0, _preview.isReactComponent)(selectedFrame.this)) { - return this.renderReactComponent(); - } - - return null; - } -} - -const mapStateToProps = state => ({ - selectedFrame: (0, _selectors.getSelectedFrame)(state), - popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(FrameworkComponent); - -/***/ }), - -/***/ 3625: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.getRelativeSources = getRelativeSources; - -var _selectors = __webpack_require__(3590); - -var _source = __webpack_require__(1356); - -function getRelativeUrl(url, root) { - if (!root) { - return (0, _source.getSourcePath)(url); - } - - // + 1 removes the leading "/" - return url.slice(url.indexOf(root) + root.length + 1); -} - -function formatSource(source, root) { - return _extends({}, source, { - relativeUrl: getRelativeUrl(source.url, root) - }); -} - -/* - * Gets the sources that are below a project root - */ -function getRelativeSources(state) { - const sources = (0, _selectors.getSources)(state); - const root = (0, _selectors.getProjectDirectoryRoot)(state); - return sources.valueSeq().toJS().filter(({ url }) => url && url.includes(root)).map(source => formatSource(source, root)); -} - -/***/ }), - -/***/ 3626: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_3626__; - -/***/ }), - -/***/ 3628: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createEditor = createEditor; - -var _sourceEditor = __webpack_require__(197); - -var _sourceEditor2 = _interopRequireDefault(_sourceEditor); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function createEditor(value) { - return new _sourceEditor2.default({ - mode: "javascript", - foldGutter: false, - enableCodeFolding: false, - readOnly: "nocursor", - lineNumbers: false, - theme: "mozilla mozilla-breakpoint", - styleActiveLine: false, - lineWrapping: false, - matchBrackets: false, - showAnnotationRuler: false, - gutters: false, - value: value || "", - scrollbarStyle: null - }); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 363: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3631: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3632: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3634: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = __webpack_require__(4); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _classnames = __webpack_require__(175); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _devtoolsSourceMap = __webpack_require__(3646); - -var _Close = __webpack_require__(1374); - -var _Close2 = _interopRequireDefault(_Close); - -var _breakpoint = __webpack_require__(1364); - -var _prefs = __webpack_require__(226); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function getBreakpointLocation(source, line, column) { - const isWasm = source && source.isWasm; - const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : ""; - const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`; - - return bpLocation; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function getBreakpointText(selectedSource, breakpoint) { - const { condition, text, originalText } = breakpoint; - - if (condition) { - return condition; - } - - if (!selectedSource || (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) || originalText.length == 0) { - return text; - } - - return originalText; -} - -class Breakpoint extends _react.Component { - - componentDidMount() { - this.setupEditor(); - } - - componentDidUpdate(prevProps) { - if (getBreakpointText(this.props.selectedSource, this.props.breakpoint) != getBreakpointText(prevProps.selectedSource, prevProps.breakpoint)) { - this.destroyEditor(); - } - this.setupEditor(); - } - - componentWillUnmount() { - this.destroyEditor(); - } - - shouldComponentUpdate(nextProps) { - const prevBreakpoint = this.props.breakpoint; - const nextBreakpoint = nextProps.breakpoint; - - return !prevBreakpoint || this.props.selectedSource != nextProps.selectedSource || prevBreakpoint.text != nextBreakpoint.text || prevBreakpoint.disabled != nextBreakpoint.disabled || prevBreakpoint.condition != nextBreakpoint.condition || prevBreakpoint.hidden != nextBreakpoint.hidden || prevBreakpoint.isCurrentlyPaused != nextBreakpoint.isCurrentlyPaused; - } - - destroyEditor() { - if (this.editor) { - this.editor.destroy(); - this.editor = null; - } - } - - setupEditor() { - if (this.editor) { - return; - } - - const { selectedSource, breakpoint } = this.props; - - this.editor = (0, _breakpoint.createEditor)(getBreakpointText(selectedSource, breakpoint)); - - // disables the default search shortcuts - // $FlowIgnore - this.editor._initShortcuts = () => {}; - - const node = _reactDom2.default.findDOMNode(this); - if (node instanceof HTMLElement) { - const mountNode = node.querySelector(".breakpoint-label"); - if (node instanceof HTMLElement) { - // $FlowIgnore - mountNode.innerHTML = ""; - this.editor.appendToLocalElement(mountNode); - this.editor.codeMirror.on("mousedown", (_, e) => e.preventDefault()); - } - } - } - - renderCheckbox() { - const { onChange, breakpoint } = this.props; - const { disabled } = breakpoint; - - return _react2.default.createElement("input", { - type: "checkbox", - className: "breakpoint-checkbox", - checked: !disabled, - onChange: onChange, - onClick: ev => ev.stopPropagation() - }); - } - - renderText() { - const { selectedSource, breakpoint } = this.props; - const text = getBreakpointText(selectedSource, breakpoint); - - return _react2.default.createElement( - "label", - { className: "breakpoint-label", title: text }, - text - ); - } - - renderLineClose() { - const { breakpoint, onCloseClick, selectedSource } = this.props; - const { location } = breakpoint; - - let { line, column } = location; - if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) && breakpoint.generatedLocation) { - line = breakpoint.generatedLocation.line; - column = breakpoint.generatedLocation.column; - } - - return _react2.default.createElement( - "div", - { className: "breakpoint-line-close" }, - _react2.default.createElement( - "div", - { className: "breakpoint-line" }, - getBreakpointLocation(breakpoint.source, line, column) - ), - _react2.default.createElement(_Close2.default, { - handleClick: onCloseClick, - tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip") - }) - ); - } - - render() { - const { breakpoint, onClick, onContextMenu } = this.props; - - const locationId = breakpoint.locationId; - const isCurrentlyPaused = breakpoint.isCurrentlyPaused; - const isDisabled = breakpoint.disabled; - const isConditional = !!breakpoint.condition; - - return _react2.default.createElement( - "div", - { - className: (0, _classnames2.default)({ - breakpoint, - paused: isCurrentlyPaused, - disabled: isDisabled, - "is-conditional": isConditional - }), - key: locationId, - onClick: onClick, - onContextMenu: onContextMenu - }, - this.renderCheckbox(), - this.renderText(), - this.renderLineClose() - ); - } -} - -exports.default = Breakpoint; - -/***/ }), - -/***/ 3635: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.filterSortedArray = filterSortedArray; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function findInsertionLocation(array, callback) { - let left = 0; - let right = array.length; - while (left < right) { - const mid = Math.floor((left + right) / 2); - const item = array[mid]; - - const result = callback(item); - if (result === 0) { - left = mid; - break; - } - if (result >= 0) { - right = mid; - } else { - left = mid + 1; - } - } - - // Ensure the value is the start of any set of matches. - let i = left; - if (i < array.length) { - while (i >= 0 && callback(array[i]) >= 0) { - i--; - } - return i + 1; - } - - return i; -} - -function filterSortedArray(array, callback) { - const start = findInsertionLocation(array, callback); - - const results = []; - for (let i = start; i < array.length && callback(array[i]) === 0; i++) { - results.push(array[i]); - } - - return results; -} - -/***/ }), - -/***/ 3636: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -exports.fetchExtra = fetchExtra; -exports.getExtra = getExtra; - -var _selectors = __webpack_require__(3590); - -var _preview = __webpack_require__(1807); - -var _ast = __webpack_require__(1638); - -async function getReactProps(evaluate) { - const componentNames = await evaluate(` - if(this.hasOwnProperty('_reactInternalFiber')) { - let componentNames = []; - let componentNode = this._reactInternalFiber; - while(componentNode) { - componentNames.push(componentNode.type.name); - componentNode = componentNode._debugOwner - } - componentNames; - } - else { - [this._reactInternalInstance.getName()]; - } - `); - const items = componentNames.result.preview && componentNames.result.preview.items; - if (items) { - return { - displayName: items[0], - componentStack: items - }; - } -} - -async function getImmutableProps(expression, evaluate) { - const immutableEntries = await evaluate((exp => `${exp}.toJS()`)(expression)); - - const immutableType = await evaluate((exp => `${exp}.constructor.name`)(expression)); - - return { - type: immutableType.result, - entries: immutableEntries.result - }; -} - -async function getExtraProps(getState, expression, result, evaluate) { - const props = {}; - if ((0, _preview.isReactComponent)(result)) { - const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); - const source = (0, _selectors.getSource)(getState(), selectedFrame.location.sourceId); - const symbols = (0, _selectors.getSymbols)(getState(), source); - - if (symbols && symbols.classes) { - const originalClass = (0, _ast.findClosestClass)(symbols, selectedFrame.location); - - if (originalClass) { - props.react = { displayName: originalClass.name }; - } - } - - props.react = _extends({}, (await getReactProps(evaluate)), props.react); - } - - if ((0, _preview.isImmutable)(result)) { - props.immutable = await getImmutableProps(expression, evaluate); - } - - return props; -} - -function fetchExtra() { - return async function ({ dispatch, getState }) { - const frame = (0, _selectors.getSelectedFrame)(getState()); - const extra = await dispatch(getExtra("this;", frame.this)); - dispatch({ - type: "ADD_EXTRA", - extra: extra - }); - }; -} - -function getExtra(expression, result) { - return async ({ dispatch, getState, client, sourceMaps }) => { - const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); - if (!selectedFrame) { - return; - } - - const extra = await getExtraProps(getState, expression, result, expr => client.evaluateInFrame(expr, selectedFrame.id)); - - return extra; - }; -} - -/***/ }), - -/***/ 3637: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// TODO : Localize this (was l10n.getStr("frame.unknownSource")) -const UNKNOWN_SOURCE_STRING = "(unknown)"; - -// Character codes used in various parsing helper functions. -const CHAR_CODE_A = "a".charCodeAt(0); -const CHAR_CODE_B = "b".charCodeAt(0); -const CHAR_CODE_C = "c".charCodeAt(0); -const CHAR_CODE_D = "d".charCodeAt(0); -const CHAR_CODE_E = "e".charCodeAt(0); -const CHAR_CODE_F = "f".charCodeAt(0); -const CHAR_CODE_H = "h".charCodeAt(0); -const CHAR_CODE_I = "i".charCodeAt(0); -const CHAR_CODE_J = "j".charCodeAt(0); -const CHAR_CODE_L = "l".charCodeAt(0); -const CHAR_CODE_M = "m".charCodeAt(0); -const CHAR_CODE_N = "n".charCodeAt(0); -const CHAR_CODE_O = "o".charCodeAt(0); -const CHAR_CODE_P = "p".charCodeAt(0); -const CHAR_CODE_R = "r".charCodeAt(0); -const CHAR_CODE_S = "s".charCodeAt(0); -const CHAR_CODE_T = "t".charCodeAt(0); -const CHAR_CODE_U = "u".charCodeAt(0); -const CHAR_CODE_W = "w".charCodeAt(0); -const CHAR_CODE_COLON = ":".charCodeAt(0); -const CHAR_CODE_DASH = "-".charCodeAt(0); -const CHAR_CODE_L_SQUARE_BRACKET = "[".charCodeAt(0); -const CHAR_CODE_SLASH = "/".charCodeAt(0); -const CHAR_CODE_CAP_S = "S".charCodeAt(0); - -// The cache used in the `parseURL` function. -const gURLStore = new Map(); -// The cache used in the `getSourceNames` function. -const gSourceNamesStore = new Map(); - -/** -* Takes a string and returns an object containing all the properties -* available on an URL instance, with additional properties (fileName), -* Leverages caching. -* -* @param {String} location -* @return {Object?} An object containing most properties available -* in https://developer.mozilla.org/en-US/docs/Web/API/URL -*/ - -function parseURL(location) { - let url = gURLStore.get(location); - - if (url !== void 0) { - return url; - } - - try { - url = new URL(location); - // The callers were generally written to expect a URL from - // sdk/url, which is subtly different. So, work around some - // important differences here. - url = { - href: url.href, - protocol: url.protocol, - host: url.host, - hostname: url.hostname, - port: url.port || null, - pathname: url.pathname, - search: url.search, - hash: url.hash, - username: url.username, - password: url.password, - origin: url.origin - }; - - // Definitions: - // Example: https://foo.com:8888/file.js - // `hostname`: "foo.com" - // `host`: "foo.com:8888" - let isChrome = isChromeScheme(location); - - url.fileName = url.pathname ? url.pathname.slice(url.pathname.lastIndexOf("/") + 1) || "/" : "/"; - - if (isChrome) { - url.hostname = null; - url.host = null; - } - - gURLStore.set(location, url); - return url; - } catch (e) { - gURLStore.set(location, null); - return null; - } -} - -/** -* Parse a source into a short and long name as well as a host name. -* -* @param {String} source -* The source to parse. Can be a URI or names like "(eval)" or -* "self-hosted". -* @return {Object} -* An object with the following properties: -* - {String} short: A short name for the source. -* - "http://page.com/test.js#go?q=query" -> "test.js" -* - {String} long: The full, long name for the source, with - hash/query stripped. -* - "http://page.com/test.js#go?q=query" -> "http://page.com/test.js" -* - {String?} host: If available, the host name for the source. -* - "http://page.com/test.js#go?q=query" -> "page.com" -*/ -function getSourceNames(source) { - let data = gSourceNamesStore.get(source); - - if (data) { - return data; - } - - let short, long, host; - const sourceStr = source ? String(source) : ""; - - // If `data:...` uri - if (isDataScheme(sourceStr)) { - let commaIndex = sourceStr.indexOf(","); - if (commaIndex > -1) { - // The `short` name for a data URI becomes `data:` followed by the actual - // encoded content, omitting the MIME type, and charset. - short = `data:${sourceStr.substring(commaIndex + 1)}`.slice(0, 100); - let result = { short, long: sourceStr }; - gSourceNamesStore.set(source, result); - return result; - } - } - - // If Scratchpad URI, like "Scratchpad/1"; no modifications, - // and short/long are the same. - if (isScratchpadScheme(sourceStr)) { - let result = { short: sourceStr, long: sourceStr }; - gSourceNamesStore.set(source, result); - return result; - } - - const parsedUrl = parseURL(sourceStr); - - if (!parsedUrl) { - // Malformed URI. - long = sourceStr; - short = sourceStr.slice(0, 100); - } else { - host = parsedUrl.host; - - long = parsedUrl.href; - if (parsedUrl.hash) { - long = long.replace(parsedUrl.hash, ""); - } - if (parsedUrl.search) { - long = long.replace(parsedUrl.search, ""); - } - - short = parsedUrl.fileName; - // If `short` is just a slash, and we actually have a path, - // strip the slash and parse again to get a more useful short name. - // e.g. "http://foo.com/bar/" -> "bar", rather than "/" - if (short === "/" && parsedUrl.pathname !== "/") { - short = parseURL(long.replace(/\/$/, "")).fileName; - } - } - - if (!short) { - if (!long) { - long = UNKNOWN_SOURCE_STRING; - } - short = long.slice(0, 100); - } - - let result = { short, long, host }; - gSourceNamesStore.set(source, result); - return result; -} - -// For the functions below, we assume that we will never access the location -// argument out of bounds, which is indeed the vast majority of cases. -// -// They are written this way because they are hot. Each frame is checked for -// being content or chrome when processing the profile. - -function isColonSlashSlash(location, i = 0) { - return location.charCodeAt(++i) === CHAR_CODE_COLON && location.charCodeAt(++i) === CHAR_CODE_SLASH && location.charCodeAt(++i) === CHAR_CODE_SLASH; -} - -/** -* Checks for a Scratchpad URI, like "Scratchpad/1" -*/ -function isScratchpadScheme(location, i = 0) { - return location.charCodeAt(i) === CHAR_CODE_CAP_S && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_H && location.charCodeAt(++i) === CHAR_CODE_P && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_D && location.charCodeAt(++i) === CHAR_CODE_SLASH; -} - -function isDataScheme(location, i = 0) { - return location.charCodeAt(i) === CHAR_CODE_D && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_COLON; -} - -function isContentScheme(location, i = 0) { - let firstChar = location.charCodeAt(i); - - switch (firstChar) { - // "http://" or "https://" - case CHAR_CODE_H: - if (location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_P) { - if (location.charCodeAt(i + 1) === CHAR_CODE_S) { - ++i; - } - return isColonSlashSlash(location, i); - } - return false; - - // "file://" - case CHAR_CODE_F: - if (location.charCodeAt(++i) === CHAR_CODE_I && location.charCodeAt(++i) === CHAR_CODE_L && location.charCodeAt(++i) === CHAR_CODE_E) { - return isColonSlashSlash(location, i); - } - return false; - - // "app://" - case CHAR_CODE_A: - if (location.charCodeAt(++i) == CHAR_CODE_P && location.charCodeAt(++i) == CHAR_CODE_P) { - return isColonSlashSlash(location, i); - } - return false; - - // "blob:" - case CHAR_CODE_B: - if (location.charCodeAt(++i) == CHAR_CODE_L && location.charCodeAt(++i) == CHAR_CODE_O && location.charCodeAt(++i) == CHAR_CODE_B && location.charCodeAt(++i) == CHAR_CODE_COLON) { - return isContentScheme(location, i + 1); - } - return false; - - default: - return false; - } -} - -function isChromeScheme(location, i = 0) { - let firstChar = location.charCodeAt(i); - - switch (firstChar) { - // "chrome://" - case CHAR_CODE_C: - if (location.charCodeAt(++i) === CHAR_CODE_H && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_O && location.charCodeAt(++i) === CHAR_CODE_M && location.charCodeAt(++i) === CHAR_CODE_E) { - return isColonSlashSlash(location, i); - } - return false; - - // "resource://" - case CHAR_CODE_R: - if (location.charCodeAt(++i) === CHAR_CODE_E && location.charCodeAt(++i) === CHAR_CODE_S && location.charCodeAt(++i) === CHAR_CODE_O && location.charCodeAt(++i) === CHAR_CODE_U && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_E) { - return isColonSlashSlash(location, i); - } - return false; - - // "jar:file://" - case CHAR_CODE_J: - if (location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_COLON && location.charCodeAt(++i) === CHAR_CODE_F && location.charCodeAt(++i) === CHAR_CODE_I && location.charCodeAt(++i) === CHAR_CODE_L && location.charCodeAt(++i) === CHAR_CODE_E) { - return isColonSlashSlash(location, i); - } - return false; - - default: - return false; - } -} - -function isWASM(location, i = 0) { - return ( - // "wasm-function[" - location.charCodeAt(i) === CHAR_CODE_W && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_S && location.charCodeAt(++i) === CHAR_CODE_M && location.charCodeAt(++i) === CHAR_CODE_DASH && location.charCodeAt(++i) === CHAR_CODE_F && location.charCodeAt(++i) === CHAR_CODE_U && location.charCodeAt(++i) === CHAR_CODE_N && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_I && location.charCodeAt(++i) === CHAR_CODE_O && location.charCodeAt(++i) === CHAR_CODE_N && location.charCodeAt(++i) === CHAR_CODE_L_SQUARE_BRACKET - ); -} - -/** -* A utility method to get the file name from a sourcemapped location -* The sourcemap location can be in any form. This method returns a -* formatted file name for different cases like Windows or OSX. -* @param source -* @returns String -*/ -function getSourceMappedFile(source) { - // If sourcemapped source is a OSX path, return - // the characters after last "/". - // If sourcemapped source is a Windowss path, return - // the characters after last "\\". - if (source.lastIndexOf("/") >= 0) { - source = source.slice(source.lastIndexOf("/") + 1); - } else if (source.lastIndexOf("\\") >= 0) { - source = source.slice(source.lastIndexOf("\\") + 1); - } - return source; -} - -module.exports = { - parseURL, - getSourceNames, - isScratchpadScheme, - isChromeScheme, - isContentScheme, - isWASM, - isDataScheme, - getSourceMappedFile -}; - -/***/ }), - -/***/ 3638: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// This file is a chrome-API-free version of the module -// devtools/client/shared/unicode-url.js in the mozilla-central repository, so -// that it can be used in Chrome-API-free applications, such as the Launchpad. -// But because of this, it cannot take advantage of utilizing chrome APIs and -// should implement the similar functionalities on its own. -// -// Please keep in mind that if the feature in this file has changed, don't -// forget to also change that accordingly in -// devtools/client/shared/unicode-url.js in the mozilla-central repository. - - - -const punycode = __webpack_require__(3641); - -/** - * Gets a readble Unicode hostname from a hostname. - * - * If the `hostname` is a readable ASCII hostname, such as example.org, then - * this function will simply return the original `hostname`. - * - * If the `hostname` is a Punycode hostname representing a Unicode domain name, - * such as xn--g6w.xn--8pv, then this function will return the readable Unicode - * domain name by decoding the Punycode hostname. - * - * @param {string} hostname - * the hostname from which the Unicode hostname will be - * parsed, such as example.org, xn--g6w.xn--8pv. - * @return {string} The Unicode hostname. It may be the same as the `hostname` - * passed to this function if the `hostname` itself is - * a readable ASCII hostname or a Unicode hostname. - */ -function getUnicodeHostname(hostname) { - try { - return punycode.toUnicode(hostname); - } catch (err) {} - return hostname; -} - -/** - * Gets a readble Unicode URL pathname from a URL pathname. - * - * If the `urlPath` is a readable ASCII URL pathname, such as /a/b/c.js, then - * this function will simply return the original `urlPath`. - * - * If the `urlPath` is a URI-encoded pathname, such as %E8%A9%A6/%E6%B8%AC.js, - * then this function will return the readable Unicode pathname. - * - * If the `urlPath` is a malformed URL pathname, then this function will simply - * return the original `urlPath`. - * - * @param {string} urlPath - * the URL path from which the Unicode URL path will be parsed, - * such as /a/b/c.js, %E8%A9%A6/%E6%B8%AC.js. - * @return {string} The Unicode URL Path. It may be the same as the `urlPath` - * passed to this function if the `urlPath` itself is a readable - * ASCII url or a Unicode url. - */ -function getUnicodeUrlPath(urlPath) { - try { - return decodeURIComponent(urlPath); - } catch (err) {} - return urlPath; -} - -/** - * Gets a readable Unicode URL from a URL. - * - * If the `url` is a readable ASCII URL, such as http://example.org/a/b/c.js, - * then this function will simply return the original `url`. - * - * If the `url` includes either an unreadable Punycode domain name or an - * unreadable URI-encoded pathname, such as - * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js, then this function will return - * the readable URL by decoding all its unreadable URL components to Unicode - * characters. - * - * If the `url` is a malformed URL, then this function will return the original - * `url`. - * - * If the `url` is a data: URI, then this function will return the original - * `url`. - * - * @param {string} url - * the full URL, or a data: URI. from which the readable URL - * will be parsed, such as, http://example.org/a/b/c.js, - * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js - * @return {string} The readable URL. It may be the same as the `url` passed to - * this function if the `url` itself is readable. - */ -function getUnicodeUrl(url) { - try { - const { protocol, hostname } = new URL(url); - if (protocol === "data:") { - // Never convert a data: URI. - return url; - } - const readableHostname = getUnicodeHostname(hostname); - url = decodeURIComponent(url); - return url.replace(hostname, readableHostname); - } catch (err) {} - return url; -} - -module.exports = { - getUnicodeHostname, - getUnicodeUrlPath, - getUnicodeUrl -}; - -/***/ }), - -/***/ 3639: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactRedux = __webpack_require__(3592); - -var _actions = __webpack_require__(1354); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = __webpack_require__(3590); - -__webpack_require__(1338); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class ReactComponentStack extends _react.PureComponent { - render() { - const { componentStack } = this.props.extra.react; - return _react2.default.createElement( - "div", - { className: "pane frames" }, - _react2.default.createElement( - "ul", - null, - componentStack.slice().reverse().map((component, index) => _react2.default.createElement( - "li", - { key: index }, - component - )) - ) - ); - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const mapStateToProps = state => ({ - extra: (0, _selectors.getExtra)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ReactComponentStack); - -/***/ }), - -/***/ 364: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3640: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.toggleSkipPausing = toggleSkipPausing; - -var _selectors = __webpack_require__(3590); - -/** - * @memberof actions/pause - * @static - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function toggleSkipPausing() { - return async ({ dispatch, client, getState, sourceMaps }) => { - const skipPausing = !(0, _selectors.getSkipPausing)(getState()); - - // NOTE: enable this when we land the endpoint in m-c - // await client.setSkipPausing(skipPausing); - - dispatch({ type: "TOGGLE_SKIP_PAUSING", skipPausing }); - }; -} - -/***/ }), - -/***/ 3641: -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */ -;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw new RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * https://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.4.1', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - true - ) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { - return punycode; - }).call(exports, __webpack_require__, exports, module), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { - // in Node.js, io.js, or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { - // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { - // in Rhino or a web browser - root.punycode = punycode; - } - -}(this)); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(793)(module), __webpack_require__(792))) - -/***/ }), - -/***/ 3642: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_3642__; - -/***/ }), - -/***/ 3643: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_3643__; - -/***/ }), - -/***/ 3644: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const validProtocols = /(http|https|ftp|data|resource|chrome):/i; -const tokenSplitRegex = /(\s|\'|\"|\\)+/; -const ELLIPSIS = "\u2026"; -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Returns true if the given object is a grip (see RDP protocol) - */ -function isGrip(object) { - return object && object.actor; -} - -function escapeNewLines(value) { - return value.replace(/\r/gm, "\\r").replace(/\n/gm, "\\n"); -} - -// Map from character code to the corresponding escape sequence. \0 -// isn't here because it would require special treatment in some -// situations. \b, \f, and \v aren't here because they aren't very -// common. \' isn't here because there's no need, we only -// double-quote strings. -const escapeMap = { - // Tab. - 9: "\\t", - // Newline. - 0xa: "\\n", - // Carriage return. - 0xd: "\\r", - // Quote. - 0x22: '\\"', - // Backslash. - 0x5c: "\\\\" -}; - -// Regexp that matches any character we might possibly want to escape. -// Note that we over-match here, because it's difficult to, say, match -// an unpaired surrogate with a regexp. The details are worked out by -// the replacement function; see |escapeString|. -const escapeRegexp = new RegExp("[" + -// Quote and backslash. -'"\\\\' + -// Controls. -"\x00-\x1f" + -// More controls. -"\x7f-\x9f" + -// BOM -"\ufeff" + -// Specials, except for the replacement character. -"\ufff0-\ufffc\ufffe\uffff" + -// Surrogates. -"\ud800-\udfff" + -// Mathematical invisibles. -"\u2061-\u2064" + -// Line and paragraph separators. -"\u2028-\u2029" + -// Private use area. -"\ue000-\uf8ff" + "]", "g"); - -/** - * Escape a string so that the result is viewable and valid JS. - * Control characters, other invisibles, invalid characters, - * backslash, and double quotes are escaped. The resulting string is - * surrounded by double quotes. - * - * @param {String} str - * the input - * @param {Boolean} escapeWhitespace - * if true, TAB, CR, and NL characters will be escaped - * @return {String} the escaped string - */ -function escapeString(str, escapeWhitespace) { - return `"${str.replace(escapeRegexp, (match, offset) => { - const c = match.charCodeAt(0); - if (c in escapeMap) { - if (!escapeWhitespace && (c === 9 || c === 0xa || c === 0xd)) { - return match[0]; - } - return escapeMap[c]; - } - if (c >= 0xd800 && c <= 0xdfff) { - // Find the full code point containing the surrogate, with a - // special case for a trailing surrogate at the start of the - // string. - if (c >= 0xdc00 && offset > 0) { - --offset; - } - const codePoint = str.codePointAt(offset); - if (codePoint >= 0xd800 && codePoint <= 0xdfff) { - // Unpaired surrogate. - return `\\u${codePoint.toString(16)}`; - } else if (codePoint >= 0xf0000 && codePoint <= 0x10fffd) { - // Private use area. Because we visit each pair of a such a - // character, return the empty string for one half and the - // real result for the other, to avoid duplication. - if (c <= 0xdbff) { - return `\\u{${codePoint.toString(16)}}`; - } - return ""; - } - // Other surrogate characters are passed through. - return match; - } - return `\\u${`0000${c.toString(16)}`.substr(-4)}`; - })}"`; -} - -/** - * Escape a property name, if needed. "Escaping" in this context - * means surrounding the property name with quotes. - * - * @param {String} - * name the property name - * @return {String} either the input, or the input surrounded by - * quotes, properly quoted in JS syntax. - */ -function maybeEscapePropertyName(name) { - // Quote the property name if it needs quoting. This particular - // test is an approximation; see - // https://mathiasbynens.be/notes/javascript-properties. However, - // the full solution requires a fair amount of Unicode data, and so - // let's defer that until either it's important, or the \p regexp - // syntax lands, see - // https://github.com/tc39/proposal-regexp-unicode-property-escapes. - if (!/^\w+$/.test(name)) { - name = escapeString(name); - } - return name; -} - -function cropMultipleLines(text, limit) { - return escapeNewLines(cropString(text, limit)); -} - -function rawCropString(text, limit, alternativeText = ELLIPSIS) { - // Crop the string only if a limit is actually specified. - if (!limit || limit <= 0) { - return text; - } - - // Set the limit at least to the length of the alternative text - // plus one character of the original text. - if (limit <= alternativeText.length) { - limit = alternativeText.length + 1; - } - - const halfLimit = (limit - alternativeText.length) / 2; - - if (text.length > limit) { - return text.substr(0, Math.ceil(halfLimit)) + alternativeText + text.substr(text.length - Math.floor(halfLimit)); - } - - return text; -} - -function cropString(text, limit, alternativeText) { - return rawCropString(sanitizeString(`${text}`), limit, alternativeText); -} - -function sanitizeString(text) { - // Replace all non-printable characters, except of - // (horizontal) tab (HT: \x09) and newline (LF: \x0A, CR: \x0D), - // with unicode replacement character (u+fffd). - // eslint-disable-next-line no-control-regex - const re = new RegExp("[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]", "g"); - return text.replace(re, "\ufffd"); -} - -function parseURLParams(url) { - url = new URL(url); - return parseURLEncodedText(url.searchParams); -} - -function parseURLEncodedText(text) { - const params = []; - - // In case the text is empty just return the empty parameters - if (text == "") { - return params; - } - - const searchParams = new URLSearchParams(text); - const entries = [...searchParams.entries()]; - return entries.map(entry => { - return { - name: entry[0], - value: entry[1] - }; - }); -} - -function getFileName(url) { - const split = splitURLBase(url); - return split.name; -} - -function splitURLBase(url) { - if (!isDataURL(url)) { - return splitURLTrue(url); - } - return {}; -} - -function getURLDisplayString(url) { - return cropString(url); -} - -function isDataURL(url) { - return url && url.substr(0, 5) == "data:"; -} - -function splitURLTrue(url) { - const reSplitFile = /(.*?):\/{2,3}([^\/]*)(.*?)([^\/]*?)($|\?.*)/; - const m = reSplitFile.exec(url); - - if (!m) { - return { - name: url, - path: url - }; - } else if (m[4] == "" && m[5] == "") { - return { - protocol: m[1], - domain: m[2], - path: m[3], - name: m[3] != "/" ? m[3] : m[2] - }; - } - - return { - protocol: m[1], - domain: m[2], - path: m[2] + m[3], - name: m[4] + m[5] - }; -} - -/** - * Wrap the provided render() method of a rep in a try/catch block that will - * render a fallback rep if the render fails. - */ -function wrapRender(renderMethod) { - const wrappedFunction = function (props) { - try { - return renderMethod.call(this, props); - } catch (e) { - console.error(e); - return span({ - className: "objectBox objectBox-failure", - title: "This object could not be rendered, " + "please file a bug on bugzilla.mozilla.org" - }, - /* Labels have to be hardcoded for reps, see Bug 1317038. */ - "Invalid object"); - } - }; - wrappedFunction.propTypes = renderMethod.propTypes; - return wrappedFunction; -} - -/** - * Get preview items from a Grip. - * - * @param {Object} Grip from which we want the preview items - * @return {Array} Array of the preview items of the grip, or an empty array - * if the grip does not have preview items - */ -function getGripPreviewItems(grip) { - if (!grip) { - return []; - } - - // Promise resolved value Grip - if (grip.promiseState && grip.promiseState.value) { - return [grip.promiseState.value]; - } - - // Array Grip - if (grip.preview && grip.preview.items) { - return grip.preview.items; - } - - // Node Grip - if (grip.preview && grip.preview.childNodes) { - return grip.preview.childNodes; - } - - // Set or Map Grip - if (grip.preview && grip.preview.entries) { - return grip.preview.entries.reduce((res, entry) => res.concat(entry), []); - } - - // Event Grip - if (grip.preview && grip.preview.target) { - const keys = Object.keys(grip.preview.properties); - const values = Object.values(grip.preview.properties); - return [grip.preview.target, ...keys, ...values]; - } - - // RegEx Grip - if (grip.displayString) { - return [grip.displayString]; - } - - // Generic Grip - if (grip.preview && grip.preview.ownProperties) { - let propertiesValues = Object.values(grip.preview.ownProperties).map(property => property.value || property); - - const propertyKeys = Object.keys(grip.preview.ownProperties); - propertiesValues = propertiesValues.concat(propertyKeys); - - // ArrayBuffer Grip - if (grip.preview.safeGetterValues) { - propertiesValues = propertiesValues.concat(Object.values(grip.preview.safeGetterValues).map(property => property.getterValue || property)); - } - - return propertiesValues; - } - - return []; -} - -/** - * Get the type of an object. - * - * @param {Object} Grip from which we want the type. - * @param {boolean} noGrip true if the object is not a grip. - * @return {boolean} - */ -function getGripType(object, noGrip) { - if (noGrip || Object(object) !== object) { - return typeof object; - } - if (object.type === "object") { - return object.class; - } - return object.type; -} - -/** - * Determines whether a grip is a string containing a URL. - * - * @param string grip - * The grip, which may contain a URL. - * @return boolean - * Whether the grip is a string containing a URL. - */ -function containsURL(grip) { - // An URL can't be shorter than 5 char (e.g. "ftp:"). - if (typeof grip !== "string" || grip.length < 5) { - return false; - } - - return validProtocols.test(grip); -} - -/** - * Determines whether a string token is a valid URL. - * - * @param string token - * The token. - * @return boolean - * Whenther the token is a URL. - */ -function isURL(token) { - try { - if (!validProtocols.test(token)) { - return false; - } - new URL(token); - return true; - } catch (e) { - return false; - } -} - -/** - * Returns new array in which `char` are interleaved between the original items. - * - * @param {Array} items - * @param {String} char - * @returns Array - */ -function interleave(items, char) { - return items.reduce((res, item, index) => { - if (index !== items.length - 1) { - return res.concat(item, char); - } - return res.concat(item); - }, []); -} - -const ellipsisElement = span({ - key: "more", - className: "more-ellipsis", - title: `more${ELLIPSIS}` -}, ELLIPSIS); - -module.exports = { - interleave, - isGrip, - isURL, - cropString, - containsURL, - rawCropString, - sanitizeString, - escapeString, - wrapRender, - cropMultipleLines, - parseURLParams, - parseURLEncodedText, - getFileName, - getURLDisplayString, - maybeEscapePropertyName, - getGripPreviewItems, - getGripType, - tokenSplitRegex, - ellipsisElement, - ELLIPSIS -}; - -/***/ }), - -/***/ 3645: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -module.exports = { - MODE: { - TINY: Symbol("TINY"), - SHORT: Symbol("SHORT"), - LONG: Symbol("LONG") - } -}; - -/***/ }), - -/***/ 3646: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { - originalToGeneratedId, - generatedToOriginalId, - isGeneratedId, - isOriginalId -} = __webpack_require__(3652); - -const { workerUtils: { WorkerDispatcher } } = __webpack_require__(3651); - -const dispatcher = new WorkerDispatcher(); - -const getOriginalURLs = dispatcher.task("getOriginalURLs"); -const getGeneratedRanges = dispatcher.task("getGeneratedRanges", { - queue: true -}); -const getGeneratedLocation = dispatcher.task("getGeneratedLocation", { - queue: true -}); -const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", { - queue: true -}); -const getOriginalLocation = dispatcher.task("getOriginalLocation"); -const getLocationScopes = dispatcher.task("getLocationScopes"); -const getOriginalSourceText = dispatcher.task("getOriginalSourceText"); -const applySourceMap = dispatcher.task("applySourceMap"); -const clearSourceMaps = dispatcher.task("clearSourceMaps"); -const hasMappedSource = dispatcher.task("hasMappedSource"); - -module.exports = { - originalToGeneratedId, - generatedToOriginalId, - isGeneratedId, - isOriginalId, - hasMappedSource, - getOriginalURLs, - getGeneratedRanges, - getGeneratedLocation, - getAllGeneratedLocations, - getOriginalLocation, - getLocationScopes, - getOriginalSourceText, - applySourceMap, - clearSourceMaps, - startSourceMapWorker: dispatcher.start.bind(dispatcher), - stopSourceMapWorker: dispatcher.stop.bind(dispatcher) -}; - -/***/ }), - -/***/ 3647: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -__webpack_require__(3672); - -// Load all existing rep templates -const Undefined = __webpack_require__(3673); -const Null = __webpack_require__(3674); -const StringRep = __webpack_require__(3648); -const Number = __webpack_require__(3675); -const ArrayRep = __webpack_require__(3649); -const Obj = __webpack_require__(3676); -const SymbolRep = __webpack_require__(3677); -const InfinityRep = __webpack_require__(3678); -const NaNRep = __webpack_require__(3679); -const Accessor = __webpack_require__(3680); - -// DOM types (grips) -const Attribute = __webpack_require__(3681); -const DateTime = __webpack_require__(3682); -const Document = __webpack_require__(3683); -const DocumentType = __webpack_require__(3684); -const Event = __webpack_require__(3685); -const Func = __webpack_require__(3658); -const PromiseRep = __webpack_require__(3686); -const RegExp = __webpack_require__(3687); -const StyleSheet = __webpack_require__(3688); -const CommentNode = __webpack_require__(3689); -const ElementNode = __webpack_require__(3690); -const TextNode = __webpack_require__(3691); -const ErrorRep = __webpack_require__(3660); -const Window = __webpack_require__(3692); -const ObjectWithText = __webpack_require__(3693); -const ObjectWithURL = __webpack_require__(3694); -const GripArray = __webpack_require__(3661); -const GripMap = __webpack_require__(3663); -const GripMapEntry = __webpack_require__(3664); -const Grip = __webpack_require__(3656); - -// List of all registered template. -// XXX there should be a way for extensions to register a new -// or modify an existing rep. -const reps = [RegExp, StyleSheet, Event, DateTime, CommentNode, ElementNode, TextNode, Attribute, Func, PromiseRep, ArrayRep, Document, DocumentType, Window, ObjectWithText, ObjectWithURL, ErrorRep, GripArray, GripMap, GripMapEntry, Grip, Undefined, Null, StringRep, Number, SymbolRep, InfinityRep, NaNRep, Accessor]; - -/** - * Generic rep that is used for rendering native JS types or an object. - * The right template used for rendering is picked automatically according - * to the current value type. The value must be passed is as 'object' - * property. - */ -const Rep = function (props) { - const { object, defaultRep } = props; - const rep = getRep(object, defaultRep, props.noGrip); - return rep(props); -}; - -// Helpers - -/** - * Return a rep object that is responsible for rendering given - * object. - * - * @param object {Object} Object to be rendered in the UI. This - * can be generic JS object as well as a grip (handle to a remote - * debuggee object). - * - * @param defaultRep {React.Component} The default template - * that should be used to render given object if none is found. - * - * @param noGrip {Boolean} If true, will only check reps not made for remote - * objects. - */ -function getRep(object, defaultRep = Obj, noGrip = false) { - for (let i = 0; i < reps.length; i++) { - const rep = reps[i]; - try { - // supportsObject could return weight (not only true/false - // but a number), which would allow to priorities templates and - // support better extensibility. - if (rep.supportsObject(object, noGrip)) { - return rep.rep; - } - } catch (err) { - console.error(err); - } - } - - return defaultRep.rep; -} - -module.exports = { - Rep, - REPS: { - Accessor, - ArrayRep, - Attribute, - CommentNode, - DateTime, - Document, - DocumentType, - ElementNode, - ErrorRep, - Event, - Func, - Grip, - GripArray, - GripMap, - GripMapEntry, - InfinityRep, - NaNRep, - Null, - Number, - Obj, - ObjectWithText, - ObjectWithURL, - PromiseRep, - RegExp, - Rep, - StringRep, - StyleSheet, - SymbolRep, - TextNode, - Undefined, - Window - }, - // Exporting for tests - getRep -}; - -/***/ }), - -/***/ 3648: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); - -const { - containsURL, - isURL, - escapeString, - getGripType, - rawCropString, - sanitizeString, - wrapRender, - isGrip, - tokenSplitRegex, - ELLIPSIS -} = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { a, span } = dom; - -/** - * Renders a string. String value is enclosed within quotes. - */ -StringRep.propTypes = { - useQuotes: PropTypes.bool, - escapeWhitespace: PropTypes.bool, - style: PropTypes.object, - cropLimit: PropTypes.number.isRequired, - member: PropTypes.object, - object: PropTypes.object.isRequired, - openLink: PropTypes.func, - className: PropTypes.string -}; - -function StringRep(props) { - const { - className, - style, - cropLimit, - object, - useQuotes = true, - escapeWhitespace = true, - member, - openLink - } = props; - - let text = object; - - const isLong = isLongString(object); - const isOpen = member && member.open; - const shouldCrop = !isOpen && cropLimit && text.length > cropLimit; - - if (isLong) { - text = maybeCropLongString({ - shouldCrop, - cropLimit - }, text); - - const { fullText } = object; - if (isOpen && fullText) { - text = fullText; - } - } - - text = formatText({ - useQuotes, - escapeWhitespace - }, text); - - const config = getElementConfig({ - className, - style, - actor: object.actor - }); - - if (!isLong) { - if (containsURL(text)) { - return span(config, ...getLinkifiedElements(text, shouldCrop && cropLimit, openLink)); - } - - // Cropping of longString has been handled before formatting. - text = maybeCropString({ - isLong, - shouldCrop, - cropLimit - }, text); - } - - return span(config, text); -} - -function maybeCropLongString(opts, text) { - const { shouldCrop, cropLimit } = opts; - - const { initial, length } = text; - - text = shouldCrop ? initial.substring(0, cropLimit) : initial; - - if (text.length < length) { - text += ELLIPSIS; - } - - return text; -} - -function formatText(opts, text) { - const { useQuotes, escapeWhitespace } = opts; - - return useQuotes ? escapeString(text, escapeWhitespace) : sanitizeString(text); -} - -function getElementConfig(opts) { - const { className, style, actor } = opts; - - const config = {}; - - if (actor) { - config["data-link-actor-id"] = actor; - } - - const classNames = ["objectBox", "objectBox-string"]; - if (className) { - classNames.push(className); - } - config.className = classNames.join(" "); - - if (style) { - config.style = style; - } - - return config; -} - -function maybeCropString(opts, text) { - const { shouldCrop, cropLimit } = opts; - - return shouldCrop ? rawCropString(text, cropLimit) : text; -} - -/** - * Get an array of the elements representing the string, cropped if needed, - * with actual links. - * - * @param {String} text: The actual string to linkify. - * @param {Integer | null} cropLimit - * @param {Function} openLink: Function handling the link opening. - * @returns {Array} - */ -function getLinkifiedElements(text, cropLimit, openLink) { - const halfLimit = Math.ceil((cropLimit - ELLIPSIS.length) / 2); - const startCropIndex = cropLimit ? halfLimit : null; - const endCropIndex = cropLimit ? text.length - halfLimit : null; - - // As we walk through the tokens of the source string, we make sure to - // preserve the original whitespace that separated the tokens. - let currentIndex = 0; - const items = []; - for (const token of text.split(tokenSplitRegex)) { - if (isURL(token)) { - // Let's grab all the non-url strings before the link. - const tokenStart = text.indexOf(token, currentIndex); - let nonUrlText = text.slice(currentIndex, tokenStart); - nonUrlText = getCroppedString(nonUrlText, currentIndex, startCropIndex, endCropIndex); - if (nonUrlText) { - items.push(nonUrlText); - } - - // Update the index to match the beginning of the token. - currentIndex = tokenStart; - - const linkText = getCroppedString(token, currentIndex, startCropIndex, endCropIndex); - if (linkText) { - items.push(a({ - className: "url", - title: token, - draggable: false, - onClick: openLink ? e => { - e.preventDefault(); - openLink(token); - } : null - }, linkText)); - } - - currentIndex = tokenStart + token.length; - } - } - - // Clean up any non-URL text at the end of the source string, - // i.e. not handled in the loop. - if (currentIndex !== text.length) { - let nonUrlText = text.slice(currentIndex, text.length); - if (currentIndex < endCropIndex) { - const cutIndex = endCropIndex - currentIndex; - nonUrlText = nonUrlText.substring(cutIndex); - } - items.push(nonUrlText); - } - - return items; -} - -/** - * Returns a cropped substring given an offset, start and end crop indices in a - * parent string. - * - * @param {String} text: The substring to crop. - * @param {Integer} offset: The offset corresponding to the index at which - * the substring is in the parent string. - * @param {Integer|null} startCropIndex: the index where the start of the crop - * should happen in the parent string. - * @param {Integer|null} endCropIndex: the index where the end of the crop - * should happen in the parent string - * @returns {String|null} The cropped substring, or null if the text is - * completly cropped. - */ -function getCroppedString(text, offset = 0, startCropIndex, endCropIndex) { - if (!startCropIndex) { - return text; - } - - const start = offset; - const end = offset + text.length; - - const shouldBeVisible = !(start >= startCropIndex && end <= endCropIndex); - if (!shouldBeVisible) { - return null; - } - - const shouldCropEnd = start < startCropIndex && end > startCropIndex; - const shouldCropStart = start < endCropIndex && end > endCropIndex; - if (shouldCropEnd) { - const cutIndex = startCropIndex - start; - return text.substring(0, cutIndex) + ELLIPSIS + (shouldCropStart ? text.substring(endCropIndex - start) : ""); - } - - if (shouldCropStart) { - // The string should be cropped at the beginning. - const cutIndex = endCropIndex - start; - return text.substring(cutIndex); - } - - return text; -} - -function isLongString(object) { - return object && object.type === "longString"; -} - -function supportsObject(object, noGrip = false) { - if (noGrip === false && isGrip(object)) { - return isLongString(object); - } - - return getGripType(object, noGrip) == "string"; -} - -// Exports from this module - -module.exports = { - rep: wrapRender(StringRep), - supportsObject, - isLongString -}; - -/***/ }), - -/***/ 3649: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const dom = __webpack_require__(3643); -const PropTypes = __webpack_require__(3642); -const { wrapRender } = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); -const { span } = dom; - -const ModePropType = PropTypes.oneOf( -// @TODO Change this to Object.values when supported in Node's version of V8 -Object.keys(MODE).map(key => MODE[key])); - -/** - * Renders an array. The array is enclosed by left and right bracket - * and the max number of rendered items depends on the current mode. - */ -ArrayRep.propTypes = { - mode: ModePropType, - object: PropTypes.array.isRequired -}; - -function ArrayRep(props) { - const { object, mode = MODE.SHORT } = props; - - let items; - let brackets; - const needSpace = function (space) { - return space ? { left: "[ ", right: " ]" } : { left: "[", right: "]" }; - }; - - if (mode === MODE.TINY) { - const isEmpty = object.length === 0; - if (isEmpty) { - items = []; - } else { - items = [span({ - className: "more-ellipsis", - title: "more…" - }, "…")]; - } - brackets = needSpace(false); - } else { - items = arrayIterator(props, object, maxLengthMap.get(mode)); - brackets = needSpace(items.length > 0); - } - - return span({ - className: "objectBox objectBox-array" - }, span({ - className: "arrayLeftBracket" - }, brackets.left), ...items, span({ - className: "arrayRightBracket" - }, brackets.right)); -} - -function arrayIterator(props, array, max) { - const items = []; - - for (let i = 0; i < array.length && i < max; i++) { - const config = { - mode: MODE.TINY, - delim: i == array.length - 1 ? "" : ", " - }; - let item; - - try { - item = ItemRep(_extends({}, props, config, { - object: array[i] - })); - } catch (exc) { - item = ItemRep(_extends({}, props, config, { - object: exc - })); - } - items.push(item); - } - - if (array.length > max) { - items.push(span({ - className: "more-ellipsis", - title: "more…" - }, "…")); - } - - return items; -} - -/** - * Renders array item. Individual values are separated by a comma. - */ -ItemRep.propTypes = { - object: PropTypes.any.isRequired, - delim: PropTypes.string.isRequired, - mode: ModePropType -}; - -function ItemRep(props) { - const { Rep } = __webpack_require__(3647); - - const { object, delim, mode } = props; - return span({}, Rep(_extends({}, props, { - object: object, - mode: mode - })), delim); -} - -function getLength(object) { - return object.length; -} - -function supportsObject(object) { - return Array.isArray(object) || Object.prototype.toString.call(object) === "[object Arguments]"; -} - -const maxLengthMap = new Map(); -maxLengthMap.set(MODE.SHORT, 3); -maxLengthMap.set(MODE.LONG, 10); - -// Exports from this module -module.exports = { - rep: wrapRender(ArrayRep), - supportsObject, - maxLengthMap, - getLength, - ModePropType -}; - -/***/ }), - -/***/ 365: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3650: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); -const { maybeEscapePropertyName, wrapRender } = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); - -const { span } = __webpack_require__(3643); - -/** - * Property for Obj (local JS objects), Grip (remote JS objects) - * and GripMap (remote JS maps and weakmaps) reps. - * It's used to render object properties. - */ -PropRep.propTypes = { - // Property name. - name: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired, - // Equal character rendered between property name and value. - equal: PropTypes.string, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func, - // Normally a PropRep will quote a property name that isn't valid - // when unquoted; but this flag can be used to suppress the - // quoting. - suppressQuotes: PropTypes.bool -}; - -/** - * Function that given a name, a delimiter and an object returns an array - * of React elements representing an object property (e.g. `name: value`) - * - * @param {Object} props - * @return {Array} Array of React elements. - */ -function PropRep(props) { - const Grip = __webpack_require__(3656); - const { Rep } = __webpack_require__(3647); - - let { name, mode, equal, suppressQuotes } = props; - - let key; - // The key can be a simple string, for plain objects, - // or another object for maps and weakmaps. - if (typeof name === "string") { - if (!suppressQuotes) { - name = maybeEscapePropertyName(name); - } - key = span({ className: "nodeName" }, name); - } else { - key = Rep(_extends({}, props, { - className: "nodeName", - object: name, - mode: mode || MODE.TINY, - defaultRep: Grip - })); - } - - return [key, span({ - className: "objectEqual" - }, equal), Rep(_extends({}, props))]; -} - -// Exports from this module -module.exports = wrapRender(PropRep); - -/***/ }), - -/***/ 3651: -/***/ (function(module, exports, __webpack_require__) { - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const networkRequest = __webpack_require__(3653); -const workerUtils = __webpack_require__(3654); - -module.exports = { - networkRequest, - workerUtils -}; - -/***/ }), - -/***/ 3652: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const md5 = __webpack_require__(248); - -function originalToGeneratedId(originalId) { - const match = originalId.match(/(.*)\/originalSource/); - return match ? match[1] : ""; -} - -function generatedToOriginalId(generatedId, url) { - return `${generatedId}/originalSource-${md5(url)}`; -} - -function isOriginalId(id) { - return !!id.match(/\/originalSource/); -} - -function isGeneratedId(id) { - return !isOriginalId(id); -} - -/** - * Trims the query part or reference identifier of a URL string, if necessary. - */ -function trimUrlQuery(url) { - const length = url.length; - const q1 = url.indexOf("?"); - const q2 = url.indexOf("&"); - const q3 = url.indexOf("#"); - const q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length); - - return url.slice(0, q); -} - -// Map suffix to content type. -const contentMap = { - js: "text/javascript", - jsm: "text/javascript", - mjs: "text/javascript", - ts: "text/typescript", - tsx: "text/typescript-jsx", - jsx: "text/jsx", - vue: "text/vue", - coffee: "text/coffeescript", - elm: "text/elm", - cljs: "text/x-clojure" -}; - -/** - * Returns the content type for the specified URL. If no specific - * content type can be determined, "text/plain" is returned. - * - * @return String - * The content type. - */ -function getContentType(url) { - url = trimUrlQuery(url); - const dot = url.lastIndexOf("."); - if (dot >= 0) { - const name = url.substring(dot + 1); - if (name in contentMap) { - return contentMap[name]; - } - } - return "text/plain"; -} - -module.exports = { - originalToGeneratedId, - generatedToOriginalId, - isOriginalId, - isGeneratedId, - getContentType, - contentMapForTesting: contentMap -}; - -/***/ }), - -/***/ 3653: -/***/ (function(module, exports) { - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function networkRequest(url, opts) { - return fetch(url, { - cache: opts.loadFromCache ? "default" : "no-cache" - }).then(res => { - if (res.status >= 200 && res.status < 300) { - return res.text().then(text => ({ content: text })); - } - return Promise.reject(`request failed with status ${res.status}`); - }); -} - -module.exports = networkRequest; - -/***/ }), - -/***/ 3654: -/***/ (function(module, exports) { - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -function WorkerDispatcher() { - this.msgId = 1; - this.worker = null; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -WorkerDispatcher.prototype = { - start(url) { - this.worker = new Worker(url); - this.worker.onerror = () => { - console.error(`Error in worker ${url}`); - }; - }, - - stop() { - if (!this.worker) { - return; - } - - this.worker.terminate(); - this.worker = null; - }, - - task(method, { queue = false } = {}) { - const calls = []; - const push = args => { - return new Promise((resolve, reject) => { - if (queue && calls.length === 0) { - Promise.resolve().then(flush); - } - - calls.push([args, resolve, reject]); - - if (!queue) { - flush(); - } - }); - }; - - const flush = () => { - const items = calls.slice(); - calls.length = 0; - - if (!this.worker) { - return; - } - - const id = this.msgId++; - this.worker.postMessage({ - id, - method, - calls: items.map(item => item[0]) - }); - - const listener = ({ data: result }) => { - if (result.id !== id) { - return; - } - - if (!this.worker) { - return; - } - - this.worker.removeEventListener("message", listener); - - result.results.forEach((resultData, i) => { - const [, resolve, reject] = items[i]; - - if (resultData.error) { - reject(resultData.error); - } else { - resolve(resultData.response); - } - }); - }; - - this.worker.addEventListener("message", listener); - }; - - return (...args) => push(args); - } -}; - -function workerHandler(publicInterface) { - return function (msg) { - const { id, method, calls } = msg.data; - - Promise.all(calls.map(args => { - try { - const response = publicInterface[method].apply(undefined, args); - if (response instanceof Promise) { - return response.then(val => ({ response: val }), - // Error can't be sent via postMessage, so be sure to - // convert to string. - err => ({ error: err.toString() })); - } - return { response }; - } catch (error) { - // Error can't be sent via postMessage, so be sure to convert to - // string. - return { error: error.toString() }; - } - })).then(results => { - self.postMessage({ id, results }); - }); - }; -} - -function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) { - let streamingWorker = (() => { - var _ref = _asyncToGenerator(function* (id, tasks) { - let isWorking = true; - - const timeoutId = setTimeout(function () { - isWorking = false; - }, timeout); - - const results = []; - while (tasks.length !== 0 && isWorking) { - const { callback, context, args } = tasks.shift(); - const result = yield callback.call(context, args); - results.push(result); - } - worker.postMessage({ id, status: "pending", data: results }); - clearTimeout(timeoutId); - - if (tasks.length !== 0) { - yield streamingWorker(id, tasks); - } - }); - - return function streamingWorker(_x, _x2) { - return _ref.apply(this, arguments); - }; - })(); - - return (() => { - var _ref2 = _asyncToGenerator(function* (msg) { - const { id, method, args } = msg.data; - const workerMethod = publicInterface[method]; - if (!workerMethod) { - console.error(`Could not find ${method} defined in worker.`); - } - worker.postMessage({ id, status: "start" }); - - try { - const tasks = workerMethod(args); - yield streamingWorker(id, tasks); - worker.postMessage({ id, status: "done" }); - } catch (error) { - worker.postMessage({ id, status: "error", error }); - } - }); - - return function (_x3) { - return _ref2.apply(this, arguments); - }; - })(); -} - -module.exports = { - WorkerDispatcher, - workerHandler, - streamingWorkerHandler -}; - -/***/ }), - -/***/ 3655: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { MODE } = __webpack_require__(3645); -const { REPS, getRep } = __webpack_require__(3647); -const ObjectInspector = __webpack_require__(3695); -const ObjectInspectorUtils = __webpack_require__(3657); - -const { - parseURLEncodedText, - parseURLParams, - maybeEscapePropertyName, - getGripPreviewItems -} = __webpack_require__(3644); - -module.exports = { - REPS, - getRep, - MODE, - maybeEscapePropertyName, - parseURLEncodedText, - parseURLParams, - getGripPreviewItems, - ObjectInspector, - ObjectInspectorUtils -}; - -/***/ }), - -/***/ 3656: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Dependencies -const { interleave, isGrip, wrapRender } = __webpack_require__(3644); -const PropRep = __webpack_require__(3650); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders generic grip. Grip is client representation - * of remote JS object and is used as an input object - * for this rep component. - */ -GripRep.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - isInterestingProp: PropTypes.func, - title: PropTypes.string, - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func, - noGrip: PropTypes.bool -}; - -const DEFAULT_TITLE = "Object"; - -function GripRep(props) { - const { mode = MODE.SHORT, object } = props; - - const config = { - "data-link-actor-id": object.actor, - className: "objectBox objectBox-object" - }; - - if (mode === MODE.TINY) { - const propertiesLength = getPropertiesLength(object); - - const tinyModeItems = []; - if (getTitle(props, object) !== DEFAULT_TITLE) { - tinyModeItems.push(getTitleElement(props, object)); - } else { - tinyModeItems.push(span({ - className: "objectLeftBrace" - }, "{"), propertiesLength > 0 ? span({ - key: "more", - className: "more-ellipsis", - title: "more…" - }, "…") : null, span({ - className: "objectRightBrace" - }, "}")); - } - - return span(config, ...tinyModeItems); - } - - const propsArray = safePropIterator(props, object, maxLengthMap.get(mode)); - - return span(config, getTitleElement(props, object), span({ - className: "objectLeftBrace" - }, " { "), ...interleave(propsArray, ", "), span({ - className: "objectRightBrace" - }, " }")); -} - -function getTitleElement(props, object) { - return span({ - className: "objectTitle" - }, getTitle(props, object)); -} - -function getTitle(props, object) { - return props.title || object.class || DEFAULT_TITLE; -} - -function getPropertiesLength(object) { - let propertiesLength = object.preview && object.preview.ownPropertiesLength ? object.preview.ownPropertiesLength : object.ownPropertyLength; - - if (object.preview && object.preview.safeGetterValues) { - propertiesLength += Object.keys(object.preview.safeGetterValues).length; - } - - if (object.preview && object.preview.ownSymbols) { - propertiesLength += object.preview.ownSymbolsLength; - } - - return propertiesLength; -} - -function safePropIterator(props, object, max) { - max = typeof max === "undefined" ? maxLengthMap.get(MODE.SHORT) : max; - try { - return propIterator(props, object, max); - } catch (err) { - console.error(err); - } - return []; -} - -function propIterator(props, object, max) { - if (object.preview && Object.keys(object.preview).includes("wrappedValue")) { - const { Rep } = __webpack_require__(3647); - - return [Rep({ - object: object.preview.wrappedValue, - mode: props.mode || MODE.TINY, - defaultRep: Grip - })]; - } - - // Property filter. Show only interesting properties to the user. - const isInterestingProp = props.isInterestingProp || ((type, value) => { - return type == "boolean" || type == "number" || type == "string" && value.length != 0; - }); - - let properties = object.preview ? object.preview.ownProperties || {} : {}; - - const propertiesLength = getPropertiesLength(object); - - if (object.preview && object.preview.safeGetterValues) { - properties = _extends({}, properties, object.preview.safeGetterValues); - } - - let indexes = getPropIndexes(properties, max, isInterestingProp); - if (indexes.length < max && indexes.length < propertiesLength) { - // There are not enough props yet. - // Then add uninteresting props to display them. - indexes = indexes.concat(getPropIndexes(properties, max - indexes.length, (t, value, name) => { - return !isInterestingProp(t, value, name); - })); - } - - // The server synthesizes some property names for a Proxy, like - // and ; we don't want to quote these because, - // as synthetic properties, they appear more natural when - // unquoted. - const suppressQuotes = object.class === "Proxy"; - const propsArray = getProps(props, properties, indexes, suppressQuotes); - - // Show symbols. - if (object.preview && object.preview.ownSymbols) { - const { ownSymbols } = object.preview; - const length = max - indexes.length; - - const symbolsProps = ownSymbols.slice(0, length).map(symbolItem => { - return PropRep(_extends({}, props, { - mode: MODE.TINY, - name: symbolItem, - object: symbolItem.descriptor.value, - equal: ": ", - defaultRep: Grip, - title: null, - suppressQuotes - })); - }); - - propsArray.push(...symbolsProps); - } - - if (Object.keys(properties).length > max || propertiesLength > max || - // When the object has non-enumerable properties, we don't have them in the - // packet, but we might want to show there's something in the object. - propertiesLength > propsArray.length) { - // There are some undisplayed props. Then display "more...". - propsArray.push(span({ - key: "more", - className: "more-ellipsis", - title: "more…" - }, "…")); - } - - return propsArray; -} - -/** - * Get props ordered by index. - * - * @param {Object} componentProps Grip Component props. - * @param {Object} properties Properties of the object the Grip describes. - * @param {Array} indexes Indexes of properties. - * @param {Boolean} suppressQuotes true if we should suppress quotes - * on property names. - * @return {Array} Props. - */ -function getProps(componentProps, properties, indexes, suppressQuotes) { - // Make indexes ordered by ascending. - indexes.sort(function (a, b) { - return a - b; - }); - - const propertiesKeys = Object.keys(properties); - return indexes.map(i => { - const name = propertiesKeys[i]; - const value = getPropValue(properties[name]); - - return PropRep(_extends({}, componentProps, { - mode: MODE.TINY, - name, - object: value, - equal: ": ", - defaultRep: Grip, - title: null, - suppressQuotes - })); - }); -} - -/** - * Get the indexes of props in the object. - * - * @param {Object} properties Props object. - * @param {Number} max The maximum length of indexes array. - * @param {Function} filter Filter the props you want. - * @return {Array} Indexes of interesting props in the object. - */ -function getPropIndexes(properties, max, filter) { - const indexes = []; - - try { - let i = 0; - for (const name in properties) { - if (indexes.length >= max) { - return indexes; - } - - // Type is specified in grip's "class" field and for primitive - // values use typeof. - const value = getPropValue(properties[name]); - let type = value.class || typeof value; - type = type.toLowerCase(); - - if (filter(type, value, name)) { - indexes.push(i); - } - i++; - } - } catch (err) { - console.error(err); - } - return indexes; -} - -/** - * Get the actual value of a property. - * - * @param {Object} property - * @return {Object} Value of the property. - */ -function getPropValue(property) { - let value = property; - if (typeof property === "object") { - const keys = Object.keys(property); - if (keys.includes("value")) { - value = property.value; - } else if (keys.includes("getterValue")) { - value = property.getterValue; - } - } - return value; -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - - if (object.class === "DeadObject") { - return true; - } - - return object.preview ? typeof object.preview.ownProperties !== "undefined" : typeof object.ownPropertyLength !== "undefined"; -} - -const maxLengthMap = new Map(); -maxLengthMap.set(MODE.SHORT, 3); -maxLengthMap.set(MODE.LONG, 10); - -// Grip is used in propIterator and has to be defined here. -const Grip = { - rep: wrapRender(GripRep), - supportsObject, - maxLengthMap -}; - -// Exports from this module -module.exports = Grip; - -/***/ }), - -/***/ 3657: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const client = __webpack_require__(3665); -const loadProperties = __webpack_require__(3666); -const node = __webpack_require__(3667); -const { nodeIsError, nodeIsPrimitive } = node; -const selection = __webpack_require__(3698); - -const { MODE } = __webpack_require__(3645); -const { REPS: { Rep, Grip } } = __webpack_require__(3647); - - -function shouldRenderRootsInReps(roots) { - if (roots.length > 1) { - return false; - } - - const root = roots[0]; - const name = root && root.name; - return (name === null || typeof name === "undefined") && (nodeIsPrimitive(root) || nodeIsError(root)); -} - -function renderRep(item, props) { - return Rep(_extends({}, props, { - object: node.getValue(item), - mode: props.mode || MODE.TINY, - defaultRep: Grip - })); -} - -module.exports = { - client, - loadProperties, - node, - renderRep, - selection, - shouldRenderRootsInReps -}; - -/***/ }), - -/***/ 3658: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { getGripType, isGrip, cropString, wrapRender } = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; - -const IGNORED_SOURCE_URLS = ["debugger eval code"]; - -/** - * This component represents a template for Function objects. - */ -FunctionRep.propTypes = { - object: PropTypes.object.isRequired, - parameterNames: PropTypes.array, - onViewSourceInDebugger: PropTypes.func -}; - -function FunctionRep(props) { - const { object: grip, onViewSourceInDebugger } = props; - - let jumpToDefinitionButton; - if (onViewSourceInDebugger && grip.location && grip.location.url && !IGNORED_SOURCE_URLS.includes(grip.location.url)) { - jumpToDefinitionButton = dom.button({ - className: "jump-definition", - draggable: false, - title: "Jump to definition", - onClick: e => { - // Stop the event propagation so we don't trigger ObjectInspector - // expand/collapse. - e.stopPropagation(); - onViewSourceInDebugger(grip.location); - } - }); - } - - return span({ - "data-link-actor-id": grip.actor, - className: "objectBox objectBox-function", - // Set dir="ltr" to prevent function parentheses from - // appearing in the wrong direction - dir: "ltr" - }, getTitle(grip, props), getFunctionName(grip, props), "(", ...renderParams(props), ")", jumpToDefinitionButton); -} - -function getTitle(grip, props) { - const { mode } = props; - - if (mode === MODE.TINY && !grip.isGenerator && !grip.isAsync) { - return null; - } - - let title = mode === MODE.TINY ? "" : "function "; - - if (grip.isGenerator) { - title = mode === MODE.TINY ? "* " : "function* "; - } - - if (grip.isAsync) { - title = `${"async" + " "}${title}`; - } - - return span({ - className: "objectTitle" - }, title); -} - -/** - * Returns a ReactElement representing the function name. - * - * @param {Object} grip : Function grip - * @param {Object} props: Function rep props - */ -function getFunctionName(grip, props = {}) { - let { functionName } = props; - let name; - - if (functionName) { - const end = functionName.length - 1; - functionName = functionName.startsWith('"') && functionName.endsWith('"') ? functionName.substring(1, end) : functionName; - } - - if (grip.displayName != undefined && functionName != undefined && grip.displayName != functionName) { - name = `${functionName}:${grip.displayName}`; - } else { - name = cleanFunctionName(grip.userDisplayName || grip.displayName || grip.name || props.functionName || ""); - } - - return cropString(name, 100); -} - -const objectProperty = /([\w\d]+)$/; -const arrayProperty = /\[(.*?)\]$/; -const functionProperty = /([\w\d]+)[\/\.<]*?$/; -const annonymousProperty = /([\w\d]+)\(\^\)$/; - -/** - * Decodes an anonymous naming scheme that - * spider monkey implements based on "Naming Anonymous JavaScript Functions" - * http://johnjbarton.github.io/nonymous/index.html - * - * @param {String} name : Function name to clean up - * @returns String - */ -function cleanFunctionName(name) { - for (const reg of [objectProperty, arrayProperty, functionProperty, annonymousProperty]) { - const match = reg.exec(name); - if (match) { - return match[1]; - } - } - - return name; -} - -function renderParams(props) { - const { parameterNames = [] } = props; - - return parameterNames.filter(param => param).reduce((res, param, index, arr) => { - res.push(span({ className: "param" }, param)); - if (index < arr.length - 1) { - res.push(span({ className: "delimiter" }, ", ")); - } - return res; - }, []); -} - -// Registration -function supportsObject(grip, noGrip = false) { - const type = getGripType(grip, noGrip); - if (noGrip === true || !isGrip(grip)) { - return type == "function"; - } - - return type == "Function"; -} - -// Exports from this module - -module.exports = { - rep: wrapRender(FunctionRep), - supportsObject, - cleanFunctionName, - // exported for testing purpose. - getFunctionName -}; - -/***/ }), - -/***/ 3659: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -module.exports = { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12, - - // DocumentPosition - DOCUMENT_POSITION_DISCONNECTED: 0x01, - DOCUMENT_POSITION_PRECEDING: 0x02, - DOCUMENT_POSITION_FOLLOWING: 0x04, - DOCUMENT_POSITION_CONTAINS: 0x08, - DOCUMENT_POSITION_CONTAINED_BY: 0x10, - DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 0x20 -}; - -/***/ }), - -/***/ 366: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3660: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); -// Utils -const { getGripType, isGrip, wrapRender } = __webpack_require__(3644); -const { cleanFunctionName } = __webpack_require__(3658); -const { isLongString } = __webpack_require__(3648); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; -const IGNORED_SOURCE_URLS = ["debugger eval code"]; - -/** - * Renders Error objects. - */ -ErrorRep.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])) -}; - -function ErrorRep(props) { - const object = props.object; - const preview = object.preview; - - let name; - if (preview && preview.name && preview.kind) { - switch (preview.kind) { - case "Error": - name = preview.name; - break; - case "DOMException": - name = preview.kind; - break; - default: - throw new Error("Unknown preview kind for the Error rep."); - } - } else { - name = "Error"; - } - - const content = []; - - if (props.mode === MODE.TINY) { - content.push(name); - } else { - content.push(`${name}: "${preview.message}"`); - } - - if (preview.stack && props.mode !== MODE.TINY) { - content.push("\n", getStacktraceElements(props, preview)); - } - - return span({ - "data-link-actor-id": object.actor, - className: "objectBox-stackTrace" - }, content); -} - -/** - * Returns a React element reprensenting the Error stacktrace, i.e. - * transform error.stack from: - * - * semicolon@debugger eval code:1:109 - * jkl@debugger eval code:1:63 - * asdf@debugger eval code:1:28 - * @debugger eval code:1:227 - * - * Into a column layout: - * - * semicolon (:8:10) - * jkl (:5:10) - * asdf (:2:10) - * (:11:1) - */ -function getStacktraceElements(props, preview) { - const stack = []; - if (!preview.stack) { - return stack; - } - - const isStacktraceALongString = isLongString(preview.stack); - const stackString = isStacktraceALongString ? preview.stack.initial : preview.stack; - - stackString.split("\n").forEach((frame, index) => { - if (!frame) { - // Skip any blank lines - return; - } - - let functionName; - let location; - - // Given the input: "functionName@scriptLocation:2:100" - // Result: [ - // "functionName@scriptLocation:2:100", - // "functionName", - // "scriptLocation:2:100" - // ] - const result = frame.match(/^(.*)@(.*)$/); - if (result && result.length === 3) { - functionName = result[1]; - - // If the resource was loaded by base-loader.js, the location looks like: - // resource://devtools/shared/base-loader.js -> resource://path/to/file.js . - // What's needed is only the last part after " -> ". - location = result[2].split(" -> ").pop(); - } - - if (!functionName) { - functionName = ""; - } - - let onLocationClick; - // Given the input: "scriptLocation:2:100" - // Result: - // ["scriptLocation:2:100", "scriptLocation", "2", "100"] - const locationParts = location.match(/^(.*):(\d+):(\d+)$/); - if (props.onViewSourceInDebugger && location && !IGNORED_SOURCE_URLS.includes(locationParts[1]) && locationParts) { - const [, url, line, column] = locationParts; - onLocationClick = e => { - // Don't trigger ObjectInspector expand/collapse. - e.stopPropagation(); - props.onViewSourceInDebugger({ - url, - line: Number(line), - column: Number(column) - }); - }; - } - - stack.push(span({ - key: `fn${index}`, - className: "objectBox-stackTrace-fn" - }, cleanFunctionName(functionName)), span({ - key: `location${index}`, - className: "objectBox-stackTrace-location", - onClick: onLocationClick, - title: onLocationClick ? `View source in debugger → ${location}` : undefined - }, location)); - }); - - if (isStacktraceALongString) { - // Remove the last frame (i.e. 2 last elements in the array, the function - // name and the location) which is certainly incomplete. - // Can be removed when https://bugzilla.mozilla.org/show_bug.cgi?id=1448833 - // is fixed. - stack.splice(-2); - } - - return span({ - key: "stack", - className: "objectBox-stackTrace-grid" - }, stack); -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - return object.preview && getGripType(object, noGrip) === "Error" || object.class === "DOMException"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(ErrorRep), - supportsObject -}; - -/***/ }), - -/***/ 3661: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); - -const { lengthBubble } = __webpack_require__(3662); -const { - interleave, - getGripType, - isGrip, - wrapRender, - ellipsisElement -} = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; -const { ModePropType } = __webpack_require__(3649); -const DEFAULT_TITLE = "Array"; - -/** - * Renders an array. The array is enclosed by left and right bracket - * and the max number of rendered items depends on the current mode. - */ -GripArray.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: ModePropType, - provider: PropTypes.object, - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func -}; - -function GripArray(props) { - const { object, mode = MODE.SHORT } = props; - - let brackets; - const needSpace = function (space) { - return space ? { left: "[ ", right: " ]" } : { left: "[", right: "]" }; - }; - - const config = { - "data-link-actor-id": object.actor, - className: "objectBox objectBox-array" - }; - - const title = getTitle(props, object); - - if (mode === MODE.TINY) { - const isEmpty = getLength(object) === 0; - - // Omit bracketed ellipsis for non-empty non-Array arraylikes (f.e: Sets). - if (!isEmpty && object.class !== "Array") { - return span(config, title); - } - - brackets = needSpace(false); - return span(config, title, span({ - className: "arrayLeftBracket" - }, brackets.left), isEmpty ? null : ellipsisElement, span({ - className: "arrayRightBracket" - }, brackets.right)); - } - - const max = maxLengthMap.get(mode); - const items = arrayIterator(props, object, max); - brackets = needSpace(items.length > 0); - - return span({ - "data-link-actor-id": object.actor, - className: "objectBox objectBox-array" - }, title, span({ - className: "arrayLeftBracket" - }, brackets.left), ...interleave(items, ", "), span({ - className: "arrayRightBracket" - }, brackets.right), span({ - className: "arrayProperties", - role: "group" - })); -} - -function getLength(grip) { - if (!grip.preview) { - return 0; - } - - return grip.preview.length || grip.preview.childNodesLength || 0; -} - -function getTitle(props, object) { - const objectLength = getLength(object); - const isEmpty = objectLength === 0; - - let title = props.title || object.class || DEFAULT_TITLE; - - const length = lengthBubble({ - object, - mode: props.mode, - maxLengthMap, - getLength - }); - - if (props.mode === MODE.TINY) { - if (isEmpty) { - if (object.class === DEFAULT_TITLE) { - return null; - } - - return span({ className: "objectTitle" }, `${title} `); - } - - let trailingSpace; - if (object.class === DEFAULT_TITLE) { - title = null; - trailingSpace = " "; - } - - return span({ className: "objectTitle" }, title, length, trailingSpace); - } - - return span({ className: "objectTitle" }, title, length, " "); -} - -function getPreviewItems(grip) { - if (!grip.preview) { - return null; - } - - return grip.preview.items || grip.preview.childNodes || []; -} - -function arrayIterator(props, grip, max) { - const { Rep } = __webpack_require__(3647); - - let items = []; - const gripLength = getLength(grip); - - if (!gripLength) { - return items; - } - - const previewItems = getPreviewItems(grip); - const provider = props.provider; - - let emptySlots = 0; - let foldedEmptySlots = 0; - items = previewItems.reduce((res, itemGrip) => { - if (res.length >= max) { - return res; - } - - let object; - try { - if (!provider && itemGrip === null) { - emptySlots++; - return res; - } - - object = provider ? provider.getValue(itemGrip) : itemGrip; - } catch (exc) { - object = exc; - } - - if (emptySlots > 0) { - res.push(getEmptySlotsElement(emptySlots)); - foldedEmptySlots = foldedEmptySlots + emptySlots - 1; - emptySlots = 0; - } - - if (res.length < max) { - res.push(Rep(_extends({}, props, { - object, - mode: MODE.TINY, - // Do not propagate title to array items reps - title: undefined - }))); - } - - return res; - }, []); - - // Handle trailing empty slots if there are some. - if (items.length < max && emptySlots > 0) { - items.push(getEmptySlotsElement(emptySlots)); - foldedEmptySlots = foldedEmptySlots + emptySlots - 1; - } - - const itemsShown = items.length + foldedEmptySlots; - if (gripLength > itemsShown) { - items.push(ellipsisElement); - } - - return items; -} - -function getEmptySlotsElement(number) { - // TODO: Use l10N - See https://github.com/devtools-html/reps/issues/141 - return `<${number} empty slot${number > 1 ? "s" : ""}>`; -} - -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return grip.preview && (grip.preview.kind == "ArrayLike" || getGripType(grip, noGrip) === "DocumentFragment"); -} - -const maxLengthMap = new Map(); -maxLengthMap.set(MODE.SHORT, 3); -maxLengthMap.set(MODE.LONG, 10); - -// Exports from this module -module.exports = { - rep: wrapRender(GripArray), - supportsObject, - maxLengthMap, - getLength -}; - -/***/ }), - -/***/ 3662: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const PropTypes = __webpack_require__(3642); - -const { wrapRender } = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); -const { ModePropType } = __webpack_require__(3649); - -const dom = __webpack_require__(3643); -const { span } = dom; - -GripLengthBubble.propTypes = { - object: PropTypes.object.isRequired, - maxLengthMap: PropTypes.instanceOf(Map).isRequired, - getLength: PropTypes.func.isRequired, - mode: ModePropType, - visibilityThreshold: PropTypes.number -}; - -function GripLengthBubble(props) { - const { - object, - mode = MODE.SHORT, - visibilityThreshold = 2, - maxLengthMap, - getLength, - showZeroLength = false - } = props; - - const length = getLength(object); - const isEmpty = length === 0; - const isObvious = [MODE.SHORT, MODE.LONG].includes(mode) && length > 0 && length <= maxLengthMap.get(mode) && length <= visibilityThreshold; - if (isEmpty && !showZeroLength || isObvious) { - return ""; - } - - return span({ - className: "objectLengthBubble" - }, `(${length})`); -} - -module.exports = { - lengthBubble: wrapRender(GripLengthBubble) -}; - -/***/ }), - -/***/ 3663: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies - -const { lengthBubble } = __webpack_require__(3662); -const PropTypes = __webpack_require__(3642); -const { - interleave, - isGrip, - wrapRender, - ellipsisElement -} = __webpack_require__(3644); -const PropRep = __webpack_require__(3650); -const { MODE } = __webpack_require__(3645); -const { ModePropType } = __webpack_require__(3649); - -const { span } = __webpack_require__(3643); - -/** - * Renders an map. A map is represented by a list of its - * entries enclosed in curly brackets. - */ -GripMap.propTypes = { - object: PropTypes.object, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: ModePropType, - isInterestingEntry: PropTypes.func, - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func, - title: PropTypes.string -}; - -function GripMap(props) { - const { mode, object } = props; - - const config = { - "data-link-actor-id": object.actor, - className: "objectBox objectBox-object" - }; - - const title = getTitle(props, object); - const isEmpty = getLength(object) === 0; - - if (isEmpty || mode === MODE.TINY) { - return span(config, title); - } - - const propsArray = safeEntriesIterator(props, object, maxLengthMap.get(mode)); - - return span(config, title, span({ - className: "objectLeftBrace" - }, " { "), ...interleave(propsArray, ", "), span({ - className: "objectRightBrace" - }, " }")); -} - -function getTitle(props, object) { - const title = props.title || (object && object.class ? object.class : "Map"); - return span({ - className: "objectTitle" - }, title, lengthBubble({ - object, - mode: props.mode, - maxLengthMap, - getLength, - showZeroLength: true - })); -} - -function safeEntriesIterator(props, object, max) { - max = typeof max === "undefined" ? 3 : max; - try { - return entriesIterator(props, object, max); - } catch (err) { - console.error(err); - } - return []; -} - -function entriesIterator(props, object, max) { - // Entry filter. Show only interesting entries to the user. - const isInterestingEntry = props.isInterestingEntry || ((type, value) => { - return type == "boolean" || type == "number" || type == "string" && value.length != 0; - }); - - const mapEntries = object.preview && object.preview.entries ? object.preview.entries : []; - - let indexes = getEntriesIndexes(mapEntries, max, isInterestingEntry); - if (indexes.length < max && indexes.length < mapEntries.length) { - // There are not enough entries yet, so we add uninteresting entries. - indexes = indexes.concat(getEntriesIndexes(mapEntries, max - indexes.length, (t, value, name) => { - return !isInterestingEntry(t, value, name); - })); - } - - const entries = getEntries(props, mapEntries, indexes); - if (entries.length < getLength(object)) { - // There are some undisplayed entries. Then display "…". - entries.push(ellipsisElement); - } - - return entries; -} - -/** - * Get entries ordered by index. - * - * @param {Object} props Component props. - * @param {Array} entries Entries array. - * @param {Array} indexes Indexes of entries. - * @return {Array} Array of PropRep. - */ -function getEntries(props, entries, indexes) { - const { onDOMNodeMouseOver, onDOMNodeMouseOut, onInspectIconClick } = props; - - // Make indexes ordered by ascending. - indexes.sort(function (a, b) { - return a - b; - }); - - return indexes.map((index, i) => { - const [key, entryValue] = entries[index]; - const value = entryValue.value !== undefined ? entryValue.value : entryValue; - - return PropRep({ - name: key, - equal: " \u2192 ", - object: value, - mode: MODE.TINY, - onDOMNodeMouseOver, - onDOMNodeMouseOut, - onInspectIconClick - }); - }); -} - -/** - * Get the indexes of entries in the map. - * - * @param {Array} entries Entries array. - * @param {Number} max The maximum length of indexes array. - * @param {Function} filter Filter the entry you want. - * @return {Array} Indexes of filtered entries in the map. - */ -function getEntriesIndexes(entries, max, filter) { - return entries.reduce((indexes, [key, entry], i) => { - if (indexes.length < max) { - const value = entry && entry.value !== undefined ? entry.value : entry; - // Type is specified in grip's "class" field and for primitive - // values use typeof. - const type = (value && value.class ? value.class : typeof value).toLowerCase(); - - if (filter(type, value, key)) { - indexes.push(i); - } - } - - return indexes; - }, []); -} - -function getLength(grip) { - return grip.preview.size || 0; -} - -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - return grip.preview && grip.preview.kind == "MapLike"; -} - -const maxLengthMap = new Map(); -maxLengthMap.set(MODE.SHORT, 3); -maxLengthMap.set(MODE.LONG, 10); - -// Exports from this module -module.exports = { - rep: wrapRender(GripMap), - supportsObject, - maxLengthMap, - getLength -}; - -/***/ }), - -/***/ 3664: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); -// Shortcuts -const dom = __webpack_require__(3643); -const { span } = dom; -const { wrapRender } = __webpack_require__(3644); -const PropRep = __webpack_require__(3650); -const { MODE } = __webpack_require__(3645); -/** - * Renders an map entry. A map entry is represented by its key, - * a column and its value. - */ -GripMapEntry.propTypes = { - object: PropTypes.object, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func -}; - -function GripMapEntry(props) { - const { object } = props; - - const { key, value } = object.preview; - - return span({ - className: "objectBox objectBox-map-entry" - }, PropRep(_extends({}, props, { - name: key, - object: value, - equal: " \u2192 ", - title: null, - suppressQuotes: false - }))); -} - -function supportsObject(grip, noGrip = false) { - if (noGrip === true) { - return false; - } - return grip && (grip.type === "mapEntry" || grip.type === "storageEntry") && grip.preview; -} - -function createGripMapEntry(key, value) { - return { - type: "mapEntry", - preview: { - key, - value - } - }; -} - -// Exports from this module -module.exports = { - rep: wrapRender(GripMapEntry), - createGripMapEntry, - supportsObject -}; - -/***/ }), - -/***/ 3665: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -async function enumIndexedProperties(objectClient, start, end) { - try { - const { iterator } = await objectClient.enumProperties({ - ignoreNonIndexedProperties: true - }); - const response = await iteratorSlice(iterator, start, end); - return response; - } catch (e) { - console.error("Error in enumIndexedProperties", e); - return {}; - } -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -async function enumNonIndexedProperties(objectClient, start, end) { - try { - const { iterator } = await objectClient.enumProperties({ - ignoreIndexedProperties: true - }); - const response = await iteratorSlice(iterator, start, end); - return response; - } catch (e) { - console.error("Error in enumNonIndexedProperties", e); - return {}; - } -} - -async function enumEntries(objectClient, start, end) { - try { - const { iterator } = await objectClient.enumEntries(); - const response = await iteratorSlice(iterator, start, end); - return response; - } catch (e) { - console.error("Error in enumEntries", e); - return {}; - } -} - -async function enumSymbols(objectClient, start, end) { - try { - const { iterator } = await objectClient.enumSymbols(); - const response = await iteratorSlice(iterator, start, end); - return response; - } catch (e) { - console.error("Error in enumSymbols", e); - return {}; - } -} - -async function getPrototype(objectClient) { - if (typeof objectClient.getPrototype !== "function") { - console.error("objectClient.getPrototype is not a function"); - return Promise.resolve({}); - } - return objectClient.getPrototype(); -} - -async function getFullText(longStringClient, object) { - const { initial, length } = object; - - return new Promise((resolve, reject) => { - longStringClient.substring(initial.length, length, response => { - if (response.error) { - console.error("LongStringClient.substring", `${response.error}: ${response.message}`); - reject({}); - return; - } - - resolve({ - fullText: initial + response.substring - }); - }); - }); -} - -function iteratorSlice(iterator, start, end) { - start = start || 0; - const count = end ? end - start + 1 : iterator.count; - - if (count === 0) { - return Promise.resolve({}); - } - return iterator.slice(start, count); -} - -module.exports = { - enumEntries, - enumIndexedProperties, - enumNonIndexedProperties, - enumSymbols, - getPrototype, - getFullText -}; - -/***/ }), - -/***/ 3666: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { - enumEntries, - enumIndexedProperties, - enumNonIndexedProperties, - getPrototype, - enumSymbols, - getFullText -} = __webpack_require__(3665); - -const { - getClosestGripNode, - getClosestNonBucketNode, - getValue, - nodeHasAccessors, - nodeHasAllEntriesInPreview, - nodeHasProperties, - nodeIsBucket, - nodeIsDefaultProperties, - nodeIsEntries, - nodeIsMapEntry, - nodeIsPrimitive, - nodeIsProxy, - nodeNeedsNumericalBuckets, - nodeIsLongString -} = __webpack_require__(3667); - -function loadItemProperties(item, createObjectClient, createLongStringClient, loadedProperties) { - const gripItem = getClosestGripNode(item); - const value = getValue(gripItem); - - const [start, end] = item.meta ? [item.meta.startIndex, item.meta.endIndex] : []; - - const promises = []; - let objectClient; - const getObjectClient = () => objectClient || createObjectClient(value); - - if (shouldLoadItemIndexedProperties(item, loadedProperties)) { - promises.push(enumIndexedProperties(getObjectClient(), start, end)); - } - - if (shouldLoadItemNonIndexedProperties(item, loadedProperties)) { - promises.push(enumNonIndexedProperties(getObjectClient(), start, end)); - } - - if (shouldLoadItemEntries(item, loadedProperties)) { - promises.push(enumEntries(getObjectClient(), start, end)); - } - - if (shouldLoadItemPrototype(item, loadedProperties)) { - promises.push(getPrototype(getObjectClient())); - } - - if (shouldLoadItemSymbols(item, loadedProperties)) { - promises.push(enumSymbols(getObjectClient(), start, end)); - } - - if (shouldLoadItemFullText(item, loadedProperties)) { - promises.push(getFullText(createLongStringClient(value), value)); - } - - return Promise.all(promises).then(mergeResponses); -} - -function mergeResponses(responses) { - const data = {}; - - for (const response of responses) { - if (response.hasOwnProperty("ownProperties")) { - data.ownProperties = _extends({}, data.ownProperties, response.ownProperties); - } - - if (response.ownSymbols && response.ownSymbols.length > 0) { - data.ownSymbols = response.ownSymbols; - } - - if (response.prototype) { - data.prototype = response.prototype; - } - - if (response.fullText) { - data.fullText = response.fullText; - } - } - - return data; -} - -function shouldLoadItemIndexedProperties(item, loadedProperties = new Map()) { - const gripItem = getClosestGripNode(item); - const value = getValue(gripItem); - - return value && nodeHasProperties(gripItem) && !loadedProperties.has(item.path) && !nodeIsProxy(item) && !nodeNeedsNumericalBuckets(item) && !nodeIsEntries(getClosestNonBucketNode(item)) && - // The data is loaded when expanding the window node. - !nodeIsDefaultProperties(item); -} - -function shouldLoadItemNonIndexedProperties(item, loadedProperties = new Map()) { - const gripItem = getClosestGripNode(item); - const value = getValue(gripItem); - - return value && nodeHasProperties(gripItem) && !loadedProperties.has(item.path) && !nodeIsProxy(item) && !nodeIsEntries(getClosestNonBucketNode(item)) && !nodeIsBucket(item) && - // The data is loaded when expanding the window node. - !nodeIsDefaultProperties(item); -} - -function shouldLoadItemEntries(item, loadedProperties = new Map()) { - const gripItem = getClosestGripNode(item); - const value = getValue(gripItem); - - return value && nodeIsEntries(getClosestNonBucketNode(item)) && !nodeHasAllEntriesInPreview(gripItem) && !loadedProperties.has(item.path) && !nodeNeedsNumericalBuckets(item); -} - -function shouldLoadItemPrototype(item, loadedProperties = new Map()) { - const value = getValue(item); - - return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsLongString(item); -} - -function shouldLoadItemSymbols(item, loadedProperties = new Map()) { - const value = getValue(item); - - return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsLongString(item) && !nodeIsProxy(item); -} - -function shouldLoadItemFullText(item, loadedProperties = new Map()) { - return !loadedProperties.has(item.path) && nodeIsLongString(item); -} - -module.exports = { - loadItemProperties, - mergeResponses, - shouldLoadItemEntries, - shouldLoadItemIndexedProperties, - shouldLoadItemNonIndexedProperties, - shouldLoadItemPrototype, - shouldLoadItemSymbols, - shouldLoadItemFullText -}; - -/***/ }), - -/***/ 3667: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { maybeEscapePropertyName } = __webpack_require__(3644); -const ArrayRep = __webpack_require__(3649); -const GripArrayRep = __webpack_require__(3661); -const GripMap = __webpack_require__(3663); -const GripMapEntryRep = __webpack_require__(3664); -const ErrorRep = __webpack_require__(3660); -const { isLongString } = __webpack_require__(3648); - -const MAX_NUMERICAL_PROPERTIES = 100; - -const NODE_TYPES = { - BUCKET: Symbol("[n…m]"), - DEFAULT_PROPERTIES: Symbol(""), - ENTRIES: Symbol(""), - GET: Symbol(""), - GRIP: Symbol("GRIP"), - MAP_ENTRY_KEY: Symbol(""), - MAP_ENTRY_VALUE: Symbol(""), - PROMISE_REASON: Symbol(""), - PROMISE_STATE: Symbol(""), - PROMISE_VALUE: Symbol(""), - PROXY_HANDLER: Symbol(""), - PROXY_TARGET: Symbol(""), - SET: Symbol(""), - PROTOTYPE: Symbol(""), - BLOCK: Symbol("☲") -}; - -let WINDOW_PROPERTIES = {}; - -if (typeof window === "object") { - WINDOW_PROPERTIES = Object.getOwnPropertyNames(window); -} - -function getType(item) { - return item.type; -} - -function getValue(item) { - if (item && item.contents && item.contents.hasOwnProperty("value")) { - return item.contents.value; - } - - if (item && item.contents && item.contents.hasOwnProperty("getterValue")) { - return item.contents.getterValue; - } - - if (nodeHasAccessors(item)) { - return item.contents; - } - - return undefined; -} - -function nodeIsBucket(item) { - return getType(item) === NODE_TYPES.BUCKET; -} - -function nodeIsEntries(item) { - return getType(item) === NODE_TYPES.ENTRIES; -} - -function nodeIsMapEntry(item) { - return GripMapEntryRep.supportsObject(getValue(item)); -} - -function nodeHasChildren(item) { - return Array.isArray(item.contents); -} - -function nodeIsObject(item) { - const value = getValue(item); - return value && value.type === "object"; -} - -function nodeIsArrayLike(item) { - const value = getValue(item); - return GripArrayRep.supportsObject(value) || ArrayRep.supportsObject(value); -} - -function nodeIsFunction(item) { - const value = getValue(item); - return value && value.class === "Function"; -} - -function nodeIsOptimizedOut(item) { - const value = getValue(item); - return !nodeHasChildren(item) && value && value.optimizedOut; -} - -function nodeIsUninitializedBinding(item) { - const value = getValue(item); - return value && value.uninitialized; -} - -// Used to check if an item represents a binding that exists in a sourcemap's -// original file content, but does not match up with a binding found in the -// generated code. -function nodeIsUnmappedBinding(item) { - const value = getValue(item); - return value && value.unmapped; -} - -// Used to check if an item represents a binding that exists in the debugger's -// parser result, but does not match up with a binding returned by the -// debugger server. -function nodeIsUnscopedBinding(item) { - const value = getValue(item); - return value && value.unscoped; -} - -function nodeIsMissingArguments(item) { - const value = getValue(item); - return !nodeHasChildren(item) && value && value.missingArguments; -} - -function nodeHasProperties(item) { - return !nodeHasChildren(item) && nodeIsObject(item); -} - -function nodeIsPrimitive(item) { - return !nodeHasChildren(item) && !nodeHasProperties(item) && !nodeIsEntries(item) && !nodeIsMapEntry(item) && !nodeHasAccessors(item) && !nodeIsBucket(item) && !nodeIsLongString(item); -} - -function nodeIsDefaultProperties(item) { - return getType(item) === NODE_TYPES.DEFAULT_PROPERTIES; -} - -function isDefaultWindowProperty(name) { - return WINDOW_PROPERTIES.includes(name); -} - -function nodeIsPromise(item) { - const value = getValue(item); - if (!value) { - return false; - } - - return value.class == "Promise"; -} - -function nodeIsProxy(item) { - const value = getValue(item); - if (!value) { - return false; - } - - return value.class == "Proxy"; -} - -function nodeIsPrototype(item) { - return getType(item) === NODE_TYPES.PROTOTYPE; -} - -function nodeIsWindow(item) { - const value = getValue(item); - if (!value) { - return false; - } - - return value.class == "Window"; -} - -function nodeIsGetter(item) { - return getType(item) === NODE_TYPES.GET; -} - -function nodeIsSetter(item) { - return getType(item) === NODE_TYPES.SET; -} - -function nodeIsBlock(item) { - return getType(item) === NODE_TYPES.BLOCK; -} - -function nodeIsError(item) { - return ErrorRep.supportsObject(getValue(item)); -} - -function nodeIsLongString(item) { - return isLongString(getValue(item)); -} - -function nodeHasFullText(item) { - const value = getValue(item); - return nodeIsLongString(item) && value.hasOwnProperty("fullText"); -} - -function nodeHasAccessors(item) { - return !!getNodeGetter(item) || !!getNodeSetter(item); -} - -function nodeSupportsNumericalBucketing(item) { - // We exclude elements with entries since it's the node - // itself that can have buckets. - return nodeIsArrayLike(item) && !nodeHasEntries(item) || nodeIsEntries(item) || nodeIsBucket(item); -} - -function nodeHasEntries(item) { - const value = getValue(item); - if (!value) { - return false; - } - - return value.class === "Map" || value.class === "Set" || value.class === "WeakMap" || value.class === "WeakSet" || value.class === "Storage"; -} - -function nodeHasAllEntriesInPreview(item) { - const { preview } = getValue(item) || {}; - if (!preview) { - return false; - } - - const { entries, items, length, size } = preview; - - if (!entries && !items) { - return false; - } - - return entries ? entries.length === size : items.length === length; -} - -function nodeNeedsNumericalBuckets(item) { - return nodeSupportsNumericalBucketing(item) && getNumericalPropertiesCount(item) > MAX_NUMERICAL_PROPERTIES; -} - -function makeNodesForPromiseProperties(item) { - const { promiseState: { reason, value, state } } = getValue(item); - - const properties = []; - - if (state) { - properties.push(createNode({ - parent: item, - name: "", - contents: { value: state }, - type: NODE_TYPES.PROMISE_STATE - })); - } - - if (reason) { - properties.push(createNode({ - parent: item, - name: "", - contents: { value: reason }, - type: NODE_TYPES.PROMISE_REASON - })); - } - - if (value) { - properties.push(createNode({ - parent: item, - name: "", - contents: { value: value }, - type: NODE_TYPES.PROMISE_VALUE - })); - } - - return properties; -} - -function makeNodesForProxyProperties(item) { - const { proxyHandler, proxyTarget } = getValue(item); - - return [createNode({ - parent: item, - name: "", - contents: { value: proxyTarget }, - type: NODE_TYPES.PROXY_TARGET - }), createNode({ - parent: item, - name: "", - contents: { value: proxyHandler }, - type: NODE_TYPES.PROXY_HANDLER - })]; -} - -function makeNodesForEntries(item) { - const nodeName = ""; - const entriesPath = ""; - - if (nodeHasAllEntriesInPreview(item)) { - let entriesNodes = []; - const { preview } = getValue(item); - if (preview.entries) { - entriesNodes = preview.entries.map(([key, value], index) => { - return createNode({ - parent: item, - name: index, - path: `${entriesPath}/${index}`, - contents: { value: GripMapEntryRep.createGripMapEntry(key, value) } - }); - }); - } else if (preview.items) { - entriesNodes = preview.items.map((value, index) => { - return createNode({ - parent: item, - name: index, - path: `${entriesPath}/${index}`, - contents: { value } - }); - }); - } - return createNode({ - parent: item, - name: nodeName, - contents: entriesNodes, - type: NODE_TYPES.ENTRIES - }); - } - return createNode({ - parent: item, - name: nodeName, - contents: null, - type: NODE_TYPES.ENTRIES - }); -} - -function makeNodesForMapEntry(item) { - const nodeValue = getValue(item); - if (!nodeValue || !nodeValue.preview) { - return []; - } - - const { key, value } = nodeValue.preview; - - return [createNode({ - parent: item, - name: "", - contents: { value: key }, - type: NODE_TYPES.MAP_ENTRY_KEY - }), createNode({ - parent: item, - name: "", - contents: { value }, - type: NODE_TYPES.MAP_ENTRY_VALUE - })]; -} - -function getNodeGetter(item) { - return item && item.contents ? item.contents.get : undefined; -} - -function getNodeSetter(item) { - return item && item.contents ? item.contents.set : undefined; -} - -function makeNodesForAccessors(item) { - const accessors = []; - - const getter = getNodeGetter(item); - if (getter && getter.type !== "undefined") { - accessors.push(createNode({ - parent: item, - name: "", - contents: { value: getter }, - type: NODE_TYPES.GET - })); - } - - const setter = getNodeSetter(item); - if (setter && setter.type !== "undefined") { - accessors.push(createNode({ - parent: item, - name: "", - contents: { value: setter }, - type: NODE_TYPES.SET - })); - } - - return accessors; -} - -function sortProperties(properties) { - return properties.sort((a, b) => { - // Sort numbers in ascending order and sort strings lexicographically - const aInt = parseInt(a, 10); - const bInt = parseInt(b, 10); - - if (isNaN(aInt) || isNaN(bInt)) { - return a > b ? 1 : -1; - } - - return aInt - bInt; - }); -} - -function makeNumericalBuckets(parent) { - const numProperties = getNumericalPropertiesCount(parent); - - // We want to have at most a hundred slices. - const bucketSize = 10 ** Math.max(2, Math.ceil(Math.log10(numProperties)) - 2); - const numBuckets = Math.ceil(numProperties / bucketSize); - - const buckets = []; - for (let i = 1; i <= numBuckets; i++) { - const minKey = (i - 1) * bucketSize; - const maxKey = Math.min(i * bucketSize - 1, numProperties - 1); - const startIndex = nodeIsBucket(parent) ? parent.meta.startIndex : 0; - const minIndex = startIndex + minKey; - const maxIndex = startIndex + maxKey; - const bucketName = `[${minIndex}…${maxIndex}]`; - - buckets.push(createNode({ - parent, - name: bucketName, - contents: null, - type: NODE_TYPES.BUCKET, - meta: { - startIndex: minIndex, - endIndex: maxIndex - } - })); - } - return buckets; -} - -function makeDefaultPropsBucket(propertiesNames, parent, ownProperties) { - const userPropertiesNames = []; - const defaultProperties = []; - - propertiesNames.forEach(name => { - if (isDefaultWindowProperty(name)) { - defaultProperties.push(name); - } else { - userPropertiesNames.push(name); - } - }); - - const nodes = makeNodesForOwnProps(userPropertiesNames, parent, ownProperties); - - if (defaultProperties.length > 0) { - const defaultPropertiesNode = createNode({ - parent, - name: "", - contents: null, - type: NODE_TYPES.DEFAULT_PROPERTIES - }); - - const defaultNodes = defaultProperties.map((name, index) => createNode({ - parent: defaultPropertiesNode, - name: maybeEscapePropertyName(name), - path: `${index}/${name}`, - contents: ownProperties[name] - })); - nodes.push(setNodeChildren(defaultPropertiesNode, defaultNodes)); - } - return nodes; -} - -function makeNodesForOwnProps(propertiesNames, parent, ownProperties) { - return propertiesNames.map(name => createNode({ - parent, - name: maybeEscapePropertyName(name), - contents: ownProperties[name] - })); -} - -function makeNodesForProperties(objProps, parent) { - const { - ownProperties = {}, - ownSymbols, - prototype, - safeGetterValues - } = objProps; - - const parentValue = getValue(parent); - - const allProperties = _extends({}, ownProperties, safeGetterValues); - - // Ignore properties that are neither non-concrete nor getters/setters. - const propertiesNames = sortProperties(Object.keys(allProperties)).filter(name => { - if (!allProperties[name]) { - return false; - } - - const properties = Object.getOwnPropertyNames(allProperties[name]); - return properties.some(property => ["value", "getterValue", "get", "set"].includes(property)); - }); - - let nodes = []; - if (parentValue && parentValue.class == "Window") { - nodes = makeDefaultPropsBucket(propertiesNames, parent, allProperties); - } else { - nodes = makeNodesForOwnProps(propertiesNames, parent, allProperties); - } - - if (Array.isArray(ownSymbols)) { - ownSymbols.forEach((ownSymbol, index) => { - nodes.push(createNode({ - parent, - name: ownSymbol.name, - path: `symbol-${index}`, - contents: ownSymbol.descriptor || null - })); - }, this); - } - - if (nodeIsPromise(parent)) { - nodes.push(...makeNodesForPromiseProperties(parent)); - } - - if (nodeHasEntries(parent)) { - nodes.push(makeNodesForEntries(parent)); - } - - // Add the prototype if it exists and is not null - if (prototype && prototype.type !== "null") { - nodes.push(makeNodeForPrototype(objProps, parent)); - } - - return nodes; -} - -function setNodeFullText(loadedProps, node) { - if (nodeHasFullText(node)) { - return node; - } - - if (nodeIsLongString(node)) { - node.contents.value.fullText = loadedProps.fullText; - } - - return node; -} - -function makeNodeForPrototype(objProps, parent) { - const { prototype } = objProps || {}; - - // Add the prototype if it exists and is not null - if (prototype && prototype.type !== "null") { - return createNode({ - parent, - name: "", - contents: { value: prototype }, - type: NODE_TYPES.PROTOTYPE - }); - } - - return null; -} - -function createNode(options) { - const { - parent, - name, - path, - contents, - type = NODE_TYPES.GRIP, - meta - } = options; - - if (contents === undefined) { - return null; - } - - // The path is important to uniquely identify the item in the entire - // tree. This helps debugging & optimizes React's rendering of large - // lists. The path will be separated by property name, wrapped in a Symbol - // to avoid name clashing, - // i.e. `{ foo: { bar: { baz: 5 }}}` will have a path of Symbol(`foo/bar/baz`) - // for the inner object. - return { - parent, - name, - path: parent ? Symbol(`${getSymbolDescriptor(parent.path)}/${path || name}`) : Symbol(path || name), - contents, - type, - meta - }; -} - -function getSymbolDescriptor(symbol) { - return symbol.toString().replace(/^(Symbol\()(.*)(\))$/, "$2"); -} - -function setNodeChildren(node, children) { - node.contents = children; - return node; -} - -function getChildren(options) { - const { cachedNodes, loadedProperties = new Map(), item } = options; - - const key = item.path; - if (cachedNodes && cachedNodes.has(key)) { - return cachedNodes.get(key); - } - - const loadedProps = loadedProperties.get(key); - const hasLoadedProps = loadedProperties.has(key); - - // Because we are dynamically creating the tree as the user - // expands it (not precalculated tree structure), we cache child - // arrays. This not only helps performance, but is necessary - // because the expanded state depends on instances of nodes - // being the same across renders. If we didn't do this, each - // node would be a new instance every render. - // If the node needs properties, we only add children to - // the cache if the properties are loaded. - const addToCache = children => { - if (cachedNodes) { - cachedNodes.set(item.path, children); - } - return children; - }; - - // Nodes can either have children already, or be an object with - // properties that we need to go and fetch. - if (nodeHasChildren(item)) { - return addToCache(item.contents); - } - - if (nodeHasAccessors(item)) { - return addToCache(makeNodesForAccessors(item)); - } - - if (nodeIsMapEntry(item)) { - return addToCache(makeNodesForMapEntry(item)); - } - - if (nodeIsProxy(item)) { - return addToCache(makeNodesForProxyProperties(item)); - } - - if (nodeIsLongString(item) && hasLoadedProps) { - // Set longString object's fullText to fetched one. - return addToCache(setNodeFullText(loadedProps, item)); - } - - if (nodeNeedsNumericalBuckets(item) && hasLoadedProps) { - // Even if we have numerical buckets, we should have loaded non indexed - // properties. - const bucketNodes = makeNumericalBuckets(item); - return addToCache(bucketNodes.concat(makeNodesForProperties(loadedProps, item))); - } - - if (!nodeIsEntries(item) && !nodeIsBucket(item) && !nodeHasProperties(item)) { - return []; - } - - if (!hasLoadedProps) { - return []; - } - - return addToCache(makeNodesForProperties(loadedProps, item)); -} - -function getParent(item) { - return item.parent; -} - -function getNumericalPropertiesCount(item) { - if (nodeIsBucket(item)) { - return item.meta.endIndex - item.meta.startIndex + 1; - } - - const value = getValue(getClosestGripNode(item)); - if (!value) { - return 0; - } - - if (GripArrayRep.supportsObject(value)) { - return GripArrayRep.getLength(value); - } - - if (GripMap.supportsObject(value)) { - return GripMap.getLength(value); - } - - // TODO: We can also have numerical properties on Objects, but at the - // moment we don't have a way to distinguish them from non-indexed properties, - // as they are all computed in a ownPropertiesLength property. - - return 0; -} - -function getClosestGripNode(item) { - const type = getType(item); - if (type !== NODE_TYPES.BUCKET && type !== NODE_TYPES.DEFAULT_PROPERTIES && type !== NODE_TYPES.ENTRIES) { - return item; - } - - const parent = getParent(item); - if (!parent) { - return null; - } - - return getClosestGripNode(parent); -} - -function getClosestNonBucketNode(item) { - const type = getType(item); - - if (type !== NODE_TYPES.BUCKET) { - return item; - } - - const parent = getParent(item); - if (!parent) { - return null; - } - - return getClosestNonBucketNode(parent); -} - -module.exports = { - createNode, - getChildren, - getClosestGripNode, - getClosestNonBucketNode, - getParent, - getNumericalPropertiesCount, - getValue, - makeNodesForEntries, - makeNodesForPromiseProperties, - makeNodesForProperties, - makeNumericalBuckets, - nodeHasAccessors, - nodeHasAllEntriesInPreview, - nodeHasChildren, - nodeHasEntries, - nodeHasProperties, - nodeIsBlock, - nodeIsBucket, - nodeIsDefaultProperties, - nodeIsEntries, - nodeIsError, - nodeIsLongString, - nodeHasFullText, - nodeIsFunction, - nodeIsGetter, - nodeIsMapEntry, - nodeIsMissingArguments, - nodeIsObject, - nodeIsOptimizedOut, - nodeIsPrimitive, - nodeIsPromise, - nodeIsPrototype, - nodeIsProxy, - nodeIsSetter, - nodeIsUninitializedBinding, - nodeIsUnmappedBinding, - nodeIsUnscopedBinding, - nodeIsWindow, - nodeNeedsNumericalBuckets, - nodeSupportsNumericalBucketing, - setNodeChildren, - sortProperties, - NODE_TYPES -}; - -/***/ }), - -/***/ 3669: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _tree = __webpack_require__(3670); - -var _tree2 = _interopRequireDefault(_tree); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -module.exports = { - Tree: _tree2.default -}; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/***/ }), - -/***/ 367: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3670: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = __webpack_require__(0); - -var _react2 = _interopRequireDefault(_react); - -var _reactDomFactories = __webpack_require__(3643); - -var _reactDomFactories2 = _interopRequireDefault(_reactDomFactories); - -var _propTypes = __webpack_require__(3642); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { Component, createFactory } = _react2.default; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -__webpack_require__(3671); - -// depth -const AUTO_EXPAND_DEPTH = 0; - -/** - * An arrow that displays whether its node is expanded (▼) or collapsed - * (▶). When its node has no children, it is hidden. - */ -class ArrowExpander extends Component { - static get propTypes() { - return { - expanded: _propTypes2.default.bool - }; - } - - shouldComponentUpdate(nextProps, nextState) { - return this.props.expanded !== nextProps.expanded; - } - - render() { - const { expanded } = this.props; - - const classNames = ["arrow"]; - if (expanded) { - classNames.push("expanded"); - } - return _reactDomFactories2.default.img({ - className: classNames.join(" ") - }); - } -} - -const treeIndent = _reactDomFactories2.default.span({ className: "tree-indent" }, "\u200B"); - -class TreeNode extends Component { - static get propTypes() { - return { - id: _propTypes2.default.any.isRequired, - index: _propTypes2.default.number.isRequired, - depth: _propTypes2.default.number.isRequired, - focused: _propTypes2.default.bool.isRequired, - expanded: _propTypes2.default.bool.isRequired, - item: _propTypes2.default.any.isRequired, - isExpandable: _propTypes2.default.bool.isRequired, - onClick: _propTypes2.default.func, - renderItem: _propTypes2.default.func.isRequired - }; - } - - shouldComponentUpdate(nextProps) { - return this.props.item !== nextProps.item || this.props.focused !== nextProps.focused || this.props.expanded !== nextProps.expanded; - } - - render() { - const { - depth, - id, - item, - focused, - expanded, - renderItem, - isExpandable - } = this.props; - - const arrow = isExpandable ? ArrowExpanderFactory({ - item, - expanded - }) : null; - - let ariaExpanded; - if (this.props.isExpandable) { - ariaExpanded = false; - } - if (this.props.expanded) { - ariaExpanded = true; - } - - const indents = Array.from({ length: depth }).fill(treeIndent); - const items = indents.concat(renderItem(item, depth, focused, arrow, expanded)); - - return _reactDomFactories2.default.div({ - id, - className: `tree-node${focused ? " focused" : ""}`, - onClick: this.props.onClick, - role: "treeitem", - "aria-level": depth + 1, - "aria-expanded": ariaExpanded, - "data-expandable": this.props.isExpandable - }, ...items); - } -} - -const ArrowExpanderFactory = createFactory(ArrowExpander); -const TreeNodeFactory = createFactory(TreeNode); - -/** - * Create a function that calls the given function `fn` only once per animation - * frame. - * - * @param {Function} fn - * @returns {Function} - */ -function oncePerAnimationFrame(fn) { - let animationId = null; - let argsToPass = null; - return function (...args) { - argsToPass = args; - if (animationId !== null) { - return; - } - - animationId = requestAnimationFrame(() => { - fn.call(this, ...argsToPass); - animationId = null; - argsToPass = null; - }); - }; -} - -/** - * A generic tree component. See propTypes for the public API. - * - * This tree component doesn't make any assumptions about the structure of your - * tree data. Whether children are computed on demand, or stored in an array in - * the parent's `_children` property, it doesn't matter. We only require the - * implementation of `getChildren`, `getRoots`, `getParent`, and `isExpanded` - * functions. - * - * This tree component is well tested and reliable. See the tests in ./tests - * and its usage in the performance and memory panels in mozilla-central. - * - * This tree component doesn't make any assumptions about how to render items in - * the tree. You provide a `renderItem` function, and this component will ensure - * that only those items whose parents are expanded and which are visible in the - * viewport are rendered. The `renderItem` function could render the items as a - * "traditional" tree or as rows in a table or anything else. It doesn't - * restrict you to only one certain kind of tree. - * - * The tree comes with basic styling for the indent, the arrow, as well as - * hovered and focused styles which can be override in CSS. - * - * ### Example Usage - * - * Suppose we have some tree data where each item has this form: - * - * { - * id: Number, - * label: String, - * parent: Item or null, - * children: Array of child items, - * expanded: bool, - * } - * - * Here is how we could render that data with this component: - * - * class MyTree extends Component { - * static get propTypes() { - * // The root item of the tree, with the form described above. - * return { - * root: PropTypes.object.isRequired - * }; - * }, - * - * render() { - * return Tree({ - * itemHeight: 20, // px - * - * getRoots: () => [this.props.root], - * - * getParent: item => item.parent, - * getChildren: item => item.children, - * getKey: item => item.id, - * isExpanded: item => item.expanded, - * - * renderItem: (item, depth, isFocused, arrow, isExpanded) => { - * let className = "my-tree-item"; - * if (isFocused) { - * className += " focused"; - * } - * return dom.div({ - * className, - * }, - * arrow, - * // And here is the label for this item. - * dom.span({ className: "my-tree-item-label" }, item.label) - * ); - * }, - * - * onExpand: item => dispatchExpandActionToRedux(item), - * onCollapse: item => dispatchCollapseActionToRedux(item), - * }); - * } - * } - */ -class Tree extends Component { - static get propTypes() { - return { - // Required props - - // A function to get an item's parent, or null if it is a root. - // - // Type: getParent(item: Item) -> Maybe - // - // Example: - // - // // The parent of this item is stored in its `parent` property. - // getParent: item => item.parent - getParent: _propTypes2.default.func.isRequired, - - // A function to get an item's children. - // - // Type: getChildren(item: Item) -> [Item] - // - // Example: - // - // // This item's children are stored in its `children` property. - // getChildren: item => item.children - getChildren: _propTypes2.default.func.isRequired, - - // A function which takes an item and ArrowExpander component instance and - // returns a component, or text, or anything else that React considers - // renderable. - // - // Type: renderItem(item: Item, - // depth: Number, - // isFocused: Boolean, - // arrow: ReactComponent, - // isExpanded: Boolean) -> ReactRenderable - // - // Example: - // - // renderItem: (item, depth, isFocused, arrow, isExpanded) => { - // let className = "my-tree-item"; - // if (isFocused) { - // className += " focused"; - // } - // return dom.div( - // { - // className, - // style: { marginLeft: depth * 10 + "px" } - // }, - // arrow, - // dom.span({ className: "my-tree-item-label" }, item.label) - // ); - // }, - renderItem: _propTypes2.default.func.isRequired, - - // A function which returns the roots of the tree (forest). - // - // Type: getRoots() -> [Item] - // - // Example: - // - // // In this case, we only have one top level, root item. You could - // // return multiple items if you have many top level items in your - // // tree. - // getRoots: () => [this.props.rootOfMyTree] - getRoots: _propTypes2.default.func.isRequired, - - // A function to get a unique key for the given item. This helps speed up - // React's rendering a *TON*. - // - // Type: getKey(item: Item) -> String - // - // Example: - // - // getKey: item => `my-tree-item-${item.uniqueId}` - getKey: _propTypes2.default.func.isRequired, - - // A function to get whether an item is expanded or not. If an item is not - // expanded, then it must be collapsed. - // - // Type: isExpanded(item: Item) -> Boolean - // - // Example: - // - // isExpanded: item => item.expanded, - isExpanded: _propTypes2.default.func.isRequired, - - // Optional props - - // The currently focused item, if any such item exists. - focused: _propTypes2.default.any, - - // Handle when a new item is focused. - onFocus: _propTypes2.default.func, - - // The depth to which we should automatically expand new items. - autoExpandDepth: _propTypes2.default.number, - // Should auto expand all new items or just the new items under the first - // root item. - autoExpandAll: _propTypes2.default.bool, - - // Note: the two properties below are mutually exclusive. Only one of the - // label properties is necessary. - // ID of an element whose textual content serves as an accessible label - // for a tree. - labelledby: _propTypes2.default.string, - // Accessibility label for a tree widget. - label: _propTypes2.default.string, - - // Optional event handlers for when items are expanded or collapsed. - // Useful for dispatching redux events and updating application state, - // maybe lazily loading subtrees from a worker, etc. - // - // Type: - // onExpand(item: Item) - // onCollapse(item: Item) - // - // Example: - // - // onExpand: item => dispatchExpandActionToRedux(item) - onExpand: _propTypes2.default.func, - onCollapse: _propTypes2.default.func, - // Optional event handler called with the current focused node when the - // Enter key is pressed. Can be useful to allow further keyboard actions - // within the tree node. - onActivate: _propTypes2.default.func, - isExpandable: _propTypes2.default.func, - // Additional classes to add to the root element. - className: _propTypes2.default.string, - // style object to be applied to the root element. - style: _propTypes2.default.object - }; - } - - static get defaultProps() { - return { - autoExpandDepth: AUTO_EXPAND_DEPTH, - autoExpandAll: true - }; - } - - constructor(props) { - super(props); - - this.state = { - seen: new Set() - }; - - this._onExpand = oncePerAnimationFrame(this._onExpand).bind(this); - this._onCollapse = oncePerAnimationFrame(this._onCollapse).bind(this); - this._focusPrevNode = oncePerAnimationFrame(this._focusPrevNode).bind(this); - this._focusNextNode = oncePerAnimationFrame(this._focusNextNode).bind(this); - this._focusParentNode = oncePerAnimationFrame(this._focusParentNode).bind(this); - this._focusFirstNode = oncePerAnimationFrame(this._focusFirstNode).bind(this); - this._focusLastNode = oncePerAnimationFrame(this._focusLastNode).bind(this); - - this._autoExpand = this._autoExpand.bind(this); - this._preventArrowKeyScrolling = this._preventArrowKeyScrolling.bind(this); - this._dfs = this._dfs.bind(this); - this._dfsFromRoots = this._dfsFromRoots.bind(this); - this._focus = this._focus.bind(this); - this._scrollNodeIntoView = this._scrollNodeIntoView.bind(this); - this._onBlur = this._onBlur.bind(this); - this._onKeyDown = this._onKeyDown.bind(this); - this._nodeIsExpandable = this._nodeIsExpandable.bind(this); - this._activateNode = oncePerAnimationFrame(this._activateNode).bind(this); - } - - componentDidMount() { - this._autoExpand(); - if (this.props.focused) { - this._scrollNodeIntoView(this.props.focused); - // Always keep the focus on the tree itself. - this.treeRef.focus(); - } - } - - componentWillReceiveProps(nextProps) { - this._autoExpand(); - } - - componentDidUpdate(prevProps, prevState) { - if (this.props.focused && prevProps.focused !== this.props.focused) { - this._scrollNodeIntoView(this.props.focused); - // Always keep the focus on the tree itself. - this.treeRef.focus(); - } - } - - _autoExpand() { - if (!this.props.autoExpandDepth) { - return; - } - - // Automatically expand the first autoExpandDepth levels for new items. Do - // not use the usual DFS infrastructure because we don't want to ignore - // collapsed nodes. - const autoExpand = (item, currentDepth) => { - if (currentDepth >= this.props.autoExpandDepth || this.state.seen.has(item)) { - return; - } - - this.props.onExpand(item); - this.state.seen.add(item); - - const children = this.props.getChildren(item); - const length = children.length; - for (let i = 0; i < length; i++) { - autoExpand(children[i], currentDepth + 1); - } - }; - - const roots = this.props.getRoots(); - const length = roots.length; - if (this.props.autoExpandAll) { - for (let i = 0; i < length; i++) { - autoExpand(roots[i], 0); - } - } else if (length != 0) { - autoExpand(roots[0], 0); - } - } - - _preventArrowKeyScrolling(e) { - switch (e.key) { - case "ArrowUp": - case "ArrowDown": - case "ArrowLeft": - case "ArrowRight": - e.preventDefault(); - e.stopPropagation(); - if (e.nativeEvent) { - if (e.nativeEvent.preventDefault) { - e.nativeEvent.preventDefault(); - } - if (e.nativeEvent.stopPropagation) { - e.nativeEvent.stopPropagation(); - } - } - } - } - - /** - * Perform a pre-order depth-first search from item. - */ - _dfs(item, maxDepth = Infinity, traversal = [], _depth = 0) { - traversal.push({ item, depth: _depth }); - - if (!this.props.isExpanded(item)) { - return traversal; - } - - const nextDepth = _depth + 1; - - if (nextDepth > maxDepth) { - return traversal; - } - - const children = this.props.getChildren(item); - const length = children.length; - for (let i = 0; i < length; i++) { - this._dfs(children[i], maxDepth, traversal, nextDepth); - } - - return traversal; - } - - /** - * Perform a pre-order depth-first search over the whole forest. - */ - _dfsFromRoots(maxDepth = Infinity) { - const traversal = []; - - const roots = this.props.getRoots(); - const length = roots.length; - for (let i = 0; i < length; i++) { - this._dfs(roots[i], maxDepth, traversal); - } - - return traversal; - } - - /** - * Expands current row. - * - * @param {Object} item - * @param {Boolean} expandAllChildren - */ - _onExpand(item, expandAllChildren) { - if (this.props.onExpand) { - this.props.onExpand(item); - - if (expandAllChildren) { - const children = this._dfs(item); - const length = children.length; - for (let i = 0; i < length; i++) { - this.props.onExpand(children[i].item); - } - } - } - } - - /** - * Collapses current row. - * - * @param {Object} item - */ - _onCollapse(item) { - if (this.props.onCollapse) { - this.props.onCollapse(item); - } - } - - /** - * Sets the passed in item to be the focused item. - * - * @param {Object|undefined} item - * The item to be focused, or undefined to focus no item. - * - * @param {Object|undefined} options - * An options object which can contain: - * - dir: "up" or "down" to indicate if we should scroll the element - * to the top or the bottom of the scrollable container when - * the element is off canvas. - */ - _focus(item, options = {}) { - const { preventAutoScroll } = options; - if (item && !preventAutoScroll) { - this._scrollNodeIntoView(item, options); - } - if (this.props.onFocus) { - this.props.onFocus(item); - } - } - - /** - * Sets the passed in item to be the focused item. - * - * @param {Object|undefined} item - * The item to be scrolled to. - * - * @param {Object|undefined} options - * An options object which can contain: - * - dir: "up" or "down" to indicate if we should scroll the element - * to the top or the bottom of the scrollable container when - * the element is off canvas. - */ - _scrollNodeIntoView(item, options = {}) { - if (item !== undefined) { - const treeElement = this.treeRef; - const element = document.getElementById(this.props.getKey(item)); - - if (element) { - const { top, bottom } = element.getBoundingClientRect(); - const closestScrolledParent = node => { - if (node == null) { - return null; - } - - if (node.scrollHeight > node.clientHeight) { - return node; - } - return closestScrolledParent(node.parentNode); - }; - const scrolledParent = closestScrolledParent(treeElement); - const scrolledParentRect = scrolledParent ? scrolledParent.getBoundingClientRect() : null; - const isVisible = !scrolledParent || top >= scrolledParentRect.top && bottom <= scrolledParentRect.bottom; - - if (!isVisible) { - const { alignTo } = options; - const scrollToTop = alignTo ? alignTo === "top" : !scrolledParentRect || top < scrolledParentRect.top; - element.scrollIntoView(scrollToTop); - } - } - } - } - - /** - * Sets the state to have no focused item. - */ - _onBlur() { - this._focus(undefined); - } - - /** - * Handles key down events in the tree's container. - * - * @param {Event} e - */ - _onKeyDown(e) { - if (this.props.focused == null) { - return; - } - - // Allow parent nodes to use navigation arrows with modifiers. - if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { - return; - } - - this._preventArrowKeyScrolling(e); - - switch (e.key) { - case "ArrowUp": - this._focusPrevNode(); - return; - - case "ArrowDown": - this._focusNextNode(); - return; - - case "ArrowLeft": - if (this.props.isExpanded(this.props.focused) && this._nodeIsExpandable(this.props.focused)) { - this._onCollapse(this.props.focused); - } else { - this._focusParentNode(); - } - return; - - case "ArrowRight": - if (this._nodeIsExpandable(this.props.focused) && !this.props.isExpanded(this.props.focused)) { - this._onExpand(this.props.focused); - } else { - this._focusNextNode(); - } - return; - - case "Home": - this._focusFirstNode(); - return; - - case "End": - this._focusLastNode(); - return; - - case "Enter": - this._activateNode(); - } - } - - /** - * Sets the previous node relative to the currently focused item, to focused. - */ - _focusPrevNode() { - // Start a depth first search and keep going until we reach the currently - // focused node. Focus the previous node in the DFS, if it exists. If it - // doesn't exist, we're at the first node already. - - let prev; - - const traversal = this._dfsFromRoots(); - const length = traversal.length; - for (let i = 0; i < length; i++) { - const item = traversal[i].item; - if (item === this.props.focused) { - break; - } - prev = item; - } - if (prev === undefined) { - return; - } - - this._focus(prev, { alignTo: "top" }); - } - - /** - * Handles the down arrow key which will focus either the next child - * or sibling row. - */ - _focusNextNode() { - // Start a depth first search and keep going until we reach the currently - // focused node. Focus the next node in the DFS, if it exists. If it - // doesn't exist, we're at the last node already. - const traversal = this._dfsFromRoots(); - const length = traversal.length; - let i = 0; - - while (i < length) { - if (traversal[i].item === this.props.focused) { - break; - } - i++; - } - - if (i + 1 < traversal.length) { - this._focus(traversal[i + 1].item, { alignTo: "bottom" }); - } - } - - /** - * Handles the left arrow key, going back up to the current rows' - * parent row. - */ - _focusParentNode() { - const parent = this.props.getParent(this.props.focused); - if (!parent) { - this._focusPrevNode(this.props.focused); - return; - } - - const traversal = this._dfsFromRoots(); - const length = traversal.length; - let parentIndex = 0; - for (; parentIndex < length; parentIndex++) { - if (traversal[parentIndex].item === parent) { - break; - } - } - - this._focus(parent, { alignTo: "top" }); - } - - _focusFirstNode() { - const traversal = this._dfsFromRoots(); - this._focus(traversal[0].item, { alignTo: "top" }); - } - - _focusLastNode() { - const traversal = this._dfsFromRoots(); - const lastIndex = traversal.length - 1; - this._focus(traversal[lastIndex].item, { alignTo: "bottom" }); - } - - _activateNode() { - if (this.props.onActivate) { - this.props.onActivate(this.props.focused); - } - } - - _nodeIsExpandable(item) { - return this.props.isExpandable ? this.props.isExpandable(item) : !!this.props.getChildren(item).length; - } - - render() { - const traversal = this._dfsFromRoots(); - const { focused } = this.props; - - const nodes = traversal.map((v, i) => { - const { item, depth } = traversal[i]; - const key = this.props.getKey(item, i); - return TreeNodeFactory({ - key, - id: key, - index: i, - item, - depth, - renderItem: this.props.renderItem, - focused: focused === item, - expanded: this.props.isExpanded(item), - isExpandable: this._nodeIsExpandable(item), - onExpand: this._onExpand, - onCollapse: this._onCollapse, - onClick: e => { - // Since the user just clicked the node, there's no need to check if - // it should be scrolled into view. - this._focus(item, { preventAutoScroll: true }); - if (this.props.isExpanded(item)) { - this.props.onCollapse(item); - } else { - this.props.onExpand(item, e.altKey); - } - } - }); - }); - - const style = Object.assign({}, this.props.style || {}, { - padding: 0, - margin: 0 - }); - - return _reactDomFactories2.default.div({ - className: `tree ${this.props.className ? this.props.className : ""}`, - ref: el => { - this.treeRef = el; - }, - role: "tree", - tabIndex: "0", - onKeyDown: this._onKeyDown, - onKeyPress: this._preventArrowKeyScrolling, - onKeyUp: this._preventArrowKeyScrolling, - onFocus: ({ nativeEvent }) => { - if (focused || !nativeEvent || !this.treeRef) { - return; - } - - const { explicitOriginalTarget } = nativeEvent; - // Only set default focus to the first tree node if the focus came - // from outside the tree (e.g. by tabbing to the tree from other - // external elements). - if (explicitOriginalTarget !== this.treeRef && !this.treeRef.contains(explicitOriginalTarget)) { - this._focus(traversal[0].item); - } - }, - onBlur: this._onBlur, - "aria-label": this.props.label, - "aria-labelledby": this.props.labelledby, - "aria-activedescendant": focused && this.props.getKey(focused), - style - }, nodes); - } -} - -exports.default = Tree; - -/***/ }), - -/***/ 3671: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 3672: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 3673: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const { getGripType, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders undefined value - */ -const Undefined = function () { - return span({ className: "objectBox objectBox-undefined" }, "undefined"); -}; - -function supportsObject(object, noGrip = false) { - if (noGrip === true) { - return object === undefined; - } - - return object && object.type && object.type == "undefined" || getGripType(object, noGrip) == "undefined"; -} - -// Exports from this module - -module.exports = { - rep: wrapRender(Undefined), - supportsObject -}; - -/***/ }), - -/***/ 3674: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const { wrapRender } = __webpack_require__(3644); -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders null value - */ -function Null(props) { - return span({ className: "objectBox objectBox-null" }, "null"); -} - -function supportsObject(object, noGrip = false) { - if (noGrip === true) { - return object === null; - } - - if (object && object.type && object.type == "null") { - return true; - } - - return object == null; -} - -// Exports from this module - -module.exports = { - rep: wrapRender(Null), - supportsObject -}; - -/***/ }), - -/***/ 3675: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); - -const { getGripType, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a number - */ -Number.propTypes = { - object: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.bool]).isRequired -}; - -function Number(props) { - const value = props.object; - - return span({ className: "objectBox objectBox-number" }, stringify(value)); -} - -function stringify(object) { - const isNegativeZero = Object.is(object, -0) || object.type && object.type == "-0"; - - return isNegativeZero ? "-0" : String(object); -} - -function supportsObject(object, noGrip = false) { - return ["boolean", "number", "-0"].includes(getGripType(object, noGrip)); -} - -// Exports from this module - -module.exports = { - rep: wrapRender(Number), - supportsObject -}; - -/***/ }), - -/***/ 3676: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); -const { wrapRender, ellipsisElement } = __webpack_require__(3644); -const PropRep = __webpack_require__(3650); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; - -const DEFAULT_TITLE = "Object"; - -/** - * Renders an object. An object is represented by a list of its - * properties enclosed in curly brackets. - */ -ObjectRep.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - title: PropTypes.string -}; - -function ObjectRep(props) { - const object = props.object; - const propsArray = safePropIterator(props, object); - - if (props.mode === MODE.TINY) { - const tinyModeItems = []; - if (getTitle(props, object) !== DEFAULT_TITLE) { - tinyModeItems.push(getTitleElement(props, object)); - } else { - tinyModeItems.push(span({ - className: "objectLeftBrace" - }, "{"), propsArray.length > 0 ? ellipsisElement : null, span({ - className: "objectRightBrace" - }, "}")); - } - - return span({ className: "objectBox objectBox-object" }, ...tinyModeItems); - } - - return span({ className: "objectBox objectBox-object" }, getTitleElement(props, object), span({ - className: "objectLeftBrace" - }, " { "), ...propsArray, span({ - className: "objectRightBrace" - }, " }")); -} - -function getTitleElement(props, object) { - return span({ className: "objectTitle" }, getTitle(props, object)); -} - -function getTitle(props, object) { - return props.title || DEFAULT_TITLE; -} - -function safePropIterator(props, object, max) { - max = typeof max === "undefined" ? 3 : max; - try { - return propIterator(props, object, max); - } catch (err) { - console.error(err); - } - return []; -} - -function propIterator(props, object, max) { - // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=945377 - if (Object.prototype.toString.call(object) === "[object Generator]") { - object = Object.getPrototypeOf(object); - } - - const elements = []; - const unimportantProperties = []; - let propertiesNumber = 0; - const propertiesNames = Object.keys(object); - - const pushPropRep = (name, value) => { - elements.push(PropRep(_extends({}, props, { - key: name, - mode: MODE.TINY, - name, - object: value, - equal: ": " - }))); - propertiesNumber++; - - if (propertiesNumber < propertiesNames.length) { - elements.push(", "); - } - }; - - try { - for (const name of propertiesNames) { - if (propertiesNumber >= max) { - break; - } - - let value; - try { - value = object[name]; - } catch (exc) { - continue; - } - - // Object members with non-empty values are preferred since it gives the - // user a better overview of the object. - if (isInterestingProp(value)) { - pushPropRep(name, value); - } else { - // If the property is not important, put its name on an array for later - // use. - unimportantProperties.push(name); - } - } - } catch (err) { - console.error(err); - } - - if (propertiesNumber < max) { - for (const name of unimportantProperties) { - if (propertiesNumber >= max) { - break; - } - - let value; - try { - value = object[name]; - } catch (exc) { - continue; - } - - pushPropRep(name, value); - } - } - - if (propertiesNumber < propertiesNames.length) { - elements.push(ellipsisElement); - } - - return elements; -} - -function isInterestingProp(value) { - const type = typeof value; - return type == "boolean" || type == "number" || type == "string" && value; -} - -function supportsObject(object) { - return true; -} - -// Exports from this module -module.exports = { - rep: wrapRender(ObjectRep), - supportsObject -}; - -/***/ }), - -/***/ 3677: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); - -const { getGripType, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a symbol. - */ -SymbolRep.propTypes = { - object: PropTypes.object.isRequired -}; - -function SymbolRep(props) { - const { className = "objectBox objectBox-symbol", object } = props; - const { name } = object; - - return span({ - className, - "data-link-actor-id": object.actor - }, `Symbol(${name || ""})`); -} - -function supportsObject(object, noGrip = false) { - return getGripType(object, noGrip) == "symbol"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(SymbolRep), - supportsObject -}; - -/***/ }), - -/***/ 3678: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); - -const { getGripType, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a Infinity object - */ -InfinityRep.propTypes = { - object: PropTypes.object.isRequired -}; - -function InfinityRep(props) { - const { object } = props; - - return span({ className: "objectBox objectBox-number" }, object.type); -} - -function supportsObject(object, noGrip = false) { - const type = getGripType(object, noGrip); - return type == "Infinity" || type == "-Infinity"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(InfinityRep), - supportsObject -}; - -/***/ }), - -/***/ 3679: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const { getGripType, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a NaN object - */ -function NaNRep(props) { - return span({ className: "objectBox objectBox-nan" }, "NaN"); -} - -function supportsObject(object, noGrip = false) { - return getGripType(object, noGrip) == "NaN"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(NaNRep), - supportsObject -}; - -/***/ }), - -/***/ 368: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3680: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const dom = __webpack_require__(3643); -const PropTypes = __webpack_require__(3642); -const { wrapRender } = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); -const { span } = dom; - -/** - * Renders an object. An object is represented by a list of its - * properties enclosed in curly brackets. - */ -Accessor.propTypes = { - object: PropTypes.object.isRequired, - mode: PropTypes.oneOf(Object.values(MODE)) -}; - -function Accessor(props) { - const { object } = props; - - const accessors = []; - if (hasGetter(object)) { - accessors.push("Getter"); - } - if (hasSetter(object)) { - accessors.push("Setter"); - } - const title = accessors.join(" & "); - - return span({ className: "objectBox objectBox-accessor objectTitle" }, title); -} - -function hasGetter(object) { - return object && object.get && object.get.type !== "undefined"; -} - -function hasSetter(object) { - return object && object.set && object.set.type !== "undefined"; -} - -function supportsObject(object, noGrip = false) { - if (noGrip !== true && (hasGetter(object) || hasSetter(object))) { - return true; - } - - return false; -} - -// Exports from this module -module.exports = { - rep: wrapRender(Accessor), - supportsObject -}; - -/***/ }), - -/***/ 3681: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); -const dom = __webpack_require__(3643); -const { span } = dom; - -// Reps -const { getGripType, isGrip, wrapRender } = __webpack_require__(3644); -const { rep: StringRep } = __webpack_require__(3648); - -/** - * Renders DOM attribute - */ -Attribute.propTypes = { - object: PropTypes.object.isRequired -}; - -function Attribute(props) { - const { object } = props; - const value = object.preview.value; - - return span({ - "data-link-actor-id": object.actor, - className: "objectBox-Attr" - }, span({ className: "attrName" }, getTitle(object)), span({ className: "attrEqual" }, "="), StringRep({ className: "attrValue", object: value })); -} - -function getTitle(grip) { - return grip.preview.nodeName; -} - -// Registration -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return getGripType(grip, noGrip) == "Attr" && grip.preview; -} - -module.exports = { - rep: wrapRender(Attribute), - supportsObject -}; - -/***/ }), - -/***/ 3682: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { getGripType, isGrip, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Used to render JS built-in Date() object. - */ -DateTime.propTypes = { - object: PropTypes.object.isRequired -}; - -function DateTime(props) { - const grip = props.object; - let date; - try { - date = span({ - "data-link-actor-id": grip.actor, - className: "objectBox" - }, getTitle(grip), span({ className: "Date" }, new Date(grip.preview.timestamp).toISOString())); - } catch (e) { - date = span({ className: "objectBox" }, "Invalid Date"); - } - - return date; -} - -function getTitle(grip) { - return span({ - className: "objectTitle" - }, `${grip.class} `); -} - -// Registration -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return getGripType(grip, noGrip) == "Date" && grip.preview; -} - -// Exports from this module -module.exports = { - rep: wrapRender(DateTime), - supportsObject -}; - -/***/ }), - -/***/ 3683: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { - getGripType, - isGrip, - getURLDisplayString, - wrapRender -} = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders DOM document object. - */ -Document.propTypes = { - object: PropTypes.object.isRequired -}; - -function Document(props) { - const grip = props.object; - const location = getLocation(grip); - return span({ - "data-link-actor-id": grip.actor, - className: "objectBox objectBox-document" - }, getTitle(grip), location ? span({ className: "location" }, ` ${location}`) : null); -} - -function getLocation(grip) { - const location = grip.preview.location; - return location ? getURLDisplayString(location) : null; -} - -function getTitle(grip) { - return span({ - className: "objectTitle" - }, grip.class); -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - - const type = getGripType(object, noGrip); - return object.preview && (type === "HTMLDocument" || type === "XULDocument"); -} - -// Exports from this module -module.exports = { - rep: wrapRender(Document), - supportsObject -}; - -/***/ }), - -/***/ 3684: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { getGripType, isGrip, wrapRender } = __webpack_require__(3644); -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders DOM documentType object. - */ -DocumentType.propTypes = { - object: PropTypes.object.isRequired -}; - -function DocumentType(props) { - const { object } = props; - const name = object && object.preview && object.preview.nodeName ? ` ${object.preview.nodeName}` : ""; - return span({ - "data-link-actor-id": props.object.actor, - className: "objectBox objectBox-document" - }, ``); -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - - const type = getGripType(object, noGrip); - return object.preview && type === "DocumentType"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(DocumentType), - supportsObject -}; - -/***/ }), - -/***/ 3685: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { isGrip, wrapRender } = __webpack_require__(3644); - -const { MODE } = __webpack_require__(3645); -const { rep } = __webpack_require__(3656); - -/** - * Renders DOM event objects. - */ -Event.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func -}; - -function Event(props) { - const gripProps = _extends({}, props, { - title: getTitle(props), - object: _extends({}, props.object, { - preview: _extends({}, props.object.preview, { - ownProperties: {} - }) - }) - }); - - if (gripProps.object.preview.target) { - Object.assign(gripProps.object.preview.ownProperties, { - target: gripProps.object.preview.target - }); - } - Object.assign(gripProps.object.preview.ownProperties, gripProps.object.preview.properties); - - delete gripProps.object.preview.properties; - gripProps.object.ownPropertyLength = Object.keys(gripProps.object.preview.ownProperties).length; - - switch (gripProps.object.class) { - case "MouseEvent": - gripProps.isInterestingProp = (type, value, name) => { - return ["target", "clientX", "clientY", "layerX", "layerY"].includes(name); - }; - break; - case "KeyboardEvent": - gripProps.isInterestingProp = (type, value, name) => { - return ["target", "key", "charCode", "keyCode"].includes(name); - }; - break; - case "MessageEvent": - gripProps.isInterestingProp = (type, value, name) => { - return ["target", "isTrusted", "data"].includes(name); - }; - break; - default: - gripProps.isInterestingProp = (type, value, name) => { - // We want to show the properties in the order they are declared. - return Object.keys(gripProps.object.preview.ownProperties).includes(name); - }; - } - - return rep(gripProps); -} - -function getTitle(props) { - const preview = props.object.preview; - let title = preview.type; - - if (preview.eventKind == "key" && preview.modifiers && preview.modifiers.length) { - title = `${title} ${preview.modifiers.join("-")}`; - } - return title; -} - -// Registration -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return grip.preview && grip.preview.kind == "DOMEvent"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(Event), - supportsObject -}; - -/***/ }), - -/***/ 3686: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); -// Dependencies -const { getGripType, isGrip, wrapRender } = __webpack_require__(3644); - -const PropRep = __webpack_require__(3650); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a DOM Promise object. - */ -PromiseRep.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func -}; - -function PromiseRep(props) { - const object = props.object; - const { promiseState } = object; - - const config = { - "data-link-actor-id": object.actor, - className: "objectBox objectBox-object" - }; - - if (props.mode === MODE.TINY) { - const { Rep } = __webpack_require__(3647); - - return span(config, getTitle(object), span({ - className: "objectLeftBrace" - }, " { "), Rep({ object: promiseState.state }), span({ - className: "objectRightBrace" - }, " }")); - } - - const propsArray = getProps(props, promiseState); - return span(config, getTitle(object), span({ - className: "objectLeftBrace" - }, " { "), ...propsArray, span({ - className: "objectRightBrace" - }, " }")); -} - -function getTitle(object) { - return span({ - className: "objectTitle" - }, object.class); -} - -function getProps(props, promiseState) { - const keys = ["state"]; - if (Object.keys(promiseState).includes("value")) { - keys.push("value"); - } - - return keys.reduce((res, key, i) => { - const object = promiseState[key]; - res = res.concat(PropRep(_extends({}, props, { - mode: MODE.TINY, - name: `<${key}>`, - object, - equal: ": ", - suppressQuotes: true - }))); - - // Interleave commas between elements - if (i !== keys.length - 1) { - res.push(", "); - } - - return res; - }, []); -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - return getGripType(object, noGrip) == "Promise"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(PromiseRep), - supportsObject -}; - -/***/ }), - -/***/ 3687: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { getGripType, isGrip, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a grip object with regular expression. - */ -RegExp.propTypes = { - object: PropTypes.object.isRequired -}; - -function RegExp(props) { - const { object } = props; - - return span({ - "data-link-actor-id": object.actor, - className: "objectBox objectBox-regexp regexpSource" - }, getSource(object)); -} - -function getSource(grip) { - return grip.displayString; -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - - return getGripType(object, noGrip) == "RegExp"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(RegExp), - supportsObject -}; - -/***/ }), - -/***/ 3688: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { - getGripType, - isGrip, - getURLDisplayString, - wrapRender -} = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a grip representing CSSStyleSheet - */ -StyleSheet.propTypes = { - object: PropTypes.object.isRequired -}; - -function StyleSheet(props) { - const grip = props.object; - - return span({ - "data-link-actor-id": grip.actor, - className: "objectBox objectBox-object" - }, getTitle(grip), span({ className: "objectPropValue" }, getLocation(grip))); -} - -function getTitle(grip) { - const title = "StyleSheet "; - return span({ className: "objectBoxTitle" }, title); -} - -function getLocation(grip) { - // Embedded stylesheets don't have URL and so, no preview. - const url = grip.preview ? grip.preview.url : ""; - return url ? getURLDisplayString(url) : ""; -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - - return getGripType(object, noGrip) == "CSSStyleSheet"; -} - -// Exports from this module - -module.exports = { - rep: wrapRender(StyleSheet), - supportsObject -}; - -/***/ }), - -/***/ 3689: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// Dependencies -const PropTypes = __webpack_require__(3642); -const { - isGrip, - cropString, - cropMultipleLines, - wrapRender -} = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); -const nodeConstants = __webpack_require__(3659); -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders DOM comment node. - */ -CommentNode.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])) -}; - -function CommentNode(props) { - const { object, mode = MODE.SHORT } = props; - - let { textContent } = object.preview; - if (mode === MODE.TINY) { - textContent = cropMultipleLines(textContent, 30); - } else if (mode === MODE.SHORT) { - textContent = cropString(textContent, 50); - } - - return span({ - className: "objectBox theme-comment", - "data-link-actor-id": object.actor - }, ``); -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - return object.preview && object.preview.nodeType === nodeConstants.COMMENT_NODE; -} - -// Exports from this module -module.exports = { - rep: wrapRender(CommentNode), - supportsObject -}; - -/***/ }), - -/***/ 369: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3690: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Utils -const { isGrip, wrapRender } = __webpack_require__(3644); -const { rep: StringRep } = __webpack_require__(3648); -const { MODE } = __webpack_require__(3645); -const nodeConstants = __webpack_require__(3659); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders DOM element node. - */ -ElementNode.propTypes = { - object: PropTypes.object.isRequired, - inspectIconTitle: PropTypes.string, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - onDOMNodeClick: PropTypes.func, - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func -}; - -function ElementNode(props) { - const { - object, - inspectIconTitle, - mode, - onDOMNodeClick, - onDOMNodeMouseOver, - onDOMNodeMouseOut, - onInspectIconClick - } = props; - const elements = getElements(object, mode); - - const isInTree = object.preview && object.preview.isConnected === true; - - const baseConfig = { - "data-link-actor-id": object.actor, - className: "objectBox objectBox-node" - }; - let inspectIcon; - if (isInTree) { - if (onDOMNodeClick) { - Object.assign(baseConfig, { - onClick: _ => onDOMNodeClick(object) - }); - } - - if (onDOMNodeMouseOver) { - Object.assign(baseConfig, { - onMouseOver: _ => onDOMNodeMouseOver(object) - }); - } - - if (onDOMNodeMouseOut) { - Object.assign(baseConfig, { - onMouseOut: onDOMNodeMouseOut - }); - } - - if (onInspectIconClick) { - inspectIcon = dom.button({ - className: "open-inspector", - // TODO: Localize this with "openNodeInInspector" when Bug 1317038 lands - title: inspectIconTitle || "Click to select the node in the inspector", - onClick: e => { - if (onDOMNodeClick) { - e.stopPropagation(); - } - - onInspectIconClick(object, e); - } - }); - } - } - - return span(baseConfig, ...elements, inspectIcon); -} - -function getElements(grip, mode) { - const { - attributes, - nodeName, - isAfterPseudoElement, - isBeforePseudoElement - } = grip.preview; - const nodeNameElement = span({ - className: "tag-name" - }, nodeName); - - if (isAfterPseudoElement || isBeforePseudoElement) { - return [span({ className: "attrName" }, `::${isAfterPseudoElement ? "after" : "before"}`)]; - } - - if (mode === MODE.TINY) { - const elements = [nodeNameElement]; - if (attributes.id) { - elements.push(span({ className: "attrName" }, `#${attributes.id}`)); - } - if (attributes.class) { - elements.push(span({ className: "attrName" }, attributes.class.trim().split(/\s+/).map(cls => `.${cls}`).join(""))); - } - return elements; - } - - const attributeKeys = Object.keys(attributes); - if (attributeKeys.includes("class")) { - attributeKeys.splice(attributeKeys.indexOf("class"), 1); - attributeKeys.unshift("class"); - } - if (attributeKeys.includes("id")) { - attributeKeys.splice(attributeKeys.indexOf("id"), 1); - attributeKeys.unshift("id"); - } - const attributeElements = attributeKeys.reduce((arr, name, i, keys) => { - const value = attributes[name]; - const attribute = span({}, span({ className: "attrName" }, name), span({ className: "attrEqual" }, "="), StringRep({ className: "attrValue", object: value })); - - return arr.concat([" ", attribute]); - }, []); - - return [span({ className: "angleBracket" }, "<"), nodeNameElement, ...attributeElements, span({ className: "angleBracket" }, ">")]; -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - return object.preview && object.preview.nodeType === nodeConstants.ELEMENT_NODE; -} - -// Exports from this module -module.exports = { - rep: wrapRender(ElementNode), - supportsObject -}; - -/***/ }), - -/***/ 3691: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { isGrip, cropString, wrapRender } = __webpack_require__(3644); -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders DOM #text node. - */ -TextNode.propTypes = { - object: PropTypes.object.isRequired, - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - onDOMNodeMouseOver: PropTypes.func, - onDOMNodeMouseOut: PropTypes.func, - onInspectIconClick: PropTypes.func -}; - -function TextNode(props) { - const { - object: grip, - mode = MODE.SHORT, - onDOMNodeMouseOver, - onDOMNodeMouseOut, - onInspectIconClick - } = props; - - const baseConfig = { - "data-link-actor-id": grip.actor, - className: "objectBox objectBox-textNode" - }; - let inspectIcon; - const isInTree = grip.preview && grip.preview.isConnected === true; - - if (isInTree) { - if (onDOMNodeMouseOver) { - Object.assign(baseConfig, { - onMouseOver: _ => onDOMNodeMouseOver(grip) - }); - } - - if (onDOMNodeMouseOut) { - Object.assign(baseConfig, { - onMouseOut: onDOMNodeMouseOut - }); - } - - if (onInspectIconClick) { - inspectIcon = dom.button({ - className: "open-inspector", - draggable: false, - // TODO: Localize this with "openNodeInInspector" when Bug 1317038 lands - title: "Click to select the node in the inspector", - onClick: e => onInspectIconClick(grip, e) - }); - } - } - - if (mode === MODE.TINY) { - return span(baseConfig, getTitle(grip), inspectIcon); - } - - return span(baseConfig, getTitle(grip), span({ className: "nodeValue" }, " ", `"${getTextContent(grip)}"`), inspectIcon); -} - -function getTextContent(grip) { - return cropString(grip.preview.textContent); -} - -function getTitle(grip) { - const title = "#text"; - return span({}, title); -} - -// Registration -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return grip.preview && grip.class == "Text"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(TextNode), - supportsObject -}; - -/***/ }), - -/***/ 3692: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { - getGripType, - isGrip, - getURLDisplayString, - wrapRender -} = __webpack_require__(3644); - -const { MODE } = __webpack_require__(3645); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a grip representing a window. - */ -WindowRep.propTypes = { - // @TODO Change this to Object.values when supported in Node's version of V8 - mode: PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])), - object: PropTypes.object.isRequired -}; - -function WindowRep(props) { - const { mode, object } = props; - - const config = { - "data-link-actor-id": object.actor, - className: "objectBox objectBox-Window" - }; - - if (mode === MODE.TINY) { - return span(config, getTitle(object)); - } - - return span(config, getTitle(object, true), span({ className: "location" }, getLocation(object))); -} - -function getTitle(object, trailingSpace) { - let title = object.displayClass || object.class || "Window"; - if (trailingSpace === true) { - title = `${title} `; - } - return span({ className: "objectTitle" }, title); -} - -function getLocation(object) { - return getURLDisplayString(object.preview.url); -} - -// Registration -function supportsObject(object, noGrip = false) { - if (noGrip === true || !isGrip(object)) { - return false; - } - - return object.preview && getGripType(object, noGrip) == "Window"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(WindowRep), - supportsObject -}; - -/***/ }), - -/***/ 3693: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { isGrip, wrapRender } = __webpack_require__(3644); - -const String = __webpack_require__(3648).rep; - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a grip object with textual data. - */ -ObjectWithText.propTypes = { - object: PropTypes.object.isRequired -}; - -function ObjectWithText(props) { - const grip = props.object; - return span({ - "data-link-actor-id": grip.actor, - className: `objectTitle objectBox objectBox-${getType(grip)}` - }, `${getType(grip)} `, getDescription(grip)); -} - -function getType(grip) { - return grip.class; -} - -function getDescription(grip) { - return String({ - object: grip.preview.text - }); -} - -// Registration -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return grip.preview && grip.preview.kind == "ObjectWithText"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(ObjectWithText), - supportsObject -}; - -/***/ }), - -/***/ 3694: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// ReactJS -const PropTypes = __webpack_require__(3642); - -// Reps -const { isGrip, getURLDisplayString, wrapRender } = __webpack_require__(3644); - -const dom = __webpack_require__(3643); -const { span } = dom; - -/** - * Renders a grip object with URL data. - */ -ObjectWithURL.propTypes = { - object: PropTypes.object.isRequired -}; - -function ObjectWithURL(props) { - const grip = props.object; - return span({ - "data-link-actor-id": grip.actor, - className: `objectBox objectBox-${getType(grip)}` - }, getTitle(grip), span({ className: "objectPropValue" }, getDescription(grip))); -} - -function getTitle(grip) { - return span({ className: "objectTitle" }, `${getType(grip)} `); -} - -function getType(grip) { - return grip.class; -} - -function getDescription(grip) { - return getURLDisplayString(grip.preview.url); -} - -// Registration -function supportsObject(grip, noGrip = false) { - if (noGrip === true || !isGrip(grip)) { - return false; - } - - return grip.preview && grip.preview.kind == "ObjectWithURL"; -} - -// Exports from this module -module.exports = { - rep: wrapRender(ObjectWithURL), - supportsObject -}; - -/***/ }), - -/***/ 3695: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { createElement, createFactory, PureComponent } = __webpack_require__(0); -const { Provider } = __webpack_require__(3592); -const ObjectInspector = createFactory(__webpack_require__(3696)); -const createStore = __webpack_require__(3700); -const Utils = __webpack_require__(3657); -const { renderRep, shouldRenderRootsInReps } = Utils; - -class OI extends PureComponent { - constructor(props) { - super(props); - this.store = createStore(props); - } - - getStore() { - return this.store; - } - - render() { - return createElement(Provider, { store: this.store }, ObjectInspector(this.props)); - } -} - -module.exports = props => { - const { roots } = props; - if (shouldRenderRootsInReps(roots)) { - return renderRep(roots[0], props); - } - return new OI(props); -}; - -/***/ }), - -/***/ 3696: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _devtoolsComponents = __webpack_require__(3669); - -var _devtoolsComponents2 = _interopRequireDefault(_devtoolsComponents); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { Component, createFactory } = __webpack_require__(0); -const dom = __webpack_require__(3643); -const { connect } = __webpack_require__(3592); -const { bindActionCreators } = __webpack_require__(3593); - -const Tree = createFactory(_devtoolsComponents2.default.Tree); -__webpack_require__(3697); - -const classnames = __webpack_require__(175); -const { MODE } = __webpack_require__(3645); - -const Utils = __webpack_require__(3657); - -const { - getChildren, - getClosestGripNode, - getParent, - getValue, - nodeHasAccessors, - nodeHasProperties, - nodeIsBlock, - nodeIsDefaultProperties, - nodeIsFunction, - nodeIsGetter, - nodeIsMapEntry, - nodeIsMissingArguments, - nodeIsOptimizedOut, - nodeIsPrimitive, - nodeIsPrototype, - nodeIsSetter, - nodeIsUninitializedBinding, - nodeIsUnmappedBinding, - nodeIsUnscopedBinding, - nodeIsWindow, - nodeIsLongString, - nodeHasFullText -} = Utils.node; - -// This implements a component that renders an interactive inspector -// for looking at JavaScript objects. It expects descriptions of -// objects from the protocol, and will dynamically fetch children -// properties as objects are expanded. -// -// If you want to inspect a single object, pass the name and the -// protocol descriptor of it: -// -// ObjectInspector({ -// name: "foo", -// desc: { writable: true, ..., { value: { actor: "1", ... }}}, -// ... -// }) -// -// If you want multiple top-level objects (like scopes), you can pass -// an array of manually constructed nodes as `roots`: -// -// ObjectInspector({ -// roots: [{ name: ... }, ...], -// ... -// }); - -// There are 3 types of nodes: a simple node with a children array, an -// object that has properties that should be children when they are -// fetched, and a primitive value that should be displayed with no -// children. - -class ObjectInspector extends Component { - constructor(props) { - super(); - this.cachedNodes = new Map(); - - const self = this; - - self.getItemChildren = this.getItemChildren.bind(this); - self.renderTreeItem = this.renderTreeItem.bind(this); - self.setExpanded = this.setExpanded.bind(this); - self.focusItem = this.focusItem.bind(this); - self.getRoots = this.getRoots.bind(this); - } - - shouldComponentUpdate(nextProps) { - const { expandedPaths, focusedItem, loadedProperties, roots } = this.props; - - if (roots !== nextProps.roots) { - // Since the roots changed, we assume the properties did as well, - // so we need to cleanup the component internal state. - - // We can clear the cachedNodes to avoid bugs and memory leaks. - this.cachedNodes.clear(); - // The rootsChanged action will be handled in a middleware to release the - // actors of the old roots, as well as cleanup the state properties - // (expandedPaths, loadedProperties, …). - this.props.rootsChanged(nextProps); - // We don't render right away since the state is going to be changed by - // the rootsChanged action. The `state.forceUpdate` flag will be set - // to `true` so we can execute a new render cycle with the cleaned state. - return false; - } - - if (nextProps.forceUpdate === true) { - return true; - } - - // We should update if: - // - there are new loaded properties - // - OR the expanded paths number changed, and all of them have properties - // loaded - // - OR the expanded paths number did not changed, but old and new sets - // differ - // - OR the focused node changed. - return loadedProperties.size !== nextProps.loadedProperties.size || expandedPaths.size !== nextProps.expandedPaths.size && [...nextProps.expandedPaths].every(path => nextProps.loadedProperties.has(path)) || expandedPaths.size === nextProps.expandedPaths.size && [...nextProps.expandedPaths].some(key => !expandedPaths.has(key)) || focusedItem !== nextProps.focusedItem; - } - - componentDidUpdate(prevProps) { - if (this.props.forceUpdate) { - // If the component was updated, we can then reset the forceUpdate flag. - this.props.forceUpdated(); - } - } - - componentWillUnmount() { - const { releaseActor } = this.props; - if (typeof releaseActor !== "function") { - return; - } - - const { actors } = this.props; - for (const actor of actors) { - releaseActor(actor); - } - } - - getItemChildren(item) { - const { loadedProperties } = this.props; - const { cachedNodes } = this; - - return getChildren({ - loadedProperties, - cachedNodes, - item - }); - } - - getRoots() { - return this.props.roots; - } - - getNodeKey(item) { - return item.path && typeof item.path.toString === "function" ? item.path.toString() : JSON.stringify(item); - } - - setExpanded(item, expand) { - if (nodeIsPrimitive(item)) { - return; - } - - const { - createObjectClient, - createLongStringClient, - loadedProperties, - nodeExpand, - nodeCollapse, - roots - } = this.props; - - if (expand === true) { - const gripItem = getClosestGripNode(item); - const value = getValue(gripItem); - const isRoot = value && roots.some(root => { - const rootValue = getValue(root); - return rootValue && rootValue.actor === value.actor; - }); - const actor = isRoot || !value ? null : value.actor; - nodeExpand(item, actor, loadedProperties, createObjectClient, createLongStringClient); - } else { - nodeCollapse(item); - } - } - - focusItem(item) { - const { focusable = true, focusedItem, nodeFocus, onFocus } = this.props; - - if (focusable && focusedItem !== item) { - nodeFocus(item); - if (focusedItem !== item && onFocus) { - onFocus(item); - } - } - } - - // eslint-disable-next-line complexity - getTreeItemLabelAndValue(item, depth, expanded) { - const label = item.name; - const isPrimitive = nodeIsPrimitive(item); - - if (nodeIsOptimizedOut(item)) { - return { - label, - value: dom.span({ className: "unavailable" }, "(optimized away)") - }; - } - - if (nodeIsUninitializedBinding(item)) { - return { - label, - value: dom.span({ className: "unavailable" }, "(uninitialized)") - }; - } - - if (nodeIsUnmappedBinding(item)) { - return { - label, - value: dom.span({ className: "unavailable" }, "(unmapped)") - }; - } - - if (nodeIsUnscopedBinding(item)) { - return { - label, - value: dom.span({ className: "unavailable" }, "(unscoped)") - }; - } - - const itemValue = getValue(item); - const unavailable = isPrimitive && itemValue && itemValue.hasOwnProperty && itemValue.hasOwnProperty("unavailable"); - - if (nodeIsMissingArguments(item) || unavailable) { - return { - label, - value: dom.span({ className: "unavailable" }, "(unavailable)") - }; - } - - if (nodeIsFunction(item) && !nodeIsGetter(item) && !nodeIsSetter(item) && (this.props.mode === MODE.TINY || !this.props.mode)) { - return { - label: Utils.renderRep(item, _extends({}, this.props, { - functionName: label - })) - }; - } - - if (nodeHasProperties(item) || nodeHasAccessors(item) || nodeIsMapEntry(item) || nodeIsLongString(item) || isPrimitive) { - const repProps = _extends({}, this.props); - if (depth > 0) { - repProps.mode = this.props.mode === MODE.LONG ? MODE.SHORT : MODE.TINY; - } - if (expanded) { - repProps.mode = MODE.TINY; - } - - if (nodeIsLongString(item)) { - repProps.member = { - open: nodeHasFullText(item) && expanded - }; - } - - return { - label, - value: Utils.renderRep(item, repProps) - }; - } - - return { - label - }; - } - - renderTreeItemLabel(label, item, depth, focused, expanded) { - if (label === null || typeof label === "undefined") { - return null; - } - - const { onLabelClick } = this.props; - - return dom.span({ - className: "object-label", - onClick: onLabelClick ? event => { - event.stopPropagation(); - - // If the user selected text, bail out. - if (Utils.selection.documentHasSelection()) { - return; - } - - onLabelClick(item, { - depth, - focused, - expanded, - setExpanded: this.setExpanded - }); - } : undefined - }, label); - } - - getTreeTopElementProps(item, depth, focused, expanded) { - const { onCmdCtrlClick, onDoubleClick, dimTopLevelWindow } = this.props; - - const parentElementProps = { - className: classnames("node object-node", { - focused, - lessen: !expanded && (nodeIsDefaultProperties(item) || nodeIsPrototype(item) || dimTopLevelWindow === true && nodeIsWindow(item) && depth === 0), - block: nodeIsBlock(item) - }), - onClick: e => { - if (e.metaKey && onCmdCtrlClick) { - onCmdCtrlClick(item, { - depth, - event: e, - focused, - expanded - }); - e.stopPropagation(); - return; - } - - // If this click happened because the user selected some text, bail out. - // Note that if the user selected some text before and then clicks here, - // the previously selected text will be first unselected, unless the - // user clicked on the arrow itself. Indeed because the arrow is an - // image, clicking on it does not remove any existing text selection. - // So we need to also check if the arrow was clicked. - if (Utils.selection.documentHasSelection() && !(e.target && e.target.matches && e.target.matches(".arrow"))) { - e.stopPropagation(); - } - } - }; - - if (onDoubleClick) { - parentElementProps.onDoubleClick = e => { - e.stopPropagation(); - onDoubleClick(item, { - depth, - focused, - expanded - }); - }; - } - - return parentElementProps; - } - - renderTreeItem(item, depth, focused, arrow, expanded) { - const { label, value } = this.getTreeItemLabelAndValue(item, depth, expanded); - const labelElement = this.renderTreeItemLabel(label, item, depth, focused, expanded); - const delimiter = value && labelElement ? dom.span({ className: "object-delimiter" }, ": ") : null; - - return dom.div(this.getTreeTopElementProps(item, depth, focused, expanded), arrow, labelElement, delimiter, value); - } - - render() { - const { - autoExpandAll = true, - autoExpandDepth = 1, - focusable = true, - disableWrap = false, - expandedPaths, - focusedItem, - inline - } = this.props; - - return Tree({ - className: classnames({ - inline, - nowrap: disableWrap, - "object-inspector": true - }), - autoExpandAll, - autoExpandDepth, - - isExpanded: item => expandedPaths && expandedPaths.has(item.path), - isExpandable: item => nodeIsPrimitive(item) === false, - focused: focusedItem, - - getRoots: this.getRoots, - getParent, - getChildren: this.getItemChildren, - getKey: this.getNodeKey, - - onExpand: item => this.setExpanded(item, true), - onCollapse: item => this.setExpanded(item, false), - onFocus: focusable ? this.focusItem : null, - - renderItem: this.renderTreeItem - }); - } -} - -function mapStateToProps(state, props) { - return { - actors: state.actors, - expandedPaths: state.expandedPaths, - // If the root changes, we want to pass a possibly new focusedItem property - focusedItem: state.roots !== props.roots ? props.focusedItem : state.focusedItem, - loadedProperties: state.loadedProperties, - forceUpdate: state.forceUpdate - }; -} - -function mapDispatchToProps(dispatch) { - return bindActionCreators(__webpack_require__(3699), dispatch); -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(ObjectInspector); - -/***/ }), - -/***/ 3697: -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ 3698: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function documentHasSelection() { - const selection = getSelection(); - if (!selection) { - return false; - } - - return selection.type === "Range"; -} - -module.exports = { - documentHasSelection -}; - -/***/ }), - -/***/ 3699: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const { loadItemProperties } = __webpack_require__(3666); /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * This action is responsible for expanding a given node, which also means that - * it will call the action responsible to fetch properties. - */ -function nodeExpand(node, actor, loadedProperties, createObjectClient, createLongStringClient) { - return async ({ dispatch }) => { - dispatch({ - type: "NODE_EXPAND", - data: { node } - }); - - if (!loadedProperties.has(node.path)) { - dispatch(nodeLoadProperties(node, actor, loadedProperties, createObjectClient, createLongStringClient)); - } - }; -} - -function nodeCollapse(node) { - return { - type: "NODE_COLLAPSE", - data: { node } - }; -} - -function nodeFocus(node) { - return { - type: "NODE_FOCUS", - data: { node } - }; -} -/* - * This action checks if we need to fetch properties, entries, prototype and - * symbols for a given node. If we do, it will call the appropriate ObjectClient - * functions. - */ -function nodeLoadProperties(item, actor, loadedProperties, createObjectClient, createLongStringClient) { - return async ({ dispatch }) => { - try { - const properties = await loadItemProperties(item, createObjectClient, createLongStringClient, loadedProperties); - dispatch(nodePropertiesLoaded(item, actor, properties)); - } catch (e) { - console.error(e); - } - }; -} - -function nodePropertiesLoaded(node, actor, properties) { - return { - type: "NODE_PROPERTIES_LOADED", - data: { node, actor, properties } - }; -} - -/* - * This action is dispatched when the `roots` prop, provided by a consumer of - * the ObjectInspector (inspector, console, …), is modified. It will clean the - * internal state properties (expandedPaths, loadedProperties, …) and release - * the actors consumed with the previous roots. - * It takes a props argument which reflects what is passed by the upper-level - * consumer. - */ -function rootsChanged(props) { - return { - type: "ROOTS_CHANGED", - data: props - }; -} - -/* - * This action will reset the `forceUpdate` flag in the state. - */ -function forceUpdated() { - return { - type: "FORCE_UPDATED" - }; -} - -module.exports = { - forceUpdated, - nodeExpand, - nodeCollapse, - nodeFocus, - nodeLoadProperties, - nodePropertiesLoaded, - rootsChanged -}; - -/***/ }), - -/***/ 370: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3700: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const { applyMiddleware, createStore, compose } = __webpack_require__(3593); -const { thunk } = __webpack_require__(3701); -const { - waitUntilService -} = __webpack_require__(3702); -const reducer = __webpack_require__(3703); - -function createInitialState(overrides) { - return _extends({ - actors: new Set(), - expandedPaths: new Set(), - focusedItem: null, - loadedProperties: new Map(), - forceUpdated: false - }, overrides); -} - -function enableStateReinitializer(props) { - return next => (innerReducer, initialState, enhancer) => { - function reinitializerEnhancer(state, action) { - if (action.type !== "ROOTS_CHANGED") { - return innerReducer(state, action); - } - - if (props.releaseActor && initialState.actors) { - initialState.actors.forEach(props.releaseActor); - } - - return _extends({}, action.data, { - actors: new Set(), - expandedPaths: new Set(), - loadedProperties: new Map(), - // Indicates to the component that we do want to render on the next - // render cycle. - forceUpdate: true - }); - } - return next(reinitializerEnhancer, initialState, enhancer); - }; -} - -module.exports = props => { - const middlewares = [thunk]; - - if (props.injectWaitService) { - middlewares.push(waitUntilService); - } - - return createStore(reducer, createInitialState(props), compose(applyMiddleware(...middlewares), enableStateReinitializer(props))); -}; - -/***/ }), - -/***/ 3701: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/** - * A middleware that allows thunks (functions) to be dispatched. - * If it's a thunk, it is called with `dispatch` and `getState`, - * allowing the action to create multiple actions (most likely - * asynchronously). - */ -function thunk({ dispatch, getState }) { - return next => action => { - return typeof action === "function" ? action({ dispatch, getState }) : next(action); - }; -} -exports.thunk = thunk; - -/***/ }), - -/***/ 3702: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const WAIT_UNTIL_TYPE = "@@service/waitUntil"; -/** - * A middleware which acts like a service, because it is stateful - * and "long-running" in the background. It provides the ability - * for actions to install a function to be run once when a specific - * condition is met by an action coming through the system. Think of - * it as a thunk that blocks until the condition is met. Example: - * - * ```js - * const services = { WAIT_UNTIL: require('wait-service').NAME }; - * - * { type: services.WAIT_UNTIL, - * predicate: action => action.type === "ADD_ITEM", - * run: (dispatch, getState, action) => { - * // Do anything here. You only need to accept the arguments - * // if you need them. `action` is the action that satisfied - * // the predicate. - * } - * } - * ``` - */ -function waitUntilService({ dispatch, getState }) { - let pending = []; - - function checkPending(action) { - const readyRequests = []; - const stillPending = []; - - // Find the pending requests whose predicates are satisfied with - // this action. Wait to run the requests until after we update the - // pending queue because the request handler may synchronously - // dispatch again and run this service (that use case is - // completely valid). - for (const request of pending) { - if (request.predicate(action)) { - readyRequests.push(request); - } else { - stillPending.push(request); - } - } - - pending = stillPending; - for (const request of readyRequests) { - request.run(dispatch, getState, action); - } - } - - return next => action => { - if (action.type === WAIT_UNTIL_TYPE) { - pending.push(action); - return null; - } - const result = next(action); - checkPending(action); - return result; - }; -} - -module.exports = { - WAIT_UNTIL_TYPE, - waitUntilService -}; - -/***/ }), - -/***/ 3703: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -function reducer(state = {}, action) { - const { type, data } = action; - - const cloneState = overrides => _extends({}, state, overrides); - - if (type === "NODE_EXPAND") { - return cloneState({ - expandedPaths: new Set(state.expandedPaths).add(data.node.path) - }); - } - - if (type === "NODE_COLLAPSE") { - const expandedPaths = new Set(state.expandedPaths); - expandedPaths.delete(data.node.path); - return cloneState({ expandedPaths }); - } - - if (type === "NODE_PROPERTIES_LOADED") { - return cloneState({ - actors: data.actor ? new Set(state.actors || []).add(data.actor) : state.actors, - loadedProperties: new Map(state.loadedProperties).set(data.node.path, action.data.properties) - }); - } - - if (type === "NODE_FOCUS") { - if (state.focusedItem === data.node) { - return state; - } - - return cloneState({ - focusedItem: data.node - }); - } - - if (type === "FORCE_UPDATED") { - return cloneState({ - forceUpdate: false - }); - } - - return state; -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - - -module.exports = reducer; - -/***/ }), - -/***/ 371: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 372: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 3720: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.positionCmp = positionCmp; - -var _locColumn = __webpack_require__(2349); - -/** - * * === 0 - Positions are equal. - * * < 0 - first position before second position - * * > 0 - first position after second position - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function positionCmp(p1, p2) { - if (p1.line === p2.line) { - const l1 = (0, _locColumn.locColumn)(p1); - const l2 = (0, _locColumn.locColumn)(p2); - - if (l1 === l2) { - return 0; - } - return l1 < l2 ? -1 : 1; - } - - return p1.line < p2.line ? -1 : 1; -} - -/***/ }), - -/***/ 3721: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* WEBPACK VAR INJECTION */(function(process) { - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isDevelopment = isDevelopment; -exports.isTesting = isTesting; -exports.isFirefoxPanel = isFirefoxPanel; -exports.isFirefox = isFirefox; -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -const flag = __webpack_require__(52); - -function isBrowser() { - return typeof window == "object"; -} - -function isNode() { - return process && process.release && process.release.name == 'node'; -} - -function isDevelopment() { - if (!isNode && isBrowser()) { - const href = window.location ? window.location.href : ""; - return href.match(/^file:/) || href.match(/localhost:/); - } - - return "production" != "production"; -} - -function isTesting() { - return flag.testing; -} - -function isFirefoxPanel() { - return !isDevelopment(); -} - -function isFirefox() { - return (/firefox/i.test(navigator.userAgent) - ); -} -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120))) - -/***/ }), - -/***/ 3722: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.mappingContains = mappingContains; - -var _positionCmp = __webpack_require__(3720); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -function mappingContains(mapped, item) { - return (0, _positionCmp.positionCmp)(item.start, mapped.start) >= 0 && (0, _positionCmp.positionCmp)(item.end, mapped.end) <= 0; -} - -/***/ }), - -/***/ 3723: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -// eslint-disable-next-line max-len - - -exports.buildMappedScopes = buildMappedScopes; - -var _parser = __webpack_require__(1365); - -var _locColumn = __webpack_require__(2349); - -var _findGeneratedBindingFromPosition = __webpack_require__(2358); - -var _buildGeneratedBindingList = __webpack_require__(3725); - -var _log = __webpack_require__(2359); - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -async function buildMappedScopes(source, frame, scopes, sourceMaps, client) { - const originalAstScopes = await (0, _parser.getScopes)(frame.location); - const generatedAstScopes = await (0, _parser.getScopes)(frame.generatedLocation); - - if (!originalAstScopes || !generatedAstScopes) { - return null; - } - - const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this); - - const { - mappedOriginalScopes, - expressionLookup - } = await mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps); - - const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes); - - return isReliableScope(mappedGeneratedScopes) ? { mappings: expressionLookup, scope: mappedGeneratedScopes } : null; -} - -async function mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps) { - const expressionLookup = {}; - const mappedOriginalScopes = []; - - const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps); - - for (const item of originalAstScopes) { - const generatedBindings = {}; - - for (const name of Object.keys(item.bindings)) { - const binding = item.bindings[name]; - - const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, generatedAstBindings); - - if (result) { - generatedBindings[name] = result.grip; - - if (binding.refs.length !== 0 && - // These are assigned depth-first, so we don't want shadowed - // bindings in parent scopes overwriting the expression. - !Object.prototype.hasOwnProperty.call(expressionLookup, name)) { - expressionLookup[name] = result.expression; - } - } - } - - mappedOriginalScopes.push(_extends({}, item, { - generatedBindings - })); - } - - return { - mappedOriginalScopes, - expressionLookup - }; -} - -/** - * Consider a scope and its parents reliable if the vast majority of its - * bindings were successfully mapped to generated scope bindings. - */ -function isReliableScope(scope) { - let totalBindings = 0; - let unknownBindings = 0; - - for (let s = scope; s; s = s.parent) { - const vars = s.bindings && s.bindings.variables || {}; - for (const key of Object.keys(vars)) { - const binding = vars[key]; - - totalBindings += 1; - if (binding.value && typeof binding.value === "object" && (binding.value.type === "unscoped" || binding.value.type === "unmapped")) { - unknownBindings += 1; - } - } - } - - // As determined by fair dice roll. - return totalBindings === 0 || unknownBindings / totalBindings < 0.1; -} - -function batchScopeMappings(originalAstScopes, source, sourceMaps) { - const precalculatedRanges = new Map(); - const precalculatedLocations = new Map(); - - // Explicitly dispatch all of the sourcemap requests synchronously up front so - // that they will be batched into a single request for the worker to process. - for (const item of originalAstScopes) { - for (const name of Object.keys(item.bindings)) { - for (const ref of item.bindings[name].refs) { - const locs = [ref]; - if (ref.type !== "ref") { - locs.push(ref.declaration); - } - - for (const loc of locs) { - precalculatedRanges.set(buildLocationKey(loc.start), sourceMaps.getGeneratedRanges(loc.start, source)); - precalculatedLocations.set(buildLocationKey(loc.start), sourceMaps.getGeneratedLocation(loc.start, source)); - precalculatedLocations.set(buildLocationKey(loc.end), sourceMaps.getGeneratedLocation(loc.end, source)); - } - } - } - } - - return { - async getGeneratedRanges(pos, s) { - const key = buildLocationKey(pos); - - if (s !== source || !precalculatedRanges.has(key)) { - (0, _log.log)("Bad precalculated mapping"); - return sourceMaps.getGeneratedRanges(pos, s); - } - return precalculatedRanges.get(key); - }, - async getGeneratedLocation(pos, s) { - const key = buildLocationKey(pos); - - if (s !== source || !precalculatedLocations.has(key)) { - (0, _log.log)("Bad precalculated mapping"); - return sourceMaps.getGeneratedLocation(pos, s); - } - return precalculatedLocations.get(key); - } - }; -} -function buildLocationKey(loc) { - return `${loc.line}:${(0, _locColumn.locColumn)(loc)}`; -} - -function generateClientScope(scopes, originalScopes) { - // Pull the root object scope and root lexical scope to reuse them in - // our mapped scopes. This assumes that file file being processed is - // a CommonJS or ES6 module, which might not be ideal. Potentially - let globalLexicalScope = null; - for (let s = scopes; s.parent; s = s.parent) { - // $FlowIgnore - Flow doesn't like casting 'parent'. - globalLexicalScope = s; - } - if (!globalLexicalScope) { - throw new Error("Assertion failure - there should always be a scope"); - } - - // Build a structure similar to the client's linked scope object using - // the original AST scopes, but pulling in the generated bindings - // linked to each scope. - const result = originalScopes.slice(0, -2).reverse().reduce((acc, orig, i) => { - const _orig$generatedBindin = orig.generatedBindings, - { - // The 'this' binding data we have is handled independently, so - // the binding data is not included here. - // eslint-disable-next-line no-unused-vars - this: _this - } = _orig$generatedBindin, - variables = _objectWithoutProperties(_orig$generatedBindin, ["this"]); - - return _extends({ - // Flow doesn't like casting 'parent'. - parent: acc, - actor: `originalActor${i}`, - type: orig.type, - bindings: { - arguments: [], - variables - } - }, orig.type === "function" ? { - function: { - displayName: orig.displayName - } - } : null, orig.type === "block" ? { - block: { - displayName: orig.displayName - } - } : null); - }, globalLexicalScope); - - // The rendering logic in getScope 'this' bindings only runs on the current - // selected frame scope, so we pluck out the 'this' binding that was mapped, - // and put it in a special location - const thisScope = originalScopes.find(scope => scope.bindings.this); - if (thisScope) { - result.bindings.this = thisScope.generatedBindings.this || null; - } - - return result; -} - -async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, generatedAstBindings) { - // If there are no references to the implicits, then we have no way to - // even attempt to map it back to the original since there is no location - // data to use. Bail out instead of just showing it as unmapped. - if (originalBinding.type === "implicit" && !originalBinding.refs.some(item => item.type === "ref")) { - return null; - } - - const { refs } = originalBinding; - - let genContent = null; - for (const pos of refs) { - if (originalBinding.type === "import") { - genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); - } else { - genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); - } - - if ((pos.type === "class-decl" || pos.type === "class-inner") && source.contentType && source.contentType.match(/\/typescript/)) { - // Resolve to first binding in the range - const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); - - if (declContent) { - // Prefer the declaration mapping in this case because TS sometimes - // maps class declaration names to "export.Foo = Foo;" or to - // the decorator logic itself - genContent = declContent; - } - } - - if (!genContent && (pos.type === "import-decl" || pos.type === "import-ns-decl")) { - // match the import declaration location - genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); - } - - if (genContent) { - break; - } - } - - if (genContent && genContent.desc) { - return { - grip: genContent.desc, - expression: genContent.expression - }; - } else if (genContent) { - // If there is no descriptor for 'this', then this is not the top-level - // 'this' that the server gave us a binding for, and we can just ignore it. - if (name === "this") { - return null; - } - - // If the location is found but the descriptor is not, then it - // means that the server scope information didn't match the scope - // information from the DevTools parsed scopes. - return { - grip: { - configurable: false, - enumerable: true, - writable: false, - value: { - type: "unscoped", - unscoped: true, - - // HACK: Until support for "unscoped" lands in devtools-reps, - // this will make these show as (unavailable). - missingArguments: true - } - }, - expression: null - }; - } - - // If no location mapping is found, then the map is bad, or - // the map is okay but it original location is inside - // of some scope, but the generated location is outside, leading - // us to search for bindings that don't technically exist. - return { - grip: { - configurable: false, - enumerable: true, - writable: false, - value: { - type: "unmapped", - unmapped: true, - - // HACK: Until support for "unmapped" lands in devtools-reps, - // this will make these show as (unavailable). - missingArguments: true - } - }, - expression: null - }; -} - -/***/ }), - -/***/ 3724: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getGeneratedLocationRanges = getGeneratedLocationRanges; - -var _positionCmp = __webpack_require__(3720); - -var _filtering = __webpack_require__(3635); - -var _mappingContains = __webpack_require__(3722); - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -async function getGeneratedLocationRanges(generatedAstBindings, source, { - start, - end -}, bindingType, locationType, sourceMaps) { - const endPosition = await sourceMaps.getGeneratedLocation(end, source); - const startPosition = await sourceMaps.getGeneratedLocation(start, source); - - // If the start and end positions collapse into eachother, it means that - // the range in the original content didn't _start_ at the start position. - // Since this likely means that the range doesn't logically apply to this - // binding location, we skip it. - if ((0, _positionCmp.positionCmp)(startPosition, endPosition) === 0) { - return []; - } - - const ranges = await sourceMaps.getGeneratedRanges(start, source); - - const resultRanges = ranges.reduce((acc, mapRange) => { - // Some tooling creates ranges that map a line as a whole, which is useful - // for step-debugging, but can easily lead to finding the wrong binding. - // To avoid these false-positives, we entirely ignore ranges that cover - // full lines. - if (locationType === "ref" && mapRange.columnStart === 0 && mapRange.columnEnd === Infinity) { - return acc; - } - - const range = { - start: { - line: mapRange.line, - column: mapRange.columnStart - }, - end: { - line: mapRange.line, - // SourceMapConsumer's 'lastColumn' is inclusive, so we add 1 to make - // it exclusive like all other locations. - column: mapRange.columnEnd + 1 - } - }; - - const previous = acc[acc.length - 1]; - - if (previous && (previous.end.line === range.start.line && previous.end.column === range.start.column || previous.end.line + 1 === range.start.line && previous.end.column === Infinity && range.start.column === 0)) { - previous.end.line = range.end.line; - previous.end.column = range.end.column; - } else { - acc.push(range); - } - - return acc; - }, []); - - // When searching for imports, we expand the range to up to the next available - // mapping to allow for import declarations that are composed of multiple - // variable statements, where the later ones are entirely unmapped. - // Babel 6 produces imports in this style, e.g. - // - // var _mod = require("mod"); // mapped from import statement - // var _mod2 = interop(_mod); // entirely unmapped - if (bindingType === "import" && locationType !== "ref") { - for (const range of resultRanges) { - if ((0, _mappingContains.mappingContains)(range, { start: startPosition, end: startPosition }) && (0, _positionCmp.positionCmp)(range.end, endPosition) < 0) { - range.end.line = endPosition.line; - range.end.column = endPosition.column; - break; - } - } - } - - return filterApplicableBindings(generatedAstBindings, resultRanges); -} - -function filterApplicableBindings(bindings, ranges) { - const result = []; - for (const range of ranges) { - // Any binding overlapping a part of the mapping range. - const filteredBindings = (0, _filtering.filterSortedArray)(bindings, binding => { - if ((0, _positionCmp.positionCmp)(binding.loc.end, range.start) <= 0) { - return -1; - } - if ((0, _positionCmp.positionCmp)(binding.loc.start, range.end) >= 0) { - return 1; - } - - return 0; - }); - - let firstInRange = true; - let firstOnLine = true; - let line = -1; - - for (const binding of filteredBindings) { - if (binding.loc.start.line === line) { - firstOnLine = false; - } else { - line = binding.loc.start.line; - firstOnLine = true; - } - - result.push({ - binding, - range, - firstOnLine, - firstInRange - }); - - firstInRange = false; - } - } - - return result; -} - -/***/ }), - -/***/ 3725: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.buildGeneratedBindingList = buildGeneratedBindingList; - -var _lodash = __webpack_require__(2); - -var _firefox = __webpack_require__(1500); - -var _locColumn = __webpack_require__(2349); - -function buildGeneratedBindingList(scopes, generatedAstScopes, thisBinding) { - // The server's binding data doesn't include general 'this' binding - // information, so we manually inject the one 'this' binding we have into - // the normal binding data we are working with. - const frameThisOwner = generatedAstScopes.find(generated => "this" in generated.bindings); - - let globalScope = null; - const clientScopes = []; - for (let s = scopes; s; s = s.parent) { - const bindings = s.bindings ? Object.assign({}, ...s.bindings.arguments, s.bindings.variables) : {}; - - clientScopes.push(bindings); - globalScope = s; - } - - const generatedMainScopes = generatedAstScopes.slice(0, -2); - const generatedGlobalScopes = generatedAstScopes.slice(-2); - - const clientMainScopes = clientScopes.slice(0, generatedMainScopes.length); - const clientGlobalScopes = clientScopes.slice(generatedMainScopes.length); - - // Map the main parsed script body using the nesting hierarchy of the - // generated and client scopes. - const generatedBindings = generatedMainScopes.reduce((acc, generated, i) => { - const bindings = clientMainScopes[i]; - - if (generated === frameThisOwner && thisBinding) { - bindings.this = { - value: thisBinding - }; - } - - for (const name of Object.keys(generated.bindings)) { - // If there is no 'this' value, we exclude the binding entirely. - // Otherwise it would pass through as found, but "(unscoped)", causing - // the search logic to stop with a match. - if (name === "this" && !bindings[name]) { - continue; - } - - const { refs } = generated.bindings[name]; - for (const loc of refs) { - acc.push({ - name, - loc, - desc: () => Promise.resolve(bindings[name] || null) - }); - } - } - return acc; - }, []); - - // Bindings in the global/lexical global of the generated code may or - // may not be the real global if the generated code is running inside - // of an evaled context. To handle this, we just look up the client scope - // hierarchy to find the closest binding with that name. - for (const generated of generatedGlobalScopes) { - for (const name of Object.keys(generated.bindings)) { - const { refs } = generated.bindings[name]; - const bindings = clientGlobalScopes.find(b => (0, _lodash.has)(b, name)); - - for (const loc of refs) { - if (bindings) { - generatedBindings.push({ - name, - loc, - desc: () => Promise.resolve(bindings[name]) - }); - } else { - const globalGrip = globalScope && globalScope.object; - if (globalGrip) { - // Should always exist, just checking to keep Flow happy. - - generatedBindings.push({ - name, - loc, - desc: async () => { - const objectClient = (0, _firefox.createObjectClient)(globalGrip); - return (await objectClient.getProperty(name)).descriptor; - } - }); - } - } - } - } - } - - // Sort so we can binary-search. - return generatedBindings.sort((a, b) => { - const aStart = a.loc.start; - const bStart = b.loc.start; - - if (aStart.line === bStart.line) { - return (0, _locColumn.locColumn)(aStart) - (0, _locColumn.locColumn)(bStart); - } - return aStart.line - bStart.line; - }); -} /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ - -/***/ }), - -/***/ 4: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_4__; - -/***/ }), - -/***/ 46: -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(1459); - - -/***/ }), - -/***/ 52: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_52__; - -/***/ }), - -/***/ 6: -/***/ (function(module, exports, __webpack_require__) { - -var Symbol = __webpack_require__(7), - getRawTag = __webpack_require__(10), - objectToString = __webpack_require__(11); - -/** `Object#toString` result references. */ -var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - -/** Built-in value references. */ -var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - -/** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ -function baseGetTag(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); -} - -module.exports = baseGetTag; - - -/***/ }), - -/***/ 66: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -exports.decode = exports.parse = __webpack_require__(121); -exports.encode = exports.stringify = __webpack_require__(122); - - -/***/ }), - -/***/ 677: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_677__; - -/***/ }), - -/***/ 678: -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_678__; - -/***/ }), - -/***/ 7: -/***/ (function(module, exports, __webpack_require__) { - -var root = __webpack_require__(8); - -/** Built-in value references. */ -var Symbol = root.Symbol; - -module.exports = Symbol; - - -/***/ }), - -/***/ 70: -/***/ (function(module, exports) { - -/** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(document.body.children); - * // => false - * - * _.isArray('abc'); - * // => false - * - * _.isArray(_.noop); - * // => false - */ -var isArray = Array.isArray; - -module.exports = isArray; - - -/***/ }), - -/***/ 72: -/***/ (function(module, exports, __webpack_require__) { - -var baseGetTag = __webpack_require__(6), - isObjectLike = __webpack_require__(14); - -/** `Object#toString` result references. */ -var symbolTag = '[object Symbol]'; - -/** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ -function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); -} - -module.exports = isSymbol; - - -/***/ }), - -/***/ 792: -/***/ (function(module, exports) { - -var g; - -// This works in non-strict mode -g = (function() { - return this; -})(); - -try { - // This works if eval is allowed (see CSP) - g = g || Function("return this")() || (1,eval)("this"); -} catch(e) { - // This works if the window reference is available - if(typeof window === "object") - g = window; -} - -// g can still be undefined, but nothing to do about it... -// We return undefined, instead of nothing here, so it's -// easier to handle this case. if(!global) { ...} - -module.exports = g; - - -/***/ }), - -/***/ 793: -/***/ (function(module, exports) { - -module.exports = function(module) { - if(!module.webpackPolyfill) { - module.deprecate = function() {}; - module.paths = []; - // module.parent = undefined by default - if(!module.children) module.children = []; - Object.defineProperty(module, "loaded", { - enumerable: true, - get: function() { - return module.l; - } - }); - Object.defineProperty(module, "id", { - enumerable: true, - get: function() { - return module.i; - } - }); - module.webpackPolyfill = 1; - } - return module; -}; - - -/***/ }), - -/***/ 8: -/***/ (function(module, exports, __webpack_require__) { - -var freeGlobal = __webpack_require__(9); - -/** Detect free variable `self`. */ -var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - -/** Used as a reference to the global object. */ -var root = freeGlobal || freeSelf || Function('return this')(); - -module.exports = root; - - -/***/ }), - -/***/ 806: -/***/ (function(module, exports) { - -module.exports = "dojo_square" - -/***/ }), - -/***/ 9: -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ -var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - -module.exports = freeGlobal; - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(792))) - -/***/ }), - -/***/ 919: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 920: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 993: -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -exports.__esModule = true; -exports.defaultMemoize = defaultMemoize; -exports.createSelectorCreator = createSelectorCreator; -exports.createStructuredSelector = createStructuredSelector; -function defaultEqualityCheck(a, b) { - return a === b; -} - -function areArgumentsShallowlyEqual(equalityCheck, prev, next) { - if (prev === null || next === null || prev.length !== next.length) { - return false; - } - - // Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible. - var length = prev.length; - for (var i = 0; i < length; i++) { - if (!equalityCheck(prev[i], next[i])) { - return false; - } - } - - return true; -} - -function defaultMemoize(func) { - var equalityCheck = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultEqualityCheck; - - var lastArgs = null; - var lastResult = null; - // we reference arguments instead of spreading them for performance reasons - return function () { - if (!areArgumentsShallowlyEqual(equalityCheck, lastArgs, arguments)) { - // apply arguments instead of spreading for performance. - lastResult = func.apply(null, arguments); - } - - lastArgs = arguments; - return lastResult; - }; -} - -function getDependencies(funcs) { - var dependencies = Array.isArray(funcs[0]) ? funcs[0] : funcs; - - if (!dependencies.every(function (dep) { - return typeof dep === 'function'; - })) { - var dependencyTypes = dependencies.map(function (dep) { - return typeof dep; - }).join(', '); - throw new Error('Selector creators expect all input-selectors to be functions, ' + ('instead received the following types: [' + dependencyTypes + ']')); - } - - return dependencies; -} - -function createSelectorCreator(memoize) { - for (var _len = arguments.length, memoizeOptions = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - memoizeOptions[_key - 1] = arguments[_key]; - } - - return function () { - for (var _len2 = arguments.length, funcs = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - funcs[_key2] = arguments[_key2]; - } - - var recomputations = 0; - var resultFunc = funcs.pop(); - var dependencies = getDependencies(funcs); - - var memoizedResultFunc = memoize.apply(undefined, [function () { - recomputations++; - // apply arguments instead of spreading for performance. - return resultFunc.apply(null, arguments); - }].concat(memoizeOptions)); - - // If a selector is called with the exact same arguments we don't need to traverse our dependencies again. - var selector = defaultMemoize(function () { - var params = []; - var length = dependencies.length; - - for (var i = 0; i < length; i++) { - // apply arguments instead of spreading and mutate a local list of params for performance. - params.push(dependencies[i].apply(null, arguments)); - } - - // apply arguments instead of spreading for performance. - return memoizedResultFunc.apply(null, params); - }); - - selector.resultFunc = resultFunc; - selector.recomputations = function () { - return recomputations; - }; - selector.resetRecomputations = function () { - return recomputations = 0; - }; - return selector; - }; -} - -var createSelector = exports.createSelector = createSelectorCreator(defaultMemoize); - -function createStructuredSelector(selectors) { - var selectorCreator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : createSelector; - - if (typeof selectors !== 'object') { - throw new Error('createStructuredSelector expects first argument to be an object ' + ('where each property is a selector, instead received a ' + typeof selectors)); - } - var objectKeys = Object.keys(selectors); - return selectorCreator(objectKeys.map(function (key) { - return selectors[key]; - }), function () { - for (var _len3 = arguments.length, values = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - values[_key3] = arguments[_key3]; - } - - return values.reduce(function (composition, value, index) { - composition[objectKeys[index]] = value; - return composition; - }, {}); - }); -} - -/***/ }), - -/***/ 997: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 998: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }), - -/***/ 999: -/***/ (function(module, exports) { - -module.exports = "" - -/***/ }) - -/******/ }); -}); \ No newline at end of file diff --git a/devtools/client/debugger/new/debugger.css b/devtools/client/debugger/new/dist/debugger.css similarity index 100% rename from devtools/client/debugger/new/debugger.css rename to devtools/client/debugger/new/dist/debugger.css diff --git a/devtools/client/debugger/new/dist/moz.build b/devtools/client/debugger/new/dist/moz.build new file mode 100644 index 000000000000..1158ea3e2778 --- /dev/null +++ b/devtools/client/debugger/new/dist/moz.build @@ -0,0 +1,12 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DevToolsModules( + 'debugger.css', + 'parser-worker.js', + 'pretty-print-worker.js', + 'search-worker.js', + 'vendors.js' +) diff --git a/devtools/client/debugger/new/parser-worker.js b/devtools/client/debugger/new/dist/parser-worker.js similarity index 100% rename from devtools/client/debugger/new/parser-worker.js rename to devtools/client/debugger/new/dist/parser-worker.js diff --git a/devtools/client/debugger/new/pretty-print-worker.js b/devtools/client/debugger/new/dist/pretty-print-worker.js similarity index 100% rename from devtools/client/debugger/new/pretty-print-worker.js rename to devtools/client/debugger/new/dist/pretty-print-worker.js diff --git a/devtools/client/debugger/new/search-worker.js b/devtools/client/debugger/new/dist/search-worker.js similarity index 100% rename from devtools/client/debugger/new/search-worker.js rename to devtools/client/debugger/new/dist/search-worker.js diff --git a/devtools/client/debugger/new/dist/vendors.css b/devtools/client/debugger/new/dist/vendors.css new file mode 100644 index 000000000000..22faeaecd3c3 --- /dev/null +++ b/devtools/client/debugger/new/dist/vendors.css @@ -0,0 +1,466 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.split-box { + display: flex; + flex: 1; + min-width: 0; + height: 100%; + width: 100%; +} + +.split-box.vert { + flex-direction: row; +} + +.split-box.horz { + flex-direction: column; +} + +.split-box > .uncontrolled { + display: flex; + flex: 1; + min-width: 0; + overflow: auto; +} + +.split-box > .controlled { + display: flex; + overflow: auto; +} + +.split-box > .splitter { + background-image: none; + border: 0; + border-style: solid; + border-color: transparent; + background-color: var(--theme-splitter-color); + background-clip: content-box; + position: relative; + + box-sizing: border-box; + + /* Positive z-index positions the splitter on top of its siblings and makes + it clickable on both sides. */ + z-index: 1; +} + +.split-box.vert > .splitter { + min-width: calc(var(--devtools-splitter-inline-start-width) + + var(--devtools-splitter-inline-end-width) + 1px); + + border-left-width: var(--devtools-splitter-inline-start-width); + border-right-width: var(--devtools-splitter-inline-end-width); + + margin-left: calc(-1 * var(--devtools-splitter-inline-start-width) - 1px); + margin-right: calc(-1 * var(--devtools-splitter-inline-end-width)); + + cursor: ew-resize; +} + +.split-box.horz > .splitter { + min-height: calc(var(--devtools-splitter-top-width) + + var(--devtools-splitter-bottom-width) + 1px); + + border-top-width: var(--devtools-splitter-top-width); + border-bottom-width: var(--devtools-splitter-bottom-width); + + margin-top: calc(-1 * var(--devtools-splitter-top-width) - 1px); + margin-bottom: calc(-1 * var(--devtools-splitter-bottom-width)); + + cursor: ns-resize; +} + +.split-box.disabled { + pointer-events: none; +} + +/** + * Make sure splitter panels are not processing any mouse + * events. This is good for performance during splitter + * bar dragging. + */ +.split-box.dragging > .controlled, +.split-box.dragging > .uncontrolled { + pointer-events: none; +} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +.arrow, +.worker, +.refresh, +.shortcut, +.add-button { + fill: var(--theme-splitter-color); +} + +.folder, +.domain, +.source-icon, +.file, +.extension { + background-color: var(--theme-comment); +} + +.worker, +.file, +.folder, +.source-icon, +.extension { + position: relative; + top: 2px; +} + +.domain, +.worker, +.refresh, +.add-button { + position: relative; + top: 1px; +} + +.worker svg, +.refresh svg, +.shortcut svg, +.add-button svg { + width: 15px; +} + +img.domain, +img.folder, +img.source-icon { + width: 15px; + height: 15px; +} + +img.extension { + width: 13px; + height: 13px; + margin-inline-start: 2px; +} + +img.result-item-icon { + height: 18px; + width: 18px; +} + +img.domain { + mask: url("chrome://devtools/skin/images/debugger/domain.svg") no-repeat; +} + +img.folder { + mask: url("chrome://devtools/skin/images/debugger/folder.svg") no-repeat; +} + +img.coffeescript { + mask: url("chrome://devtools/skin/images/debugger/coffeescript.svg") no-repeat; +} + +img.javascript { + mask: url("chrome://devtools/skin/images/debugger/javascript.svg") no-repeat; +} + +img.tab { + mask: url("chrome://devtools/skin/images/debugger/tab.svg") no-repeat; +} + +img.react { + mask: url("chrome://devtools/skin/images/debugger/react.svg") no-repeat; +} + +img.typescript { + mask: url("chrome://devtools/skin/images/debugger/typescript.svg") no-repeat; +} + +img.extension { + mask: url("chrome://devtools/skin/images/debugger/extension.svg") no-repeat; +} + +img.file { + mask: url("chrome://devtools/skin/images/debugger/file.svg") no-repeat; + width: 13px; + height: 13px; +} + +img.domain, +img.folder, +img.file, +img.source-icon, +img.extension { + mask-size: 100%; + margin-inline-end: 5px; + display: inline-block; +} + +img.result-item-icon { + mask-size: 100%; + margin-inline-end: 15px; + margin-inline-start: 5px; + display: inline-block; +} + +.refresh svg, +.shortcut svg, +.worker svg { + margin-inline-end: 5px; +} + +img.arrow { + mask: url("chrome://devtools/skin/images/debugger/arrow.svg"); + margin-inline-end: 5px; + margin-top: 3px; + width: 9px; + height: 9px; + padding-top: 9px; + background: var(--disclosure-arrow); + mask-size: 100%; + display: inline-block; + margin-bottom: 1px; + transform: rotate(-90deg); + transition: transform 0.18s ease; +} + +html[dir="ltr"] img.arrow { + transform: rotate(-90deg); +} + +html[dir="rtl"] img.arrow { + transform: rotate(90deg); +} + +.arrow svg { + transition: transform 0.125s ease; + width: 10px; + margin-inline-end: 5px; + transform: rotate(-90deg); +} + +html[dir="rtl"] .arrow svg, +.arrow svg:dir(rtl), +.arrow svg:-moz-locale-dir(rtl) { + transform: rotate(90deg); +} + +.arrow.expanded.expanded svg { + transform: rotate(0deg); +} + +.arrow.hidden { + visibility: hidden; +} + +.webpack svg { + width: 15px; + height: 15px; + margin-right: 5px; + vertical-align: sub; +} + +.function svg { + height: 10px; + width: 15px; +} + +.function path { + fill: var(--theme-body-color); +} + +.angular svg, +.source-icon svg { + width: 15px; + height: 15px; + margin-right: 5px; + vertical-align: sub; +} + +.angular, +.webpack { + opacity: 0.8; +} + +.theme-dark .angular, +.theme-dark .webpack { + opacity: 0.5; +} + +.source-icon svg { + fill: var(--theme-comment); +} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.tree { + overflow: auto; +} + +.tree.inline { + display: inline-block; +} + +.tree.nowrap { + white-space: nowrap; +} + +.tree.noselect { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.tree .tree-node { + display: flex; +} + +.tree .tree-node:not(.focused):hover { + background-color: var(--theme-selection-background-hover); +} + +.tree-indent { + display: inline-block; + width: 12px; + margin-inline-start: 5px; + border-inline-start: 1px solid #A2D1FF; + flex-shrink: 0; +} + +/* Align with expandables siblings (where we have the arrow) */ +.tree-node[data-expandable="false"] .tree-indent:last-of-type { + margin-inline-end: 15px; +} + +/* For non expandable root nodes, we don't have .tree-indent elements, so we declare + the margin on the start of the node */ +.tree-node[data-expandable="false"][aria-level="1"] { + padding-inline-start: 15px +} + +.tree .tree-node[data-expandable="true"] { + cursor: default; +} + +.tree-node img.arrow { + mask: url("chrome://devtools/skin/images/devtools-components/arrow.svg") no-repeat; + mask-size: 100%; + width: 9px; + height: 9px; + margin-inline-start: 1px; + margin-inline-end: 4px; + background-color: var(--theme-splitter-color, #9B9B9B); + transform: rotate(-90deg); + transition: transform 0.125s ease; + align-self: center; +} + +html[dir="rtl"] .tree-node img.arrow { + transform: rotate(90deg); +} + +.tree-node img.arrow.expanded.expanded { + transform: rotate(0deg); + } + +.tree .tree-node.focused { + color: white; + background-color: var(--theme-selection-background, #0a84ff); +} + +.tree-node.focused img.arrow { + background-color: currentColor; +} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +menu { + display: inline; + padding: 0; +} + +menu > menuitem::after { + content: "\25BA"; + float: right; + padding-left: 5px; +} + +menu > menupopup { + display: none; +} + +menu > menuitem:hover + menupopup, +menu > menupopup:hover { + display: block; +} + +menupopup { + position: fixed; + z-index: 10000; + background: white; + border: 1px solid #cccccc; + padding: 5px 0; + background: #f2f2f2; + border-radius: 5px; + color: #585858; + box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8); + min-width: 130px; +} + +menuitem { + display: block; + padding: 0 20px; + line-height: 20px; + font-weight: 500; + font-size: 13px; + -moz-user-select: none; + user-select: none; +} + +menuitem:hover { + background: #3780fb; + color: white; + cursor: pointer; +} + +menuitem[disabled=true] { + color: #cccccc; +} + +menuitem[disabled=true]:hover { + background-color: transparent; + cursor: default; +} + +menuitem[type=checkbox]::before { + content: ""; + width: 10px; + display: inline-block; +} + +menuitem[type=checkbox][checked=true]::before { + content: "\2713"; + left: -8px; + position: relative; +} + +menuseparator { + border-bottom: 1px solid #cacdd3; + width: 100%; + height: 5px; + display: block; + margin-bottom: 5px; +} + +#contextmenu-mask.show { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999; +} diff --git a/devtools/client/debugger/new/dist/vendors.js b/devtools/client/debugger/new/dist/vendors.js new file mode 100644 index 000000000000..51128b11e338 --- /dev/null +++ b/devtools/client/debugger/new/dist/vendors.js @@ -0,0 +1,9634 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")); + else if(typeof define === 'function' && define.amd) + define(["devtools/client/shared/vendor/react", "devtools/client/shared/vendor/react-dom", "Services", "devtools/shared/flags", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react-dom-factories"], factory); + else { + var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")) : factory(root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/react-dom"], root["Services"], root["devtools/shared/flags"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react-dom-factories"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_52__, __WEBPACK_EXTERNAL_MODULE_3642__, __WEBPACK_EXTERNAL_MODULE_3643__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/assets/build"; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 3728); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_0__; + +/***/ }), + +/***/ 10: +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(7); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +module.exports = getRawTag; + + +/***/ }), + +/***/ 100: +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(96); + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +module.exports = listCacheSet; + + +/***/ }), + +/***/ 1000: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1001: +/***/ (function(module, exports) { + +module.exports = "icon" + +/***/ }), + +/***/ 1002: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1003: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1004: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 101: +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(81), + root = __webpack_require__(8); + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +module.exports = Map; + + +/***/ }), + +/***/ 102: +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(103); + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +module.exports = mapCacheDelete; + + +/***/ }), + +/***/ 103: +/***/ (function(module, exports, __webpack_require__) { + +var isKeyable = __webpack_require__(104); + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +module.exports = getMapData; + + +/***/ }), + +/***/ 104: +/***/ (function(module, exports) { + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +module.exports = isKeyable; + + +/***/ }), + +/***/ 1043: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1044: +/***/ (function(module, exports) { + +module.exports = "Created with Sketch." + +/***/ }), + +/***/ 1045: +/***/ (function(module, exports) { + +module.exports = "Created with Sketch." + +/***/ }), + +/***/ 105: +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(103); + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +module.exports = mapCacheGet; + + +/***/ }), + +/***/ 106: +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(103); + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +module.exports = mapCacheHas; + + +/***/ }), + +/***/ 107: +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(103); + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +module.exports = mapCacheSet; + + +/***/ }), + +/***/ 108: +/***/ (function(module, exports, __webpack_require__) { + +var baseToString = __webpack_require__(109); + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + return value == null ? '' : baseToString(value); +} + +module.exports = toString; + + +/***/ }), + +/***/ 109: +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(7), + arrayMap = __webpack_require__(110), + isArray = __webpack_require__(70), + isSymbol = __webpack_require__(72); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +module.exports = baseToString; + + +/***/ }), + +/***/ 11: +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString.call(value); +} + +module.exports = objectToString; + + +/***/ }), + +/***/ 110: +/***/ (function(module, exports) { + +/** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + +module.exports = arrayMap; + + +/***/ }), + +/***/ 111: +/***/ (function(module, exports, __webpack_require__) { + +var isSymbol = __webpack_require__(72); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ +function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +module.exports = toKey; + + +/***/ }), + +/***/ 1117: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1118: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1119: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 112: +/***/ (function(module, exports, __webpack_require__) { + +var baseSet = __webpack_require__(113); + +/** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ +function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); +} + +module.exports = set; + + +/***/ }), + +/***/ 113: +/***/ (function(module, exports, __webpack_require__) { + +var assignValue = __webpack_require__(114), + castPath = __webpack_require__(69), + isIndex = __webpack_require__(117), + isObject = __webpack_require__(84), + toKey = __webpack_require__(111); + +/** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ +function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; +} + +module.exports = baseSet; + + +/***/ }), + +/***/ 114: +/***/ (function(module, exports, __webpack_require__) { + +var baseAssignValue = __webpack_require__(115), + eq = __webpack_require__(97); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } +} + +module.exports = assignValue; + + +/***/ }), + +/***/ 115: +/***/ (function(module, exports, __webpack_require__) { + +var defineProperty = __webpack_require__(116); + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +module.exports = baseAssignValue; + + +/***/ }), + +/***/ 116: +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(81); + +var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +module.exports = defineProperty; + + +/***/ }), + +/***/ 117: +/***/ (function(module, exports) { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +module.exports = isIndex; + + +/***/ }), + +/***/ 1174: +/***/ (function(module, exports) { + +module.exports = "image/svg+xml" + +/***/ }), + +/***/ 118: +/***/ (function(module, exports) { + + + +/***/ }), + +/***/ 119: +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120))) + +/***/ }), + +/***/ 120: +/***/ (function(module, exports) { + +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + + +/***/ }), + +/***/ 121: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +// If obj.hasOwnProperty has been overridden, then calling +// obj.hasOwnProperty(prop) will break. +// See: https://github.com/joyent/node/issues/1707 +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + + +/***/ }), + +/***/ 122: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } +}; + +module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; +} + +var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; +}; + + +/***/ }), + +/***/ 1233: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1290: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1301: +/***/ (function(module, exports) { + +// removed by extract-text-webpack-plugin + +/***/ }), + +/***/ 1309: +/***/ (function(module, exports) { + +// removed by extract-text-webpack-plugin + +/***/ }), + +/***/ 1310: +/***/ (function(module, exports) { + +// removed by extract-text-webpack-plugin + +/***/ }), + +/***/ 1347: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1348: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 1355: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const feature = __webpack_require__(1461); + +module.exports = feature; + +/***/ }), + +/***/ 1359: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Svg = __webpack_require__(1540); + +var _Svg2 = _interopRequireDefault(_Svg); + +__webpack_require__(1310); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * This file maps the SVG React Components in the assets/images directory. + */ + +exports.default = _Svg2.default; + +/***/ }), + +/***/ 1363: +/***/ (function(module, exports, __webpack_require__) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const networkRequest = __webpack_require__(1367); +const workerUtils = __webpack_require__(1368); + +module.exports = { + networkRequest, + workerUtils +}; + +/***/ }), + +/***/ 1367: +/***/ (function(module, exports) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function networkRequest(url, opts) { + return fetch(url, { + cache: opts.loadFromCache ? "default" : "no-cache" + }).then(res => { + if (res.status >= 200 && res.status < 300) { + return res.text().then(text => ({ content: text })); + } + return Promise.reject(`request failed with status ${res.status}`); + }); +} + +module.exports = networkRequest; + +/***/ }), + +/***/ 1368: +/***/ (function(module, exports) { + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +function WorkerDispatcher() { + this.msgId = 1; + this.worker = null; +} /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +WorkerDispatcher.prototype = { + start(url) { + this.worker = new Worker(url); + this.worker.onerror = () => { + console.error(`Error in worker ${url}`); + }; + }, + + stop() { + if (!this.worker) { + return; + } + + this.worker.terminate(); + this.worker = null; + }, + + task(method, { queue = false } = {}) { + const calls = []; + const push = args => { + return new Promise((resolve, reject) => { + if (queue && calls.length === 0) { + Promise.resolve().then(flush); + } + + calls.push([args, resolve, reject]); + + if (!queue) { + flush(); + } + }); + }; + + const flush = () => { + const items = calls.slice(); + calls.length = 0; + + const id = this.msgId++; + this.worker.postMessage({ id, method, calls: items.map(item => item[0]) }); + + const listener = ({ data: result }) => { + if (result.id !== id) { + return; + } + + if (!this.worker) { + return; + } + + this.worker.removeEventListener("message", listener); + + result.results.forEach((resultData, i) => { + const [, resolve, reject] = items[i]; + + if (resultData.error) { + reject(resultData.error); + } else { + resolve(resultData.response); + } + }); + }; + + this.worker.addEventListener("message", listener); + }; + + return (...args) => push(args); + } +}; + +function workerHandler(publicInterface) { + return function (msg) { + const { id, method, calls } = msg.data; + + Promise.all(calls.map(args => { + try { + const response = publicInterface[method].apply(undefined, args); + if (response instanceof Promise) { + return response.then(val => ({ response: val }), + // Error can't be sent via postMessage, so be sure to + // convert to string. + err => ({ error: err.toString() })); + } else { + return { response }; + } + } catch (error) { + // Error can't be sent via postMessage, so be sure to convert to + // string. + return { error: error.toString() }; + } + })).then(results => { + self.postMessage({ id, results }); + }); + }; +} + +function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) { + let streamingWorker = (() => { + var _ref = _asyncToGenerator(function* (id, tasks) { + let isWorking = true; + + const intervalId = setTimeout(function () { + isWorking = false; + }, timeout); + + const results = []; + while (tasks.length !== 0 && isWorking) { + const { callback, context, args } = tasks.shift(); + const result = yield callback.call(context, args); + results.push(result); + } + worker.postMessage({ id, status: "pending", data: results }); + clearInterval(intervalId); + + if (tasks.length !== 0) { + yield streamingWorker(id, tasks); + } + }); + + return function streamingWorker(_x, _x2) { + return _ref.apply(this, arguments); + }; + })(); + + return (() => { + var _ref2 = _asyncToGenerator(function* (msg) { + const { id, method, args } = msg.data; + const workerMethod = publicInterface[method]; + if (!workerMethod) { + console.error(`Could not find ${method} defined in worker.`); + } + worker.postMessage({ id, status: "start" }); + + try { + const tasks = workerMethod(args); + yield streamingWorker(id, tasks); + worker.postMessage({ id, status: "done" }); + } catch (error) { + worker.postMessage({ id, status: "error", error }); + } + }); + + return function (_x3) { + return _ref2.apply(this, arguments); + }; + })(); +} + +module.exports = { + WorkerDispatcher, + workerHandler, + streamingWorkerHandler +}; + +/***/ }), + +/***/ 1376: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const Menu = __webpack_require__(1464); +const MenuItem = __webpack_require__(1466); +const { PrefsHelper } = __webpack_require__(1467); +const Services = __webpack_require__(22); +const KeyShortcuts = __webpack_require__(1468); +const { ZoomKeys } = __webpack_require__(1469); +const EventEmitter = __webpack_require__(1382); +const SourceUtils = __webpack_require__(3637); +const { getUnicodeHostname, getUnicodeUrlPath, getUnicodeUrl } = __webpack_require__(3638); + +module.exports = { + KeyShortcuts, + Menu, + MenuItem, + PrefsHelper, + Services, + ZoomKeys, + EventEmitter, + SourceUtils, + getUnicodeHostname, + getUnicodeUrlPath, + getUnicodeUrl +}; + +/***/ }), + +/***/ 1382: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var EventEmitter = function EventEmitter() {}; +module.exports = EventEmitter; + +const promise = __webpack_require__(1465); + +/** + * Decorate an object with event emitter functionality. + * + * @param Object aObjectToDecorate + * Bind all public methods of EventEmitter to + * the aObjectToDecorate object. + */ +EventEmitter.decorate = function EventEmitter_decorate(aObjectToDecorate) { + let emitter = new EventEmitter(); + aObjectToDecorate.on = emitter.on.bind(emitter); + aObjectToDecorate.off = emitter.off.bind(emitter); + aObjectToDecorate.once = emitter.once.bind(emitter); + aObjectToDecorate.emit = emitter.emit.bind(emitter); +}; + +EventEmitter.prototype = { + /** + * Connect a listener. + * + * @param string aEvent + * The event name to which we're connecting. + * @param function aListener + * Called when the event is fired. + */ + on: function EventEmitter_on(aEvent, aListener) { + if (!this._eventEmitterListeners) this._eventEmitterListeners = new Map(); + if (!this._eventEmitterListeners.has(aEvent)) { + this._eventEmitterListeners.set(aEvent, []); + } + this._eventEmitterListeners.get(aEvent).push(aListener); + }, + + /** + * Listen for the next time an event is fired. + * + * @param string aEvent + * The event name to which we're connecting. + * @param function aListener + * (Optional) Called when the event is fired. Will be called at most + * one time. + * @return promise + * A promise which is resolved when the event next happens. The + * resolution value of the promise is the first event argument. If + * you need access to second or subsequent event arguments (it's rare + * that this is needed) then use aListener + */ + once: function EventEmitter_once(aEvent, aListener) { + let deferred = promise.defer(); + + let handler = (aEvent, aFirstArg, ...aRest) => { + this.off(aEvent, handler); + if (aListener) { + aListener.apply(null, [aEvent, aFirstArg, ...aRest]); + } + deferred.resolve(aFirstArg); + }; + + handler._originalListener = aListener; + this.on(aEvent, handler); + + return deferred.promise; + }, + + /** + * Remove a previously-registered event listener. Works for events + * registered with either on or once. + * + * @param string aEvent + * The event name whose listener we're disconnecting. + * @param function aListener + * The listener to remove. + */ + off: function EventEmitter_off(aEvent, aListener) { + if (!this._eventEmitterListeners) return; + let listeners = this._eventEmitterListeners.get(aEvent); + if (listeners) { + this._eventEmitterListeners.set(aEvent, listeners.filter(l => { + return l !== aListener && l._originalListener !== aListener; + })); + } + }, + + /** + * Emit an event. All arguments to this method will + * be sent to listener functions. + */ + emit: function EventEmitter_emit(aEvent) { + if (!this._eventEmitterListeners || !this._eventEmitterListeners.has(aEvent)) { + return; + } + + let originalListeners = this._eventEmitterListeners.get(aEvent); + for (let listener of this._eventEmitterListeners.get(aEvent)) { + // If the object was destroyed during event emission, stop + // emitting. + if (!this._eventEmitterListeners) { + break; + } + + // If listeners were removed during emission, make sure the + // event handler we're going to fire wasn't removed. + if (originalListeners === this._eventEmitterListeners.get(aEvent) || this._eventEmitterListeners.get(aEvent).some(l => l === listener)) { + try { + listener.apply(null, arguments); + } catch (ex) { + // Prevent a bad listener from interfering with the others. + let msg = ex + ": " + ex.stack; + //console.error(msg); + console.log(msg); + } + } + } + } +}; + +/***/ }), + +/***/ 14: +/***/ (function(module, exports) { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + + +/***/ }), + +/***/ 1413: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { Menu, MenuItem } = __webpack_require__(1376); + +function inToolbox() { + return window.parent.document.documentURI == "about:devtools-toolbox"; +} + +if (!inToolbox()) { + __webpack_require__(1301); +} + +function createPopup(doc) { + let popup = doc.createElement("menupopup"); + popup.className = "landing-popup"; + if (popup.openPopupAtScreen) { + return popup; + } + + function preventDefault(e) { + e.preventDefault(); + e.returnValue = false; + } + + let mask = document.querySelector("#contextmenu-mask"); + if (!mask) { + mask = doc.createElement("div"); + mask.id = "contextmenu-mask"; + document.body.appendChild(mask); + } + + mask.onclick = () => popup.hidePopup(); + + popup.openPopupAtScreen = function (clientX, clientY) { + this.style.setProperty("left", `${clientX}px`); + this.style.setProperty("top", `${clientY}px`); + mask = document.querySelector("#contextmenu-mask"); + window.onwheel = preventDefault; + mask.classList.add("show"); + this.dispatchEvent(new Event("popupshown")); + this.popupshown; + }; + + popup.hidePopup = function () { + this.remove(); + mask = document.querySelector("#contextmenu-mask"); + mask.classList.remove("show"); + window.onwheel = null; + }; + + return popup; +} + +if (!inToolbox()) { + Menu.prototype.createPopup = createPopup; +} + +function onShown(menu, popup) { + popup.childNodes.forEach((menuItemNode, i) => { + let item = menu.items[i]; + + if (!item.disabled && item.visible) { + menuItemNode.onclick = () => { + item.click(); + popup.hidePopup(); + }; + + showSubMenu(item.submenu, menuItemNode, popup); + } + }); +} + +function showMenu(evt, items) { + if (items.length === 0) { + return; + } + + let menu = new Menu(); + items.filter(item => item.visible === undefined || item.visible === true).forEach(item => { + let menuItem = new MenuItem(item); + menuItem.submenu = createSubMenu(item.submenu); + menu.append(menuItem); + }); + + if (inToolbox()) { + menu.popup(evt.screenX, evt.screenY, { doc: window.parent.document }); + return; + } + + menu.on("open", (_, popup) => onShown(menu, popup)); + menu.popup(evt.clientX, evt.clientY, { doc: document }); +} + +function createSubMenu(subItems) { + if (subItems) { + let subMenu = new Menu(); + subItems.forEach(subItem => { + subMenu.append(new MenuItem(subItem)); + }); + return subMenu; + } + return null; +} + +function showSubMenu(subMenu, menuItemNode, popup) { + if (subMenu) { + let subMenuNode = menuItemNode.querySelector("menupopup"); + let { top } = menuItemNode.getBoundingClientRect(); + let { left, width } = popup.getBoundingClientRect(); + subMenuNode.style.setProperty("left", `${left + width - 1}px`); + subMenuNode.style.setProperty("top", `${top}px`); + + let subMenuItemNodes = menuItemNode.querySelector("menupopup:not(.landing-popup)").childNodes; + subMenuItemNodes.forEach((subMenuItemNode, j) => { + let subMenuItem = subMenu.items.filter(item => item.visible === undefined || item.visible === true)[j]; + if (!subMenuItem.disabled && subMenuItem.visible) { + subMenuItemNode.onclick = () => { + subMenuItem.click(); + popup.hidePopup(); + }; + } + }); + } +} + +function buildMenu(items) { + return items.map(itm => { + const hide = typeof itm.hidden === "function" ? itm.hidden() : itm.hidden; + return hide ? null : itm.item; + }).filter(itm => itm !== null); +} + +module.exports = { + showMenu, + buildMenu +}; + +/***/ }), + +/***/ 1440: +/***/ (function(module, exports, __webpack_require__) { + +const SplitBox = __webpack_require__(1536); + +module.exports = SplitBox; + +/***/ }), + +/***/ 1461: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const pick = __webpack_require__(67); +const put = __webpack_require__(112); +const fs = __webpack_require__(118); +const path = __webpack_require__(119); + +let config; + +const flag = __webpack_require__(52); + +function isBrowser() { + return typeof window == "object" && typeof module == "undefined"; +} + +/** + * Gets a config value for a given key + * e.g "chrome.webSocketPort" + */ +function getValue(key) { + return pick(config, key); +} + +function setValue(key, value) { + return put(config, key, value); +} + +function isEnabled(key) { + return config.features && typeof config.features[key] == "object" ? config.features[key].enabled : config.features[key]; +} + +function isDevelopment() { + if (isBrowser()) { + if (true) { + return false; + } + const href = window.location ? window.location.href : ""; + return href.match(/^file:/) || href.match(/localhost:/); + } + + if (isFirefoxPanel()) { + // Default to production if compiling for the Firefox panel + return "production" === "development"; + } + return "production" !== "production"; +} + +function isTesting() { + return flag.testing; +} + +function isFirefoxPanel() { + return "firefox-panel" == "firefox-panel"; +} + +function isApplication() { + return "firefox-panel" == "application"; +} + +function isFirefox() { + return (/firefox/i.test(navigator.userAgent) + ); +} + +function setConfig(value) { + config = value; +} + +function getConfig() { + return config; +} + +function updateLocalConfig(relativePath) { + const localConfigPath = path.resolve(relativePath, "../configs/local.json"); + const output = JSON.stringify(config, null, 2); + fs.writeFileSync(localConfigPath, output, { flag: "w" }); + return output; +} + +module.exports = { + isEnabled, + getValue, + setValue, + isDevelopment, + isTesting, + isFirefoxPanel, + isApplication, + isFirefox, + getConfig, + setConfig, + updateLocalConfig +}; + +/***/ }), + +/***/ 1464: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const EventEmitter = __webpack_require__(1382); + +function inToolbox() { + return window.parent.document.documentURI == "about:devtools-toolbox"; +} + +/** + * A partial implementation of the Menu API provided by electron: + * https://github.com/electron/electron/blob/master/docs/api/menu.md. + * + * Extra features: + * - Emits an 'open' and 'close' event when the menu is opened/closed + + * @param String id (non standard) + * Needed so tests can confirm the XUL implementation is working + */ +function Menu({ id = null } = {}) { + this.menuitems = []; + this.id = id; + + Object.defineProperty(this, "items", { + get() { + return this.menuitems; + } + }); + + EventEmitter.decorate(this); +} + +/** + * Add an item to the end of the Menu + * + * @param {MenuItem} menuItem + */ +Menu.prototype.append = function (menuItem) { + this.menuitems.push(menuItem); +}; + +/** + * Add an item to a specified position in the menu + * + * @param {int} pos + * @param {MenuItem} menuItem + */ +Menu.prototype.insert = function (pos, menuItem) { + throw Error("Not implemented"); +}; + +/** + * Show the Menu at a specified location on the screen + * + * Missing features: + * - browserWindow - BrowserWindow (optional) - Default is null. + * - positioningItem Number - (optional) OS X + * + * @param {int} screenX + * @param {int} screenY + * @param Toolbox toolbox (non standard) + * Needed so we in which window to inject XUL + */ +Menu.prototype.popup = function (screenX, screenY, toolbox) { + let doc = toolbox.doc; + let popupset = doc.querySelector("popupset"); + // See bug 1285229, on Windows, opening the same popup multiple times in a + // row ends up duplicating the popup. The newly inserted popup doesn't + // dismiss the old one. So remove any previously displayed popup before + // opening a new one. + let popup = popupset.querySelector("menupopup[menu-api=\"true\"]"); + if (popup) { + popup.hidePopup(); + } + + popup = this.createPopup(doc); + popup.setAttribute("menu-api", "true"); + + if (this.id) { + popup.id = this.id; + } + this._createMenuItems(popup); + + // Remove the menu from the DOM once it's hidden. + popup.addEventListener("popuphidden", e => { + if (e.target === popup) { + popup.remove(); + this.emit("close", popup); + } + }); + + popup.addEventListener("popupshown", e => { + if (e.target === popup) { + this.emit("open", popup); + } + }); + + popupset.appendChild(popup); + popup.openPopupAtScreen(screenX, screenY, true); +}; + +Menu.prototype.createPopup = function (doc) { + return doc.createElement("menupopup"); +}; + +Menu.prototype._createMenuItems = function (parent) { + let doc = parent.ownerDocument; + this.menuitems.forEach(item => { + if (!item.visible) { + return; + } + + if (item.submenu) { + let menupopup = doc.createElement("menupopup"); + item.submenu._createMenuItems(menupopup); + + let menuitem = doc.createElement("menuitem"); + menuitem.setAttribute("label", item.label); + if (!inToolbox()) { + menuitem.textContent = item.label; + } + + let menu = doc.createElement("menu"); + menu.appendChild(menuitem); + menu.appendChild(menupopup); + if (item.disabled) { + menu.setAttribute("disabled", "true"); + } + if (item.accesskey) { + menu.setAttribute("accesskey", item.accesskey); + } + if (item.id) { + menu.id = item.id; + } + parent.appendChild(menu); + } else if (item.type === "separator") { + let menusep = doc.createElement("menuseparator"); + parent.appendChild(menusep); + } else { + let menuitem = doc.createElement("menuitem"); + menuitem.setAttribute("label", item.label); + + if (!inToolbox()) { + menuitem.textContent = item.label; + } + + menuitem.addEventListener("command", () => item.click()); + + if (item.type === "checkbox") { + menuitem.setAttribute("type", "checkbox"); + } + if (item.type === "radio") { + menuitem.setAttribute("type", "radio"); + } + if (item.disabled) { + menuitem.setAttribute("disabled", "true"); + } + if (item.checked) { + menuitem.setAttribute("checked", "true"); + } + if (item.accesskey) { + menuitem.setAttribute("accesskey", item.accesskey); + } + if (item.id) { + menuitem.id = item.id; + } + + parent.appendChild(menuitem); + } + }); +}; + +Menu.setApplicationMenu = () => { + throw Error("Not implemented"); +}; + +Menu.sendActionToFirstResponder = () => { + throw Error("Not implemented"); +}; + +Menu.buildFromTemplate = () => { + throw Error("Not implemented"); +}; + +module.exports = Menu; + +/***/ }), + +/***/ 1465: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/Promise.jsm + */ + +/** + * Promise.jsm is mostly the Promise web API with a `defer` method. Just drop this in here, + * and use the native web API (although building with webpack/babel, it may replace this + * with it's own version if we want to target environments that do not have `Promise`. + */ + +let p = typeof window != "undefined" ? window.Promise : Promise; +p.defer = function defer() { + var resolve, reject; + var promise = new Promise(function () { + resolve = arguments[0]; + reject = arguments[1]; + }); + return { + resolve: resolve, + reject: reject, + promise: promise + }; +}; + +module.exports = p; + +/***/ }), + +/***/ 1466: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * A partial implementation of the MenuItem API provided by electron: + * https://github.com/electron/electron/blob/master/docs/api/menu-item.md. + * + * Missing features: + * - id String - Unique within a single menu. If defined then it can be used + * as a reference to this item by the position attribute. + * - role String - Define the action of the menu item; when specified the + * click property will be ignored + * - sublabel String + * - accelerator Accelerator + * - icon NativeImage + * - position String - This field allows fine-grained definition of the + * specific location within a given menu. + * + * Implemented features: + * @param Object options + * Function click + * Will be called with click(menuItem, browserWindow) when the menu item + * is clicked + * String type + * Can be normal, separator, submenu, checkbox or radio + * String label + * Boolean enabled + * If false, the menu item will be greyed out and unclickable. + * Boolean checked + * Should only be specified for checkbox or radio type menu items. + * Menu submenu + * Should be specified for submenu type menu items. If submenu is specified, + * the type: 'submenu' can be omitted. If the value is not a Menu then it + * will be automatically converted to one using Menu.buildFromTemplate. + * Boolean visible + * If false, the menu item will be entirely hidden. + */ +function MenuItem({ + accesskey = null, + checked = false, + click = () => {}, + disabled = false, + label = "", + id = null, + submenu = null, + type = "normal", + visible = true +} = {}) { + this.accesskey = accesskey; + this.checked = checked; + this.click = click; + this.disabled = disabled; + this.id = id; + this.label = label; + this.submenu = submenu; + this.type = type; + this.visible = visible; +} + +module.exports = MenuItem; + +/***/ }), + +/***/ 1467: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const Services = __webpack_require__(22); +const EventEmitter = __webpack_require__(1382); + +/** + * Shortcuts for lazily accessing and setting various preferences. + * Usage: + * let prefs = new Prefs("root.path.to.branch", { + * myIntPref: ["Int", "leaf.path.to.my-int-pref"], + * myCharPref: ["Char", "leaf.path.to.my-char-pref"], + * myJsonPref: ["Json", "leaf.path.to.my-json-pref"], + * myFloatPref: ["Float", "leaf.path.to.my-float-pref"] + * ... + * }); + * + * Get/set: + * prefs.myCharPref = "foo"; + * let aux = prefs.myCharPref; + * + * Observe: + * prefs.registerObserver(); + * prefs.on("pref-changed", (prefName, prefValue) => { + * ... + * }); + * + * @param string prefsRoot + * The root path to the required preferences branch. + * @param object prefsBlueprint + * An object containing { accessorName: [prefType, prefName, prefDefault] } keys. + */ +function PrefsHelper(prefsRoot = "", prefsBlueprint = {}) { + EventEmitter.decorate(this); + + let cache = new Map(); + + for (let accessorName in prefsBlueprint) { + let [prefType, prefName, prefDefault] = prefsBlueprint[accessorName]; + map(this, cache, accessorName, prefType, prefsRoot, prefName, prefDefault); + } + + let observer = makeObserver(this, cache, prefsRoot, prefsBlueprint); + this.registerObserver = () => observer.register(); + this.unregisterObserver = () => observer.unregister(); +} + +/** + * Helper method for getting a pref value. + * + * @param Map cache + * @param string prefType + * @param string prefsRoot + * @param string prefName + * @return any + */ +function get(cache, prefType, prefsRoot, prefName) { + let cachedPref = cache.get(prefName); + if (cachedPref !== undefined) { + return cachedPref; + } + let value = Services.prefs["get" + prefType + "Pref"]([prefsRoot, prefName].join(".")); + cache.set(prefName, value); + return value; +} + +/** + * Helper method for setting a pref value. + * + * @param Map cache + * @param string prefType + * @param string prefsRoot + * @param string prefName + * @param any value + */ +function set(cache, prefType, prefsRoot, prefName, value) { + Services.prefs["set" + prefType + "Pref"]([prefsRoot, prefName].join("."), value); + cache.set(prefName, value); +} + +/** + * Maps a property name to a pref, defining lazy getters and setters. + * Supported types are "Bool", "Char", "Int", "Float" (sugar around "Char" + * type and casting), and "Json" (which is basically just sugar for "Char" + * using the standard JSON serializer). + * + * @param PrefsHelper self + * @param Map cache + * @param string accessorName + * @param string prefType + * @param string prefsRoot + * @param string prefName + * @param string prefDefault + * @param array serializer [optional] + */ +function map(self, cache, accessorName, prefType, prefsRoot, prefName, prefDefault, serializer = { in: e => e, out: e => e }) { + if (prefName in self) { + throw new Error(`Can't use ${prefName} because it overrides a property` + "on the instance."); + } + if (prefType == "Json") { + map(self, cache, accessorName, "String", prefsRoot, prefName, prefDefault, { + in: JSON.parse, + out: JSON.stringify + }); + return; + } + if (prefType == "Float") { + map(self, cache, accessorName, "Char", prefsRoot, prefName, prefDefault, { + in: Number.parseFloat, + out: n => n + "" + }); + return; + } + + Object.defineProperty(self, accessorName, { + get: () => { + try { + return serializer.in(get(cache, prefType, prefsRoot, prefName)); + } catch (e) { + if (typeof prefDefault !== 'undefined') { + return prefDefault; + } + throw e; + } + }, + set: e => set(cache, prefType, prefsRoot, prefName, serializer.out(e)) + }); +} + +/** + * Finds the accessor for the provided pref, based on the blueprint object + * used in the constructor. + * + * @param PrefsHelper self + * @param object prefsBlueprint + * @return string + */ +function accessorNameForPref(somePrefName, prefsBlueprint) { + for (let accessorName in prefsBlueprint) { + let [, prefName] = prefsBlueprint[accessorName]; + if (somePrefName == prefName) { + return accessorName; + } + } + return ""; +} + +/** + * Creates a pref observer for `self`. + * + * @param PrefsHelper self + * @param Map cache + * @param string prefsRoot + * @param object prefsBlueprint + * @return object + */ +function makeObserver(self, cache, prefsRoot, prefsBlueprint) { + return { + register: function () { + this._branch = Services.prefs.getBranch(prefsRoot + "."); + this._branch.addObserver("", this); + }, + unregister: function () { + this._branch.removeObserver("", this); + }, + observe: function (subject, topic, prefName) { + // If this particular pref isn't handled by the blueprint object, + // even though it's in the specified branch, ignore it. + let accessorName = accessorNameForPref(prefName, prefsBlueprint); + if (!(accessorName in self)) { + return; + } + cache.delete(prefName); + self.emit("pref-changed", accessorName, self[accessorName]); + } + }; +} + +exports.PrefsHelper = PrefsHelper; + +/***/ }), + +/***/ 1468: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { appinfo } = __webpack_require__(22); +const EventEmitter = __webpack_require__(1382); +const isOSX = appinfo.OS === "Darwin"; + +// List of electron keys mapped to DOM API (DOM_VK_*) key code +const ElectronKeysMapping = { + "F1": "DOM_VK_F1", + "F2": "DOM_VK_F2", + "F3": "DOM_VK_F3", + "F4": "DOM_VK_F4", + "F5": "DOM_VK_F5", + "F6": "DOM_VK_F6", + "F7": "DOM_VK_F7", + "F8": "DOM_VK_F8", + "F9": "DOM_VK_F9", + "F10": "DOM_VK_F10", + "F11": "DOM_VK_F11", + "F12": "DOM_VK_F12", + "F13": "DOM_VK_F13", + "F14": "DOM_VK_F14", + "F15": "DOM_VK_F15", + "F16": "DOM_VK_F16", + "F17": "DOM_VK_F17", + "F18": "DOM_VK_F18", + "F19": "DOM_VK_F19", + "F20": "DOM_VK_F20", + "F21": "DOM_VK_F21", + "F22": "DOM_VK_F22", + "F23": "DOM_VK_F23", + "F24": "DOM_VK_F24", + "Space": "DOM_VK_SPACE", + "Backspace": "DOM_VK_BACK_SPACE", + "Delete": "DOM_VK_DELETE", + "Insert": "DOM_VK_INSERT", + "Return": "DOM_VK_RETURN", + "Enter": "DOM_VK_RETURN", + "Up": "DOM_VK_UP", + "Down": "DOM_VK_DOWN", + "Left": "DOM_VK_LEFT", + "Right": "DOM_VK_RIGHT", + "Home": "DOM_VK_HOME", + "End": "DOM_VK_END", + "PageUp": "DOM_VK_PAGE_UP", + "PageDown": "DOM_VK_PAGE_DOWN", + "Escape": "DOM_VK_ESCAPE", + "Esc": "DOM_VK_ESCAPE", + "Tab": "DOM_VK_TAB", + "VolumeUp": "DOM_VK_VOLUME_UP", + "VolumeDown": "DOM_VK_VOLUME_DOWN", + "VolumeMute": "DOM_VK_VOLUME_MUTE", + "PrintScreen": "DOM_VK_PRINTSCREEN" +}; + +/** + * Helper to listen for keyboard events decribed in .properties file. + * + * let shortcuts = new KeyShortcuts({ + * window + * }); + * shortcuts.on("Ctrl+F", event => { + * // `event` is the KeyboardEvent which relates to the key shortcuts + * }); + * + * @param DOMWindow window + * The window object of the document to listen events from. + * @param DOMElement target + * Optional DOM Element on which we should listen events from. + * If omitted, we listen for all events fired on `window`. + */ +function KeyShortcuts({ window, target }) { + this.window = window; + this.target = target || window; + this.keys = new Map(); + this.eventEmitter = new EventEmitter(); + this.target.addEventListener("keydown", this); +} + +/* + * Parse an electron-like key string and return a normalized object which + * allow efficient match on DOM key event. The normalized object matches DOM + * API. + * + * @param DOMWindow window + * Any DOM Window object, just to fetch its `KeyboardEvent` object + * @param String str + * The shortcut string to parse, following this document: + * https://github.com/electron/electron/blob/master/docs/api/accelerator.md + */ +KeyShortcuts.parseElectronKey = function (window, str) { + let modifiers = str.split("+"); + let key = modifiers.pop(); + + let shortcut = { + ctrl: false, + meta: false, + alt: false, + shift: false, + // Set for character keys + key: undefined, + // Set for non-character keys + keyCode: undefined + }; + for (let mod of modifiers) { + if (mod === "Alt") { + shortcut.alt = true; + } else if (["Command", "Cmd"].includes(mod)) { + shortcut.meta = true; + } else if (["CommandOrControl", "CmdOrCtrl"].includes(mod)) { + if (isOSX) { + shortcut.meta = true; + } else { + shortcut.ctrl = true; + } + } else if (["Control", "Ctrl"].includes(mod)) { + shortcut.ctrl = true; + } else if (mod === "Shift") { + shortcut.shift = true; + } else { + console.error("Unsupported modifier:", mod, "from key:", str); + return null; + } + } + + // Plus is a special case. It's a character key and shouldn't be matched + // against a keycode as it is only accessible via Shift/Capslock + if (key === "Plus") { + key = "+"; + } + + if (typeof key === "string" && key.length === 1) { + // Match any single character + shortcut.key = key.toLowerCase(); + } else if (key in ElectronKeysMapping) { + // Maps the others manually to DOM API DOM_VK_* + key = ElectronKeysMapping[key]; + shortcut.keyCode = window.KeyboardEvent[key]; + // Used only to stringify the shortcut + shortcut.keyCodeString = key; + shortcut.key = key; + } else { + console.error("Unsupported key:", key); + return null; + } + + return shortcut; +}; + +KeyShortcuts.stringify = function (shortcut) { + let list = []; + if (shortcut.alt) { + list.push("Alt"); + } + if (shortcut.ctrl) { + list.push("Ctrl"); + } + if (shortcut.meta) { + list.push("Cmd"); + } + if (shortcut.shift) { + list.push("Shift"); + } + let key; + if (shortcut.key) { + key = shortcut.key.toUpperCase(); + } else { + key = shortcut.keyCodeString; + } + list.push(key); + return list.join("+"); +}; + +KeyShortcuts.prototype = { + destroy() { + this.target.removeEventListener("keydown", this); + this.keys.clear(); + }, + + doesEventMatchShortcut(event, shortcut) { + if (shortcut.meta != event.metaKey) { + return false; + } + if (shortcut.ctrl != event.ctrlKey) { + return false; + } + if (shortcut.alt != event.altKey) { + return false; + } + // Shift is a special modifier, it may implicitely be required if the + // expected key is a special character accessible via shift. + if (shortcut.shift != event.shiftKey && event.key && event.key.match(/[a-zA-Z]/)) { + return false; + } + if (shortcut.keyCode) { + return event.keyCode == shortcut.keyCode; + } else if (event.key in ElectronKeysMapping) { + return ElectronKeysMapping[event.key] === shortcut.key; + } + + // get the key from the keyCode if key is not provided. + let key = event.key || String.fromCharCode(event.keyCode); + + // For character keys, we match if the final character is the expected one. + // But for digits we also accept indirect match to please azerty keyboard, + // which requires Shift to be pressed to get digits. + return key.toLowerCase() == shortcut.key || shortcut.key.match(/^[0-9]$/) && event.keyCode == shortcut.key.charCodeAt(0); + }, + + handleEvent(event) { + for (let [key, shortcut] of this.keys) { + if (this.doesEventMatchShortcut(event, shortcut)) { + this.eventEmitter.emit(key, event); + } + } + }, + + on(key, listener) { + if (typeof listener !== "function") { + throw new Error("KeyShortcuts.on() expects a function as " + "second argument"); + } + if (!this.keys.has(key)) { + let shortcut = KeyShortcuts.parseElectronKey(this.window, key); + // The key string is wrong and we were unable to compute the key shortcut + if (!shortcut) { + return; + } + this.keys.set(key, shortcut); + } + this.eventEmitter.on(key, listener); + }, + + off(key, listener) { + this.eventEmitter.off(key, listener); + } +}; +module.exports = KeyShortcuts; + +/***/ }), + +/***/ 1469: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + + +/** + * Empty shim for "devtools/client/shared/zoom-keys" module + * + * Based on nsIMarkupDocumentViewer.fullZoom API + * https://developer.mozilla.org/en-US/Firefox/Releases/3/Full_page_zoom + */ + +exports.register = function (window) {}; + +/***/ }), + +/***/ 1536: +/***/ (function(module, exports, __webpack_require__) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const React = __webpack_require__(0); +const ReactDOM = __webpack_require__(4); +const Draggable = React.createFactory(__webpack_require__(1537)); +const { Component } = React; +const PropTypes = __webpack_require__(3642); +const dom = __webpack_require__(3643); + +__webpack_require__(1309); + +/** + * This component represents a Splitter. The splitter supports vertical + * as well as horizontal mode. + */ +class SplitBox extends Component { + static get propTypes() { + return { + // Custom class name. You can use more names separated by a space. + className: PropTypes.string, + // Initial size of controlled panel. + initialSize: PropTypes.any, + // Optional initial width of controlled panel. + initialWidth: PropTypes.number, + // Optional initial height of controlled panel. + initialHeight: PropTypes.number, + // Left/top panel + startPanel: PropTypes.any, + // Left/top panel collapse state. + startPanelCollapsed: PropTypes.bool, + // Min panel size. + minSize: PropTypes.any, + // Max panel size. + maxSize: PropTypes.any, + // Right/bottom panel + endPanel: PropTypes.any, + // Right/bottom panel collapse state. + endPanelCollapsed: PropTypes.bool, + // True if the right/bottom panel should be controlled. + endPanelControl: PropTypes.bool, + // Size of the splitter handle bar. + splitterSize: PropTypes.number, + // True if the splitter bar is vertical (default is vertical). + vert: PropTypes.bool, + // Optional style properties passed into the splitbox + style: PropTypes.object, + // Optional callback when splitbox resize stops + onResizeEnd: PropTypes.func + }; + } + + static get defaultProps() { + return { + splitterSize: 5, + vert: true, + endPanelControl: false, + endPanelCollapsed: false, + startPanelCollapsed: false + }; + } + + constructor(props) { + super(props); + + this.state = { + vert: props.vert, + // We use integers for these properties + width: parseInt(props.initialWidth || props.initialSize, 10), + height: parseInt(props.initialHeight || props.initialSize, 10) + }; + + this.onStartMove = this.onStartMove.bind(this); + this.onStopMove = this.onStopMove.bind(this); + this.onMove = this.onMove.bind(this); + this.preparePanelStyles = this.preparePanelStyles.bind(this); + } + + componentWillReceiveProps(nextProps) { + if (this.props.vert !== nextProps.vert) { + this.setState({ vert: nextProps.vert }); + } + } + + // Dragging Events + + /** + * Set 'resizing' cursor on entire document during splitter dragging. + * This avoids cursor-flickering that happens when the mouse leaves + * the splitter bar area (happens frequently). + */ + onStartMove() { + const splitBox = ReactDOM.findDOMNode(this); + const doc = splitBox.ownerDocument; + let defaultCursor = doc.documentElement.style.cursor; + doc.documentElement.style.cursor = this.state.vert ? "ew-resize" : "ns-resize"; + + splitBox.classList.add("dragging"); + + this.setState({ + defaultCursor: defaultCursor + }); + } + + onStopMove() { + const splitBox = ReactDOM.findDOMNode(this); + const doc = splitBox.ownerDocument; + doc.documentElement.style.cursor = this.state.defaultCursor; + + splitBox.classList.remove("dragging"); + + if (this.props.onResizeEnd) { + this.props.onResizeEnd(this.state.vert ? this.state.width : this.state.height); + } + } + + /** + * Adjust size of the controlled panel. Depending on the current + * orientation we either remember the width or height of + * the splitter box. + */ + onMove({ movementX, movementY }) { + const node = ReactDOM.findDOMNode(this); + const doc = node.ownerDocument; + + if (this.props.endPanelControl) { + // For the end panel we need to increase the width/height when the + // movement is towards the left/top. + movementX = -movementX; + movementY = -movementY; + } + + if (this.state.vert) { + const isRtl = doc.dir === "rtl"; + if (isRtl) { + // In RTL we need to reverse the movement again -- but only for vertical + // splitters + movementX = -movementX; + } + + this.setState((state, props) => ({ + width: state.width + movementX + })); + } else { + this.setState((state, props) => ({ + height: state.height + movementY + })); + } + } + + // Rendering + preparePanelStyles() { + const vert = this.state.vert; + const { + minSize, + maxSize, + startPanelCollapsed, + endPanelControl, + endPanelCollapsed + } = this.props; + let leftPanelStyle, rightPanelStyle; + + // Set proper size for panels depending on the current state. + if (vert) { + let startWidth = endPanelControl ? null : this.state.width, + endWidth = endPanelControl ? this.state.width : null; + + leftPanelStyle = { + maxWidth: endPanelControl ? null : maxSize, + minWidth: endPanelControl ? null : minSize, + width: startPanelCollapsed ? 0 : startWidth + }; + rightPanelStyle = { + maxWidth: endPanelControl ? maxSize : null, + minWidth: endPanelControl ? minSize : null, + width: endPanelCollapsed ? 0 : endWidth + }; + } else { + let startHeight = endPanelControl ? null : this.state.height, + endHeight = endPanelControl ? this.state.height : null; + + leftPanelStyle = { + maxHeight: endPanelControl ? null : maxSize, + minHeight: endPanelControl ? null : minSize, + height: endPanelCollapsed ? maxSize : startHeight + }; + rightPanelStyle = { + maxHeight: endPanelControl ? maxSize : null, + minHeight: endPanelControl ? minSize : null, + height: startPanelCollapsed ? maxSize : endHeight + }; + } + + return { leftPanelStyle, rightPanelStyle }; + } + + render() { + const vert = this.state.vert; + const { + startPanelCollapsed, + startPanel, + endPanel, + endPanelControl, + splitterSize, + endPanelCollapsed + } = this.props; + + let style = Object.assign({}, this.props.style); + + // Calculate class names list. + let classNames = ["split-box"]; + classNames.push(vert ? "vert" : "horz"); + if (this.props.className) { + classNames = classNames.concat(this.props.className.split(" ")); + } + + const { leftPanelStyle, rightPanelStyle } = this.preparePanelStyles(); + + // Calculate splitter size + let splitterStyle = { + flex: `0 0 ${splitterSize}px` + }; + + return dom.div({ + className: classNames.join(" "), + style: style + }, !startPanelCollapsed ? dom.div({ + className: endPanelControl ? "uncontrolled" : "controlled", + style: leftPanelStyle + }, startPanel) : null, Draggable({ + className: "splitter", + style: splitterStyle, + onStart: this.onStartMove, + onStop: this.onStopMove, + onMove: this.onMove + }), !endPanelCollapsed ? dom.div({ + className: endPanelControl ? "controlled" : "uncontrolled", + style: rightPanelStyle + }, endPanel) : null); + } +} + +module.exports = SplitBox; + +/***/ }), + +/***/ 1537: +/***/ (function(module, exports, __webpack_require__) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const React = __webpack_require__(0); +const ReactDOM = __webpack_require__(4); +const { Component } = React; +const PropTypes = __webpack_require__(3642); +const dom = __webpack_require__(3643); + +class Draggable extends Component { + static get propTypes() { + return { + onMove: PropTypes.func.isRequired, + onStart: PropTypes.func, + onStop: PropTypes.func, + style: PropTypes.object, + className: PropTypes.string + }; + } + + constructor(props) { + super(props); + this.startDragging = this.startDragging.bind(this); + this.onMove = this.onMove.bind(this); + this.onUp = this.onUp.bind(this); + } + + startDragging(ev) { + ev.preventDefault(); + const doc = ReactDOM.findDOMNode(this).ownerDocument; + doc.addEventListener("mousemove", this.onMove); + doc.addEventListener("mouseup", this.onUp); + this.props.onStart && this.props.onStart(); + } + + onMove(ev) { + ev.preventDefault(); + // We pass the whole event because we don't know which properties + // the callee needs. + this.props.onMove(ev); + } + + onUp(ev) { + ev.preventDefault(); + const doc = ReactDOM.findDOMNode(this).ownerDocument; + doc.removeEventListener("mousemove", this.onMove); + doc.removeEventListener("mouseup", this.onUp); + this.props.onStop && this.props.onStop(); + } + + render() { + return dom.div({ + style: this.props.style, + className: this.props.className, + onMouseDown: this.startDragging + }); + } +} + +module.exports = Draggable; + +/***/ }), + +/***/ 1540: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _svgInlineReact = __webpack_require__(1763); + +var _svgInlineReact2 = _interopRequireDefault(_svgInlineReact); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +const React = __webpack_require__(0); + + +const svg = { + "angle-brackets": __webpack_require__(347), + angular: __webpack_require__(247), + arrow: __webpack_require__(348), + babel: __webpack_require__(3595), + backbone: __webpack_require__(997), + blackBox: __webpack_require__(349), + breadcrumb: __webpack_require__(3603), + breakpoint: __webpack_require__(350), + "column-breakpoint": __webpack_require__(998), + "case-match": __webpack_require__(351), + choo: __webpack_require__(1290), + close: __webpack_require__(352), + coffeescript: __webpack_require__(2250), + dojo: __webpack_require__(806), + domain: __webpack_require__(353), + extension: __webpack_require__(3632), + file: __webpack_require__(354), + folder: __webpack_require__(355), + globe: __webpack_require__(356), + home: __webpack_require__(3604), + javascript: __webpack_require__(2251), + jquery: __webpack_require__(999), + underscore: __webpack_require__(1117), + lodash: __webpack_require__(1118), + ember: __webpack_require__(1119), + vuejs: __webpack_require__(1174), + "magnifying-glass": __webpack_require__(357), + "arrow-up": __webpack_require__(919), + "arrow-down": __webpack_require__(920), + pause: __webpack_require__(358), + "pause-exceptions": __webpack_require__(359), + plus: __webpack_require__(360), + preact: __webpack_require__(1233), + aframe: __webpack_require__(1648), + prettyPrint: __webpack_require__(361), + react: __webpack_require__(1000), + "regex-match": __webpack_require__(362), + redux: __webpack_require__(256), + immutable: __webpack_require__(258), + resume: __webpack_require__(363), + settings: __webpack_require__(364), + stepIn: __webpack_require__(365), + stepOut: __webpack_require__(366), + stepOver: __webpack_require__(367), + subSettings: __webpack_require__(368), + tab: __webpack_require__(3631), + toggleBreakpoints: __webpack_require__(369), + togglePanes: __webpack_require__(370), + typescript: __webpack_require__(2252), + "whole-word-match": __webpack_require__(371), + worker: __webpack_require__(372), + "sad-face": __webpack_require__(1347), + refresh: __webpack_require__(1348), + webpack: __webpack_require__(1001), + node: __webpack_require__(1002), + express: __webpack_require__(1003), + pug: __webpack_require__(1004), + extjs: __webpack_require__(1043), + mobx: __webpack_require__(1733), + marko: __webpack_require__(1649), + nextjs: __webpack_require__(1650), + showSources: __webpack_require__(1044), + showOutline: __webpack_require__(1045), + nuxtjs: __webpack_require__(1651), + rxjs: __webpack_require__(1808) +}; + +function Svg({ name, className, onClick, "aria-label": ariaLabel }) { + if (!svg[name]) { + const error = `Unknown SVG: ${name}`; + console.warn(error); + return null; + } + + className = `${name} ${className || ""}`; + if (name === "subSettings") { + className = ""; + } + + const props = { + className, + onClick, + ["aria-label"]: ariaLabel, + src: svg[name] + }; + + return React.createElement(_svgInlineReact2.default, props); +} + +Svg.displayName = "Svg"; + +module.exports = Svg; + +/***/ }), + +/***/ 161: +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(process) {(function() { + var Query, defaultPathSeparator, filter, matcher, parseOptions, pathScorer, preparedQueryCache, scorer; + + filter = __webpack_require__(162); + + matcher = __webpack_require__(166); + + scorer = __webpack_require__(163); + + pathScorer = __webpack_require__(164); + + Query = __webpack_require__(165); + + preparedQueryCache = null; + + defaultPathSeparator = (typeof process !== "undefined" && process !== null ? process.platform : void 0) === "win32" ? '\\' : '/'; + + module.exports = { + filter: function(candidates, query, options) { + if (options == null) { + options = {}; + } + if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) { + return []; + } + options = parseOptions(options, query); + return filter(candidates, query, options); + }, + score: function(string, query, options) { + if (options == null) { + options = {}; + } + if (!((string != null ? string.length : void 0) && (query != null ? query.length : void 0))) { + return 0; + } + options = parseOptions(options, query); + if (options.usePathScoring) { + return pathScorer.score(string, query, options); + } else { + return scorer.score(string, query, options); + } + }, + match: function(string, query, options) { + var _i, _ref, _results; + if (options == null) { + options = {}; + } + if (!string) { + return []; + } + if (!query) { + return []; + } + if (string === query) { + return (function() { + _results = []; + for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + } + options = parseOptions(options, query); + return matcher.match(string, query, options); + }, + wrap: function(string, query, options) { + if (options == null) { + options = {}; + } + if (!string) { + return []; + } + if (!query) { + return []; + } + options = parseOptions(options, query); + return matcher.wrap(string, query, options); + }, + prepareQuery: function(query, options) { + if (options == null) { + options = {}; + } + options = parseOptions(options, query); + return options.preparedQuery; + } + }; + + parseOptions = function(options, query) { + if (options.allowErrors == null) { + options.allowErrors = false; + } + if (options.usePathScoring == null) { + options.usePathScoring = true; + } + if (options.useExtensionBonus == null) { + options.useExtensionBonus = false; + } + if (options.pathSeparator == null) { + options.pathSeparator = defaultPathSeparator; + } + if (options.optCharRegEx == null) { + options.optCharRegEx = null; + } + if (options.wrap == null) { + options.wrap = null; + } + if (options.preparedQuery == null) { + options.preparedQuery = preparedQueryCache && preparedQueryCache.query === query ? preparedQueryCache : (preparedQueryCache = new Query(query, options)); + } + return options; + }; + +}).call(this); + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120))) + +/***/ }), + +/***/ 162: +/***/ (function(module, exports, __webpack_require__) { + +(function() { + var Query, pathScorer, pluckCandidates, scorer, sortCandidates; + + scorer = __webpack_require__(163); + + pathScorer = __webpack_require__(164); + + Query = __webpack_require__(165); + + pluckCandidates = function(a) { + return a.candidate; + }; + + sortCandidates = function(a, b) { + return b.score - a.score; + }; + + module.exports = function(candidates, query, options) { + var bKey, candidate, key, maxInners, maxResults, score, scoreProvider, scoredCandidates, spotLeft, string, usePathScoring, _i, _len; + scoredCandidates = []; + key = options.key, maxResults = options.maxResults, maxInners = options.maxInners, usePathScoring = options.usePathScoring; + spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : candidates.length + 1; + bKey = key != null; + scoreProvider = usePathScoring ? pathScorer : scorer; + for (_i = 0, _len = candidates.length; _i < _len; _i++) { + candidate = candidates[_i]; + string = bKey ? candidate[key] : candidate; + if (!string) { + continue; + } + score = scoreProvider.score(string, query, options); + if (score > 0) { + scoredCandidates.push({ + candidate: candidate, + score: score + }); + if (!--spotLeft) { + break; + } + } + } + scoredCandidates.sort(sortCandidates); + candidates = scoredCandidates.map(pluckCandidates); + if (maxResults != null) { + candidates = candidates.slice(0, maxResults); + } + return candidates; + }; + +}).call(this); + + +/***/ }), + +/***/ 163: +/***/ (function(module, exports) { + +(function() { + var AcronymResult, computeScore, emptyAcronymResult, isAcronymFullWord, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_size, wm; + + wm = 150; + + pos_bonus = 20; + + tau_size = 150; + + miss_coeff = 0.75; + + exports.score = function(string, query, options) { + var allowErrors, preparedQuery, score, string_lw; + preparedQuery = options.preparedQuery, allowErrors = options.allowErrors; + if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) { + return 0; + } + string_lw = string.toLowerCase(); + score = computeScore(string, string_lw, preparedQuery); + return Math.ceil(score); + }; + + exports.isMatch = isMatch = function(subject, query_lw, query_up) { + var i, j, m, n, qj_lw, qj_up, si; + m = subject.length; + n = query_lw.length; + if (!m || n > m) { + return false; + } + i = -1; + j = -1; + while (++j < n) { + qj_lw = query_lw.charCodeAt(j); + qj_up = query_up.charCodeAt(j); + while (++i < m) { + si = subject.charCodeAt(i); + if (si === qj_lw || si === qj_up) { + break; + } + } + if (i === m) { + return false; + } + } + return true; + }; + + exports.computeScore = computeScore = function(subject, subject_lw, preparedQuery) { + var acro, acro_score, align, csc_diag, csc_row, csc_score, csc_should_rebuild, i, j, m, miss_budget, miss_left, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz; + query = preparedQuery.query; + query_lw = preparedQuery.query_lw; + m = subject.length; + n = query.length; + acro = scoreAcronyms(subject, subject_lw, query, query_lw); + acro_score = acro.score; + if (acro.count === n) { + return scoreExact(n, m, acro_score, acro.pos); + } + pos = subject_lw.indexOf(query_lw); + if (pos > -1) { + return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m); + } + score_row = new Array(n); + csc_row = new Array(n); + sz = scoreSize(n, m); + miss_budget = Math.ceil(miss_coeff * n) + 5; + miss_left = miss_budget; + csc_should_rebuild = true; + j = -1; + while (++j < n) { + score_row[j] = 0; + csc_row[j] = 0; + } + i = -1; + while (++i < m) { + si_lw = subject_lw[i]; + if (!si_lw.charCodeAt(0) in preparedQuery.charCodes) { + if (csc_should_rebuild) { + j = -1; + while (++j < n) { + csc_row[j] = 0; + } + csc_should_rebuild = false; + } + continue; + } + score = 0; + score_diag = 0; + csc_diag = 0; + record_miss = true; + csc_should_rebuild = true; + j = -1; + while (++j < n) { + score_up = score_row[j]; + if (score_up > score) { + score = score_up; + } + csc_score = 0; + if (query_lw[j] === si_lw) { + start = isWordStart(i, subject, subject_lw); + csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); + align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score); + if (align > score) { + score = align; + miss_left = miss_budget; + } else { + if (record_miss && --miss_left <= 0) { + return Math.max(score, score_row[n - 1]) * sz; + } + record_miss = false; + } + } + score_diag = score_up; + csc_diag = csc_row[j]; + csc_row[j] = csc_score; + score_row[j] = score; + } + } + score = score_row[n - 1]; + return score * sz; + }; + + exports.isWordStart = isWordStart = function(pos, subject, subject_lw) { + var curr_s, prev_s; + if (pos === 0) { + return true; + } + curr_s = subject[pos]; + prev_s = subject[pos - 1]; + return isSeparator(prev_s) || (curr_s !== subject_lw[pos] && prev_s === subject_lw[pos - 1]); + }; + + exports.isWordEnd = isWordEnd = function(pos, subject, subject_lw, len) { + var curr_s, next_s; + if (pos === len - 1) { + return true; + } + curr_s = subject[pos]; + next_s = subject[pos + 1]; + return isSeparator(next_s) || (curr_s === subject_lw[pos] && next_s !== subject_lw[pos + 1]); + }; + + isSeparator = function(c) { + return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c === '\\'; + }; + + scorePosition = function(pos) { + var sc; + if (pos < pos_bonus) { + sc = pos_bonus - pos; + return 100 + sc * sc; + } else { + return Math.max(100 + pos_bonus - pos, 0); + } + }; + + exports.scoreSize = scoreSize = function(n, m) { + return tau_size / (tau_size + Math.abs(m - n)); + }; + + scoreExact = function(n, m, quality, pos) { + return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m); + }; + + exports.scorePattern = scorePattern = function(count, len, sameCase, start, end) { + var bonus, sz; + sz = count; + bonus = 6; + if (sameCase === count) { + bonus += 2; + } + if (start) { + bonus += 3; + } + if (end) { + bonus += 1; + } + if (count === len) { + if (start) { + if (sameCase === len) { + sz += 2; + } else { + sz += 1; + } + } + if (end) { + bonus += 1; + } + } + return sameCase + sz * (sz + bonus); + }; + + exports.scoreCharacter = scoreCharacter = function(i, j, start, acro_score, csc_score) { + var posBonus; + posBonus = scorePosition(i); + if (start) { + return posBonus + wm * ((acro_score > csc_score ? acro_score : csc_score) + 10); + } + return posBonus + wm * csc_score; + }; + + exports.scoreConsecutives = scoreConsecutives = function(subject, subject_lw, query, query_lw, i, j, startOfWord) { + var k, m, mi, n, nj, sameCase, sz; + m = subject.length; + n = query.length; + mi = m - i; + nj = n - j; + k = mi < nj ? mi : nj; + sameCase = 0; + sz = 0; + if (query[j] === subject[i]) { + sameCase++; + } + while (++sz < k && query_lw[++j] === subject_lw[++i]) { + if (query[j] === subject[i]) { + sameCase++; + } + } + if (sz < k) { + i--; + } + if (sz === 1) { + return 1 + 2 * sameCase; + } + return scorePattern(sz, n, sameCase, startOfWord, isWordEnd(i, subject, subject_lw, m)); + }; + + exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, query, query_lw, pos, n, m) { + var end, i, pos2, sameCase, start; + start = isWordStart(pos, subject, subject_lw); + if (!start) { + pos2 = subject_lw.indexOf(query_lw, pos + 1); + if (pos2 > -1) { + start = isWordStart(pos2, subject, subject_lw); + if (start) { + pos = pos2; + } + } + } + i = -1; + sameCase = 0; + while (++i < n) { + if (query[pos + i] === subject[i]) { + sameCase++; + } + } + end = isWordEnd(pos + n - 1, subject, subject_lw, m); + return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos); + }; + + AcronymResult = (function() { + function AcronymResult(score, pos, count) { + this.score = score; + this.pos = pos; + this.count = count; + } + + return AcronymResult; + + })(); + + emptyAcronymResult = new AcronymResult(0, 0.1, 0); + + exports.scoreAcronyms = scoreAcronyms = function(subject, subject_lw, query, query_lw) { + var count, fullWord, i, j, m, n, qj_lw, sameCase, score, sepCount, sumPos; + m = subject.length; + n = query.length; + if (!(m > 1 && n > 1)) { + return emptyAcronymResult; + } + count = 0; + sepCount = 0; + sumPos = 0; + sameCase = 0; + i = -1; + j = -1; + while (++j < n) { + qj_lw = query_lw[j]; + if (isSeparator(qj_lw)) { + i = subject_lw.indexOf(qj_lw, i + 1); + if (i > -1) { + sepCount++; + continue; + } else { + break; + } + } + while (++i < m) { + if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) { + if (query[j] === subject[i]) { + sameCase++; + } + sumPos += i; + count++; + break; + } + } + if (i === m) { + break; + } + } + if (count < 2) { + return emptyAcronymResult; + } + fullWord = count === n ? isAcronymFullWord(subject, subject_lw, query, count) : false; + score = scorePattern(count, n, sameCase, true, fullWord); + return new AcronymResult(score, sumPos / count, count + sepCount); + }; + + isAcronymFullWord = function(subject, subject_lw, query, nbAcronymInQuery) { + var count, i, m, n; + m = subject.length; + n = query.length; + count = 0; + if (m > 12 * n) { + return false; + } + i = -1; + while (++i < m) { + if (isWordStart(i, subject, subject_lw) && ++count > nbAcronymInQuery) { + return false; + } + } + return true; + }; + +}).call(this); + + +/***/ }), + +/***/ 164: +/***/ (function(module, exports, __webpack_require__) { + +(function() { + var computeScore, countDir, file_coeff, getExtension, getExtensionScore, isMatch, scorePath, scoreSize, tau_depth, _ref; + + _ref = __webpack_require__(163), isMatch = _ref.isMatch, computeScore = _ref.computeScore, scoreSize = _ref.scoreSize; + + tau_depth = 20; + + file_coeff = 2.5; + + exports.score = function(string, query, options) { + var allowErrors, preparedQuery, score, string_lw; + preparedQuery = options.preparedQuery, allowErrors = options.allowErrors; + if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) { + return 0; + } + string_lw = string.toLowerCase(); + score = computeScore(string, string_lw, preparedQuery); + score = scorePath(string, string_lw, score, options); + return Math.ceil(score); + }; + + scorePath = function(subject, subject_lw, fullPathScore, options) { + var alpha, basePathScore, basePos, depth, end, extAdjust, fileLength, pathSeparator, preparedQuery, useExtensionBonus; + if (fullPathScore === 0) { + return 0; + } + preparedQuery = options.preparedQuery, useExtensionBonus = options.useExtensionBonus, pathSeparator = options.pathSeparator; + end = subject.length - 1; + while (subject[end] === pathSeparator) { + end--; + } + basePos = subject.lastIndexOf(pathSeparator, end); + fileLength = end - basePos; + extAdjust = 1.0; + if (useExtensionBonus) { + extAdjust += getExtensionScore(subject_lw, preparedQuery.ext, basePos, end, 2); + fullPathScore *= extAdjust; + } + if (basePos === -1) { + return fullPathScore; + } + depth = preparedQuery.depth; + while (basePos > -1 && depth-- > 0) { + basePos = subject.lastIndexOf(pathSeparator, basePos - 1); + } + basePathScore = basePos === -1 ? fullPathScore : extAdjust * computeScore(subject.slice(basePos + 1, end + 1), subject_lw.slice(basePos + 1, end + 1), preparedQuery); + alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1, pathSeparator)); + return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, file_coeff * fileLength); + }; + + exports.countDir = countDir = function(path, end, pathSeparator) { + var count, i; + if (end < 1) { + return 0; + } + count = 0; + i = -1; + while (++i < end && path[i] === pathSeparator) { + continue; + } + while (++i < end) { + if (path[i] === pathSeparator) { + count++; + while (++i < end && path[i] === pathSeparator) { + continue; + } + } + } + return count; + }; + + exports.getExtension = getExtension = function(str) { + var pos; + pos = str.lastIndexOf("."); + if (pos < 0) { + return ""; + } else { + return str.substr(pos + 1); + } + }; + + getExtensionScore = function(candidate, ext, startPos, endPos, maxDepth) { + var m, matched, n, pos; + if (!ext.length) { + return 0; + } + pos = candidate.lastIndexOf(".", endPos); + if (!(pos > startPos)) { + return 0; + } + n = ext.length; + m = endPos - pos; + if (m < n) { + n = m; + m = ext.length; + } + pos++; + matched = -1; + while (++matched < n) { + if (candidate[pos + matched] !== ext[matched]) { + break; + } + } + if (matched === 0 && maxDepth > 0) { + return 0.9 * getExtensionScore(candidate, ext, startPos, pos - 2, maxDepth - 1); + } + return matched / m; + }; + +}).call(this); + + +/***/ }), + +/***/ 1648: +/***/ (function(module, exports) { + +module.exports = "image/svg+xml" + +/***/ }), + +/***/ 1649: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 165: +/***/ (function(module, exports, __webpack_require__) { + +(function() { + var Query, coreChars, countDir, getCharCodes, getExtension, opt_char_re, truncatedUpperCase, _ref; + + _ref = __webpack_require__(164), countDir = _ref.countDir, getExtension = _ref.getExtension; + + module.exports = Query = (function() { + function Query(query, _arg) { + var optCharRegEx, pathSeparator, _ref1; + _ref1 = _arg != null ? _arg : {}, optCharRegEx = _ref1.optCharRegEx, pathSeparator = _ref1.pathSeparator; + if (!(query && query.length)) { + return null; + } + this.query = query; + this.query_lw = query.toLowerCase(); + this.core = coreChars(query, optCharRegEx); + this.core_lw = this.core.toLowerCase(); + this.core_up = truncatedUpperCase(this.core); + this.depth = countDir(query, query.length, pathSeparator); + this.ext = getExtension(this.query_lw); + this.charCodes = getCharCodes(this.query_lw); + } + + return Query; + + })(); + + opt_char_re = /[ _\-:\/\\]/g; + + coreChars = function(query, optCharRegEx) { + if (optCharRegEx == null) { + optCharRegEx = opt_char_re; + } + return query.replace(optCharRegEx, ''); + }; + + truncatedUpperCase = function(str) { + var char, upper, _i, _len; + upper = ""; + for (_i = 0, _len = str.length; _i < _len; _i++) { + char = str[_i]; + upper += char.toUpperCase()[0]; + } + return upper; + }; + + getCharCodes = function(str) { + var charCodes, i, len; + len = str.length; + i = -1; + charCodes = []; + while (++i < len) { + charCodes[str.charCodeAt(i)] = true; + } + return charCodes; + }; + +}).call(this); + + +/***/ }), + +/***/ 1650: +/***/ (function(module, exports) { + +module.exports = "Zeit - Black on white logo" + +/***/ }), + +/***/ 1651: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 166: +/***/ (function(module, exports, __webpack_require__) { + +(function() { + var basenameMatch, computeMatch, isMatch, isWordStart, match, mergeMatches, scoreAcronyms, scoreCharacter, scoreConsecutives, _ref; + + _ref = __webpack_require__(163), isMatch = _ref.isMatch, isWordStart = _ref.isWordStart, scoreConsecutives = _ref.scoreConsecutives, scoreCharacter = _ref.scoreCharacter, scoreAcronyms = _ref.scoreAcronyms; + + exports.match = match = function(string, query, options) { + var allowErrors, baseMatches, matches, pathSeparator, preparedQuery, string_lw; + allowErrors = options.allowErrors, preparedQuery = options.preparedQuery, pathSeparator = options.pathSeparator; + if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) { + return []; + } + string_lw = string.toLowerCase(); + matches = computeMatch(string, string_lw, preparedQuery); + if (matches.length === 0) { + return matches; + } + if (string.indexOf(pathSeparator) > -1) { + baseMatches = basenameMatch(string, string_lw, preparedQuery, pathSeparator); + matches = mergeMatches(matches, baseMatches); + } + return matches; + }; + + exports.wrap = function(string, query, options) { + var matchIndex, matchPos, matchPositions, output, strPos, tagClass, tagClose, tagOpen, _ref1; + if ((options.wrap != null)) { + _ref1 = options.wrap, tagClass = _ref1.tagClass, tagOpen = _ref1.tagOpen, tagClose = _ref1.tagClose; + } + if (tagClass == null) { + tagClass = 'highlight'; + } + if (tagOpen == null) { + tagOpen = ''; + } + if (tagClose == null) { + tagClose = ''; + } + if (string === query) { + return tagOpen + string + tagClose; + } + matchPositions = match(string, query, options); + if (matchPositions.length === 0) { + return string; + } + output = ''; + matchIndex = -1; + strPos = 0; + while (++matchIndex < matchPositions.length) { + matchPos = matchPositions[matchIndex]; + if (matchPos > strPos) { + output += string.substring(strPos, matchPos); + strPos = matchPos; + } + while (++matchIndex < matchPositions.length) { + if (matchPositions[matchIndex] === matchPos + 1) { + matchPos++; + } else { + matchIndex--; + break; + } + } + matchPos++; + if (matchPos > strPos) { + output += tagOpen; + output += string.substring(strPos, matchPos); + output += tagClose; + strPos = matchPos; + } + } + if (strPos <= string.length - 1) { + output += string.substring(strPos); + } + return output; + }; + + basenameMatch = function(subject, subject_lw, preparedQuery, pathSeparator) { + var basePos, depth, end; + end = subject.length - 1; + while (subject[end] === pathSeparator) { + end--; + } + basePos = subject.lastIndexOf(pathSeparator, end); + if (basePos === -1) { + return []; + } + depth = preparedQuery.depth; + while (depth-- > 0) { + basePos = subject.lastIndexOf(pathSeparator, basePos - 1); + if (basePos === -1) { + return []; + } + } + basePos++; + end++; + return computeMatch(subject.slice(basePos, end), subject_lw.slice(basePos, end), preparedQuery, basePos); + }; + + mergeMatches = function(a, b) { + var ai, bj, i, j, m, n, out; + m = a.length; + n = b.length; + if (n === 0) { + return a.slice(); + } + if (m === 0) { + return b.slice(); + } + i = -1; + j = 0; + bj = b[j]; + out = []; + while (++i < m) { + ai = a[i]; + while (bj <= ai && ++j < n) { + if (bj < ai) { + out.push(bj); + } + bj = b[j]; + } + out.push(ai); + } + while (j < n) { + out.push(b[j++]); + } + return out; + }; + + computeMatch = function(subject, subject_lw, preparedQuery, offset) { + var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, score_diag, score_row, score_up, si_lw, start, trace; + if (offset == null) { + offset = 0; + } + query = preparedQuery.query; + query_lw = preparedQuery.query_lw; + m = subject.length; + n = query.length; + acro_score = scoreAcronyms(subject, subject_lw, query, query_lw).score; + score_row = new Array(n); + csc_row = new Array(n); + STOP = 0; + UP = 1; + LEFT = 2; + DIAGONAL = 3; + trace = new Array(m * n); + pos = -1; + j = -1; + while (++j < n) { + score_row[j] = 0; + csc_row[j] = 0; + } + i = -1; + while (++i < m) { + score = 0; + score_up = 0; + csc_diag = 0; + si_lw = subject_lw[i]; + j = -1; + while (++j < n) { + csc_score = 0; + align = 0; + score_diag = score_up; + if (query_lw[j] === si_lw) { + start = isWordStart(i, subject, subject_lw); + csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); + align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score); + } + score_up = score_row[j]; + csc_diag = csc_row[j]; + if (score > score_up) { + move = LEFT; + } else { + score = score_up; + move = UP; + } + if (align > score) { + score = align; + move = DIAGONAL; + } else { + csc_score = 0; + } + score_row[j] = score; + csc_row[j] = csc_score; + trace[++pos] = score > 0 ? move : STOP; + } + } + i = m - 1; + j = n - 1; + pos = i * n + j; + backtrack = true; + matches = []; + while (backtrack && i >= 0 && j >= 0) { + switch (trace[pos]) { + case UP: + i--; + pos -= n; + break; + case LEFT: + j--; + pos--; + break; + case DIAGONAL: + matches.push(i + offset); + j--; + i--; + pos -= n + 1; + break; + default: + backtrack = false; + } + } + matches.reverse(); + return matches; + }; + +}).call(this); + + +/***/ }), + +/***/ 1733: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 175: +/***/ (function(module, exports, __webpack_require__) { + +var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +/* global define */ + +(function () { + 'use strict'; + + var hasOwn = {}.hasOwnProperty; + + function classNames () { + var classes = []; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + + var argType = typeof arg; + + if (argType === 'string' || argType === 'number') { + classes.push(arg); + } else if (Array.isArray(arg)) { + classes.push(classNames.apply(null, arg)); + } else if (argType === 'object') { + for (var key in arg) { + if (hasOwn.call(arg, key) && arg[key]) { + classes.push(key); + } + } + } + } + + return classes.join(' '); + } + + if (typeof module !== 'undefined' && module.exports) { + module.exports = classNames; + } else if (true) { + // register as 'classnames', consistent with npm package name + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () { + return classNames; + }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else { + window.classNames = classNames; + } +}()); + + +/***/ }), + +/***/ 1763: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(3642); + +var _util = __webpack_require__(1777); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var process = process || { env: {} }; + +var InlineSVG = function (_React$Component) { + _inherits(InlineSVG, _React$Component); + + function InlineSVG() { + _classCallCheck(this, InlineSVG); + + return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments)); + } + + _createClass(InlineSVG, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(_ref) { + var children = _ref.children; + + if ("production" !== process.env.NODE_ENV && children != null) { + console.info(': `children` prop will be ignored.'); + } + } + }, { + key: 'render', + value: function render() { + var Element = void 0, + __html = void 0, + svgProps = void 0; + + var _props = this.props, + element = _props.element, + raw = _props.raw, + src = _props.src, + otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']); + + if (raw === true) { + Element = 'svg'; + svgProps = (0, _util.extractSVGProps)(src); + __html = (0, _util.getSVGFromSource)(src).innerHTML; + } + __html = __html || src; + Element = Element || element; + svgProps = svgProps || {}; + + return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null, + dangerouslySetInnerHTML: { __html: __html } })); + } + }]); + + return InlineSVG; +}(_react2.default.Component); + +exports.default = InlineSVG; + + +InlineSVG.defaultProps = { + element: 'i', + raw: false, + src: '' +}; + +InlineSVG.propTypes = { + src: _propTypes.string.isRequired, + element: _propTypes.string, + raw: _propTypes.bool +}; + +/***/ }), + +/***/ 1777: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.convertReactSVGDOMProperty = convertReactSVGDOMProperty; +exports.startsWith = startsWith; +exports.serializeAttrs = serializeAttrs; +exports.getSVGFromSource = getSVGFromSource; +exports.extractSVGProps = extractSVGProps; +// Transform DOM prop/attr names applicable to `` element but react-limited + +function convertReactSVGDOMProperty(str) { + return str.replace(/[-|:]([a-z])/g, function (g) { + return g[1].toUpperCase(); + }); +} + +function startsWith(str, substring) { + return str.indexOf(substring) === 0; +} + +var DataPropPrefix = 'data-'; +// Serialize `Attr` objects in `NamedNodeMap` +function serializeAttrs(map) { + var ret = {}; + for (var prop, i = 0; i < map.length; i++) { + var key = map[i].name; + if (!startsWith(key, DataPropPrefix)) { + prop = convertReactSVGDOMProperty(key); + } + ret[prop] = map[i].value; + } + return ret; +} + +function getSVGFromSource(src) { + var svgContainer = document.createElement('div'); + svgContainer.innerHTML = src; + var svg = svgContainer.firstElementChild; + svg.remove(); // deref from parent element + return svg; +} + +// get element props +function extractSVGProps(src) { + var map = getSVGFromSource(src).attributes; + return map.length > 0 ? serializeAttrs(map) : null; +} + +/***/ }), + +/***/ 1808: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 22: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_22__; + +/***/ }), + +/***/ 2250: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 2251: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 2252: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 247: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 256: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 258: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 333: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; +exports.EXITING = exports.ENTERED = exports.ENTERING = exports.EXITED = exports.UNMOUNTED = undefined; + +var _propTypes = __webpack_require__(3642); + +var PropTypes = _interopRequireWildcard(_propTypes); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = __webpack_require__(4); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _PropTypes = __webpack_require__(335); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var UNMOUNTED = exports.UNMOUNTED = 'unmounted'; +var EXITED = exports.EXITED = 'exited'; +var ENTERING = exports.ENTERING = 'entering'; +var ENTERED = exports.ENTERED = 'entered'; +var EXITING = exports.EXITING = 'exiting'; + +/** + * The Transition component lets you describe a transition from one component + * state to another _over time_ with a simple declarative API. Most commonly + * it's used to animate the mounting and unmounting of a component, but can also + * be used to describe in-place transition states as well. + * + * By default the `Transition` component does not alter the behavior of the + * component it renders, it only tracks "enter" and "exit" states for the components. + * It's up to you to give meaning and effect to those states. For example we can + * add styles to a component when it enters or exits: + * + * ```jsx + * import Transition from 'react-transition-group/Transition'; + * + * const duration = 300; + * + * const defaultStyle = { + * transition: `opacity ${duration}ms ease-in-out`, + * opacity: 0, + * } + * + * const transitionStyles = { + * entering: { opacity: 0 }, + * entered: { opacity: 1 }, + * }; + * + * const Fade = ({ in: inProp }) => ( + * + * {(state) => ( + *
+ * I'm a fade Transition! + *
+ * )} + *
+ * ); + * ``` + * + * As noted the `Transition` component doesn't _do_ anything by itself to its child component. + * What it does do is track transition states over time so you can update the + * component (such as by adding styles or classes) when it changes states. + * + * There are 4 main states a Transition can be in: + * - `'entering'` + * - `'entered'` + * - `'exiting'` + * - `'exited'` + * + * Transition state is toggled via the `in` prop. When `true` the component begins the + * "Enter" stage. During this stage, the component will shift from its current transition state, + * to `'entering'` for the duration of the transition and then to the `'entered'` stage once + * it's complete. Let's take the following example: + * + * ```jsx + * state = { in: false }; + * + * toggleEnterState = () => { + * this.setState({ in: true }); + * } + * + * render() { + * return ( + *
+ * + * + *
+ * ); + * } + * ``` + * + * When the button is clicked the component will shift to the `'entering'` state and + * stay there for 500ms (the value of `timeout`) before it finally switches to `'entered'`. + * + * When `in` is `false` the same thing happens except the state moves from `'exiting'` to `'exited'`. + * + * ## Timing + * + * Timing is often the trickiest part of animation, mistakes can result in slight delays + * that are hard to pin down. A common example is when you want to add an exit transition, + * you should set the desired final styles when the state is `'exiting'`. That's when the + * transition to those styles will start and, if you matched the `timeout` prop with the + * CSS Transition duration, it will end exactly when the state changes to `'exited'`. + * + * > **Note**: For simpler transitions the `Transition` component might be enough, but + * > take into account that it's platform-agnostic, while the `CSSTransition` component + * > [forces reflows](https://github.com/reactjs/react-transition-group/blob/5007303e729a74be66a21c3e2205e4916821524b/src/CSSTransition.js#L208-L215) + * > in order to make more complex transitions more predictable. For example, even though + * > classes `example-enter` and `example-enter-active` are applied immediately one after + * > another, you can still transition from one to the other because of the forced reflow + * > (read [this issue](https://github.com/reactjs/react-transition-group/issues/159#issuecomment-322761171) + * > for more info). Take this into account when choosing between `Transition` and + * > `CSSTransition`. + * + * ## Example + * + * + * + */ + +var Transition = function (_React$Component) { + _inherits(Transition, _React$Component); + + function Transition(props, context) { + _classCallCheck(this, Transition); + + var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context)); + + var parentGroup = context.transitionGroup; + // In the context of a TransitionGroup all enters are really appears + var appear = parentGroup && !parentGroup.isMounting ? props.enter : props.appear; + + var initialStatus = void 0; + _this.nextStatus = null; + + if (props.in) { + if (appear) { + initialStatus = EXITED; + _this.nextStatus = ENTERING; + } else { + initialStatus = ENTERED; + } + } else { + if (props.unmountOnExit || props.mountOnEnter) { + initialStatus = UNMOUNTED; + } else { + initialStatus = EXITED; + } + } + + _this.state = { status: initialStatus }; + + _this.nextCallback = null; + return _this; + } + + Transition.prototype.getChildContext = function getChildContext() { + return { transitionGroup: null }; // allows for nested Transitions + }; + + Transition.prototype.componentDidMount = function componentDidMount() { + this.updateStatus(true); + }; + + Transition.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { + var _ref = this.pendingState || this.state, + status = _ref.status; + + if (nextProps.in) { + if (status === UNMOUNTED) { + this.setState({ status: EXITED }); + } + if (status !== ENTERING && status !== ENTERED) { + this.nextStatus = ENTERING; + } + } else { + if (status === ENTERING || status === ENTERED) { + this.nextStatus = EXITING; + } + } + }; + + Transition.prototype.componentDidUpdate = function componentDidUpdate() { + this.updateStatus(); + }; + + Transition.prototype.componentWillUnmount = function componentWillUnmount() { + this.cancelNextCallback(); + }; + + Transition.prototype.getTimeouts = function getTimeouts() { + var timeout = this.props.timeout; + + var exit = void 0, + enter = void 0, + appear = void 0; + + exit = enter = appear = timeout; + + if (timeout != null && typeof timeout !== 'number') { + exit = timeout.exit; + enter = timeout.enter; + appear = timeout.appear; + } + return { exit: exit, enter: enter, appear: appear }; + }; + + Transition.prototype.updateStatus = function updateStatus() { + var mounting = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + var nextStatus = this.nextStatus; + + if (nextStatus !== null) { + this.nextStatus = null; + // nextStatus will always be ENTERING or EXITING. + this.cancelNextCallback(); + var node = _reactDom2.default.findDOMNode(this); + + if (nextStatus === ENTERING) { + this.performEnter(node, mounting); + } else { + this.performExit(node); + } + } else if (this.props.unmountOnExit && this.state.status === EXITED) { + this.setState({ status: UNMOUNTED }); + } + }; + + Transition.prototype.performEnter = function performEnter(node, mounting) { + var _this2 = this; + + var enter = this.props.enter; + + var appearing = this.context.transitionGroup ? this.context.transitionGroup.isMounting : mounting; + + var timeouts = this.getTimeouts(); + + // no enter animation skip right to ENTERED + // if we are mounting and running this it means appear _must_ be set + if (!mounting && !enter) { + this.safeSetState({ status: ENTERED }, function () { + _this2.props.onEntered(node); + }); + return; + } + + this.props.onEnter(node, appearing); + + this.safeSetState({ status: ENTERING }, function () { + _this2.props.onEntering(node, appearing); + + // FIXME: appear timeout? + _this2.onTransitionEnd(node, timeouts.enter, function () { + _this2.safeSetState({ status: ENTERED }, function () { + _this2.props.onEntered(node, appearing); + }); + }); + }); + }; + + Transition.prototype.performExit = function performExit(node) { + var _this3 = this; + + var exit = this.props.exit; + + var timeouts = this.getTimeouts(); + + // no exit animation skip right to EXITED + if (!exit) { + this.safeSetState({ status: EXITED }, function () { + _this3.props.onExited(node); + }); + return; + } + this.props.onExit(node); + + this.safeSetState({ status: EXITING }, function () { + _this3.props.onExiting(node); + + _this3.onTransitionEnd(node, timeouts.exit, function () { + _this3.safeSetState({ status: EXITED }, function () { + _this3.props.onExited(node); + }); + }); + }); + }; + + Transition.prototype.cancelNextCallback = function cancelNextCallback() { + if (this.nextCallback !== null) { + this.nextCallback.cancel(); + this.nextCallback = null; + } + }; + + Transition.prototype.safeSetState = function safeSetState(nextState, callback) { + var _this4 = this; + + // We need to track pending updates for instances where a cWRP fires quickly + // after cDM and before the state flushes, which would double trigger a + // transition + this.pendingState = nextState; + + // This shouldn't be necessary, but there are weird race conditions with + // setState callbacks and unmounting in testing, so always make sure that + // we can cancel any pending setState callbacks after we unmount. + callback = this.setNextCallback(callback); + this.setState(nextState, function () { + _this4.pendingState = null; + callback(); + }); + }; + + Transition.prototype.setNextCallback = function setNextCallback(callback) { + var _this5 = this; + + var active = true; + + this.nextCallback = function (event) { + if (active) { + active = false; + _this5.nextCallback = null; + + callback(event); + } + }; + + this.nextCallback.cancel = function () { + active = false; + }; + + return this.nextCallback; + }; + + Transition.prototype.onTransitionEnd = function onTransitionEnd(node, timeout, handler) { + this.setNextCallback(handler); + + if (node) { + if (this.props.addEndListener) { + this.props.addEndListener(node, this.nextCallback); + } + if (timeout != null) { + setTimeout(this.nextCallback, timeout); + } + } else { + setTimeout(this.nextCallback, 0); + } + }; + + Transition.prototype.render = function render() { + var status = this.state.status; + if (status === UNMOUNTED) { + return null; + } + + var _props = this.props, + children = _props.children, + childProps = _objectWithoutProperties(_props, ['children']); + // filter props for Transtition + + + delete childProps.in; + delete childProps.mountOnEnter; + delete childProps.unmountOnExit; + delete childProps.appear; + delete childProps.enter; + delete childProps.exit; + delete childProps.timeout; + delete childProps.addEndListener; + delete childProps.onEnter; + delete childProps.onEntering; + delete childProps.onEntered; + delete childProps.onExit; + delete childProps.onExiting; + delete childProps.onExited; + + if (typeof children === 'function') { + return children(status, childProps); + } + + var child = _react2.default.Children.only(children); + return _react2.default.cloneElement(child, childProps); + }; + + return Transition; +}(_react2.default.Component); + +Transition.contextTypes = { + transitionGroup: PropTypes.object +}; +Transition.childContextTypes = { + transitionGroup: function transitionGroup() {} +}; + + +Transition.propTypes = false ? { + /** + * A `function` child can be used instead of a React element. + * This function is called with the current transition status + * ('entering', 'entered', 'exiting', 'exited', 'unmounted'), which can be used + * to apply context specific props to a component. + * + * ```jsx + * + * {(status) => ( + * + * )} + * + * ``` + */ + children: PropTypes.oneOfType([PropTypes.func.isRequired, PropTypes.element.isRequired]).isRequired, + + /** + * Show the component; triggers the enter or exit states + */ + in: PropTypes.bool, + + /** + * By default the child component is mounted immediately along with + * the parent `Transition` component. If you want to "lazy mount" the component on the + * first `in={true}` you can set `mountOnEnter`. After the first enter transition the component will stay + * mounted, even on "exited", unless you also specify `unmountOnExit`. + */ + mountOnEnter: PropTypes.bool, + + /** + * By default the child component stays mounted after it reaches the `'exited'` state. + * Set `unmountOnExit` if you'd prefer to unmount the component after it finishes exiting. + */ + unmountOnExit: PropTypes.bool, + + /** + * Normally a component is not transitioned if it is shown when the `` component mounts. + * If you want to transition on the first mount set `appear` to `true`, and the + * component will transition in as soon as the `` mounts. + * + * > Note: there are no specific "appear" states. `appear` only adds an additional `enter` transition. + */ + appear: PropTypes.bool, + + /** + * Enable or disable enter transitions. + */ + enter: PropTypes.bool, + + /** + * Enable or disable exit transitions. + */ + exit: PropTypes.bool, + + /** + * The duration of the transition, in milliseconds. + * Required unless `addEndListener` is provided + * + * You may specify a single timeout for all transitions like: `timeout={500}`, + * or individually like: + * + * ```jsx + * timeout={{ + * enter: 300, + * exit: 500, + * }} + * ``` + * + * @type {number | { enter?: number, exit?: number }} + */ + timeout: function timeout(props) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var pt = _PropTypes.timeoutsShape; + if (!props.addEndListener) pt = pt.isRequired; + return pt.apply(undefined, [props].concat(args)); + }, + + /** + * Add a custom transition end trigger. Called with the transitioning + * DOM node and a `done` callback. Allows for more fine grained transition end + * logic. **Note:** Timeouts are still used as a fallback if provided. + * + * ```jsx + * addEndListener={(node, done) => { + * // use the css transitionend event to mark the finish of a transition + * node.addEventListener('transitionend', done, false); + * }} + * ``` + */ + addEndListener: PropTypes.func, + + /** + * Callback fired before the "entering" status is applied. An extra parameter + * `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount + * + * @type Function(node: HtmlElement, isAppearing: bool) -> void + */ + onEnter: PropTypes.func, + + /** + * Callback fired after the "entering" status is applied. An extra parameter + * `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount + * + * @type Function(node: HtmlElement, isAppearing: bool) + */ + onEntering: PropTypes.func, + + /** + * Callback fired after the "entered" status is applied. An extra parameter + * `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount + * + * @type Function(node: HtmlElement, isAppearing: bool) -> void + */ + onEntered: PropTypes.func, + + /** + * Callback fired before the "exiting" status is applied. + * + * @type Function(node: HtmlElement) -> void + */ + onExit: PropTypes.func, + + /** + * Callback fired after the "exiting" status is applied. + * + * @type Function(node: HtmlElement) -> void + */ + onExiting: PropTypes.func, + + /** + * Callback fired after the "exited" status is applied. + * + * @type Function(node: HtmlElement) -> void + */ + onExited: PropTypes.func +} : {}; + +// Name the function so it is clearer in the documentation +function noop() {} + +Transition.defaultProps = { + in: false, + mountOnEnter: false, + unmountOnExit: false, + appear: false, + enter: true, + exit: true, + + onEnter: noop, + onEntering: noop, + onEntered: noop, + + onExit: noop, + onExiting: noop, + onExited: noop +}; + +Transition.UNMOUNTED = 0; +Transition.EXITED = 1; +Transition.ENTERING = 2; +Transition.ENTERED = 3; +Transition.EXITING = 4; + +exports.default = Transition; + +/***/ }), + +/***/ 334: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var punycode = __webpack_require__(3641); +var util = __webpack_require__(336); + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; + +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} + +// Reference: RFC 3986, RFC 1808, RFC 2396 + +// define these here so at least they only have to be +// compiled once on the first module load. +var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // Special case for a simple path URL + simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = __webpack_require__(66); + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && util.isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} + +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!util.isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + var queryIndex = url.indexOf('?'), + splitter = + (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', + uSplit = url.split(splitter), + slashRegex = /\\/g; + uSplit[0] = uSplit[0].replace(slashRegex, '/'); + url = uSplit.join(splitter); + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + if (!slashesDenoteHost && url.split('#').length === 1) { + // Try fast path regexp + var simplePath = simplePathPattern.exec(rest); + if (simplePath) { + this.path = rest; + this.href = rest; + this.pathname = simplePath[1]; + if (simplePath[2]) { + this.search = simplePath[2]; + if (parseQueryString) { + this.query = querystring.parse(this.search.substr(1)); + } else { + this.query = this.search.substr(1); + } + } else if (parseQueryString) { + this.search = ''; + this.query = {}; + } + return this; + } + } + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a punycoded representation of "domain". + // It only converts parts of the domain name that + // have non-ASCII characters, i.e. it doesn't matter if + // you call it with a domain that already is ASCII-only. + this.hostname = punycode.toASCII(this.hostname); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + if (rest.indexOf(ae) === -1) + continue; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; +}; + +// format a parsed object into a url string +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (util.isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); +} + +Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + util.isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; +}; + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} + +Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} + +Url.prototype.resolveObject = function(relative) { + if (util.isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + var tkeys = Object.keys(this); + for (var tk = 0; tk < tkeys.length; tk++) { + var tkey = tkeys[tk]; + result[tkey] = this[tkey]; + } + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + var rkeys = Object.keys(relative); + for (var rk = 0; rk < rkeys.length; rk++) { + var rkey = rkeys[rk]; + if (rkey !== 'protocol') + result[rkey] = relative[rkey]; + } + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + var keys = Object.keys(relative); + for (var v = 0; v < keys.length; v++) { + var k = keys[v]; + result[k] = relative[k]; + } + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!util.isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!util.isNull(result.pathname) || !util.isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host || srcPath.length > 1) && + (last === '.' || last === '..') || last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last === '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!util.isNull(result.pathname) || !util.isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; + +Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; +}; + + +/***/ }), + +/***/ 335: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; +exports.classNamesShape = exports.timeoutsShape = undefined; +exports.transitionTimeout = transitionTimeout; + +var _propTypes = __webpack_require__(3642); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function transitionTimeout(transitionType) { + var timeoutPropName = 'transition' + transitionType + 'Timeout'; + var enabledPropName = 'transition' + transitionType; + + return function (props) { + // If the transition is enabled + if (props[enabledPropName]) { + // If no timeout duration is provided + if (props[timeoutPropName] == null) { + return new Error(timeoutPropName + ' wasn\'t supplied to CSSTransitionGroup: ' + 'this can cause unreliable animations and won\'t be supported in ' + 'a future version of React. See ' + 'https://fb.me/react-animation-transition-group-timeout for more ' + 'information.'); + + // If the duration isn't a number + } else if (typeof props[timeoutPropName] !== 'number') { + return new Error(timeoutPropName + ' must be a number (in milliseconds)'); + } + } + + return null; + }; +} + +var timeoutsShape = exports.timeoutsShape = _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.shape({ + enter: _propTypes2.default.number, + exit: _propTypes2.default.number +}).isRequired]); + +var classNamesShape = exports.classNamesShape = _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.shape({ + enter: _propTypes2.default.string, + exit: _propTypes2.default.string, + active: _propTypes2.default.string +}), _propTypes2.default.shape({ + enter: _propTypes2.default.string, + enterDone: _propTypes2.default.string, + enterActive: _propTypes2.default.string, + exit: _propTypes2.default.string, + exitDone: _propTypes2.default.string, + exitActive: _propTypes2.default.string +})]); + +/***/ }), + +/***/ 336: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = { + isString: function(arg) { + return typeof(arg) === 'string'; + }, + isObject: function(arg) { + return typeof(arg) === 'object' && arg !== null; + }, + isNull: function(arg) { + return arg === null; + }, + isNullOrUndefined: function(arg) { + return arg == null; + } +}; + + +/***/ }), + +/***/ 347: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 348: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 349: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 350: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 351: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 352: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 353: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 354: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 355: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 356: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 357: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 358: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 359: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3595: +/***/ (function(module, exports) { + +module.exports = " Created by potrace 1.11, written by Peter Selinger 2001-2013 " + +/***/ }), + +/***/ 360: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3603: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3604: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 361: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 362: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 363: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3631: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3632: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3637: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// TODO : Localize this (was l10n.getStr("frame.unknownSource")) +const UNKNOWN_SOURCE_STRING = "(unknown)"; + +// Character codes used in various parsing helper functions. +const CHAR_CODE_A = "a".charCodeAt(0); +const CHAR_CODE_B = "b".charCodeAt(0); +const CHAR_CODE_C = "c".charCodeAt(0); +const CHAR_CODE_D = "d".charCodeAt(0); +const CHAR_CODE_E = "e".charCodeAt(0); +const CHAR_CODE_F = "f".charCodeAt(0); +const CHAR_CODE_H = "h".charCodeAt(0); +const CHAR_CODE_I = "i".charCodeAt(0); +const CHAR_CODE_J = "j".charCodeAt(0); +const CHAR_CODE_L = "l".charCodeAt(0); +const CHAR_CODE_M = "m".charCodeAt(0); +const CHAR_CODE_N = "n".charCodeAt(0); +const CHAR_CODE_O = "o".charCodeAt(0); +const CHAR_CODE_P = "p".charCodeAt(0); +const CHAR_CODE_R = "r".charCodeAt(0); +const CHAR_CODE_S = "s".charCodeAt(0); +const CHAR_CODE_T = "t".charCodeAt(0); +const CHAR_CODE_U = "u".charCodeAt(0); +const CHAR_CODE_W = "w".charCodeAt(0); +const CHAR_CODE_COLON = ":".charCodeAt(0); +const CHAR_CODE_DASH = "-".charCodeAt(0); +const CHAR_CODE_L_SQUARE_BRACKET = "[".charCodeAt(0); +const CHAR_CODE_SLASH = "/".charCodeAt(0); +const CHAR_CODE_CAP_S = "S".charCodeAt(0); + +// The cache used in the `parseURL` function. +const gURLStore = new Map(); +// The cache used in the `getSourceNames` function. +const gSourceNamesStore = new Map(); + +/** +* Takes a string and returns an object containing all the properties +* available on an URL instance, with additional properties (fileName), +* Leverages caching. +* +* @param {String} location +* @return {Object?} An object containing most properties available +* in https://developer.mozilla.org/en-US/docs/Web/API/URL +*/ + +function parseURL(location) { + let url = gURLStore.get(location); + + if (url !== void 0) { + return url; + } + + try { + url = new URL(location); + // The callers were generally written to expect a URL from + // sdk/url, which is subtly different. So, work around some + // important differences here. + url = { + href: url.href, + protocol: url.protocol, + host: url.host, + hostname: url.hostname, + port: url.port || null, + pathname: url.pathname, + search: url.search, + hash: url.hash, + username: url.username, + password: url.password, + origin: url.origin + }; + + // Definitions: + // Example: https://foo.com:8888/file.js + // `hostname`: "foo.com" + // `host`: "foo.com:8888" + let isChrome = isChromeScheme(location); + + url.fileName = url.pathname ? url.pathname.slice(url.pathname.lastIndexOf("/") + 1) || "/" : "/"; + + if (isChrome) { + url.hostname = null; + url.host = null; + } + + gURLStore.set(location, url); + return url; + } catch (e) { + gURLStore.set(location, null); + return null; + } +} + +/** +* Parse a source into a short and long name as well as a host name. +* +* @param {String} source +* The source to parse. Can be a URI or names like "(eval)" or +* "self-hosted". +* @return {Object} +* An object with the following properties: +* - {String} short: A short name for the source. +* - "http://page.com/test.js#go?q=query" -> "test.js" +* - {String} long: The full, long name for the source, with + hash/query stripped. +* - "http://page.com/test.js#go?q=query" -> "http://page.com/test.js" +* - {String?} host: If available, the host name for the source. +* - "http://page.com/test.js#go?q=query" -> "page.com" +*/ +function getSourceNames(source) { + let data = gSourceNamesStore.get(source); + + if (data) { + return data; + } + + let short, long, host; + const sourceStr = source ? String(source) : ""; + + // If `data:...` uri + if (isDataScheme(sourceStr)) { + let commaIndex = sourceStr.indexOf(","); + if (commaIndex > -1) { + // The `short` name for a data URI becomes `data:` followed by the actual + // encoded content, omitting the MIME type, and charset. + short = `data:${sourceStr.substring(commaIndex + 1)}`.slice(0, 100); + let result = { short, long: sourceStr }; + gSourceNamesStore.set(source, result); + return result; + } + } + + // If Scratchpad URI, like "Scratchpad/1"; no modifications, + // and short/long are the same. + if (isScratchpadScheme(sourceStr)) { + let result = { short: sourceStr, long: sourceStr }; + gSourceNamesStore.set(source, result); + return result; + } + + const parsedUrl = parseURL(sourceStr); + + if (!parsedUrl) { + // Malformed URI. + long = sourceStr; + short = sourceStr.slice(0, 100); + } else { + host = parsedUrl.host; + + long = parsedUrl.href; + if (parsedUrl.hash) { + long = long.replace(parsedUrl.hash, ""); + } + if (parsedUrl.search) { + long = long.replace(parsedUrl.search, ""); + } + + short = parsedUrl.fileName; + // If `short` is just a slash, and we actually have a path, + // strip the slash and parse again to get a more useful short name. + // e.g. "http://foo.com/bar/" -> "bar", rather than "/" + if (short === "/" && parsedUrl.pathname !== "/") { + short = parseURL(long.replace(/\/$/, "")).fileName; + } + } + + if (!short) { + if (!long) { + long = UNKNOWN_SOURCE_STRING; + } + short = long.slice(0, 100); + } + + let result = { short, long, host }; + gSourceNamesStore.set(source, result); + return result; +} + +// For the functions below, we assume that we will never access the location +// argument out of bounds, which is indeed the vast majority of cases. +// +// They are written this way because they are hot. Each frame is checked for +// being content or chrome when processing the profile. + +function isColonSlashSlash(location, i = 0) { + return location.charCodeAt(++i) === CHAR_CODE_COLON && location.charCodeAt(++i) === CHAR_CODE_SLASH && location.charCodeAt(++i) === CHAR_CODE_SLASH; +} + +/** +* Checks for a Scratchpad URI, like "Scratchpad/1" +*/ +function isScratchpadScheme(location, i = 0) { + return location.charCodeAt(i) === CHAR_CODE_CAP_S && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_H && location.charCodeAt(++i) === CHAR_CODE_P && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_D && location.charCodeAt(++i) === CHAR_CODE_SLASH; +} + +function isDataScheme(location, i = 0) { + return location.charCodeAt(i) === CHAR_CODE_D && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_COLON; +} + +function isContentScheme(location, i = 0) { + let firstChar = location.charCodeAt(i); + + switch (firstChar) { + // "http://" or "https://" + case CHAR_CODE_H: + if (location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_P) { + if (location.charCodeAt(i + 1) === CHAR_CODE_S) { + ++i; + } + return isColonSlashSlash(location, i); + } + return false; + + // "file://" + case CHAR_CODE_F: + if (location.charCodeAt(++i) === CHAR_CODE_I && location.charCodeAt(++i) === CHAR_CODE_L && location.charCodeAt(++i) === CHAR_CODE_E) { + return isColonSlashSlash(location, i); + } + return false; + + // "app://" + case CHAR_CODE_A: + if (location.charCodeAt(++i) == CHAR_CODE_P && location.charCodeAt(++i) == CHAR_CODE_P) { + return isColonSlashSlash(location, i); + } + return false; + + // "blob:" + case CHAR_CODE_B: + if (location.charCodeAt(++i) == CHAR_CODE_L && location.charCodeAt(++i) == CHAR_CODE_O && location.charCodeAt(++i) == CHAR_CODE_B && location.charCodeAt(++i) == CHAR_CODE_COLON) { + return isContentScheme(location, i + 1); + } + return false; + + default: + return false; + } +} + +function isChromeScheme(location, i = 0) { + let firstChar = location.charCodeAt(i); + + switch (firstChar) { + // "chrome://" + case CHAR_CODE_C: + if (location.charCodeAt(++i) === CHAR_CODE_H && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_O && location.charCodeAt(++i) === CHAR_CODE_M && location.charCodeAt(++i) === CHAR_CODE_E) { + return isColonSlashSlash(location, i); + } + return false; + + // "resource://" + case CHAR_CODE_R: + if (location.charCodeAt(++i) === CHAR_CODE_E && location.charCodeAt(++i) === CHAR_CODE_S && location.charCodeAt(++i) === CHAR_CODE_O && location.charCodeAt(++i) === CHAR_CODE_U && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_E) { + return isColonSlashSlash(location, i); + } + return false; + + // "jar:file://" + case CHAR_CODE_J: + if (location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_R && location.charCodeAt(++i) === CHAR_CODE_COLON && location.charCodeAt(++i) === CHAR_CODE_F && location.charCodeAt(++i) === CHAR_CODE_I && location.charCodeAt(++i) === CHAR_CODE_L && location.charCodeAt(++i) === CHAR_CODE_E) { + return isColonSlashSlash(location, i); + } + return false; + + default: + return false; + } +} + +function isWASM(location, i = 0) { + return ( + // "wasm-function[" + location.charCodeAt(i) === CHAR_CODE_W && location.charCodeAt(++i) === CHAR_CODE_A && location.charCodeAt(++i) === CHAR_CODE_S && location.charCodeAt(++i) === CHAR_CODE_M && location.charCodeAt(++i) === CHAR_CODE_DASH && location.charCodeAt(++i) === CHAR_CODE_F && location.charCodeAt(++i) === CHAR_CODE_U && location.charCodeAt(++i) === CHAR_CODE_N && location.charCodeAt(++i) === CHAR_CODE_C && location.charCodeAt(++i) === CHAR_CODE_T && location.charCodeAt(++i) === CHAR_CODE_I && location.charCodeAt(++i) === CHAR_CODE_O && location.charCodeAt(++i) === CHAR_CODE_N && location.charCodeAt(++i) === CHAR_CODE_L_SQUARE_BRACKET + ); +} + +/** +* A utility method to get the file name from a sourcemapped location +* The sourcemap location can be in any form. This method returns a +* formatted file name for different cases like Windows or OSX. +* @param source +* @returns String +*/ +function getSourceMappedFile(source) { + // If sourcemapped source is a OSX path, return + // the characters after last "/". + // If sourcemapped source is a Windowss path, return + // the characters after last "\\". + if (source.lastIndexOf("/") >= 0) { + source = source.slice(source.lastIndexOf("/") + 1); + } else if (source.lastIndexOf("\\") >= 0) { + source = source.slice(source.lastIndexOf("\\") + 1); + } + return source; +} + +module.exports = { + parseURL, + getSourceNames, + isScratchpadScheme, + isChromeScheme, + isContentScheme, + isWASM, + isDataScheme, + getSourceMappedFile +}; + +/***/ }), + +/***/ 3638: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This file is a chrome-API-free version of the module +// devtools/client/shared/unicode-url.js in the mozilla-central repository, so +// that it can be used in Chrome-API-free applications, such as the Launchpad. +// But because of this, it cannot take advantage of utilizing chrome APIs and +// should implement the similar functionalities on its own. +// +// Please keep in mind that if the feature in this file has changed, don't +// forget to also change that accordingly in +// devtools/client/shared/unicode-url.js in the mozilla-central repository. + + + +const punycode = __webpack_require__(3641); + +/** + * Gets a readble Unicode hostname from a hostname. + * + * If the `hostname` is a readable ASCII hostname, such as example.org, then + * this function will simply return the original `hostname`. + * + * If the `hostname` is a Punycode hostname representing a Unicode domain name, + * such as xn--g6w.xn--8pv, then this function will return the readable Unicode + * domain name by decoding the Punycode hostname. + * + * @param {string} hostname + * the hostname from which the Unicode hostname will be + * parsed, such as example.org, xn--g6w.xn--8pv. + * @return {string} The Unicode hostname. It may be the same as the `hostname` + * passed to this function if the `hostname` itself is + * a readable ASCII hostname or a Unicode hostname. + */ +function getUnicodeHostname(hostname) { + try { + return punycode.toUnicode(hostname); + } catch (err) {} + return hostname; +} + +/** + * Gets a readble Unicode URL pathname from a URL pathname. + * + * If the `urlPath` is a readable ASCII URL pathname, such as /a/b/c.js, then + * this function will simply return the original `urlPath`. + * + * If the `urlPath` is a URI-encoded pathname, such as %E8%A9%A6/%E6%B8%AC.js, + * then this function will return the readable Unicode pathname. + * + * If the `urlPath` is a malformed URL pathname, then this function will simply + * return the original `urlPath`. + * + * @param {string} urlPath + * the URL path from which the Unicode URL path will be parsed, + * such as /a/b/c.js, %E8%A9%A6/%E6%B8%AC.js. + * @return {string} The Unicode URL Path. It may be the same as the `urlPath` + * passed to this function if the `urlPath` itself is a readable + * ASCII url or a Unicode url. + */ +function getUnicodeUrlPath(urlPath) { + try { + return decodeURIComponent(urlPath); + } catch (err) {} + return urlPath; +} + +/** + * Gets a readable Unicode URL from a URL. + * + * If the `url` is a readable ASCII URL, such as http://example.org/a/b/c.js, + * then this function will simply return the original `url`. + * + * If the `url` includes either an unreadable Punycode domain name or an + * unreadable URI-encoded pathname, such as + * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js, then this function will return + * the readable URL by decoding all its unreadable URL components to Unicode + * characters. + * + * If the `url` is a malformed URL, then this function will return the original + * `url`. + * + * If the `url` is a data: URI, then this function will return the original + * `url`. + * + * @param {string} url + * the full URL, or a data: URI. from which the readable URL + * will be parsed, such as, http://example.org/a/b/c.js, + * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js + * @return {string} The readable URL. It may be the same as the `url` passed to + * this function if the `url` itself is readable. + */ +function getUnicodeUrl(url) { + try { + const { protocol, hostname } = new URL(url); + if (protocol === "data:") { + // Never convert a data: URI. + return url; + } + const readableHostname = getUnicodeHostname(hostname); + url = decodeURIComponent(url); + return url.replace(hostname, readableHostname); + } catch (err) {} + return url; +} + +module.exports = { + getUnicodeHostname, + getUnicodeUrlPath, + getUnicodeUrl +}; + +/***/ }), + +/***/ 364: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3641: +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.4.1', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { + return punycode; + }).call(exports, __webpack_require__, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(793)(module), __webpack_require__(792))) + +/***/ }), + +/***/ 3642: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_3642__; + +/***/ }), + +/***/ 3643: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_3643__; + +/***/ }), + +/***/ 365: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 366: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3669: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _tree = __webpack_require__(3670); + +var _tree2 = _interopRequireDefault(_tree); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = { + Tree: _tree2.default +}; /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/***/ }), + +/***/ 367: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3670: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _reactDomFactories = __webpack_require__(3643); + +var _reactDomFactories2 = _interopRequireDefault(_reactDomFactories); + +var _propTypes = __webpack_require__(3642); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const { Component, createFactory } = _react2.default; /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +__webpack_require__(3671); + +// depth +const AUTO_EXPAND_DEPTH = 0; + +/** + * An arrow that displays whether its node is expanded (â–¼) or collapsed + * (â–¶). When its node has no children, it is hidden. + */ +class ArrowExpander extends Component { + static get propTypes() { + return { + expanded: _propTypes2.default.bool + }; + } + + shouldComponentUpdate(nextProps, nextState) { + return this.props.expanded !== nextProps.expanded; + } + + render() { + const { expanded } = this.props; + + const classNames = ["arrow"]; + if (expanded) { + classNames.push("expanded"); + } + return _reactDomFactories2.default.img({ + className: classNames.join(" ") + }); + } +} + +const treeIndent = _reactDomFactories2.default.span({ className: "tree-indent" }, "\u200B"); + +class TreeNode extends Component { + static get propTypes() { + return { + id: _propTypes2.default.any.isRequired, + index: _propTypes2.default.number.isRequired, + depth: _propTypes2.default.number.isRequired, + focused: _propTypes2.default.bool.isRequired, + expanded: _propTypes2.default.bool.isRequired, + item: _propTypes2.default.any.isRequired, + isExpandable: _propTypes2.default.bool.isRequired, + onClick: _propTypes2.default.func, + renderItem: _propTypes2.default.func.isRequired + }; + } + + shouldComponentUpdate(nextProps) { + return this.props.item !== nextProps.item || this.props.focused !== nextProps.focused || this.props.expanded !== nextProps.expanded; + } + + render() { + const { + depth, + id, + item, + focused, + expanded, + renderItem, + isExpandable + } = this.props; + + const arrow = isExpandable ? ArrowExpanderFactory({ + item, + expanded + }) : null; + + let ariaExpanded; + if (this.props.isExpandable) { + ariaExpanded = false; + } + if (this.props.expanded) { + ariaExpanded = true; + } + + const indents = Array.from({ length: depth }).fill(treeIndent); + const items = indents.concat(renderItem(item, depth, focused, arrow, expanded)); + + return _reactDomFactories2.default.div({ + id, + className: `tree-node${focused ? " focused" : ""}`, + onClick: this.props.onClick, + role: "treeitem", + "aria-level": depth + 1, + "aria-expanded": ariaExpanded, + "data-expandable": this.props.isExpandable + }, ...items); + } +} + +const ArrowExpanderFactory = createFactory(ArrowExpander); +const TreeNodeFactory = createFactory(TreeNode); + +/** + * Create a function that calls the given function `fn` only once per animation + * frame. + * + * @param {Function} fn + * @returns {Function} + */ +function oncePerAnimationFrame(fn) { + let animationId = null; + let argsToPass = null; + return function (...args) { + argsToPass = args; + if (animationId !== null) { + return; + } + + animationId = requestAnimationFrame(() => { + fn.call(this, ...argsToPass); + animationId = null; + argsToPass = null; + }); + }; +} + +/** + * A generic tree component. See propTypes for the public API. + * + * This tree component doesn't make any assumptions about the structure of your + * tree data. Whether children are computed on demand, or stored in an array in + * the parent's `_children` property, it doesn't matter. We only require the + * implementation of `getChildren`, `getRoots`, `getParent`, and `isExpanded` + * functions. + * + * This tree component is well tested and reliable. See the tests in ./tests + * and its usage in the performance and memory panels in mozilla-central. + * + * This tree component doesn't make any assumptions about how to render items in + * the tree. You provide a `renderItem` function, and this component will ensure + * that only those items whose parents are expanded and which are visible in the + * viewport are rendered. The `renderItem` function could render the items as a + * "traditional" tree or as rows in a table or anything else. It doesn't + * restrict you to only one certain kind of tree. + * + * The tree comes with basic styling for the indent, the arrow, as well as + * hovered and focused styles which can be override in CSS. + * + * ### Example Usage + * + * Suppose we have some tree data where each item has this form: + * + * { + * id: Number, + * label: String, + * parent: Item or null, + * children: Array of child items, + * expanded: bool, + * } + * + * Here is how we could render that data with this component: + * + * class MyTree extends Component { + * static get propTypes() { + * // The root item of the tree, with the form described above. + * return { + * root: PropTypes.object.isRequired + * }; + * }, + * + * render() { + * return Tree({ + * itemHeight: 20, // px + * + * getRoots: () => [this.props.root], + * + * getParent: item => item.parent, + * getChildren: item => item.children, + * getKey: item => item.id, + * isExpanded: item => item.expanded, + * + * renderItem: (item, depth, isFocused, arrow, isExpanded) => { + * let className = "my-tree-item"; + * if (isFocused) { + * className += " focused"; + * } + * return dom.div({ + * className, + * }, + * arrow, + * // And here is the label for this item. + * dom.span({ className: "my-tree-item-label" }, item.label) + * ); + * }, + * + * onExpand: item => dispatchExpandActionToRedux(item), + * onCollapse: item => dispatchCollapseActionToRedux(item), + * }); + * } + * } + */ +class Tree extends Component { + static get propTypes() { + return { + // Required props + + // A function to get an item's parent, or null if it is a root. + // + // Type: getParent(item: Item) -> Maybe + // + // Example: + // + // // The parent of this item is stored in its `parent` property. + // getParent: item => item.parent + getParent: _propTypes2.default.func.isRequired, + + // A function to get an item's children. + // + // Type: getChildren(item: Item) -> [Item] + // + // Example: + // + // // This item's children are stored in its `children` property. + // getChildren: item => item.children + getChildren: _propTypes2.default.func.isRequired, + + // A function which takes an item and ArrowExpander component instance and + // returns a component, or text, or anything else that React considers + // renderable. + // + // Type: renderItem(item: Item, + // depth: Number, + // isFocused: Boolean, + // arrow: ReactComponent, + // isExpanded: Boolean) -> ReactRenderable + // + // Example: + // + // renderItem: (item, depth, isFocused, arrow, isExpanded) => { + // let className = "my-tree-item"; + // if (isFocused) { + // className += " focused"; + // } + // return dom.div( + // { + // className, + // style: { marginLeft: depth * 10 + "px" } + // }, + // arrow, + // dom.span({ className: "my-tree-item-label" }, item.label) + // ); + // }, + renderItem: _propTypes2.default.func.isRequired, + + // A function which returns the roots of the tree (forest). + // + // Type: getRoots() -> [Item] + // + // Example: + // + // // In this case, we only have one top level, root item. You could + // // return multiple items if you have many top level items in your + // // tree. + // getRoots: () => [this.props.rootOfMyTree] + getRoots: _propTypes2.default.func.isRequired, + + // A function to get a unique key for the given item. This helps speed up + // React's rendering a *TON*. + // + // Type: getKey(item: Item) -> String + // + // Example: + // + // getKey: item => `my-tree-item-${item.uniqueId}` + getKey: _propTypes2.default.func.isRequired, + + // A function to get whether an item is expanded or not. If an item is not + // expanded, then it must be collapsed. + // + // Type: isExpanded(item: Item) -> Boolean + // + // Example: + // + // isExpanded: item => item.expanded, + isExpanded: _propTypes2.default.func.isRequired, + + // Optional props + + // The currently focused item, if any such item exists. + focused: _propTypes2.default.any, + + // Handle when a new item is focused. + onFocus: _propTypes2.default.func, + + // The depth to which we should automatically expand new items. + autoExpandDepth: _propTypes2.default.number, + // Should auto expand all new items or just the new items under the first + // root item. + autoExpandAll: _propTypes2.default.bool, + + // Note: the two properties below are mutually exclusive. Only one of the + // label properties is necessary. + // ID of an element whose textual content serves as an accessible label + // for a tree. + labelledby: _propTypes2.default.string, + // Accessibility label for a tree widget. + label: _propTypes2.default.string, + + // Optional event handlers for when items are expanded or collapsed. + // Useful for dispatching redux events and updating application state, + // maybe lazily loading subtrees from a worker, etc. + // + // Type: + // onExpand(item: Item) + // onCollapse(item: Item) + // + // Example: + // + // onExpand: item => dispatchExpandActionToRedux(item) + onExpand: _propTypes2.default.func, + onCollapse: _propTypes2.default.func, + // Optional event handler called with the current focused node when the + // Enter key is pressed. Can be useful to allow further keyboard actions + // within the tree node. + onActivate: _propTypes2.default.func, + isExpandable: _propTypes2.default.func, + // Additional classes to add to the root element. + className: _propTypes2.default.string, + // style object to be applied to the root element. + style: _propTypes2.default.object + }; + } + + static get defaultProps() { + return { + autoExpandDepth: AUTO_EXPAND_DEPTH, + autoExpandAll: true + }; + } + + constructor(props) { + super(props); + + this.state = { + seen: new Set() + }; + + this._onExpand = oncePerAnimationFrame(this._onExpand).bind(this); + this._onCollapse = oncePerAnimationFrame(this._onCollapse).bind(this); + this._focusPrevNode = oncePerAnimationFrame(this._focusPrevNode).bind(this); + this._focusNextNode = oncePerAnimationFrame(this._focusNextNode).bind(this); + this._focusParentNode = oncePerAnimationFrame(this._focusParentNode).bind(this); + this._focusFirstNode = oncePerAnimationFrame(this._focusFirstNode).bind(this); + this._focusLastNode = oncePerAnimationFrame(this._focusLastNode).bind(this); + + this._autoExpand = this._autoExpand.bind(this); + this._preventArrowKeyScrolling = this._preventArrowKeyScrolling.bind(this); + this._dfs = this._dfs.bind(this); + this._dfsFromRoots = this._dfsFromRoots.bind(this); + this._focus = this._focus.bind(this); + this._scrollNodeIntoView = this._scrollNodeIntoView.bind(this); + this._onBlur = this._onBlur.bind(this); + this._onKeyDown = this._onKeyDown.bind(this); + this._nodeIsExpandable = this._nodeIsExpandable.bind(this); + this._activateNode = oncePerAnimationFrame(this._activateNode).bind(this); + } + + componentDidMount() { + this._autoExpand(); + if (this.props.focused) { + this._scrollNodeIntoView(this.props.focused); + // Always keep the focus on the tree itself. + this.treeRef.focus(); + } + } + + componentWillReceiveProps(nextProps) { + this._autoExpand(); + } + + componentDidUpdate(prevProps, prevState) { + if (this.props.focused && prevProps.focused !== this.props.focused) { + this._scrollNodeIntoView(this.props.focused); + // Always keep the focus on the tree itself. + this.treeRef.focus(); + } + } + + _autoExpand() { + if (!this.props.autoExpandDepth) { + return; + } + + // Automatically expand the first autoExpandDepth levels for new items. Do + // not use the usual DFS infrastructure because we don't want to ignore + // collapsed nodes. + const autoExpand = (item, currentDepth) => { + if (currentDepth >= this.props.autoExpandDepth || this.state.seen.has(item)) { + return; + } + + this.props.onExpand(item); + this.state.seen.add(item); + + const children = this.props.getChildren(item); + const length = children.length; + for (let i = 0; i < length; i++) { + autoExpand(children[i], currentDepth + 1); + } + }; + + const roots = this.props.getRoots(); + const length = roots.length; + if (this.props.autoExpandAll) { + for (let i = 0; i < length; i++) { + autoExpand(roots[i], 0); + } + } else if (length != 0) { + autoExpand(roots[0], 0); + } + } + + _preventArrowKeyScrolling(e) { + switch (e.key) { + case "ArrowUp": + case "ArrowDown": + case "ArrowLeft": + case "ArrowRight": + e.preventDefault(); + e.stopPropagation(); + if (e.nativeEvent) { + if (e.nativeEvent.preventDefault) { + e.nativeEvent.preventDefault(); + } + if (e.nativeEvent.stopPropagation) { + e.nativeEvent.stopPropagation(); + } + } + } + } + + /** + * Perform a pre-order depth-first search from item. + */ + _dfs(item, maxDepth = Infinity, traversal = [], _depth = 0) { + traversal.push({ item, depth: _depth }); + + if (!this.props.isExpanded(item)) { + return traversal; + } + + const nextDepth = _depth + 1; + + if (nextDepth > maxDepth) { + return traversal; + } + + const children = this.props.getChildren(item); + const length = children.length; + for (let i = 0; i < length; i++) { + this._dfs(children[i], maxDepth, traversal, nextDepth); + } + + return traversal; + } + + /** + * Perform a pre-order depth-first search over the whole forest. + */ + _dfsFromRoots(maxDepth = Infinity) { + const traversal = []; + + const roots = this.props.getRoots(); + const length = roots.length; + for (let i = 0; i < length; i++) { + this._dfs(roots[i], maxDepth, traversal); + } + + return traversal; + } + + /** + * Expands current row. + * + * @param {Object} item + * @param {Boolean} expandAllChildren + */ + _onExpand(item, expandAllChildren) { + if (this.props.onExpand) { + this.props.onExpand(item); + + if (expandAllChildren) { + const children = this._dfs(item); + const length = children.length; + for (let i = 0; i < length; i++) { + this.props.onExpand(children[i].item); + } + } + } + } + + /** + * Collapses current row. + * + * @param {Object} item + */ + _onCollapse(item) { + if (this.props.onCollapse) { + this.props.onCollapse(item); + } + } + + /** + * Sets the passed in item to be the focused item. + * + * @param {Object|undefined} item + * The item to be focused, or undefined to focus no item. + * + * @param {Object|undefined} options + * An options object which can contain: + * - dir: "up" or "down" to indicate if we should scroll the element + * to the top or the bottom of the scrollable container when + * the element is off canvas. + */ + _focus(item, options = {}) { + const { preventAutoScroll } = options; + if (item && !preventAutoScroll) { + this._scrollNodeIntoView(item, options); + } + if (this.props.onFocus) { + this.props.onFocus(item); + } + } + + /** + * Sets the passed in item to be the focused item. + * + * @param {Object|undefined} item + * The item to be scrolled to. + * + * @param {Object|undefined} options + * An options object which can contain: + * - dir: "up" or "down" to indicate if we should scroll the element + * to the top or the bottom of the scrollable container when + * the element is off canvas. + */ + _scrollNodeIntoView(item, options = {}) { + if (item !== undefined) { + const treeElement = this.treeRef; + const element = document.getElementById(this.props.getKey(item)); + + if (element) { + const { top, bottom } = element.getBoundingClientRect(); + const closestScrolledParent = node => { + if (node == null) { + return null; + } + + if (node.scrollHeight > node.clientHeight) { + return node; + } + return closestScrolledParent(node.parentNode); + }; + const scrolledParent = closestScrolledParent(treeElement); + const scrolledParentRect = scrolledParent ? scrolledParent.getBoundingClientRect() : null; + const isVisible = !scrolledParent || top >= scrolledParentRect.top && bottom <= scrolledParentRect.bottom; + + if (!isVisible) { + const { alignTo } = options; + const scrollToTop = alignTo ? alignTo === "top" : !scrolledParentRect || top < scrolledParentRect.top; + element.scrollIntoView(scrollToTop); + } + } + } + } + + /** + * Sets the state to have no focused item. + */ + _onBlur() { + this._focus(undefined); + } + + /** + * Handles key down events in the tree's container. + * + * @param {Event} e + */ + _onKeyDown(e) { + if (this.props.focused == null) { + return; + } + + // Allow parent nodes to use navigation arrows with modifiers. + if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { + return; + } + + this._preventArrowKeyScrolling(e); + + switch (e.key) { + case "ArrowUp": + this._focusPrevNode(); + return; + + case "ArrowDown": + this._focusNextNode(); + return; + + case "ArrowLeft": + if (this.props.isExpanded(this.props.focused) && this._nodeIsExpandable(this.props.focused)) { + this._onCollapse(this.props.focused); + } else { + this._focusParentNode(); + } + return; + + case "ArrowRight": + if (this._nodeIsExpandable(this.props.focused) && !this.props.isExpanded(this.props.focused)) { + this._onExpand(this.props.focused); + } else { + this._focusNextNode(); + } + return; + + case "Home": + this._focusFirstNode(); + return; + + case "End": + this._focusLastNode(); + return; + + case "Enter": + this._activateNode(); + } + } + + /** + * Sets the previous node relative to the currently focused item, to focused. + */ + _focusPrevNode() { + // Start a depth first search and keep going until we reach the currently + // focused node. Focus the previous node in the DFS, if it exists. If it + // doesn't exist, we're at the first node already. + + let prev; + + const traversal = this._dfsFromRoots(); + const length = traversal.length; + for (let i = 0; i < length; i++) { + const item = traversal[i].item; + if (item === this.props.focused) { + break; + } + prev = item; + } + if (prev === undefined) { + return; + } + + this._focus(prev, { alignTo: "top" }); + } + + /** + * Handles the down arrow key which will focus either the next child + * or sibling row. + */ + _focusNextNode() { + // Start a depth first search and keep going until we reach the currently + // focused node. Focus the next node in the DFS, if it exists. If it + // doesn't exist, we're at the last node already. + const traversal = this._dfsFromRoots(); + const length = traversal.length; + let i = 0; + + while (i < length) { + if (traversal[i].item === this.props.focused) { + break; + } + i++; + } + + if (i + 1 < traversal.length) { + this._focus(traversal[i + 1].item, { alignTo: "bottom" }); + } + } + + /** + * Handles the left arrow key, going back up to the current rows' + * parent row. + */ + _focusParentNode() { + const parent = this.props.getParent(this.props.focused); + if (!parent) { + this._focusPrevNode(this.props.focused); + return; + } + + const traversal = this._dfsFromRoots(); + const length = traversal.length; + let parentIndex = 0; + for (; parentIndex < length; parentIndex++) { + if (traversal[parentIndex].item === parent) { + break; + } + } + + this._focus(parent, { alignTo: "top" }); + } + + _focusFirstNode() { + const traversal = this._dfsFromRoots(); + this._focus(traversal[0].item, { alignTo: "top" }); + } + + _focusLastNode() { + const traversal = this._dfsFromRoots(); + const lastIndex = traversal.length - 1; + this._focus(traversal[lastIndex].item, { alignTo: "bottom" }); + } + + _activateNode() { + if (this.props.onActivate) { + this.props.onActivate(this.props.focused); + } + } + + _nodeIsExpandable(item) { + return this.props.isExpandable ? this.props.isExpandable(item) : !!this.props.getChildren(item).length; + } + + render() { + const traversal = this._dfsFromRoots(); + const { focused } = this.props; + + const nodes = traversal.map((v, i) => { + const { item, depth } = traversal[i]; + const key = this.props.getKey(item, i); + return TreeNodeFactory({ + key, + id: key, + index: i, + item, + depth, + renderItem: this.props.renderItem, + focused: focused === item, + expanded: this.props.isExpanded(item), + isExpandable: this._nodeIsExpandable(item), + onExpand: this._onExpand, + onCollapse: this._onCollapse, + onClick: e => { + // Since the user just clicked the node, there's no need to check if + // it should be scrolled into view. + this._focus(item, { preventAutoScroll: true }); + if (this.props.isExpanded(item)) { + this.props.onCollapse(item); + } else { + this.props.onExpand(item, e.altKey); + } + } + }); + }); + + const style = Object.assign({}, this.props.style || {}, { + padding: 0, + margin: 0 + }); + + return _reactDomFactories2.default.div({ + className: `tree ${this.props.className ? this.props.className : ""}`, + ref: el => { + this.treeRef = el; + }, + role: "tree", + tabIndex: "0", + onKeyDown: this._onKeyDown, + onKeyPress: this._preventArrowKeyScrolling, + onKeyUp: this._preventArrowKeyScrolling, + onFocus: ({ nativeEvent }) => { + if (focused || !nativeEvent || !this.treeRef) { + return; + } + + const { explicitOriginalTarget } = nativeEvent; + // Only set default focus to the first tree node if the focus came + // from outside the tree (e.g. by tabbing to the tree from other + // external elements). + if (explicitOriginalTarget !== this.treeRef && !this.treeRef.contains(explicitOriginalTarget)) { + this._focus(traversal[0].item); + } + }, + onBlur: this._onBlur, + "aria-label": this.props.label, + "aria-labelledby": this.props.labelledby, + "aria-activedescendant": focused && this.props.getKey(focused), + style + }, nodes); + } +} + +exports.default = Tree; + +/***/ }), + +/***/ 3671: +/***/ (function(module, exports) { + +// removed by extract-text-webpack-plugin + +/***/ }), + +/***/ 368: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 369: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 370: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 371: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 372: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 3721: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(process) { + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isDevelopment = isDevelopment; +exports.isTesting = isTesting; +exports.isFirefoxPanel = isFirefoxPanel; +exports.isFirefox = isFirefox; +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +const flag = __webpack_require__(52); + +function isBrowser() { + return typeof window == "object"; +} + +function isNode() { + return process && process.release && process.release.name == 'node'; +} + +function isDevelopment() { + if (!isNode && isBrowser()) { + const href = window.location ? window.location.href : ""; + return href.match(/^file:/) || href.match(/localhost:/); + } + + return "production" != "production"; +} + +function isTesting() { + return flag.testing; +} + +function isFirefoxPanel() { + return !isDevelopment(); +} + +function isFirefox() { + return (/firefox/i.test(navigator.userAgent) + ); +} +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120))) + +/***/ }), + +/***/ 3728: +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(3729); + + +/***/ }), + +/***/ 3729: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.vendored = undefined; + +var _devtoolsComponents = __webpack_require__(3669); + +var devtoolsComponents = _interopRequireWildcard(_devtoolsComponents); + +var _devtoolsConfig = __webpack_require__(1355); + +var devtoolsConfig = _interopRequireWildcard(_devtoolsConfig); + +var _devtoolsContextmenu = __webpack_require__(1413); + +var devtoolsContextmenu = _interopRequireWildcard(_devtoolsContextmenu); + +var _devtoolsEnvironment = __webpack_require__(3721); + +var devtoolsEnvironment = _interopRequireWildcard(_devtoolsEnvironment); + +var _devtoolsModules = __webpack_require__(1376); + +var devtoolsModules = _interopRequireWildcard(_devtoolsModules); + +var _devtoolsUtils = __webpack_require__(1363); + +var devtoolsUtils = _interopRequireWildcard(_devtoolsUtils); + +var _fuzzaldrinPlus = __webpack_require__(161); + +var fuzzaldrinPlus = _interopRequireWildcard(_fuzzaldrinPlus); + +var _Transition = __webpack_require__(333); + +var transition = _interopRequireWildcard(_Transition); + +var _reselect = __webpack_require__(993); + +var reselect = _interopRequireWildcard(_reselect); + +var _url = __webpack_require__(334); + +var url = _interopRequireWildcard(_url); + +var _classnames = __webpack_require__(175); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _devtoolsSplitter = __webpack_require__(1440); + +var _devtoolsSplitter2 = _interopRequireDefault(_devtoolsSplitter); + +var _Svg = __webpack_require__(1359); + +var _Svg2 = _interopRequireDefault(_Svg); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +// We cannot directly export literals containing special characters +// (eg. "my-module/Test") which is why they are nested in "vendored". +// The keys of the vendored object should match the module names +// !!! Should remain synchronized with .babel/transform-mc.js !!! +const vendored = { + classnames: _classnames2.default, + "devtools-components": devtoolsComponents, + "devtools-config": devtoolsConfig, + "devtools-contextmenu": devtoolsContextmenu, + "devtools-environment": devtoolsEnvironment, + "devtools-modules": devtoolsModules, + "devtools-splitter": _devtoolsSplitter2.default, + "devtools-utils": devtoolsUtils, + "fuzzaldrin-plus": fuzzaldrinPlus, + "react-transition-group/Transition": transition, + reselect, + // Svg is required via relative paths, so the key is not imported path. + // See .babel/transform-mc.js + Svg: _Svg2.default, + url +}; + +// Modules imported without destructuring +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Vendors.js is a file used to bundle and expose all dependencies needed to run + * the transpiled debugger modules when running in Firefox. + * + * To make transpilation easier, a vendored module should always be imported in + * same way: + * - always with destructuring (import { a } from "modA";) + * - always without destructuring (import modB from "modB") + * + * Both are fine, but cannot be mixed for the same module. + */ + +// Modules imported with destructuring +exports.vendored = vendored; + +/***/ }), + +/***/ 4: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_4__; + +/***/ }), + +/***/ 52: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_52__; + +/***/ }), + +/***/ 6: +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(7), + getRawTag = __webpack_require__(10), + objectToString = __webpack_require__(11); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; + + +/***/ }), + +/***/ 66: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.decode = exports.parse = __webpack_require__(121); +exports.encode = exports.stringify = __webpack_require__(122); + + +/***/ }), + +/***/ 67: +/***/ (function(module, exports, __webpack_require__) { + +var baseGet = __webpack_require__(68); + +/** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ +function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; +} + +module.exports = get; + + +/***/ }), + +/***/ 68: +/***/ (function(module, exports, __webpack_require__) { + +var castPath = __webpack_require__(69), + toKey = __webpack_require__(111); + +/** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ +function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; +} + +module.exports = baseGet; + + +/***/ }), + +/***/ 69: +/***/ (function(module, exports, __webpack_require__) { + +var isArray = __webpack_require__(70), + isKey = __webpack_require__(71), + stringToPath = __webpack_require__(73), + toString = __webpack_require__(108); + +/** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ +function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); +} + +module.exports = castPath; + + +/***/ }), + +/***/ 7: +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(8); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; + + +/***/ }), + +/***/ 70: +/***/ (function(module, exports) { + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +module.exports = isArray; + + +/***/ }), + +/***/ 71: +/***/ (function(module, exports, __webpack_require__) { + +var isArray = __webpack_require__(70), + isSymbol = __webpack_require__(72); + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + +/** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ +function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); +} + +module.exports = isKey; + + +/***/ }), + +/***/ 72: +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(6), + isObjectLike = __webpack_require__(14); + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); +} + +module.exports = isSymbol; + + +/***/ }), + +/***/ 73: +/***/ (function(module, exports, __webpack_require__) { + +var memoizeCapped = __webpack_require__(74); + +/** Used to match property names within property paths. */ +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; + +/** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ +var stringToPath = memoizeCapped(function(string) { + var result = []; + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; +}); + +module.exports = stringToPath; + + +/***/ }), + +/***/ 74: +/***/ (function(module, exports, __webpack_require__) { + +var memoize = __webpack_require__(75); + +/** Used as the maximum memoize cache size. */ +var MAX_MEMOIZE_SIZE = 500; + +/** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ +function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; +} + +module.exports = memoizeCapped; + + +/***/ }), + +/***/ 75: +/***/ (function(module, exports, __webpack_require__) { + +var MapCache = __webpack_require__(76); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ +function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; +} + +// Expose `MapCache`. +memoize.Cache = MapCache; + +module.exports = memoize; + + +/***/ }), + +/***/ 76: +/***/ (function(module, exports, __webpack_require__) { + +var mapCacheClear = __webpack_require__(77), + mapCacheDelete = __webpack_require__(102), + mapCacheGet = __webpack_require__(105), + mapCacheHas = __webpack_require__(106), + mapCacheSet = __webpack_require__(107); + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +module.exports = MapCache; + + +/***/ }), + +/***/ 77: +/***/ (function(module, exports, __webpack_require__) { + +var Hash = __webpack_require__(78), + ListCache = __webpack_require__(93), + Map = __webpack_require__(101); + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +module.exports = mapCacheClear; + + +/***/ }), + +/***/ 78: +/***/ (function(module, exports, __webpack_require__) { + +var hashClear = __webpack_require__(79), + hashDelete = __webpack_require__(89), + hashGet = __webpack_require__(90), + hashHas = __webpack_require__(91), + hashSet = __webpack_require__(92); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +module.exports = Hash; + + +/***/ }), + +/***/ 79: +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(80); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; +} + +module.exports = hashClear; + + +/***/ }), + +/***/ 792: +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), + +/***/ 793: +/***/ (function(module, exports) { + +module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + if(!module.children) module.children = []; + Object.defineProperty(module, "loaded", { + enumerable: true, + get: function() { + return module.l; + } + }); + Object.defineProperty(module, "id", { + enumerable: true, + get: function() { + return module.i; + } + }); + module.webpackPolyfill = 1; + } + return module; +}; + + +/***/ }), + +/***/ 8: +/***/ (function(module, exports, __webpack_require__) { + +var freeGlobal = __webpack_require__(9); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; + + +/***/ }), + +/***/ 80: +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(81); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +module.exports = nativeCreate; + + +/***/ }), + +/***/ 806: +/***/ (function(module, exports) { + +module.exports = "dojo_square" + +/***/ }), + +/***/ 81: +/***/ (function(module, exports, __webpack_require__) { + +var baseIsNative = __webpack_require__(82), + getValue = __webpack_require__(88); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; + + +/***/ }), + +/***/ 82: +/***/ (function(module, exports, __webpack_require__) { + +var isFunction = __webpack_require__(83), + isMasked = __webpack_require__(85), + isObject = __webpack_require__(84), + toSource = __webpack_require__(87); + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +module.exports = baseIsNative; + + +/***/ }), + +/***/ 83: +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(6), + isObject = __webpack_require__(84); + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +module.exports = isFunction; + + +/***/ }), + +/***/ 84: +/***/ (function(module, exports) { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + + +/***/ }), + +/***/ 85: +/***/ (function(module, exports, __webpack_require__) { + +var coreJsData = __webpack_require__(86); + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +module.exports = isMasked; + + +/***/ }), + +/***/ 86: +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(8); + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +module.exports = coreJsData; + + +/***/ }), + +/***/ 87: +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var funcProto = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +module.exports = toSource; + + +/***/ }), + +/***/ 88: +/***/ (function(module, exports) { + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +module.exports = getValue; + + +/***/ }), + +/***/ 89: +/***/ (function(module, exports) { + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +module.exports = hashDelete; + + +/***/ }), + +/***/ 9: +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +module.exports = freeGlobal; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(792))) + +/***/ }), + +/***/ 90: +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(80); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +module.exports = hashGet; + + +/***/ }), + +/***/ 91: +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(80); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); +} + +module.exports = hashHas; + + +/***/ }), + +/***/ 919: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 92: +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(80); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +module.exports = hashSet; + + +/***/ }), + +/***/ 920: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 93: +/***/ (function(module, exports, __webpack_require__) { + +var listCacheClear = __webpack_require__(94), + listCacheDelete = __webpack_require__(95), + listCacheGet = __webpack_require__(98), + listCacheHas = __webpack_require__(99), + listCacheSet = __webpack_require__(100); + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +module.exports = ListCache; + + +/***/ }), + +/***/ 94: +/***/ (function(module, exports) { + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +module.exports = listCacheClear; + + +/***/ }), + +/***/ 95: +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(96); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} + +module.exports = listCacheDelete; + + +/***/ }), + +/***/ 96: +/***/ (function(module, exports, __webpack_require__) { + +var eq = __webpack_require__(97); + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +module.exports = assocIndexOf; + + +/***/ }), + +/***/ 97: +/***/ (function(module, exports) { + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +module.exports = eq; + + +/***/ }), + +/***/ 98: +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(96); + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +module.exports = listCacheGet; + + +/***/ }), + +/***/ 99: +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(96); + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +module.exports = listCacheHas; + + +/***/ }), + +/***/ 993: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; +exports.defaultMemoize = defaultMemoize; +exports.createSelectorCreator = createSelectorCreator; +exports.createStructuredSelector = createStructuredSelector; +function defaultEqualityCheck(a, b) { + return a === b; +} + +function areArgumentsShallowlyEqual(equalityCheck, prev, next) { + if (prev === null || next === null || prev.length !== next.length) { + return false; + } + + // Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible. + var length = prev.length; + for (var i = 0; i < length; i++) { + if (!equalityCheck(prev[i], next[i])) { + return false; + } + } + + return true; +} + +function defaultMemoize(func) { + var equalityCheck = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultEqualityCheck; + + var lastArgs = null; + var lastResult = null; + // we reference arguments instead of spreading them for performance reasons + return function () { + if (!areArgumentsShallowlyEqual(equalityCheck, lastArgs, arguments)) { + // apply arguments instead of spreading for performance. + lastResult = func.apply(null, arguments); + } + + lastArgs = arguments; + return lastResult; + }; +} + +function getDependencies(funcs) { + var dependencies = Array.isArray(funcs[0]) ? funcs[0] : funcs; + + if (!dependencies.every(function (dep) { + return typeof dep === 'function'; + })) { + var dependencyTypes = dependencies.map(function (dep) { + return typeof dep; + }).join(', '); + throw new Error('Selector creators expect all input-selectors to be functions, ' + ('instead received the following types: [' + dependencyTypes + ']')); + } + + return dependencies; +} + +function createSelectorCreator(memoize) { + for (var _len = arguments.length, memoizeOptions = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + memoizeOptions[_key - 1] = arguments[_key]; + } + + return function () { + for (var _len2 = arguments.length, funcs = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + funcs[_key2] = arguments[_key2]; + } + + var recomputations = 0; + var resultFunc = funcs.pop(); + var dependencies = getDependencies(funcs); + + var memoizedResultFunc = memoize.apply(undefined, [function () { + recomputations++; + // apply arguments instead of spreading for performance. + return resultFunc.apply(null, arguments); + }].concat(memoizeOptions)); + + // If a selector is called with the exact same arguments we don't need to traverse our dependencies again. + var selector = defaultMemoize(function () { + var params = []; + var length = dependencies.length; + + for (var i = 0; i < length; i++) { + // apply arguments instead of spreading and mutate a local list of params for performance. + params.push(dependencies[i].apply(null, arguments)); + } + + // apply arguments instead of spreading for performance. + return memoizedResultFunc.apply(null, params); + }); + + selector.resultFunc = resultFunc; + selector.recomputations = function () { + return recomputations; + }; + selector.resetRecomputations = function () { + return recomputations = 0; + }; + return selector; + }; +} + +var createSelector = exports.createSelector = createSelectorCreator(defaultMemoize); + +function createStructuredSelector(selectors) { + var selectorCreator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : createSelector; + + if (typeof selectors !== 'object') { + throw new Error('createStructuredSelector expects first argument to be an object ' + ('where each property is a selector, instead received a ' + typeof selectors)); + } + var objectKeys = Object.keys(selectors); + return selectorCreator(objectKeys.map(function (key) { + return selectors[key]; + }), function () { + for (var _len3 = arguments.length, values = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + values[_key3] = arguments[_key3]; + } + + return values.reduce(function (composition, value, index) { + composition[objectKeys[index]] = value; + return composition; + }, {}); + }); +} + +/***/ }), + +/***/ 997: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 998: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }), + +/***/ 999: +/***/ (function(module, exports) { + +module.exports = "" + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/index.html b/devtools/client/debugger/new/index.html index 236df4d278c5..9795144e7a02 100644 --- a/devtools/client/debugger/new/index.html +++ b/devtools/client/debugger/new/index.html @@ -3,29 +3,25 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - - - - - - -
- - - - + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/devtools/client/debugger/new/moz.build b/devtools/client/debugger/new/moz.build index ecf13ff91f91..3069eddef312 100644 --- a/devtools/client/debugger/new/moz.build +++ b/devtools/client/debugger/new/moz.build @@ -3,11 +3,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +DIRS += [ + 'dist', + 'src', +] + DevToolsModules( - 'debugger.css', - 'debugger.js', 'panel.js', - 'parser-worker.js', - 'pretty-print-worker.js', - 'search-worker.js', ) diff --git a/devtools/client/debugger/new/src/actions/ast.js b/devtools/client/debugger/new/src/actions/ast.js new file mode 100644 index 000000000000..2bf94e38cb7b --- /dev/null +++ b/devtools/client/debugger/new/src/actions/ast.js @@ -0,0 +1,127 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setSourceMetaData = setSourceMetaData; +exports.setSymbols = setSymbols; +exports.setOutOfScopeLocations = setOutOfScopeLocations; +exports.setPausePoints = setPausePoints; + +var _selectors = require("../selectors/index"); + +var _pause = require("./pause/index"); + +var _setInScopeLines = require("./ast/setInScopeLines"); + +var _parser = require("../workers/parser/index"); + +var _promise = require("./utils/middleware/promise"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _prefs = require("../utils/prefs"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function setSourceMetaData(sourceId) { + return async ({ + dispatch, + getState + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + + if (!source || !source.text || source.isWasm) { + return; + } + + const framework = await (0, _parser.getFramework)(source.id); + dispatch({ + type: "SET_SOURCE_METADATA", + sourceId: source.id, + sourceMetaData: { + framework + } + }); + }; +} + +function setSymbols(sourceId) { + return async ({ + dispatch, + getState + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + + if (!source || !source.text || source.isWasm || (0, _selectors.hasSymbols)(getState(), source)) { + return; + } + + await dispatch({ + type: "SET_SYMBOLS", + sourceId, + [_promise.PROMISE]: (0, _parser.getSymbols)(sourceId) + }); + + if ((0, _selectors.isPaused)(getState())) { + await dispatch((0, _pause.fetchExtra)()); + await dispatch((0, _pause.mapFrames)()); + } + + await dispatch(setPausePoints(sourceId)); + await dispatch(setSourceMetaData(sourceId)); + }; +} + +function setOutOfScopeLocations() { + return async ({ + dispatch, + getState + }) => { + const location = (0, _selectors.getSelectedLocation)(getState()); + + if (!location) { + return; + } + + const source = (0, _selectors.getSource)(getState(), location.sourceId); + let locations = null; + + if (location.line && source && (0, _selectors.isPaused)(getState())) { + locations = await (0, _parser.findOutOfScopeLocations)(source.get("id"), location); + } + + dispatch({ + type: "OUT_OF_SCOPE_LOCATIONS", + locations + }); + dispatch((0, _setInScopeLines.setInScopeLines)()); + }; +} + +function setPausePoints(sourceId) { + return async ({ + dispatch, + getState, + client + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + + if (!_prefs.features.pausePoints || !source || !source.text || source.isWasm) { + return; + } + + const pausePoints = await (0, _parser.getPausePoints)(source.id); + + if ((0, _devtoolsSourceMap.isGeneratedId)(source.id)) { + await client.setPausePoints(source.id, pausePoints); + } + + dispatch({ + type: "SET_PAUSE_POINTS", + source: source.toJS(), + pausePoints + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/ast/moz.build b/devtools/client/debugger/new/src/actions/ast/moz.build new file mode 100644 index 000000000000..a6ac38790e6c --- /dev/null +++ b/devtools/client/debugger/new/src/actions/ast/moz.build @@ -0,0 +1,12 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'setInScopeLines.js', +) diff --git a/devtools/client/debugger/new/src/actions/ast/setInScopeLines.js b/devtools/client/debugger/new/src/actions/ast/setInScopeLines.js new file mode 100644 index 000000000000..6ea7b99ee637 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/ast/setInScopeLines.js @@ -0,0 +1,46 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setInScopeLines = setInScopeLines; + +var _selectors = require("../../selectors/index"); + +var _source = require("../../utils/source"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getOutOfScopeLines(outOfScopeLocations) { + if (!outOfScopeLocations) { + return null; + } + + return (0, _lodash.uniq)((0, _lodash.flatMap)(outOfScopeLocations, location => (0, _lodash.range)(location.start.line, location.end.line))); +} + +function setInScopeLines() { + return ({ + dispatch, + getState + }) => { + const sourceRecord = (0, _selectors.getSelectedSource)(getState()); + const outOfScopeLocations = (0, _selectors.getOutOfScopeLocations)(getState()); + + if (!sourceRecord || !sourceRecord.text) { + return; + } + + const linesOutOfScope = getOutOfScopeLines(outOfScopeLocations); + const sourceNumLines = (0, _source.getSourceLineCount)(sourceRecord); + const sourceLines = (0, _lodash.range)(1, sourceNumLines + 1); + const inScopeLines = !linesOutOfScope ? sourceLines : (0, _lodash.without)(sourceLines, ...linesOutOfScope); + dispatch({ + type: "IN_SCOPE_LINES", + lines: inScopeLines + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/breakpoints.js b/devtools/client/debugger/new/src/actions/breakpoints.js new file mode 100644 index 000000000000..3aeff4fb52b1 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/breakpoints.js @@ -0,0 +1,497 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.syncBreakpoint = syncBreakpoint; +exports.addBreakpoint = addBreakpoint; +exports.addHiddenBreakpoint = addHiddenBreakpoint; +exports.removeBreakpoint = removeBreakpoint; +exports.enableBreakpoint = enableBreakpoint; +exports.disableBreakpoint = disableBreakpoint; +exports.toggleAllBreakpoints = toggleAllBreakpoints; +exports.toggleBreakpoints = toggleBreakpoints; +exports.removeAllBreakpoints = removeAllBreakpoints; +exports.removeBreakpoints = removeBreakpoints; +exports.remapBreakpoints = remapBreakpoints; +exports.setBreakpointCondition = setBreakpointCondition; +exports.toggleBreakpoint = toggleBreakpoint; +exports.addOrToggleDisabledBreakpoint = addOrToggleDisabledBreakpoint; +exports.toggleDisabledBreakpoint = toggleDisabledBreakpoint; + +var _promise = require("./utils/middleware/promise"); + +var _selectors = require("../selectors/index"); + +var _breakpoint = require("../utils/breakpoint/index"); + +var _addBreakpoint = require("./breakpoints/addBreakpoint"); + +var _addBreakpoint2 = _interopRequireDefault(_addBreakpoint); + +var _remapLocations = require("./breakpoints/remapLocations"); + +var _remapLocations2 = _interopRequireDefault(_remapLocations); + +var _ast = require("../reducers/ast"); + +var _syncBreakpoint = require("./breakpoints/syncBreakpoint"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Syncing a breakpoint add breakpoint information that is stored, and + * contact the server for more data. + * + * @memberof actions/breakpoints + * @static + * @param {String} $1.sourceId String value + * @param {PendingBreakpoint} $1.location PendingBreakpoint value + */ +function syncBreakpoint(sourceId, pendingBreakpoint) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const { + breakpoint, + previousLocation + } = await (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, sourceId, pendingBreakpoint); + return dispatch({ + type: "SYNC_BREAKPOINT", + breakpoint, + previousLocation + }); + }; +} +/** + * Add a new breakpoint + * + * @memberof actions/breakpoints + * @static + * @param {String} $1.condition Conditional breakpoint condition value + * @param {Boolean} $1.disabled Disable value for breakpoint value + */ + + +function addBreakpoint(location, { + condition, + hidden +} = {}) { + const breakpoint = (0, _breakpoint.createBreakpoint)(location, { + condition, + hidden + }); + return ({ + dispatch, + getState, + sourceMaps, + client + }) => { + return dispatch({ + type: "ADD_BREAKPOINT", + breakpoint, + [_promise.PROMISE]: (0, _addBreakpoint2.default)(getState, client, sourceMaps, breakpoint) + }); + }; +} +/** + * Add a new hidden breakpoint + * + * @memberOf actions/breakpoints + * @param location + * @return {function(ThunkArgs)} + */ + + +function addHiddenBreakpoint(location) { + return ({ + dispatch + }) => { + return dispatch(addBreakpoint(location, { + hidden: true + })); + }; +} +/** + * Remove a single breakpoint + * + * @memberof actions/breakpoints + * @static + */ + + +function removeBreakpoint(location) { + return ({ + dispatch, + getState, + client + }) => { + const bp = (0, _selectors.getBreakpoint)(getState(), location); + + if (!bp || bp.loading) { + return; + } // If the breakpoint is already disabled, we don't need to communicate + // with the server. We just need to dispatch an action + // simulating a successful server request + + + if (bp.disabled) { + return dispatch({ + type: "REMOVE_BREAKPOINT", + breakpoint: bp, + status: "done" + }); + } + + return dispatch({ + type: "REMOVE_BREAKPOINT", + breakpoint: bp, + disabled: false, + [_promise.PROMISE]: client.removeBreakpoint(bp.generatedLocation) + }); + }; +} +/** + * Enabling a breakpoint + * will reuse the existing breakpoint information that is stored. + * + * @memberof actions/breakpoints + * @static + * @param {Location} $1.location Location value + */ + + +function enableBreakpoint(location) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const breakpoint = (0, _selectors.getBreakpoint)(getState(), location); + + if (!breakpoint || breakpoint.loading) { + return; + } + + return dispatch({ + type: "ENABLE_BREAKPOINT", + breakpoint, + [_promise.PROMISE]: (0, _addBreakpoint2.default)(getState, client, sourceMaps, breakpoint) + }); + }; +} +/** + * Disable a single breakpoint + * + * @memberof actions/breakpoints + * @static + */ + + +function disableBreakpoint(location) { + return async ({ + dispatch, + getState, + client + }) => { + const bp = (0, _selectors.getBreakpoint)(getState(), location); + + if (!bp || bp.loading) { + return; + } + + await client.removeBreakpoint(bp.generatedLocation); + + const newBreakpoint = _objectSpread({}, bp, { + disabled: true + }); + + return dispatch({ + type: "DISABLE_BREAKPOINT", + breakpoint: newBreakpoint + }); + }; +} +/** + * Toggle All Breakpoints + * + * @memberof actions/breakpoints + * @static + */ + + +function toggleAllBreakpoints(shouldDisableBreakpoints) { + return async ({ + dispatch, + getState, + client + }) => { + const breakpoints = (0, _selectors.getBreakpoints)(getState()); + const modifiedBreakpoints = []; + + for (const [, breakpoint] of breakpoints) { + if (shouldDisableBreakpoints) { + await client.removeBreakpoint(breakpoint.generatedLocation); + + const newBreakpoint = _objectSpread({}, breakpoint, { + disabled: true + }); + + modifiedBreakpoints.push(newBreakpoint); + } else { + const newBreakpoint = _objectSpread({}, breakpoint, { + disabled: false + }); + + modifiedBreakpoints.push(newBreakpoint); + } + } + + if (shouldDisableBreakpoints) { + return dispatch({ + type: "DISABLE_ALL_BREAKPOINTS", + breakpoints: modifiedBreakpoints + }); + } + + return dispatch({ + type: "ENABLE_ALL_BREAKPOINTS", + breakpoints: modifiedBreakpoints + }); + }; +} +/** + * Toggle Breakpoints + * + * @memberof actions/breakpoints + * @static + */ + + +function toggleBreakpoints(shouldDisableBreakpoints, breakpoints) { + return async ({ + dispatch + }) => { + for (const [, breakpoint] of breakpoints) { + if (shouldDisableBreakpoints) { + await dispatch(disableBreakpoint(breakpoint.location)); + } else { + await dispatch(enableBreakpoint(breakpoint.location)); + } + } + }; +} +/** + * Removes all breakpoints + * + * @memberof actions/breakpoints + * @static + */ + + +function removeAllBreakpoints() { + return async ({ + dispatch, + getState + }) => { + const breakpoints = (0, _selectors.getBreakpoints)(getState()); + + for (const [, breakpoint] of breakpoints) { + await dispatch(removeBreakpoint(breakpoint.location)); + } + }; +} +/** + * Removes breakpoints + * + * @memberof actions/breakpoints + * @static + */ + + +function removeBreakpoints(breakpoints) { + return async ({ + dispatch + }) => { + for (const [, breakpoint] of breakpoints) { + await dispatch(removeBreakpoint(breakpoint.location)); + } + }; +} + +function remapBreakpoints(sourceId) { + return async ({ + dispatch, + getState, + sourceMaps + }) => { + const breakpoints = (0, _selectors.getBreakpoints)(getState()); + const newBreakpoints = await (0, _remapLocations2.default)(breakpoints, sourceId, sourceMaps); + return dispatch({ + type: "REMAP_BREAKPOINTS", + breakpoints: newBreakpoints + }); + }; +} +/** + * Update the condition of a breakpoint. + * + * @throws {Error} "not implemented" + * @memberof actions/breakpoints + * @static + * @param {Location} location + * @see DebuggerController.Breakpoints.addBreakpoint + * @param {string} condition + * The condition to set on the breakpoint + * @param {Boolean} $1.disabled Disable value for breakpoint value + */ + + +function setBreakpointCondition(location, { + condition +} = {}) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const bp = (0, _selectors.getBreakpoint)(getState(), location); + + if (!bp) { + return dispatch(addBreakpoint(location, { + condition + })); + } + + if (bp.loading) { + return; + } + + if (bp.disabled) { + await dispatch(enableBreakpoint(location)); + bp.disabled = !bp.disabled; + } + + await client.setBreakpointCondition(bp.id, location, condition, sourceMaps.isOriginalId(bp.location.sourceId)); + + const newBreakpoint = _objectSpread({}, bp, { + condition + }); + + (0, _breakpoint.assertBreakpoint)(newBreakpoint); + return dispatch({ + type: "SET_BREAKPOINT_CONDITION", + breakpoint: newBreakpoint + }); + }; +} + +function toggleBreakpoint(line, column) { + return ({ + dispatch, + getState, + client, + sourceMaps + }) => { + if (!line) { + return; + } + + const state = getState(); + const selectedSource = (0, _selectors.getSelectedSource)(state); + const bp = (0, _selectors.getBreakpointAtLocation)(state, { + line, + column + }); + const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource); + + if (!bp && isEmptyLine || bp && bp.loading) { + return; + } + + if (bp) { + // NOTE: it's possible the breakpoint has slid to a column + return dispatch(removeBreakpoint({ + sourceId: bp.location.sourceId, + sourceUrl: bp.location.sourceUrl, + line: bp.location.line, + column: column || bp.location.column + })); + } + + return dispatch(addBreakpoint({ + sourceId: selectedSource.get("id"), + sourceUrl: selectedSource.get("url"), + line: line, + column: column + })); + }; +} + +function addOrToggleDisabledBreakpoint(line, column) { + return ({ + dispatch, + getState, + client, + sourceMaps + }) => { + if (!line) { + return; + } + + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + const bp = (0, _selectors.getBreakpointAtLocation)(getState(), { + line, + column + }); + + if (bp && bp.loading) { + return; + } + + if (bp) { + // NOTE: it's possible the breakpoint has slid to a column + return dispatch(toggleDisabledBreakpoint(line, column || bp.location.column)); + } + + return dispatch(addBreakpoint({ + sourceId: selectedSource.get("id"), + sourceUrl: selectedSource.get("url"), + line: line, + column: column + })); + }; +} + +function toggleDisabledBreakpoint(line, column) { + return ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const bp = (0, _selectors.getBreakpointAtLocation)(getState(), { + line, + column + }); + + if (!bp || bp.loading) { + return; + } + + if (!bp.disabled) { + return dispatch(disableBreakpoint(bp.location)); + } + + return dispatch(enableBreakpoint(bp.location)); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/breakpoints/addBreakpoint.js b/devtools/client/debugger/new/src/actions/breakpoints/addBreakpoint.js new file mode 100644 index 000000000000..2df3c0c2e08e --- /dev/null +++ b/devtools/client/debugger/new/src/actions/breakpoints/addBreakpoint.js @@ -0,0 +1,75 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = addBreakpoint; + +var _breakpoint = require("../../utils/breakpoint/index"); + +var _selectors = require("../../selectors/index"); + +var _sourceMaps = require("../../utils/source-maps"); + +var _source = require("../../utils/source"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +async function addBreakpoint(getState, client, sourceMaps, breakpoint) { + const state = getState(); + const source = (0, _selectors.getSource)(state, breakpoint.location.sourceId); + + const location = _objectSpread({}, breakpoint.location, { + sourceUrl: source.url + }); + + const generatedLocation = await (0, _sourceMaps.getGeneratedLocation)(state, source, location, sourceMaps); + const generatedSource = (0, _selectors.getSource)(state, generatedLocation.sourceId); + (0, _breakpoint.assertLocation)(location); + (0, _breakpoint.assertLocation)(generatedLocation); + + if ((0, _breakpoint.breakpointExists)(state, location)) { + const newBreakpoint = _objectSpread({}, breakpoint, { + location, + generatedLocation + }); + + (0, _breakpoint.assertBreakpoint)(newBreakpoint); + return { + breakpoint: newBreakpoint + }; + } + + const { + id, + hitCount, + actualLocation + } = await client.setBreakpoint(generatedLocation, breakpoint.condition, sourceMaps.isOriginalId(location.sourceId)); + const newGeneratedLocation = actualLocation || generatedLocation; + const newLocation = await sourceMaps.getOriginalLocation(newGeneratedLocation); + const symbols = (0, _selectors.getSymbols)(getState(), source); + const astLocation = await (0, _breakpoint.getASTLocation)(source, symbols, newLocation); + const originalText = (0, _source.getTextAtPosition)(source, location); + const text = (0, _source.getTextAtPosition)(generatedSource, actualLocation); + const newBreakpoint = { + id, + disabled: false, + hidden: breakpoint.hidden, + loading: false, + condition: breakpoint.condition, + location: newLocation, + astLocation, + hitCount, + generatedLocation: newGeneratedLocation, + text, + originalText + }; + (0, _breakpoint.assertBreakpoint)(newBreakpoint); + const previousLocation = (0, _breakpoint.locationMoved)(location, newLocation) ? location : null; + return { + breakpoint: newBreakpoint, + previousLocation + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/breakpoints/moz.build b/devtools/client/debugger/new/src/actions/breakpoints/moz.build new file mode 100644 index 000000000000..aa3d4822d933 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/breakpoints/moz.build @@ -0,0 +1,14 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'addBreakpoint.js', + 'remapLocations.js', + 'syncBreakpoint.js', +) diff --git a/devtools/client/debugger/new/src/actions/breakpoints/remapLocations.js b/devtools/client/debugger/new/src/actions/breakpoints/remapLocations.js new file mode 100644 index 000000000000..aafe2fdacfb0 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/breakpoints/remapLocations.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = remapLocations; + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function remapLocations(breakpoints, sourceId, sourceMaps) { + const sourceBreakpoints = breakpoints.map(async breakpoint => { + if (breakpoint.location.sourceId !== sourceId) { + return breakpoint; + } + + const location = await sourceMaps.getOriginalLocation(breakpoint.location); + return _objectSpread({}, breakpoint, { + location + }); + }); + return Promise.all(sourceBreakpoints.valueSeq()); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js b/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js new file mode 100644 index 000000000000..ad1df450f3cc --- /dev/null +++ b/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js @@ -0,0 +1,119 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.syncClientBreakpoint = syncClientBreakpoint; + +var _breakpoint = require("../../utils/breakpoint/index"); + +var _sourceMaps = require("../../utils/source-maps"); + +var _source = require("../../utils/source"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _selectors = require("../../selectors/index"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +async function makeScopedLocation({ + name, + offset +}, location, source) { + const scope = await (0, _breakpoint.findScopeByName)(source, name); // fallback onto the location line, if the scope is not found + // note: we may at some point want to delete the breakpoint if the scope + // disappears + + const line = scope ? scope.location.start.line + offset.line : location.line; + return { + line, + column: location.column, + sourceUrl: source.url, + sourceId: source.id + }; +} + +function createSyncData(id, pendingBreakpoint, location, generatedLocation, previousLocation, text, originalText) { + const overrides = _objectSpread({}, pendingBreakpoint, { + generatedLocation, + id, + text, + originalText + }); + + const breakpoint = (0, _breakpoint.createBreakpoint)(location, overrides); + (0, _breakpoint.assertBreakpoint)(breakpoint); + return { + breakpoint, + previousLocation + }; +} // we have three forms of syncing: disabled syncing, existing server syncing +// and adding a new breakpoint + + +async function syncClientBreakpoint(getState, client, sourceMaps, sourceId, pendingBreakpoint) { + (0, _breakpoint.assertPendingBreakpoint)(pendingBreakpoint); + const source = (0, _selectors.getSource)(getState(), sourceId); + const generatedSourceId = sourceMaps.isOriginalId(sourceId) ? (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId) : sourceId; + const generatedSource = (0, _selectors.getSource)(getState(), generatedSourceId); + const { + location, + astLocation + } = pendingBreakpoint; + + const previousLocation = _objectSpread({}, location, { + sourceId + }); + + const scopedLocation = await makeScopedLocation(astLocation, previousLocation, source); + const scopedGeneratedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source, scopedLocation, sourceMaps); // this is the generatedLocation of the pending breakpoint, with + // the source id updated to reflect the new connection + + const generatedLocation = _objectSpread({}, pendingBreakpoint.generatedLocation, { + sourceId: generatedSourceId + }); + + const isSameLocation = !(0, _breakpoint.locationMoved)(generatedLocation, scopedGeneratedLocation); + const existingClient = client.getBreakpointByLocation(generatedLocation); + /** ******* CASE 1: No server change ***********/ + // early return if breakpoint is disabled or we are in the sameLocation + // send update only to redux + + if (pendingBreakpoint.disabled || existingClient && isSameLocation) { + const id = pendingBreakpoint.disabled ? "" : existingClient.id; + const originalText = (0, _source.getTextAtPosition)(source, previousLocation); + const text = (0, _source.getTextAtPosition)(generatedSource, generatedLocation); + return createSyncData(id, pendingBreakpoint, scopedLocation, scopedGeneratedLocation, previousLocation, text, originalText); + } // clear server breakpoints if they exist and we have moved + + + if (existingClient) { + await client.removeBreakpoint(generatedLocation); + } + /** ******* Case 2: Add New Breakpoint ***********/ + // If we are not disabled, set the breakpoint on the server and get + // that info so we can set it on our breakpoints. + + + if (!scopedGeneratedLocation.line) { + return { + previousLocation, + breakpoint: null + }; + } + + const { + id, + actualLocation + } = await client.setBreakpoint(scopedGeneratedLocation, pendingBreakpoint.condition, sourceMaps.isOriginalId(sourceId)); // the breakpoint might have slid server side, so we want to get the location + // based on the server's return value + + const newGeneratedLocation = actualLocation; + const newLocation = await sourceMaps.getOriginalLocation(newGeneratedLocation); + const originalText = (0, _source.getTextAtPosition)(source, newLocation); + const text = (0, _source.getTextAtPosition)(generatedSource, newGeneratedLocation); + return createSyncData(id, pendingBreakpoint, newLocation, newGeneratedLocation, previousLocation, text, originalText); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/coverage.js b/devtools/client/debugger/new/src/actions/coverage.js new file mode 100644 index 000000000000..9be415713109 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/coverage.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.recordCoverage = recordCoverage; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function recordCoverage() { + return async function ({ + dispatch, + getState, + client + }) { + const { + coverage + } = await client.recordCoverage(); + return dispatch({ + type: "RECORD_COVERAGE", + value: { + coverage + } + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/debuggee.js b/devtools/client/debugger/new/src/actions/debuggee.js new file mode 100644 index 000000000000..b89333872130 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/debuggee.js @@ -0,0 +1,24 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.updateWorkers = updateWorkers; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function updateWorkers() { + return async function ({ + dispatch, + client + }) { + const { + workers + } = await client.fetchWorkers(); + dispatch({ + type: "SET_WORKERS", + workers + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/event-listeners.js b/devtools/client/debugger/new/src/actions/event-listeners.js new file mode 100644 index 000000000000..7b3d96f16107 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/event-listeners.js @@ -0,0 +1,180 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.fetchEventListeners = fetchEventListeners; +exports.updateEventBreakpoints = updateEventBreakpoints; + +var _DevToolsUtils = require("../utils/DevToolsUtils"); + +var _selectors = require("../selectors/index"); + +var _waitService = require("./utils/middleware/wait-service"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* global window gThreadClient setNamedTimeout EVENTS */ + +/* eslint no-shadow: 0 */ + +/** + * Redux actions for the event listeners state + * @module actions/event-listeners + */ +// delay is in ms +const FETCH_EVENT_LISTENERS_DELAY = 200; +let fetchListenersTimerID; +/** + * @memberof utils/utils + * @static + */ + +async function asPaused(state, client, func) { + if (!(0, _selectors.isPaused)(state)) { + await client.interrupt(); + let result; + + try { + result = await func(client); + } catch (e) { + // Try to put the debugger back in a working state by resuming + // it + await client.resume(); + throw e; + } + + await client.resume(); + return result; + } + + return func(client); +} +/** + * @memberof actions/event-listeners + * @static + */ + + +function fetchEventListeners() { + return ({ + dispatch, + getState, + client + }) => { + // Make sure we"re not sending a batch of closely repeated requests. + // This can easily happen whenever new sources are fetched. + if (fetchListenersTimerID) { + clearTimeout(fetchListenersTimerID); + } + + fetchListenersTimerID = setTimeout(() => { + // In case there is still a request of listeners going on (it + // takes several RDP round trips right now), make sure we wait + // on a currently running request + if (getState().eventListeners.fetchingListeners) { + dispatch({ + type: _waitService.NAME, + predicate: action => action.type === "FETCH_EVENT_LISTENERS" && action.status === "done", + run: dispatch => dispatch(fetchEventListeners()) + }); + return; + } + + dispatch({ + type: "FETCH_EVENT_LISTENERS", + status: "begin" + }); + asPaused(getState(), client, _getEventListeners).then(listeners => { + dispatch({ + type: "FETCH_EVENT_LISTENERS", + status: "done", + listeners: formatListeners(getState(), listeners) + }); + }); + }, FETCH_EVENT_LISTENERS_DELAY); + }; +} + +function formatListeners(state, listeners) { + return listeners.map(l => { + return { + selector: l.node.selector, + type: l.type, + sourceId: (0, _selectors.getSourceByURL)(state, l.function.location.url).get("id"), + line: l.function.location.line + }; + }); +} + +async function _getEventListeners(threadClient) { + const response = await threadClient.eventListeners(); // Make sure all the listeners are sorted by the event type, since + // they"re not guaranteed to be clustered together. + + response.listeners.sort((a, b) => a.type > b.type ? 1 : -1); // Add all the listeners in the debugger view event linsteners container. + + const fetchedDefinitions = new Map(); + const listeners = []; + + for (const listener of response.listeners) { + let definitionSite; + + if (fetchedDefinitions.has(listener.function.actor)) { + definitionSite = fetchedDefinitions.get(listener.function.actor); + } else if (listener.function.class == "Function") { + definitionSite = await _getDefinitionSite(threadClient, listener.function); + + if (!definitionSite) { + // We don"t know where this listener comes from so don"t show it in + // the UI as breaking on it doesn"t work (bug 942899). + continue; + } + + fetchedDefinitions.set(listener.function.actor, definitionSite); + } + + listener.function.url = definitionSite; + listeners.push(listener); + } + + fetchedDefinitions.clear(); + return listeners; +} + +async function _getDefinitionSite(threadClient, func) { + const grip = threadClient.pauseGrip(func); + let response; + + try { + response = await grip.getDefinitionSite(); + } catch (e) { + // Don't make this error fatal, it would break the entire events pane. + (0, _DevToolsUtils.reportException)("_getDefinitionSite", e); + return null; + } + + return response.source.url; +} +/** + * @memberof actions/event-listeners + * @static + * @param {string} eventNames + */ + + +function updateEventBreakpoints(eventNames) { + return dispatch => { + setNamedTimeout("event-breakpoints-update", 0, () => { + gThreadClient.pauseOnDOMEvents(eventNames, () => { + // Notify that event breakpoints were added/removed on the server. + window.emit(EVENTS.EVENT_BREAKPOINTS_UPDATED); + dispatch({ + type: "UPDATE_EVENT_BREAKPOINTS", + eventNames: eventNames + }); + }); + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/expressions.js b/devtools/client/debugger/new/src/actions/expressions.js new file mode 100644 index 000000000000..262ff566d163 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/expressions.js @@ -0,0 +1,218 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.addExpression = addExpression; +exports.autocomplete = autocomplete; +exports.clearExpressionError = clearExpressionError; +exports.updateExpression = updateExpression; +exports.deleteExpression = deleteExpression; +exports.evaluateExpressions = evaluateExpressions; +exports.getMappedExpression = getMappedExpression; + +var _selectors = require("../selectors/index"); + +var _promise = require("./utils/middleware/promise"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _expressions = require("../utils/expressions"); + +var _parser = require("../workers/parser/index"); + +var parser = _interopRequireWildcard(_parser); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Add expression for debugger to watch + * + * @param {object} expression + * @param {number} expression.id + * @memberof actions/pause + * @static + */ +function addExpression(input) { + return async ({ + dispatch, + getState + }) => { + if (!input) { + return; + } + + const expressionError = await parser.hasSyntaxError(input); + const expression = (0, _selectors.getExpression)(getState(), input); + + if (expression) { + return dispatch(evaluateExpression(expression)); + } + + dispatch({ + type: "ADD_EXPRESSION", + input, + expressionError + }); + const newExpression = (0, _selectors.getExpression)(getState(), input); + + if (newExpression) { + return dispatch(evaluateExpression(newExpression)); + } + }; +} + +function autocomplete(input, cursor) { + return async ({ + dispatch, + getState, + client + }) => { + if (!input) { + return; + } + + const frameId = (0, _selectors.getSelectedFrameId)(getState()); + const result = await client.autocomplete(input, cursor, frameId); + await dispatch({ + type: "AUTOCOMPLETE", + input, + result + }); + }; +} + +function clearExpressionError() { + return { + type: "CLEAR_EXPRESSION_ERROR" + }; +} + +function updateExpression(input, expression) { + return async ({ + dispatch, + getState + }) => { + if (!input) { + return; + } + + const expressionError = await parser.hasSyntaxError(input); + dispatch({ + type: "UPDATE_EXPRESSION", + expression, + input: expressionError ? expression.input : input, + expressionError + }); + dispatch(evaluateExpressions()); + }; +} +/** + * + * @param {object} expression + * @param {number} expression.id + * @memberof actions/pause + * @static + */ + + +function deleteExpression(expression) { + return ({ + dispatch + }) => { + dispatch({ + type: "DELETE_EXPRESSION", + input: expression.input + }); + }; +} +/** + * + * @memberof actions/pause + * @param {number} selectedFrameId + * @static + */ + + +function evaluateExpressions() { + return async function ({ + dispatch, + getState, + client + }) { + const expressions = (0, _selectors.getExpressions)(getState()).toJS(); + const inputs = expressions.map(({ + input + }) => input); + const frameId = (0, _selectors.getSelectedFrameId)(getState()); + const results = await client.evaluateExpressions(inputs, frameId); + dispatch({ + type: "EVALUATE_EXPRESSIONS", + inputs, + results + }); + }; +} + +function evaluateExpression(expression) { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + if (!expression.input) { + console.warn("Expressions should not be empty"); + return; + } + + let input = expression.input; + const frame = (0, _selectors.getSelectedFrame)(getState()); + + if (frame) { + const { + location + } = frame; + const source = (0, _selectors.getSource)(getState(), location.sourceId); + const sourceId = source.get("id"); + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (selectedSource && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) && !(0, _devtoolsSourceMap.isGeneratedId)(selectedSource.get("id"))) { + input = await dispatch(getMappedExpression(input)); + } + } + + const frameId = (0, _selectors.getSelectedFrameId)(getState()); + return dispatch({ + type: "EVALUATE_EXPRESSION", + input: expression.input, + [_promise.PROMISE]: client.evaluateInFrame((0, _expressions.wrapExpression)(input), frameId) + }); + }; +} +/** + * Gets information about original variable names from the source map + * and replaces all posible generated names. + */ + + +function getMappedExpression(expression) { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + const mappings = (0, _selectors.getSelectedScopeMappings)(getState()); + + if (!mappings) { + return expression; + } + + return parser.mapOriginalExpression(expression, mappings); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/file-search.js b/devtools/client/debugger/new/src/actions/file-search.js new file mode 100644 index 000000000000..436712a97010 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/file-search.js @@ -0,0 +1,201 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.doSearch = doSearch; +exports.doSearchForHighlight = doSearchForHighlight; +exports.setFileSearchQuery = setFileSearchQuery; +exports.toggleFileSearchModifier = toggleFileSearchModifier; +exports.updateSearchResults = updateSearchResults; +exports.searchContents = searchContents; +exports.searchContentsForHighlight = searchContentsForHighlight; +exports.traverseResults = traverseResults; +exports.closeFileSearch = closeFileSearch; + +var _editor = require("../utils/editor/index"); + +var _search = require("../workers/search/index"); + +var _selectors = require("../selectors/index"); + +var _ui = require("./ui"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function doSearch(query, editor) { + return ({ + getState, + dispatch + }) => { + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!selectedSource || !selectedSource.text) { + return; + } + + dispatch(setFileSearchQuery(query)); + dispatch(searchContents(query, editor)); + }; +} + +function doSearchForHighlight(query, editor, line, ch) { + return async ({ + getState, + dispatch + }) => { + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!selectedSource || !selectedSource.text) { + return; + } + + dispatch(searchContentsForHighlight(query, editor, line, ch)); + }; +} + +function setFileSearchQuery(query) { + return { + type: "UPDATE_FILE_SEARCH_QUERY", + query + }; +} + +function toggleFileSearchModifier(modifier) { + return { + type: "TOGGLE_FILE_SEARCH_MODIFIER", + modifier + }; +} + +function updateSearchResults(characterIndex, line, matches) { + const matchIndex = matches.findIndex(elm => elm.line === line && elm.ch === characterIndex); + return { + type: "UPDATE_SEARCH_RESULTS", + results: { + matches, + matchIndex, + count: matches.length, + index: characterIndex + } + }; +} + +function searchContents(query, editor) { + return async ({ + getState, + dispatch + }) => { + const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) { + return; + } + + const ctx = { + ed: editor, + cm: editor.codeMirror + }; + + const _modifiers = modifiers.toJS(); + + const matches = await (0, _search.getMatches)(query, selectedSource.text, _modifiers); + const res = (0, _editor.find)(ctx, query, true, _modifiers); + + if (!res) { + return; + } + + const { + ch, + line + } = res; + dispatch(updateSearchResults(ch, line, matches)); + }; +} + +function searchContentsForHighlight(query, editor, line, ch) { + return async ({ + getState, + dispatch + }) => { + const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!query || !editor || !selectedSource || !selectedSource.text || !modifiers) { + return; + } + + const ctx = { + ed: editor, + cm: editor.codeMirror + }; + + const _modifiers = modifiers.toJS(); + + (0, _editor.searchSourceForHighlight)(ctx, false, query, true, _modifiers, line, ch); + }; +} + +function traverseResults(rev, editor) { + return async ({ + getState, + dispatch + }) => { + if (!editor) { + return; + } + + const ctx = { + ed: editor, + cm: editor.codeMirror + }; + const query = (0, _selectors.getFileSearchQuery)(getState()); + const modifiers = (0, _selectors.getFileSearchModifiers)(getState()); + const { + matches + } = (0, _selectors.getFileSearchResults)(getState()); + + if (query === "") { + dispatch((0, _ui.setActiveSearch)("file")); + } + + if (modifiers) { + const matchedLocations = matches || []; + const results = rev ? (0, _editor.findPrev)(ctx, query, true, modifiers.toJS()) : (0, _editor.findNext)(ctx, query, true, modifiers.toJS()); + + if (!results) { + return; + } + + const { + ch, + line + } = results; + dispatch(updateSearchResults(ch, line, matchedLocations)); + } + }; +} + +function closeFileSearch(editor) { + return ({ + getState, + dispatch + }) => { + const query = (0, _selectors.getFileSearchQuery)(getState()); + + if (editor) { + const ctx = { + ed: editor, + cm: editor.codeMirror + }; + (0, _editor.removeOverlay)(ctx, query); + } + + dispatch(setFileSearchQuery("")); + dispatch((0, _ui.closeActiveSearch)()); + dispatch((0, _ui.clearHighlightLineRange)()); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/index.js b/devtools/client/debugger/new/src/actions/index.js new file mode 100644 index 000000000000..e7b0e04aa4fc --- /dev/null +++ b/devtools/client/debugger/new/src/actions/index.js @@ -0,0 +1,81 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _breakpoints = require("./breakpoints"); + +var breakpoints = _interopRequireWildcard(_breakpoints); + +var _expressions = require("./expressions"); + +var expressions = _interopRequireWildcard(_expressions); + +var _eventListeners = require("./event-listeners"); + +var eventListeners = _interopRequireWildcard(_eventListeners); + +var _pause = require("./pause/index"); + +var pause = _interopRequireWildcard(_pause); + +var _navigation = require("./navigation"); + +var navigation = _interopRequireWildcard(_navigation); + +var _ui = require("./ui"); + +var ui = _interopRequireWildcard(_ui); + +var _fileSearch = require("./file-search"); + +var fileSearch = _interopRequireWildcard(_fileSearch); + +var _ast = require("./ast"); + +var ast = _interopRequireWildcard(_ast); + +var _coverage = require("./coverage"); + +var coverage = _interopRequireWildcard(_coverage); + +var _projectTextSearch = require("./project-text-search"); + +var projectTextSearch = _interopRequireWildcard(_projectTextSearch); + +var _replay = require("./replay"); + +var replay = _interopRequireWildcard(_replay); + +var _quickOpen = require("./quick-open"); + +var quickOpen = _interopRequireWildcard(_quickOpen); + +var _sourceTree = require("./source-tree"); + +var sourceTree = _interopRequireWildcard(_sourceTree); + +var _sources = require("./sources/index"); + +var sources = _interopRequireWildcard(_sources); + +var _debuggee = require("./debuggee"); + +var debuggee = _interopRequireWildcard(_debuggee); + +var _toolbox = require("./toolbox"); + +var toolbox = _interopRequireWildcard(_toolbox); + +var _preview = require("./preview"); + +var preview = _interopRequireWildcard(_preview); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +exports.default = _objectSpread({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, fileSearch, ast, coverage, projectTextSearch, replay, quickOpen, sourceTree, debuggee, toolbox, preview); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/moz.build b/devtools/client/debugger/new/src/actions/moz.build new file mode 100644 index 000000000000..c47e0426aaf7 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/moz.build @@ -0,0 +1,31 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'ast', + 'breakpoints', + 'pause', + 'sources', + 'utils', +] + +DevToolsModules( + 'ast.js', + 'breakpoints.js', + 'coverage.js', + 'debuggee.js', + 'event-listeners.js', + 'expressions.js', + 'file-search.js', + 'index.js', + 'navigation.js', + 'preview.js', + 'project-text-search.js', + 'quick-open.js', + 'replay.js', + 'source-tree.js', + 'toolbox.js', + 'ui.js', +) diff --git a/devtools/client/debugger/new/src/actions/navigation.js b/devtools/client/debugger/new/src/actions/navigation.js new file mode 100644 index 000000000000..f3f873d2c895 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/navigation.js @@ -0,0 +1,103 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.willNavigate = willNavigate; +exports.navigate = navigate; +exports.connect = connect; +exports.navigated = navigated; + +var _editor = require("../utils/editor/index"); + +var _sourceQueue = require("../utils/source-queue"); + +var _sourceQueue2 = _interopRequireDefault(_sourceQueue); + +var _sources = require("../reducers/sources"); + +var _utils = require("../utils/utils"); + +var _sources2 = require("./sources/index"); + +var _debuggee = require("./debuggee"); + +var _parser = require("../workers/parser/index"); + +var _wasm = require("../utils/wasm"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Redux actions for the navigation state + * @module actions/navigation + */ + +/** + * @memberof actions/navigation + * @static + */ +function willNavigate(event) { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + await sourceMaps.clearSourceMaps(); + (0, _wasm.clearWasmStates)(); + (0, _editor.clearDocuments)(); + (0, _editor.removeEditor)(); + (0, _parser.clearSymbols)(); + (0, _parser.clearASTs)(); + (0, _parser.clearScopes)(); + (0, _parser.clearSources)(); + dispatch(navigate(event.url)); + }; +} + +function navigate(url) { + _sourceQueue2.default.clear(); + + return { + type: "NAVIGATE", + url + }; +} + +function connect(url, canRewind) { + return async function ({ + dispatch + }) { + await dispatch((0, _debuggee.updateWorkers)()); + dispatch({ + type: "CONNECT", + url, + canRewind + }); + }; +} +/** + * @memberof actions/navigation + * @static + */ + + +function navigated() { + return async function ({ + dispatch, + getState, + client + }) { + await (0, _utils.waitForMs)(100); + + if ((0, _sources.getSources)(getState()).size == 0) { + const sources = await client.fetchSources(); + dispatch((0, _sources2.newSources)(sources)); + } + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/breakOnNext.js b/devtools/client/debugger/new/src/actions/pause/breakOnNext.js new file mode 100644 index 000000000000..d9a7b87ea3b4 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/breakOnNext.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.breakOnNext = breakOnNext; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Debugger breakOnNext command. + * It's different from the comand action because we also want to + * highlight the pause icon. + * + * @memberof actions/pause + * @static + */ +function breakOnNext() { + return ({ + dispatch, + client + }) => { + client.breakOnNext(); + return dispatch({ + type: "BREAK_ON_NEXT", + value: true + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/commands.js b/devtools/client/debugger/new/src/actions/pause/commands.js new file mode 100644 index 000000000000..3ce653d94552 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/commands.js @@ -0,0 +1,257 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.command = command; +exports.stepIn = stepIn; +exports.stepOver = stepOver; +exports.stepOut = stepOut; +exports.resume = resume; +exports.rewind = rewind; +exports.reverseStepIn = reverseStepIn; +exports.reverseStepOver = reverseStepOver; +exports.reverseStepOut = reverseStepOut; +exports.astCommand = astCommand; + +var _selectors = require("../../selectors/index"); + +var _promise = require("../utils/middleware/promise"); + +var _parser = require("../../workers/parser/index"); + +var _breakpoints = require("../breakpoints"); + +var _prefs = require("../../utils/prefs"); + +/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Debugger commands like stepOver, stepIn, stepUp + * + * @param string $0.type + * @memberof actions/pause + * @static + */ +function command(type) { + return async ({ + dispatch, + client + }) => { + return dispatch({ + type: "COMMAND", + command: type, + [_promise.PROMISE]: client[type]() + }); + }; +} +/** + * StepIn + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function stepIn() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(command("stepIn")); + } + }; +} +/** + * stepOver + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function stepOver() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(astCommand("stepOver")); + } + }; +} +/** + * stepOut + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function stepOut() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(command("stepOut")); + } + }; +} +/** + * resume + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function resume() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(command("resume")); + } + }; +} +/** + * rewind + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function rewind() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(command("rewind")); + } + }; +} +/** + * reverseStepIn + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function reverseStepIn() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(command("reverseStepIn")); + } + }; +} +/** + * reverseStepOver + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function reverseStepOver() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(astCommand("reverseStepOver")); + } + }; +} +/** + * reverseStepOut + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + + +function reverseStepOut() { + return ({ + dispatch, + getState + }) => { + if ((0, _selectors.isPaused)(getState())) { + return dispatch(command("reverseStepOut")); + } + }; +} +/* + * Checks for await or yield calls on the paused line + * This avoids potentially expensive parser calls when we are likely + * not at an async expression. + */ + + +function hasAwait(source, pauseLocation) { + const { + line, + column + } = pauseLocation; + + if (!source.text) { + return false; + } + + const lineText = source.text.split("\n")[line - 1]; + + if (!lineText) { + return false; + } + + const snippet = lineText.slice(column - 50, column + 50); + return !!snippet.match(/(yield|await)/); +} +/** + * @memberOf actions/pause + * @static + * @param stepType + * @returns {function(ThunkArgs)} + */ + + +function astCommand(stepType) { + return async ({ + dispatch, + getState, + sourceMaps + }) => { + if (!_prefs.features.asyncStepping) { + return dispatch(command(stepType)); + } + + if (stepType == "stepOver") { + // This type definition is ambiguous: + const frame = (0, _selectors.getTopFrame)(getState()); + const source = (0, _selectors.getSource)(getState(), frame.location.sourceId); + + if (source && hasAwait(source, frame.location)) { + const nextLocation = await (0, _parser.getNextStep)(source.id, frame.location); + + if (nextLocation) { + await dispatch((0, _breakpoints.addHiddenBreakpoint)(nextLocation)); + return dispatch(command("resume")); + } + } + } + + return dispatch(command(stepType)); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/continueToHere.js b/devtools/client/debugger/new/src/actions/pause/continueToHere.js new file mode 100644 index 000000000000..5e34bca0e97b --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/continueToHere.js @@ -0,0 +1,43 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.continueToHere = continueToHere; + +var _selectors = require("../../selectors/index"); + +var _breakpoints = require("../breakpoints"); + +var _commands = require("./commands"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function continueToHere(line) { + return async function ({ + dispatch, + getState + }) { + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!(0, _selectors.isPaused)(getState()) || !selectedSource) { + return; + } + + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); + const debugLine = selectedFrame.location.line; + + if (debugLine == line) { + return; + } + + const action = (0, _selectors.getCanRewind)(getState()) && line < debugLine ? _commands.rewind : _commands.resume; + await dispatch((0, _breakpoints.addHiddenBreakpoint)({ + line, + column: undefined, + sourceId: selectedSource.id + })); + dispatch(action()); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/extra.js b/devtools/client/debugger/new/src/actions/pause/extra.js new file mode 100644 index 000000000000..b9b13ebd46d1 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/extra.js @@ -0,0 +1,111 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.fetchExtra = fetchExtra; +exports.getExtra = getExtra; + +var _selectors = require("../../selectors/index"); + +var _preview = require("../../utils/preview"); + +var _ast = require("../../utils/ast"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +async function getReactProps(evaluate) { + const componentNames = await evaluate(` + if(this.hasOwnProperty('_reactInternalFiber')) { + let componentNames = []; + let componentNode = this._reactInternalFiber; + while(componentNode) { + componentNames.push(componentNode.type.name); + componentNode = componentNode._debugOwner + } + componentNames; + } + else { + [this._reactInternalInstance.getName()]; + } + `); + const items = componentNames.result.preview && componentNames.result.preview.items; + + if (items) { + return { + displayName: items[0], + componentStack: items + }; + } +} + +async function getImmutableProps(expression, evaluate) { + const immutableEntries = await evaluate((exp => `${exp}.toJS()`)(expression)); + const immutableType = await evaluate((exp => `${exp}.constructor.name`)(expression)); + return { + type: immutableType.result, + entries: immutableEntries.result + }; +} + +async function getExtraProps(getState, expression, result, evaluate) { + const props = {}; + + if ((0, _preview.isReactComponent)(result)) { + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); + const source = (0, _selectors.getSource)(getState(), selectedFrame.location.sourceId); + const symbols = (0, _selectors.getSymbols)(getState(), source); + + if (symbols && symbols.classes) { + const originalClass = (0, _ast.findClosestClass)(symbols, selectedFrame.location); + + if (originalClass) { + props.react = { + displayName: originalClass.name + }; + } + } + + props.react = _objectSpread({}, (await getReactProps(evaluate)), props.react); + } + + if ((0, _preview.isImmutable)(result)) { + props.immutable = await getImmutableProps(expression, evaluate); + } + + return props; +} + +function fetchExtra() { + return async function ({ + dispatch, + getState + }) { + const frame = (0, _selectors.getSelectedFrame)(getState()); + const extra = await dispatch(getExtra("this;", frame.this)); + dispatch({ + type: "ADD_EXTRA", + extra: extra + }); + }; +} + +function getExtra(expression, result) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); + + if (!selectedFrame) { + return; + } + + const extra = await getExtraProps(getState, expression, result, expr => client.evaluateInFrame(expr, selectedFrame.id)); + return extra; + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/fetchScopes.js b/devtools/client/debugger/new/src/actions/pause/fetchScopes.js new file mode 100644 index 000000000000..94379d6bfcc8 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/fetchScopes.js @@ -0,0 +1,40 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.fetchScopes = fetchScopes; + +var _selectors = require("../../selectors/index"); + +var _mapScopes = require("./mapScopes"); + +var _promise = require("../utils/middleware/promise"); + +var _extra = require("./extra"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function fetchScopes() { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + const frame = (0, _selectors.getSelectedFrame)(getState()); + + if (!frame || (0, _selectors.getGeneratedFrameScope)(getState(), frame.id)) { + return; + } + + const scopes = dispatch({ + type: "ADD_SCOPES", + frame, + [_promise.PROMISE]: client.getFrameScopes(frame) + }); + await dispatch((0, _extra.fetchExtra)()); + await dispatch((0, _mapScopes.mapScopes)(scopes, frame)); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/index.js b/devtools/client/debugger/new/src/actions/pause/index.js new file mode 100644 index 000000000000..866d167d869d --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/index.js @@ -0,0 +1,161 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _commands = require("./commands"); + +Object.defineProperty(exports, "stepIn", { + enumerable: true, + get: function () { + return _commands.stepIn; + } +}); +Object.defineProperty(exports, "stepOver", { + enumerable: true, + get: function () { + return _commands.stepOver; + } +}); +Object.defineProperty(exports, "stepOut", { + enumerable: true, + get: function () { + return _commands.stepOut; + } +}); +Object.defineProperty(exports, "resume", { + enumerable: true, + get: function () { + return _commands.resume; + } +}); +Object.defineProperty(exports, "rewind", { + enumerable: true, + get: function () { + return _commands.rewind; + } +}); +Object.defineProperty(exports, "reverseStepIn", { + enumerable: true, + get: function () { + return _commands.reverseStepIn; + } +}); +Object.defineProperty(exports, "reverseStepOver", { + enumerable: true, + get: function () { + return _commands.reverseStepOver; + } +}); +Object.defineProperty(exports, "reverseStepOut", { + enumerable: true, + get: function () { + return _commands.reverseStepOut; + } +}); + +var _fetchScopes = require("./fetchScopes"); + +Object.defineProperty(exports, "fetchScopes", { + enumerable: true, + get: function () { + return _fetchScopes.fetchScopes; + } +}); + +var _paused = require("./paused"); + +Object.defineProperty(exports, "paused", { + enumerable: true, + get: function () { + return _paused.paused; + } +}); + +var _resumed = require("./resumed"); + +Object.defineProperty(exports, "resumed", { + enumerable: true, + get: function () { + return _resumed.resumed; + } +}); + +var _continueToHere = require("./continueToHere"); + +Object.defineProperty(exports, "continueToHere", { + enumerable: true, + get: function () { + return _continueToHere.continueToHere; + } +}); + +var _breakOnNext = require("./breakOnNext"); + +Object.defineProperty(exports, "breakOnNext", { + enumerable: true, + get: function () { + return _breakOnNext.breakOnNext; + } +}); + +var _mapFrames = require("./mapFrames"); + +Object.defineProperty(exports, "mapFrames", { + enumerable: true, + get: function () { + return _mapFrames.mapFrames; + } +}); + +var _extra = require("./extra"); + +Object.defineProperty(exports, "fetchExtra", { + enumerable: true, + get: function () { + return _extra.fetchExtra; + } +}); +Object.defineProperty(exports, "getExtra", { + enumerable: true, + get: function () { + return _extra.getExtra; + } +}); + +var _setPopupObjectProperties = require("./setPopupObjectProperties"); + +Object.defineProperty(exports, "setPopupObjectProperties", { + enumerable: true, + get: function () { + return _setPopupObjectProperties.setPopupObjectProperties; + } +}); + +var _pauseOnExceptions = require("./pauseOnExceptions"); + +Object.defineProperty(exports, "pauseOnExceptions", { + enumerable: true, + get: function () { + return _pauseOnExceptions.pauseOnExceptions; + } +}); + +var _selectFrame = require("./selectFrame"); + +Object.defineProperty(exports, "selectFrame", { + enumerable: true, + get: function () { + return _selectFrame.selectFrame; + } +}); + +var _skipPausing = require("./skipPausing"); + +Object.defineProperty(exports, "toggleSkipPausing", { + enumerable: true, + get: function () { + return _skipPausing.toggleSkipPausing; + } +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/mapFrames.js b/devtools/client/debugger/new/src/actions/pause/mapFrames.js new file mode 100644 index 000000000000..09f60e0a01f4 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/mapFrames.js @@ -0,0 +1,84 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.updateFrameLocation = updateFrameLocation; +exports.mapDisplayNames = mapDisplayNames; +exports.mapFrames = mapFrames; + +var _selectors = require("../../selectors/index"); + +var _ast = require("../../utils/ast"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function updateFrameLocation(frame, sourceMaps) { + return sourceMaps.getOriginalLocation(frame.location).then(loc => _objectSpread({}, frame, { + location: loc, + generatedLocation: frame.generatedLocation || frame.location + })); +} + +function updateFrameLocations(frames, sourceMaps) { + if (!frames || frames.length == 0) { + return Promise.resolve(frames); + } + + return Promise.all(frames.map(frame => updateFrameLocation(frame, sourceMaps))); +} + +function mapDisplayNames(frames, getState) { + return frames.map(frame => { + const source = (0, _selectors.getSource)(getState(), frame.location.sourceId); + const symbols = (0, _selectors.getSymbols)(getState(), source); + + if (!symbols || !symbols.functions) { + return frame; + } + + const originalFunction = (0, _ast.findClosestFunction)(symbols, frame.location); + + if (!originalFunction) { + return frame; + } + + const originalDisplayName = originalFunction.name; + return _objectSpread({}, frame, { + originalDisplayName + }); + }); +} +/** + * Map call stack frame locations and display names to originals. + * e.g. + * 1. When the debuggee pauses + * 2. When a source is pretty printed + * 3. When symbols are loaded + * @memberof actions/pause + * @static + */ + + +function mapFrames() { + return async function ({ + dispatch, + getState, + sourceMaps + }) { + const frames = (0, _selectors.getFrames)(getState()); + + if (!frames) { + return; + } + + let mappedFrames = await updateFrameLocations(frames, sourceMaps); + mappedFrames = mapDisplayNames(mappedFrames, getState); + dispatch({ + type: "MAP_FRAMES", + frames: mappedFrames + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/mapScopes.js b/devtools/client/debugger/new/src/actions/pause/mapScopes.js new file mode 100644 index 000000000000..3c1bc7bc7478 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/mapScopes.js @@ -0,0 +1,54 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.mapScopes = mapScopes; + +var _selectors = require("../../selectors/index"); + +var _loadSourceText = require("../sources/loadSourceText"); + +var _promise = require("../utils/middleware/promise"); + +var _prefs = require("../../utils/prefs"); + +var _log = require("../../utils/log"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _mapScopes = require("../../utils/pause/mapScopes/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function mapScopes(scopes, frame) { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + const generatedSourceRecord = (0, _selectors.getSource)(getState(), frame.generatedLocation.sourceId); + const sourceRecord = (0, _selectors.getSource)(getState(), frame.location.sourceId); + const shouldMapScopes = _prefs.features.mapScopes && !generatedSourceRecord.isWasm && !sourceRecord.isPrettyPrinted && !(0, _devtoolsSourceMap.isGeneratedId)(frame.location.sourceId); + await dispatch({ + type: "MAP_SCOPES", + frame, + [_promise.PROMISE]: async function () { + if (!shouldMapScopes) { + return null; + } + + await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord)); + + try { + return await (0, _mapScopes.buildMappedScopes)(sourceRecord.toJS(), frame, (await scopes), sourceMaps, client); + } catch (e) { + (0, _log.log)(e); + return null; + } + }() + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/moz.build b/devtools/client/debugger/new/src/actions/pause/moz.build new file mode 100644 index 000000000000..93825e7361cb --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/moz.build @@ -0,0 +1,25 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'breakOnNext.js', + 'commands.js', + 'continueToHere.js', + 'extra.js', + 'fetchScopes.js', + 'index.js', + 'mapFrames.js', + 'mapScopes.js', + 'paused.js', + 'pauseOnExceptions.js', + 'resumed.js', + 'selectFrame.js', + 'setPopupObjectProperties.js', + 'skipPausing.js', +) diff --git a/devtools/client/debugger/new/src/actions/pause/pauseOnExceptions.js b/devtools/client/debugger/new/src/actions/pause/pauseOnExceptions.js new file mode 100644 index 000000000000..b57658b6df5c --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/pauseOnExceptions.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.pauseOnExceptions = pauseOnExceptions; + +var _promise = require("../utils/middleware/promise"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * + * @memberof actions/pause + * @static + */ +function pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) { + return ({ + dispatch, + client + }) => { + return dispatch({ + type: "PAUSE_ON_EXCEPTIONS", + shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions, + [_promise.PROMISE]: client.pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/paused.js b/devtools/client/debugger/new/src/actions/pause/paused.js new file mode 100644 index 000000000000..a6da24e0a314 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/paused.js @@ -0,0 +1,105 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.paused = paused; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _selectors = require("../../selectors/index"); + +var _ = require("./index"); + +var _breakpoints = require("../breakpoints"); + +var _expressions = require("../expressions"); + +var _sources = require("../sources/index"); + +var _loadSourceText = require("../sources/loadSourceText"); + +var _ui = require("../ui"); + +var _commands = require("./commands"); + +var _pause = require("../../utils/pause/index"); + +var _mapFrames = require("./mapFrames"); + +var _fetchScopes = require("./fetchScopes"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +async function getOriginalSourceForFrame(state, frame) { + return (0, _selectors.getSources)(state).get(frame.location.sourceId); +} +/** + * Debugger has just paused + * + * @param {object} pauseInfo + * @memberof actions/pause + * @static + */ + + +function paused(pauseInfo) { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + const { + frames, + why, + loadedObjects + } = pauseInfo; + const rootFrame = frames.length > 0 ? frames[0] : null; + + if (rootFrame) { + const mappedFrame = await (0, _mapFrames.updateFrameLocation)(rootFrame, sourceMaps); + const source = await getOriginalSourceForFrame(getState(), mappedFrame); // Ensure that the original file has loaded if there is one. + + await dispatch((0, _loadSourceText.loadSourceText)(source)); + + if ((0, _pause.shouldStep)(mappedFrame, getState(), sourceMaps)) { + dispatch((0, _commands.command)("stepOver")); + return; + } + } + + dispatch({ + type: "PAUSED", + why, + frames, + selectedFrameId: rootFrame ? rootFrame.id : undefined, + loadedObjects: loadedObjects || [] + }); + const hiddenBreakpointLocation = (0, _selectors.getHiddenBreakpointLocation)(getState()); + + if (hiddenBreakpointLocation) { + dispatch((0, _breakpoints.removeBreakpoint)(hiddenBreakpointLocation)); + } + + await dispatch((0, _.mapFrames)()); + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); + + if (selectedFrame) { + const visibleFrame = (0, _selectors.getVisibleSelectedFrame)(getState()); + const location = (0, _devtoolsSourceMap.isGeneratedId)(visibleFrame.location.sourceId) ? selectedFrame.generatedLocation : selectedFrame.location; + await dispatch((0, _sources.selectLocation)(location)); + } + + dispatch((0, _ui.togglePaneCollapse)("end", false)); + await dispatch((0, _fetchScopes.fetchScopes)()); // Run after fetching scoping data so that it may make use of the sourcemap + // expression mappings for local variables. + + const atException = why.type == "exception"; + + if (!atException || !(0, _selectors.isEvaluatingExpression)(getState())) { + await dispatch((0, _expressions.evaluateExpressions)()); + } + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/resumed.js b/devtools/client/debugger/new/src/actions/pause/resumed.js new file mode 100644 index 000000000000..c86e008799f8 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/resumed.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.resumed = resumed; + +var _selectors = require("../../selectors/index"); + +var _expressions = require("../expressions"); + +var _pause = require("../../utils/pause/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Debugger has just resumed + * + * @memberof actions/pause + * @static + */ +function resumed() { + return async ({ + dispatch, + client, + getState + }) => { + const why = (0, _selectors.getPauseReason)(getState()); + const wasPausedInEval = (0, _pause.inDebuggerEval)(why); + const wasStepping = (0, _selectors.isStepping)(getState()); + dispatch({ + type: "RESUME" + }); + + if (!wasStepping && !wasPausedInEval) { + await dispatch((0, _expressions.evaluateExpressions)()); + } + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/selectFrame.js b/devtools/client/debugger/new/src/actions/pause/selectFrame.js new file mode 100644 index 000000000000..391f12d26a8f --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/selectFrame.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.selectFrame = selectFrame; + +var _sources = require("../sources/index"); + +var _expressions = require("../expressions"); + +var _fetchScopes = require("./fetchScopes"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * @memberof actions/pause + * @static + */ +function selectFrame(frame) { + return async ({ + dispatch, + client, + getState, + sourceMaps + }) => { + dispatch({ + type: "SELECT_FRAME", + frame + }); + dispatch((0, _sources.selectLocation)(frame.location)); + dispatch((0, _expressions.evaluateExpressions)()); + dispatch((0, _fetchScopes.fetchScopes)()); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/setPopupObjectProperties.js b/devtools/client/debugger/new/src/actions/pause/setPopupObjectProperties.js new file mode 100644 index 000000000000..e13516246934 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/setPopupObjectProperties.js @@ -0,0 +1,36 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setPopupObjectProperties = setPopupObjectProperties; + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * @memberof actions/pause + * @static + */ +function setPopupObjectProperties(object, properties) { + return ({ + dispatch, + client, + getState + }) => { + const objectId = object.actor || object.objectId; + + if ((0, _selectors.getPopupObjectProperties)(getState(), object.actor)) { + return; + } + + dispatch({ + type: "SET_POPUP_OBJECT_PROPERTIES", + objectId, + properties + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/pause/skipPausing.js b/devtools/client/debugger/new/src/actions/pause/skipPausing.js new file mode 100644 index 000000000000..2c6e427e466a --- /dev/null +++ b/devtools/client/debugger/new/src/actions/pause/skipPausing.js @@ -0,0 +1,33 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.toggleSkipPausing = toggleSkipPausing; + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * @memberof actions/pause + * @static + */ +function toggleSkipPausing() { + return async ({ + dispatch, + client, + getState, + sourceMaps + }) => { + const skipPausing = !(0, _selectors.getSkipPausing)(getState()); // NOTE: enable this when we land the endpoint in m-c + // await client.setSkipPausing(skipPausing); + + dispatch({ + type: "TOGGLE_SKIP_PAUSING", + skipPausing + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/preview.js b/devtools/client/debugger/new/src/actions/preview.js new file mode 100644 index 000000000000..3ab8c92d6f96 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/preview.js @@ -0,0 +1,174 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.updatePreview = updatePreview; +exports.setPreview = setPreview; +exports.clearPreview = clearPreview; + +var _preview = require("../utils/preview"); + +var _ast = require("../utils/ast"); + +var _editor = require("../utils/editor/index"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _promise = require("./utils/middleware/promise"); + +var _getExpression = require("../utils/editor/get-expression"); + +var _selectors = require("../selectors/index"); + +var _expressions = require("./expressions"); + +var _pause = require("./pause/index"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function isInvalidTarget(target) { + if (!target || !target.innerText) { + return true; + } + + const tokenText = target.innerText.trim(); + const cursorPos = target.getBoundingClientRect(); // exclude literal tokens where it does not make sense to show a preview + + const invalidType = ["cm-atom", ""].includes(target.className); // exclude syntax where the expression would be a syntax error + + const invalidToken = tokenText === "" || tokenText.match(/^[(){}\|&%,.;=<>\+-/\*\s](?=)/); + const isPresentation = target.attributes.role && target.attributes.getNamedItem("role").value == "presentation"; // exclude codemirror elements that are not tokens + + const invalidTarget = target.parentElement && !target.parentElement.closest(".CodeMirror-line") || cursorPos.top == 0; + return invalidTarget || invalidToken || invalidType || isPresentation; +} + +function updatePreview(target, editor) { + return ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const tokenPos = (0, _editor.getTokenLocation)(editor.codeMirror, target); + const cursorPos = target.getBoundingClientRect(); + const preview = (0, _selectors.getPreview)(getState()); + + if ((0, _selectors.getCanRewind)(getState())) { + return; + } + + if (preview) { + // Return early if we are currently showing another preview or + // if we are mousing over the same token as before + if (preview.updating || (0, _lodash.isEqual)(preview.tokenPos, tokenPos)) { + return; + } // We are mousing over a new token that is not in the preview + + + if (!target.classList.contains("debug-expression")) { + dispatch(clearPreview()); + } + } + + if (isInvalidTarget(target)) { + dispatch(clearPreview()); + return; + } + + if (!(0, _selectors.isSelectedFrameVisible)(getState()) || !(0, _selectors.isLineInScope)(getState(), tokenPos.line)) { + return; + } + + const source = (0, _selectors.getSelectedSource)(getState()); + const symbols = (0, _selectors.getSymbols)(getState(), source); + let match; + + if (!symbols || symbols.loading) { + match = (0, _getExpression.getExpressionFromCoords)(editor.codeMirror, tokenPos); + } else { + match = (0, _ast.findBestMatchExpression)(symbols, tokenPos); + } + + if (!match || !match.expression) { + return; + } + + const { + expression, + location + } = match; + + if ((0, _preview.isConsole)(expression)) { + return; + } + + dispatch(setPreview(expression, location, tokenPos, cursorPos)); + }; +} + +function setPreview(expression, location, tokenPos, cursorPos) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + await dispatch({ + type: "SET_PREVIEW", + [_promise.PROMISE]: async function () { + const source = (0, _selectors.getSelectedSource)(getState()); + const sourceId = source.id; + const selectedFrame = (0, _selectors.getSelectedFrame)(getState()); + + if (location && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) { + expression = await dispatch((0, _expressions.getMappedExpression)(expression)); + } + + if (!selectedFrame) { + return; + } + + const { + result + } = await client.evaluateInFrame(expression, selectedFrame.id); + + if (result === undefined) { + return; + } + + const extra = await dispatch((0, _pause.getExtra)(expression, result)); + return { + expression, + result, + location, + tokenPos, + cursorPos, + extra + }; + }() + }); + }; +} + +function clearPreview() { + return ({ + dispatch, + getState, + client + }) => { + const currentSelection = (0, _selectors.getPreview)(getState()); + + if (!currentSelection) { + return; + } + + return dispatch({ + type: "CLEAR_SELECTION" + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/project-text-search.js b/devtools/client/debugger/new/src/actions/project-text-search.js new file mode 100644 index 000000000000..be79792a5e15 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/project-text-search.js @@ -0,0 +1,117 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.addSearchQuery = addSearchQuery; +exports.clearSearchQuery = clearSearchQuery; +exports.clearSearchResults = clearSearchResults; +exports.clearSearch = clearSearch; +exports.updateSearchStatus = updateSearchStatus; +exports.closeProjectSearch = closeProjectSearch; +exports.searchSources = searchSources; +exports.searchSource = searchSource; + +var _search = require("../workers/search/index"); + +var _selectors = require("../selectors/index"); + +var _source = require("../utils/source"); + +var _loadSourceText = require("./sources/loadSourceText"); + +var _projectTextSearch = require("../reducers/project-text-search"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Redux actions for the search state + * @module actions/search + */ +function addSearchQuery(query) { + return { + type: "ADD_QUERY", + query + }; +} + +function clearSearchQuery() { + return { + type: "CLEAR_QUERY" + }; +} + +function clearSearchResults() { + return { + type: "CLEAR_SEARCH_RESULTS" + }; +} + +function clearSearch() { + return { + type: "CLEAR_SEARCH" + }; +} + +function updateSearchStatus(status) { + return { + type: "UPDATE_STATUS", + status + }; +} + +function closeProjectSearch() { + return { + type: "CLOSE_PROJECT_SEARCH" + }; +} + +function searchSources(query) { + return async ({ + dispatch, + getState + }) => { + await dispatch(clearSearchResults()); + await dispatch(addSearchQuery(query)); + dispatch(updateSearchStatus(_projectTextSearch.statusType.fetching)); + const sources = (0, _selectors.getSources)(getState()); + const validSources = sources.valueSeq().filter(source => !(0, _selectors.hasPrettySource)(getState(), source.id) && !(0, _source.isThirdParty)(source)); + + for (const source of validSources) { + await dispatch((0, _loadSourceText.loadSourceText)(source)); + await dispatch(searchSource(source.id, query)); + } + + dispatch(updateSearchStatus(_projectTextSearch.statusType.done)); + }; +} + +function searchSource(sourceId, query) { + return async ({ + dispatch, + getState + }) => { + const sourceRecord = (0, _selectors.getSource)(getState(), sourceId); + + if (!sourceRecord) { + return; + } + + const matches = await (0, _search.findSourceMatches)(sourceRecord.toJS(), query); + + if (!matches.length) { + return; + } + + dispatch({ + type: "ADD_SEARCH_RESULT", + result: { + sourceId: sourceRecord.id, + filepath: sourceRecord.url, + matches + } + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/quick-open.js b/devtools/client/debugger/new/src/actions/quick-open.js new file mode 100644 index 000000000000..4835117658fb --- /dev/null +++ b/devtools/client/debugger/new/src/actions/quick-open.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setQuickOpenQuery = setQuickOpenQuery; +exports.openQuickOpen = openQuickOpen; +exports.closeQuickOpen = closeQuickOpen; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function setQuickOpenQuery(query) { + return { + type: "SET_QUICK_OPEN_QUERY", + query + }; +} + +function openQuickOpen(query) { + if (query != null) { + return { + type: "OPEN_QUICK_OPEN", + query + }; + } + + return { + type: "OPEN_QUICK_OPEN" + }; +} + +function closeQuickOpen() { + return { + type: "CLOSE_QUICK_OPEN" + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/replay.js b/devtools/client/debugger/new/src/actions/replay.js new file mode 100644 index 000000000000..3dec5c186f3d --- /dev/null +++ b/devtools/client/debugger/new/src/actions/replay.js @@ -0,0 +1,45 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.timeTravelTo = timeTravelTo; +exports.clearHistory = clearHistory; + +var _selectors = require("../selectors/index"); + +var _sources = require("./sources/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Redux actions for replay + * @module actions/replay + */ +function timeTravelTo(position) { + return ({ + dispatch, + getState + }) => { + const data = (0, _selectors.getHistoryFrame)(getState(), position); + dispatch({ + type: "TRAVEL_TO", + data, + position + }); + dispatch((0, _sources.selectLocation)(data.paused.frames[0].location)); + }; +} + +function clearHistory() { + return ({ + dispatch, + getState + }) => { + dispatch({ + type: "CLEAR_HISTORY" + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/source-tree.js b/devtools/client/debugger/new/src/actions/source-tree.js new file mode 100644 index 000000000000..3519c6b17b61 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/source-tree.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setExpandedState = setExpandedState; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function setExpandedState(expanded) { + return ({ + dispatch, + getState + }) => { + dispatch({ + type: "SET_EXPANDED_STATE", + expanded + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/blackbox.js b/devtools/client/debugger/new/src/actions/sources/blackbox.js new file mode 100644 index 000000000000..9be0f72543b0 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/blackbox.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.toggleBlackBox = toggleBlackBox; + +var _promise = require("../utils/middleware/promise"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Redux actions for the sources state + * @module actions/sources + */ +function toggleBlackBox(source) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const { + isBlackBoxed, + id + } = source; + return dispatch({ + type: "BLACKBOX", + source, + [_promise.PROMISE]: client.blackBox(id, isBlackBoxed) + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/index.js b/devtools/client/debugger/new/src/actions/sources/index.js new file mode 100644 index 000000000000..61742e35c3e9 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/index.js @@ -0,0 +1,77 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _loadSourceText = require("./loadSourceText"); + +Object.keys(_loadSourceText).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _loadSourceText[key]; + } + }); +}); + +var _prettyPrint = require("./prettyPrint"); + +Object.keys(_prettyPrint).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _prettyPrint[key]; + } + }); +}); + +var _newSources = require("./newSources"); + +Object.keys(_newSources).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _newSources[key]; + } + }); +}); + +var _blackbox = require("./blackbox"); + +Object.keys(_blackbox).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _blackbox[key]; + } + }); +}); + +var _select = require("./select"); + +Object.keys(_select).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _select[key]; + } + }); +}); + +var _tabs = require("./tabs"); + +Object.keys(_tabs).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _tabs[key]; + } + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/loadSourceText.js b/devtools/client/debugger/new/src/actions/sources/loadSourceText.js new file mode 100644 index 000000000000..6555da229317 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/loadSourceText.js @@ -0,0 +1,114 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadSourceText = loadSourceText; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _promise = require("../utils/middleware/promise"); + +var _selectors = require("../../selectors/index"); + +var _parser = require("../../workers/parser/index"); + +var parser = _interopRequireWildcard(_parser); + +var _source = require("../../utils/source"); + +var _defer = require("../../utils/defer"); + +var _defer2 = _interopRequireDefault(_defer); + +var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const requests = new Map(); + +const loadSourceHistogram = _devtoolsModules.Services.telemetry.getHistogramById("DEVTOOLS_DEBUGGER_LOAD_SOURCE_MS"); + +async function loadSource(source, { + sourceMaps, + client +}) { + const id = source.get("id"); + + if ((0, _devtoolsSourceMap.isOriginalId)(id)) { + return await sourceMaps.getOriginalSourceText(source.toJS()); + } + + const response = await client.sourceContents(id); + return { + id, + text: response.source, + contentType: response.contentType || "text/javascript" + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function loadSourceText(source) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const id = source.get("id"); // Fetch the source text only once. + + if (requests.has(id)) { + return requests.get(id); + } + + if ((0, _source.isLoaded)(source)) { + return Promise.resolve(); + } + + const telemetryStart = performance.now(); + const deferred = (0, _defer2.default)(); + requests.set(id, deferred.promise); + + try { + await dispatch({ + type: "LOAD_SOURCE_TEXT", + sourceId: id, + [_promise.PROMISE]: loadSource(source, { + sourceMaps, + client + }) + }); + } catch (e) { + deferred.resolve(); + requests.delete(id); + return; + } + + const newSource = (0, _selectors.getSource)(getState(), source.get("id")).toJS(); + + if ((0, _devtoolsSourceMap.isOriginalId)(newSource.id) && !newSource.isWasm) { + const generatedSource = (0, _selectors.getGeneratedSource)(getState(), source.toJS()); + await dispatch(loadSourceText(generatedSource)); + } + + if (!newSource.isWasm) { + await parser.setSource(newSource); + } // signal that the action is finished + + + deferred.resolve(); + requests.delete(id); + const telemetryEnd = performance.now(); + const duration = telemetryEnd - telemetryStart; + loadSourceHistogram.add(duration); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/moz.build b/devtools/client/debugger/new/src/actions/sources/moz.build new file mode 100644 index 000000000000..a6747d3ad098 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/moz.build @@ -0,0 +1,18 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'blackbox.js', + 'index.js', + 'loadSourceText.js', + 'newSources.js', + 'prettyPrint.js', + 'select.js', + 'tabs.js', +) diff --git a/devtools/client/debugger/new/src/actions/sources/newSources.js b/devtools/client/debugger/new/src/actions/sources/newSources.js new file mode 100644 index 000000000000..4b1ab045af6f --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/newSources.js @@ -0,0 +1,206 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.newSource = newSource; +exports.newSources = newSources; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _blackbox = require("./blackbox"); + +var _breakpoints = require("../breakpoints"); + +var _loadSourceText = require("./loadSourceText"); + +var _prettyPrint = require("./prettyPrint"); + +var _sources = require("../sources/index"); + +var _source = require("../../utils/source"); + +var _selectors = require("../../selectors/index"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function createOriginalSource(originalUrl, generatedSource, sourceMaps) { + return { + url: originalUrl, + id: sourceMaps.generatedToOriginalId(generatedSource.id, originalUrl), + isPrettyPrinted: false, + isWasm: false, + isBlackBoxed: false, + loadedState: "unloaded" + }; +} + +function loadSourceMaps(sources) { + return async function ({ + dispatch, + sourceMaps + }) { + if (!sourceMaps) { + return; + } + + const originalSources = await Promise.all(sources.map(source => dispatch(loadSourceMap(source.id)))); + await dispatch(newSources((0, _lodash.flatten)(originalSources))); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function loadSourceMap(sourceId) { + return async function ({ + dispatch, + getState, + sourceMaps + }) { + const source = (0, _selectors.getSource)(getState(), sourceId).toJS(); + + if (!sourceMaps || !(0, _devtoolsSourceMap.isGeneratedId)(sourceId) || !source.sourceMapURL) { + return; + } + + let urls = null; + + try { + urls = await sourceMaps.getOriginalURLs(source); + } catch (e) { + console.error(e); + } + + if (!urls) { + // If this source doesn't have a sourcemap, enable it for pretty printing + dispatch({ + type: "UPDATE_SOURCE", + source: _objectSpread({}, source, { + sourceMapURL: "" + }) + }); + return; + } + + return urls.map(url => createOriginalSource(url, source, sourceMaps)); + }; +} // If a request has been made to show this source, go ahead and +// select it. + + +function checkSelectedSource(sourceId) { + return async ({ + dispatch, + getState + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + const pendingLocation = (0, _selectors.getPendingSelectedLocation)(getState()); + + if (!pendingLocation || !pendingLocation.url || !source.url) { + return; + } + + const pendingUrl = pendingLocation.url; + const rawPendingUrl = (0, _source.getRawSourceURL)(pendingUrl); + + if (rawPendingUrl === source.url) { + if ((0, _source.isPrettyURL)(pendingUrl)) { + return await dispatch((0, _prettyPrint.togglePrettyPrint)(source.id)); + } + + await dispatch((0, _sources.selectLocation)(_objectSpread({}, pendingLocation, { + sourceId: source.id + }))); + } + }; +} + +function checkPendingBreakpoints(sourceId) { + return async ({ + dispatch, + getState + }) => { + // source may have been modified by selectLocation + const source = (0, _selectors.getSource)(getState(), sourceId); + const pendingBreakpoints = (0, _selectors.getPendingBreakpointsForSource)(getState(), source.get("url")); + + if (!pendingBreakpoints.size) { + return; + } // load the source text if there is a pending breakpoint for it + + + await dispatch((0, _loadSourceText.loadSourceText)(source)); + const pendingBreakpointsArray = pendingBreakpoints.valueSeq().toJS(); + + for (const pendingBreakpoint of pendingBreakpointsArray) { + await dispatch((0, _breakpoints.syncBreakpoint)(sourceId, pendingBreakpoint)); + } + }; +} + +function restoreBlackBoxedSources(sources) { + return async ({ + dispatch + }) => { + const tabs = (0, _selectors.getBlackBoxList)(); + + if (tabs.length == 0) { + return; + } + + for (const source of sources) { + if (tabs.includes(source.url) && !source.isBlackBoxed) { + dispatch((0, _blackbox.toggleBlackBox)(source)); + } + } + }; +} +/** + * Handler for the debugger client's unsolicited newSource notification. + * @memberof actions/sources + * @static + */ + + +function newSource(source) { + return async ({ + dispatch + }) => { + await dispatch(newSources([source])); + }; +} + +function newSources(sources) { + return async ({ + dispatch, + getState + }) => { + const filteredSources = sources.filter(source => source && !(0, _selectors.getSource)(getState(), source.id)); + + if (filteredSources.length == 0) { + return; + } + + dispatch({ + type: "ADD_SOURCES", + sources: filteredSources + }); + + for (const source of filteredSources) { + dispatch(checkSelectedSource(source.id)); + dispatch(checkPendingBreakpoints(source.id)); + } + + await dispatch(loadSourceMaps(filteredSources)); // We would like to restore the blackboxed state + // after loading all states to make sure the correctness. + + await dispatch(restoreBlackBoxedSources(filteredSources)); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/prettyPrint.js b/devtools/client/debugger/new/src/actions/sources/prettyPrint.js new file mode 100644 index 000000000000..0bab4ae75bb2 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/prettyPrint.js @@ -0,0 +1,139 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createPrettySource = createPrettySource; +exports.togglePrettyPrint = togglePrettyPrint; + +var _assert = require("../../utils/assert"); + +var _assert2 = _interopRequireDefault(_assert); + +var _breakpoints = require("../breakpoints"); + +var _ast = require("../ast"); + +var _prettyPrint = require("../../workers/pretty-print/index"); + +var _parser = require("../../workers/parser/index"); + +var _source = require("../../utils/source"); + +var _loadSourceText = require("./loadSourceText"); + +var _sources = require("../sources/index"); + +var _pause = require("../pause/index"); + +var _selectors = require("../../selectors/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function createPrettySource(sourceId) { + return async ({ + dispatch, + getState, + sourceMaps + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + const url = (0, _source.getPrettySourceURL)(source.url); + const id = await sourceMaps.generatedToOriginalId(sourceId, url); + const prettySource = { + url, + id, + isBlackBoxed: false, + isPrettyPrinted: true, + isWasm: false, + contentType: "text/javascript", + loadedState: "loading" + }; + dispatch({ + type: "ADD_SOURCE", + source: prettySource + }); + const { + code, + mappings + } = await (0, _prettyPrint.prettyPrint)({ + source, + url + }); + await sourceMaps.applySourceMap(source.id, url, code, mappings); + + const loadedPrettySource = _objectSpread({}, prettySource, { + text: code, + loadedState: "loaded" + }); + + (0, _parser.setSource)(loadedPrettySource); + dispatch({ + type: "UPDATE_SOURCE", + source: loadedPrettySource + }); + return prettySource; + }; +} +/** + * Toggle the pretty printing of a source's text. All subsequent calls to + * |getText| will return the pretty-toggled text. Nothing will happen for + * non-javascript files. + * + * @memberof actions/sources + * @static + * @param string id The source form from the RDP. + * @returns Promise + * A promise that resolves to [aSource, prettyText] or rejects to + * [aSource, error]. + */ + + +function togglePrettyPrint(sourceId) { + return async ({ + dispatch, + getState, + client, + sourceMaps + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + + if (!source) { + return {}; + } + + if (!(0, _source.isLoaded)(source)) { + await dispatch((0, _loadSourceText.loadSourceText)(source)); + } + + (0, _assert2.default)(sourceMaps.isGeneratedId(sourceId), "Pretty-printing only allowed on generated sources"); + const selectedLocation = (0, _selectors.getSelectedLocation)(getState()); + const url = (0, _source.getPrettySourceURL)(source.url); + const prettySource = (0, _selectors.getSourceByURL)(getState(), url); + const options = {}; + + if (selectedLocation) { + options.location = await sourceMaps.getOriginalLocation(selectedLocation); + } + + if (prettySource) { + const _sourceId = prettySource.get("id"); + + return dispatch((0, _sources.selectLocation)(_objectSpread({}, options.location, { + sourceId: _sourceId + }))); + } + + const newPrettySource = await dispatch(createPrettySource(sourceId)); + await dispatch((0, _breakpoints.remapBreakpoints)(sourceId)); + await dispatch((0, _pause.mapFrames)()); + await dispatch((0, _ast.setPausePoints)(newPrettySource.id)); + await dispatch((0, _ast.setSymbols)(newPrettySource.id)); + return dispatch((0, _sources.selectLocation)(_objectSpread({}, options.location, { + sourceId: newPrettySource.id + }))); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/select.js b/devtools/client/debugger/new/src/actions/sources/select.js new file mode 100644 index 000000000000..2881e60faf3e --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/select.js @@ -0,0 +1,251 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.selectSourceURL = selectSourceURL; +exports.selectSource = selectSource; +exports.selectLocation = selectLocation; +exports.selectSpecificLocation = selectSpecificLocation; +exports.selectSpecificSource = selectSpecificSource; +exports.jumpToMappedLocation = jumpToMappedLocation; +exports.jumpToMappedSelectedLocation = jumpToMappedSelectedLocation; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _ast = require("../ast"); + +var _ui = require("../ui"); + +var _prettyPrint = require("./prettyPrint"); + +var _tabs = require("./tabs"); + +var _loadSourceText = require("./loadSourceText"); + +var _prefs = require("../../utils/prefs"); + +var _source = require("../../utils/source"); + +var _location = require("../../utils/location"); + +var _sourceMaps = require("../../utils/source-maps"); + +var _selectors = require("../../selectors/index"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Deterministically select a source that has a given URL. This will + * work regardless of the connection status or if the source exists + * yet. This exists mostly for external things to interact with the + * debugger. + * + * @memberof actions/sources + * @static + */ +function selectSourceURL(url, options = {}) { + return async ({ + dispatch, + getState + }) => { + const source = (0, _selectors.getSourceByURL)(getState(), url); + + if (source) { + const sourceId = source.id; + const location = (0, _location.createLocation)(_objectSpread({}, options.location, { + sourceId + })); + await dispatch(selectLocation(location)); + } else { + dispatch({ + type: "SELECT_SOURCE_URL", + url: url, + line: options.location ? options.location.line : null + }); + } + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function selectSource(sourceId) { + return async ({ + dispatch + }) => { + const location = (0, _location.createLocation)({ + sourceId + }); + return await dispatch(selectLocation(location)); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function selectLocation(location) { + return async ({ + dispatch, + getState, + client + }) => { + if (!client) { + // No connection, do nothing. This happens when the debugger is + // shut down too fast and it tries to display a default source. + return; + } + + const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId); + + if (!sourceRecord) { + // If there is no source we deselect the current selected source + return dispatch({ + type: "CLEAR_SELECTED_SOURCE" + }); + } + + const activeSearch = (0, _selectors.getActiveSearch)(getState()); + + if (activeSearch !== "file") { + dispatch((0, _ui.closeActiveSearch)()); + } + + const source = sourceRecord.toJS(); + dispatch((0, _tabs.addTab)(source, 0)); + dispatch({ + type: "SELECT_SOURCE", + source, + location + }); + await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord)); + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!selectedSource) { + return; + } + + const sourceId = selectedSource.id; + + if (_prefs.prefs.autoPrettyPrint && !(0, _selectors.getPrettySource)(getState(), sourceId) && (0, _source.shouldPrettyPrint)(selectedSource) && (0, _source.isMinified)(selectedSource)) { + await dispatch((0, _prettyPrint.togglePrettyPrint)(sourceId)); + dispatch((0, _tabs.closeTab)(source.url)); + } + + dispatch((0, _ast.setSymbols)(sourceId)); + dispatch((0, _ast.setOutOfScopeLocations)()); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function selectSpecificLocation(location) { + return async ({ + dispatch, + getState, + client + }) => { + if (!client) { + // No connection, do nothing. This happens when the debugger is + // shut down too fast and it tries to display a default source. + return; + } + + const sourceRecord = (0, _selectors.getSource)(getState(), location.sourceId); + + if (!sourceRecord) { + // If there is no source we deselect the current selected source + return dispatch({ + type: "CLEAR_SELECTED_SOURCE" + }); + } + + const activeSearch = (0, _selectors.getActiveSearch)(getState()); + + if (activeSearch !== "file") { + dispatch((0, _ui.closeActiveSearch)()); + } + + const source = sourceRecord.toJS(); + dispatch((0, _tabs.addTab)(source, 0)); + dispatch({ + type: "SELECT_SOURCE", + source, + location + }); + await dispatch((0, _loadSourceText.loadSourceText)(sourceRecord)); + const selectedSource = (0, _selectors.getSelectedSource)(getState()); + + if (!selectedSource) { + return; + } + + const sourceId = selectedSource.id; + dispatch((0, _ast.setSymbols)(sourceId)); + dispatch((0, _ast.setOutOfScopeLocations)()); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function selectSpecificSource(sourceId) { + return async ({ + dispatch + }) => { + const location = (0, _location.createLocation)({ + sourceId + }); + return await dispatch(selectSpecificLocation(location)); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function jumpToMappedLocation(location) { + return async function ({ + dispatch, + getState, + client, + sourceMaps + }) { + if (!client) { + return; + } + + const source = (0, _selectors.getSource)(getState(), location.sourceId); + let pairedLocation; + + if ((0, _devtoolsSourceMap.isOriginalId)(location.sourceId)) { + pairedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source, location, sourceMaps); + } else { + pairedLocation = await sourceMaps.getOriginalLocation(location, source.toJS()); + } + + return dispatch(selectLocation(_objectSpread({}, pairedLocation))); + }; +} + +function jumpToMappedSelectedLocation() { + return async function ({ + dispatch, + getState + }) { + const location = (0, _selectors.getSelectedLocation)(getState()); + await dispatch(jumpToMappedLocation(location)); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/sources/tabs.js b/devtools/client/debugger/new/src/actions/sources/tabs.js new file mode 100644 index 000000000000..3293d0426b7f --- /dev/null +++ b/devtools/client/debugger/new/src/actions/sources/tabs.js @@ -0,0 +1,91 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.addTab = addTab; +exports.moveTab = moveTab; +exports.closeTab = closeTab; +exports.closeTabs = closeTabs; + +var _editor = require("../../utils/editor/index"); + +var _sources = require("../sources/index"); + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Redux actions for the sources state + * @module actions/sources + */ +function addTab(source, tabIndex) { + return { + type: "ADD_TAB", + source, + tabIndex + }; +} + +function moveTab(url, tabIndex) { + return { + type: "MOVE_TAB", + url, + tabIndex + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function closeTab(url) { + return ({ + dispatch, + getState, + client + }) => { + (0, _editor.removeDocument)(url); + const tabs = (0, _selectors.removeSourceFromTabList)((0, _selectors.getSourceTabs)(getState()), url); + const sourceId = (0, _selectors.getNewSelectedSourceId)(getState(), tabs); + dispatch({ + type: "CLOSE_TAB", + url, + tabs + }); + dispatch((0, _sources.selectSource)(sourceId)); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function closeTabs(urls) { + return ({ + dispatch, + getState, + client + }) => { + urls.forEach(url => { + const source = (0, _selectors.getSourceByURL)(getState(), url); + + if (source) { + (0, _editor.removeDocument)(source.get("id")); + } + }); + const tabs = (0, _selectors.removeSourcesFromTabList)((0, _selectors.getSourceTabs)(getState()), urls); + dispatch({ + type: "CLOSE_TABS", + urls, + tabs + }); + const sourceId = (0, _selectors.getNewSelectedSourceId)(getState(), tabs); + dispatch((0, _sources.selectSource)(sourceId)); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/toolbox.js b/devtools/client/debugger/new/src/actions/toolbox.js new file mode 100644 index 000000000000..6e7680d57ad9 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/toolbox.js @@ -0,0 +1,61 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.openLink = openLink; +exports.openWorkerToolbox = openWorkerToolbox; +exports.evaluateInConsole = evaluateInConsole; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + isDevelopment +} = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +const { + getSelectedFrameId +} = require("../selectors/index"); + +/** + * @memberof actions/toolbox + * @static + */ +function openLink(url) { + return async function ({ + openLink: openLinkCommand + }) { + if (isDevelopment()) { + const win = window.open(url, "_blank"); + win.focus(); + } else { + openLinkCommand(url); + } + }; +} + +function openWorkerToolbox(worker) { + return async function ({ + getState, + openWorkerToolbox: openWorkerToolboxCommand + }) { + if (isDevelopment()) { + alert(worker.url); + } else { + openWorkerToolboxCommand(worker); + } + }; +} + +function evaluateInConsole(inputString) { + return async ({ + client, + getState + }) => { + const frameId = getSelectedFrameId(getState()); + client.evaluate(`console.log("${inputString}"); console.log(${inputString})`, { + frameId + }); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/ui.js b/devtools/client/debugger/new/src/actions/ui.js new file mode 100644 index 000000000000..4f2174dca724 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/ui.js @@ -0,0 +1,226 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setContextMenu = setContextMenu; +exports.setPrimaryPaneTab = setPrimaryPaneTab; +exports.closeActiveSearch = closeActiveSearch; +exports.setActiveSearch = setActiveSearch; +exports.toggleFrameworkGrouping = toggleFrameworkGrouping; +exports.showSource = showSource; +exports.togglePaneCollapse = togglePaneCollapse; +exports.highlightLineRange = highlightLineRange; +exports.flashLineRange = flashLineRange; +exports.clearHighlightLineRange = clearHighlightLineRange; +exports.openConditionalPanel = openConditionalPanel; +exports.closeConditionalPanel = closeConditionalPanel; +exports.clearProjectDirectoryRoot = clearProjectDirectoryRoot; +exports.setProjectDirectoryRoot = setProjectDirectoryRoot; +exports.setOrientation = setOrientation; + +var _selectors = require("../selectors/index"); + +var _ui = require("../reducers/ui"); + +var _source = require("../utils/source"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function setContextMenu(type, event) { + return ({ + dispatch + }) => { + dispatch({ + type: "SET_CONTEXT_MENU", + contextMenu: { + type, + event + } + }); + }; +} + +function setPrimaryPaneTab(tabName) { + return { + type: "SET_PRIMARY_PANE_TAB", + tabName + }; +} + +function closeActiveSearch() { + return { + type: "TOGGLE_ACTIVE_SEARCH", + value: null + }; +} + +function setActiveSearch(activeSearch) { + return ({ + dispatch, + getState + }) => { + const activeSearchState = (0, _selectors.getActiveSearch)(getState()); + + if (activeSearchState === activeSearch) { + return; + } + + if ((0, _selectors.getQuickOpenEnabled)(getState())) { + dispatch({ + type: "CLOSE_QUICK_OPEN" + }); + } + + dispatch({ + type: "TOGGLE_ACTIVE_SEARCH", + value: activeSearch + }); + }; +} + +function toggleFrameworkGrouping(toggleValue) { + return ({ + dispatch, + getState + }) => { + dispatch({ + type: "TOGGLE_FRAMEWORK_GROUPING", + value: toggleValue + }); + }; +} + +function showSource(sourceId) { + return ({ + dispatch, + getState + }) => { + const source = (0, _selectors.getSource)(getState(), sourceId); + + if ((0, _selectors.getPaneCollapse)(getState(), "start")) { + dispatch({ + type: "TOGGLE_PANE", + position: "start", + paneCollapsed: false + }); + } + + dispatch(setPrimaryPaneTab("sources")); + dispatch({ + type: "SHOW_SOURCE", + sourceUrl: "" + }); + dispatch({ + type: "SHOW_SOURCE", + sourceUrl: (0, _source.getRawSourceURL)(source.get("url")) + }); + }; +} + +function togglePaneCollapse(position, paneCollapsed) { + return ({ + dispatch, + getState + }) => { + const prevPaneCollapse = (0, _selectors.getPaneCollapse)(getState(), position); + + if (prevPaneCollapse === paneCollapsed) { + return; + } + + dispatch({ + type: "TOGGLE_PANE", + position, + paneCollapsed + }); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function highlightLineRange(location) { + return { + type: "HIGHLIGHT_LINES", + location + }; +} + +function flashLineRange(location) { + return ({ + dispatch + }) => { + dispatch(highlightLineRange(location)); + setTimeout(() => dispatch(clearHighlightLineRange()), 200); + }; +} +/** + * @memberof actions/sources + * @static + */ + + +function clearHighlightLineRange() { + return { + type: "CLEAR_HIGHLIGHT_LINES" + }; +} + +function openConditionalPanel(line) { + if (!line) { + return; + } + + return { + type: "OPEN_CONDITIONAL_PANEL", + line + }; +} + +function closeConditionalPanel() { + return { + type: "CLOSE_CONDITIONAL_PANEL" + }; +} + +function clearProjectDirectoryRoot() { + return { + type: "SET_PROJECT_DIRECTORY_ROOT", + url: "" + }; +} + +function setProjectDirectoryRoot(newRoot) { + return ({ + dispatch, + getState + }) => { + const curRoot = (0, _ui.getProjectDirectoryRoot)(getState()); + + if (newRoot && curRoot) { + const newRootArr = newRoot.replace(/\/+/g, "/").split("/"); + const curRootArr = curRoot.replace(/^\//, "").replace(/\/+/g, "/").split("/"); + + if (newRootArr[0] !== curRootArr[0]) { + newRootArr.splice(0, 2); + newRoot = `${curRoot}/${newRootArr.join("/")}`; + } + } + + dispatch({ + type: "SET_PROJECT_DIRECTORY_ROOT", + url: newRoot + }); + }; +} + +function setOrientation(orientation) { + return { + type: "SET_ORIENTATION", + orientation + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/create-store.js b/devtools/client/debugger/new/src/actions/utils/create-store.js new file mode 100644 index 000000000000..8b4c6402620b --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/create-store.js @@ -0,0 +1,73 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _redux = require("devtools/client/shared/vendor/redux"); + +var _waitService = require("./middleware/wait-service"); + +var _log = require("./middleware/log"); + +var _history = require("./middleware/history"); + +var _promise = require("./middleware/promise"); + +var _thunk = require("./middleware/thunk"); + +var _timing = require("./middleware/timing"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* global window */ + +/** + * Redux store utils + * @module utils/create-store + */ + +/** + * This creates a dispatcher with all the standard middleware in place + * that all code requires. It can also be optionally configured in + * various ways, such as logging and recording. + * + * @param {object} opts: + * - log: log all dispatched actions to console + * - history: an array to store every action in. Should only be + * used in tests. + * - middleware: array of middleware to be included in the redux store + * @memberof utils/create-store + * @static + */ +const configureStore = (opts = {}) => { + const middleware = [(0, _thunk.thunk)(opts.makeThunkArgs), _promise.promise, // Order is important: services must go last as they always + // operate on "already transformed" actions. Actions going through + // them shouldn't have any special fields like promises, they + // should just be normal JSON objects. + _waitService.waitUntilService]; + + if (opts.history) { + middleware.push((0, _history.history)(opts.history)); + } + + if (opts.middleware) { + opts.middleware.forEach(fn => middleware.push(fn)); + } + + if (opts.log) { + middleware.push(_log.log); + } + + if (opts.timing) { + middleware.push(_timing.timing); + } // Hook in the redux devtools browser extension if it exists + + + const devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f; + return (0, _redux.applyMiddleware)(...middleware)(devtoolsExt(_redux.createStore)); +}; + +exports.default = configureStore; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/history.js b/devtools/client/debugger/new/src/actions/utils/middleware/history.js new file mode 100644 index 000000000000..ac09b2dcba59 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/history.js @@ -0,0 +1,32 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.history = undefined; + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* global window */ + +/** + * A middleware that stores every action coming through the store in the passed + * in logging object. Should only be used for tests, as it collects all + * action information, which will cause memory bloat. + */ +const history = exports.history = (log = []) => ({ + dispatch, + getState +}) => { + return next => action => { + if ((0, _devtoolsEnvironment.isDevelopment)()) { + log.push(action); + } + + return next(action); + }; +}; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/log.js b/devtools/client/debugger/new/src/actions/utils/middleware/log.js new file mode 100644 index 000000000000..051c53d0dc98 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/log.js @@ -0,0 +1,117 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.log = log; + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const blacklist = ["SET_POPUP_OBJECT_PROPERTIES", "SET_PAUSE_POINTS", "SET_SYMBOLS", "OUT_OF_SCOPE_LOCATIONS", "MAP_SCOPES", "MAP_FRAMES", "ADD_SCOPES", "IN_SCOPE_LINES", "REMOVE_BREAKPOINT", "ADD_BREAKPOINT"]; + +function cloneAction(action) { + action = action || {}; + action = _objectSpread({}, action); // ADD_TAB, ... + + if (action.source && action.source.text) { + const source = _objectSpread({}, action.source, { + text: "" + }); + + action.source = source; + } + + if (action.sources) { + const sources = action.sources.slice(0, 20).map(source => { + const url = !source.url || source.url.includes("data:") ? "" : source.url; + return _objectSpread({}, source, { + url + }); + }); + action.sources = sources; + } // LOAD_SOURCE_TEXT + + + if (action.text) { + action.text = ""; + } + + if (action.value && action.value.text) { + const value = _objectSpread({}, action.value, { + text: "" + }); + + action.value = value; + } + + return action; +} + +function formatFrame(frame) { + const { + id, + location, + displayName + } = frame; + return { + id, + location, + displayName + }; +} + +function formatPause(pause) { + return _objectSpread({}, pause, { + pauseInfo: { + why: pause.why + }, + scopes: [], + frames: pause.frames.map(formatFrame), + loadedObjects: [] + }); +} + +function serializeAction(action) { + try { + action = cloneAction(action); + + if (blacklist.includes(action.type)) { + action = {}; + } + + if (action.type === "PAUSED") { + action = formatPause(action); + } // dump(`> ${action.type}...\n ${JSON.stringify(action)}\n`); + + + return JSON.stringify(action); + } catch (e) { + console.error(e); + } +} +/** + * A middleware that logs all actions coming through the system + * to the console. + */ + + +function log({ + dispatch, + getState +}) { + return next => action => { + const asyncMsg = !action.status ? "" : `[${action.status}]`; + + if ((0, _devtoolsEnvironment.isTesting)()) { + dump(`[ACTION] ${action.type} ${asyncMsg} - ${serializeAction(action)}\n`); + } else { + console.log(action, asyncMsg); + } + + next(action); + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/moz.build b/devtools/client/debugger/new/src/actions/utils/middleware/moz.build new file mode 100644 index 000000000000..14975be15271 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/moz.build @@ -0,0 +1,17 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'history.js', + 'log.js', + 'promise.js', + 'thunk.js', + 'timing.js', + 'wait-service.js', +) diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/promise.js b/devtools/client/debugger/new/src/actions/utils/middleware/promise.js new file mode 100644 index 000000000000..5b9635b645e0 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/promise.js @@ -0,0 +1,70 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.promise = exports.PROMISE = undefined; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _DevToolsUtils = require("../../../utils/DevToolsUtils"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +let seqIdVal = 1; + +function seqIdGen() { + return seqIdVal++; +} + +function filterAction(action) { + return (0, _lodash.fromPairs)((0, _lodash.toPairs)(action).filter(pair => pair[0] !== PROMISE)); +} + +function promiseMiddleware({ + dispatch, + getState +}) { + return next => action => { + if (!(PROMISE in action)) { + return next(action); + } + + const promiseInst = action[PROMISE]; + const seqId = seqIdGen().toString(); // Create a new action that doesn't have the promise field and has + // the `seqId` field that represents the sequence id + + action = _objectSpread({}, filterAction(action), { + seqId + }); + dispatch(_objectSpread({}, action, { + status: "start" + })); // Return the promise so action creators can still compose if they + // want to. + + return new Promise((resolve, reject) => { + promiseInst.then(value => { + (0, _DevToolsUtils.executeSoon)(() => { + dispatch(_objectSpread({}, action, { + status: "done", + value: value + })); + resolve(value); + }); + }, error => { + (0, _DevToolsUtils.executeSoon)(() => { + dispatch(_objectSpread({}, action, { + status: "error", + error: error.message || error + })); + reject(error); + }); + }); + }); + }; +} + +const PROMISE = exports.PROMISE = "@@dispatch/promise"; +exports.promise = promiseMiddleware; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/thunk.js b/devtools/client/debugger/new/src/actions/utils/middleware/thunk.js new file mode 100644 index 000000000000..9d16117f1097 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/thunk.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.thunk = thunk; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* global window */ + +/** + * A middleware that allows thunks (functions) to be dispatched. If + * it's a thunk, it is called with an argument that contains + * `dispatch`, `getState`, and any additional args passed in via the + * middleware constructure. This allows the action to create multiple + * actions (most likely asynchronously). + */ +function thunk(makeArgs) { + return ({ + dispatch, + getState + }) => { + const args = { + dispatch, + getState + }; + return next => action => { + return typeof action === "function" ? action(makeArgs ? makeArgs(args, getState()) : args) : next(action); + }; + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/timing.js b/devtools/client/debugger/new/src/actions/utils/middleware/timing.js new file mode 100644 index 000000000000..e01272b1dd4f --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/timing.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.timing = timing; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* global window */ + +/** + * Redux middleware that sets performance markers for all actions such that they + * will appear in performance tooling under the User Timing API + */ +const mark = window.performance && window.performance.mark ? window.performance.mark.bind(window.performance) : () => {}; +const measure = window.performance && window.performance.measure ? window.performance.measure.bind(window.performance) : () => {}; + +function timing(store) { + return next => action => { + mark(`${action.type}_start`); + const result = next(action); + mark(`${action.type}_end`); + measure(`${action.type}`, `${action.type}_start`, `${action.type}_end`); + return result; + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/middleware/wait-service.js b/devtools/client/debugger/new/src/actions/utils/middleware/wait-service.js new file mode 100644 index 000000000000..77f692a2d826 --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/middleware/wait-service.js @@ -0,0 +1,75 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.waitUntilService = waitUntilService; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* global window */ + +/** + * A middleware which acts like a service, because it is stateful + * and "long-running" in the background. It provides the ability + * for actions to install a function to be run once when a specific + * condition is met by an action coming through the system. Think of + * it as a thunk that blocks until the condition is met. Example: + * + * ```js + * const services = { WAIT_UNTIL: require('wait-service').NAME }; + * + * { type: services.WAIT_UNTIL, + * predicate: action => action.type === "ADD_ITEM", + * run: (dispatch, getState, action) => { + * // Do anything here. You only need to accept the arguments + * // if you need them. `action` is the action that satisfied + * // the predicate. + * } + * } + * ``` + */ +const NAME = exports.NAME = "@@service/waitUntil"; + +function waitUntilService({ + dispatch, + getState +}) { + let pending = []; + + function checkPending(action) { + const readyRequests = []; + const stillPending = []; // Find the pending requests whose predicates are satisfied with + // this action. Wait to run the requests until after we update the + // pending queue because the request handler may synchronously + // dispatch again and run this service (that use case is + // completely valid). + + for (const request of pending) { + if (request.predicate(action)) { + readyRequests.push(request); + } else { + stillPending.push(request); + } + } + + pending = stillPending; + + for (const request of readyRequests) { + request.run(dispatch, getState, action); + } + } + + return next => action => { + if (action.type === NAME) { + pending.push(action); + return null; + } + + const result = next(action); + checkPending(action); + return result; + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/actions/utils/moz.build b/devtools/client/debugger/new/src/actions/utils/moz.build new file mode 100644 index 000000000000..d0cdc8bc9b5b --- /dev/null +++ b/devtools/client/debugger/new/src/actions/utils/moz.build @@ -0,0 +1,12 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'middleware', +] + +DevToolsModules( + 'create-store.js', +) diff --git a/devtools/client/debugger/new/src/client/firefox.js b/devtools/client/debugger/new/src/client/firefox.js new file mode 100644 index 000000000000..5bca9ce46cdf --- /dev/null +++ b/devtools/client/debugger/new/src/client/firefox.js @@ -0,0 +1,89 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.clientEvents = exports.clientCommands = exports.createObjectClient = undefined; +exports.onConnect = onConnect; + +var _commands = require("./firefox/commands"); + +var _events = require("./firefox/events"); + +var _prefs = require("../utils/prefs"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let DebuggerClient; + +function createObjectClient(grip) { + return DebuggerClient.createObjectClient(grip); +} + +async function onConnect(connection, actions) { + const { + tabConnection: { + tabTarget, + threadClient, + debuggerClient + } + } = connection; + DebuggerClient = debuggerClient; + + if (!tabTarget || !threadClient || !debuggerClient) { + return { + bpClients: {} + }; + } + + const supportsWasm = _prefs.features.wasm && !!debuggerClient.mainRoot.traits.wasmBinarySource; + const { + bpClients + } = (0, _commands.setupCommands)({ + threadClient, + tabTarget, + debuggerClient, + supportsWasm + }); + + if (actions) { + (0, _events.setupEvents)({ + threadClient, + actions, + supportsWasm + }); + } + + tabTarget.on("will-navigate", actions.willNavigate); + tabTarget.on("navigate", actions.navigated); + await threadClient.reconfigure({ + observeAsmJS: true, + wasmBinarySource: supportsWasm + }); // In Firefox, we need to initially request all of the sources. This + // usually fires off individual `newSource` notifications as the + // debugger finds them, but there may be existing sources already in + // the debugger (if it's paused already, or if loading the page from + // bfcache) so explicity fire `newSource` events for all returned + // sources. + + const sources = await _commands.clientCommands.fetchSources(); + const traits = tabTarget.activeTab ? tabTarget.activeTab.traits : null; + await actions.connect(tabTarget.url, traits && traits.canRewind); + await actions.newSources(sources); // If the threadClient is already paused, make sure to show a + // paused state. + + const pausedPacket = threadClient.getLastPausePacket(); + + if (pausedPacket) { + _events.clientEvents.paused("paused", pausedPacket); + } + + return { + bpClients + }; +} + +exports.createObjectClient = createObjectClient; +exports.clientCommands = _commands.clientCommands; +exports.clientEvents = _events.clientEvents; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/client/firefox/commands.js b/devtools/client/debugger/new/src/client/firefox/commands.js new file mode 100644 index 000000000000..98b6f56fba17 --- /dev/null +++ b/devtools/client/debugger/new/src/client/firefox/commands.js @@ -0,0 +1,437 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.clientCommands = exports.setupCommands = undefined; + +var _breakpoint = require("../../utils/breakpoint/index"); + +var _create = require("./create"); + +var _frontsDevice = require("devtools/shared/fronts/device"); + +var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let bpClients; +let threadClient; +let tabTarget; +let debuggerClient; +let supportsWasm; + +function setupCommands(dependencies) { + threadClient = dependencies.threadClient; + tabTarget = dependencies.tabTarget; + debuggerClient = dependencies.debuggerClient; + supportsWasm = dependencies.supportsWasm; + bpClients = {}; + return { + bpClients + }; +} + +function sendPacket(packet, callback = r => r) { + return debuggerClient.request(packet).then(callback); +} + +function resume() { + return new Promise(resolve => { + threadClient.resume(resolve); + }); +} + +function stepIn() { + return new Promise(resolve => { + threadClient.stepIn(resolve); + }); +} + +function stepOver() { + return new Promise(resolve => { + threadClient.stepOver(resolve); + }); +} + +function stepOut() { + return new Promise(resolve => { + threadClient.stepOut(resolve); + }); +} + +function rewind() { + return new Promise(resolve => { + threadClient.rewind(resolve); + }); +} + +function reverseStepIn() { + return new Promise(resolve => { + threadClient.reverseStepIn(resolve); + }); +} + +function reverseStepOver() { + return new Promise(resolve => { + threadClient.reverseStepOver(resolve); + }); +} + +function reverseStepOut() { + return new Promise(resolve => { + threadClient.reverseStepOut(resolve); + }); +} + +function breakOnNext() { + return threadClient.breakOnNext(); +} + +function sourceContents(sourceId) { + const sourceClient = threadClient.source({ + actor: sourceId + }); + return sourceClient.source(); +} + +function getBreakpointByLocation(location) { + const id = (0, _breakpoint.makePendingLocationId)(location); + const bpClient = bpClients[id]; + + if (bpClient) { + const { + actor, + url, + line, + column, + condition + } = bpClient.location; + return { + id: bpClient.actor, + condition, + actualLocation: { + line, + column, + sourceId: actor, + sourceUrl: url + } + }; + } + + return null; +} + +function setBreakpoint(location, condition, noSliding) { + const sourceClient = threadClient.source({ + actor: location.sourceId + }); + return sourceClient.setBreakpoint({ + line: location.line, + column: location.column, + condition, + noSliding + }).then(([{ + actualLocation + }, bpClient]) => { + actualLocation = (0, _create.createBreakpointLocation)(location, actualLocation); + const id = (0, _breakpoint.makePendingLocationId)(actualLocation); + bpClients[id] = bpClient; + bpClient.location.line = actualLocation.line; + bpClient.location.column = actualLocation.column; + bpClient.location.url = actualLocation.sourceUrl || ""; + return { + id, + actualLocation + }; + }); +} + +function removeBreakpoint(generatedLocation) { + try { + const id = (0, _breakpoint.makePendingLocationId)(generatedLocation); + const bpClient = bpClients[id]; + + if (!bpClient) { + console.warn("No breakpoint to delete on server"); + return Promise.resolve(); + } + + delete bpClients[id]; + return bpClient.remove(); + } catch (_error) { + console.warn("No breakpoint to delete on server"); + } +} + +function setBreakpointCondition(breakpointId, location, condition, noSliding) { + const bpClient = bpClients[breakpointId]; + delete bpClients[breakpointId]; + return bpClient.setCondition(threadClient, condition, noSliding).then(_bpClient => { + bpClients[breakpointId] = _bpClient; + return { + id: breakpointId + }; + }); +} + +async function evaluateInFrame(script, frameId) { + return evaluate(script, { + frameId + }); +} + +async function evaluateExpressions(scripts, frameId) { + return Promise.all(scripts.map(script => evaluate(script, { + frameId + }))); +} + +function evaluate(script, { + frameId +} = {}) { + const params = frameId ? { + frameActor: frameId + } : {}; + + if (!tabTarget || !tabTarget.activeConsole || !script) { + return Promise.resolve({}); + } + + return new Promise(resolve => { + tabTarget.activeConsole.evaluateJSAsync(script, result => resolve(result), params); + }); +} + +function autocomplete(input, cursor, frameId) { + if (!tabTarget || !tabTarget.activeConsole || !input) { + return Promise.resolve({}); + } + + return new Promise(resolve => { + tabTarget.activeConsole.autocomplete(input, cursor, result => resolve(result), frameId); + }); +} + +function debuggeeCommand(script) { + tabTarget.activeConsole.evaluateJS(script, () => {}, {}); + + if (!debuggerClient) { + return; + } + + const consoleActor = tabTarget.form.consoleActor; + + const request = debuggerClient._activeRequests.get(consoleActor); + + request.emit("json-reply", {}); + + debuggerClient._activeRequests.delete(consoleActor); + + return Promise.resolve(); +} + +function navigate(url) { + return tabTarget.activeTab.navigateTo(url); +} + +function reload() { + return tabTarget.activeTab.reload(); +} + +function getProperties(grip) { + const objClient = threadClient.pauseGrip(grip); + return objClient.getPrototypeAndProperties().then(resp => { + const { + ownProperties, + safeGetterValues + } = resp; + + for (const name in safeGetterValues) { + const { + enumerable, + writable, + getterValue + } = safeGetterValues[name]; + ownProperties[name] = { + enumerable, + writable, + value: getterValue + }; + } + + return resp; + }); +} + +async function getFrameScopes(frame) { + if (frame.scope) { + return frame.scope; + } + + return threadClient.getEnvironment(frame.id); +} + +function pauseOnExceptions(shouldPauseOnExceptions, shouldPauseOnCaughtExceptions) { + return threadClient.pauseOnExceptions(shouldPauseOnExceptions, // Providing opposite value because server + // uses "shouldIgnoreCaughtExceptions" + !shouldPauseOnCaughtExceptions); +} + +function prettyPrint(sourceId, indentSize) { + const sourceClient = threadClient.source({ + actor: sourceId + }); + return sourceClient.prettyPrint(indentSize); +} + +async function blackBox(sourceId, isBlackBoxed) { + const sourceClient = threadClient.source({ + actor: sourceId + }); + + if (isBlackBoxed) { + await sourceClient.unblackBox(); + } else { + await sourceClient.blackBox(); + } + + return { + isBlackBoxed: !isBlackBoxed + }; +} + +function disablePrettyPrint(sourceId) { + const sourceClient = threadClient.source({ + actor: sourceId + }); + return sourceClient.disablePrettyPrint(); +} + +async function setPausePoints(sourceId, pausePoints) { + return sendPacket({ + to: sourceId, + type: "setPausePoints", + pausePoints + }); +} + +async function setSkipPausing(shouldSkip) { + return threadClient.request({ + skip: shouldSkip, + to: threadClient.actor, + type: "skipPausing" + }); +} + +function interrupt() { + return threadClient.interrupt(); +} + +function eventListeners() { + return threadClient.eventListeners(); +} + +function pauseGrip(func) { + return threadClient.pauseGrip(func); +} + +async function fetchSources() { + const { + sources + } = await threadClient.getSources(); + return sources.map(source => (0, _create.createSource)(source, { + supportsWasm + })); +} +/** + * Temporary helper to check if the current server will support a call to + * listWorkers. On Fennec 60 or older, the call will silently crash and prevent + * the client from resuming. + * XXX: Remove when FF60 for Android is no longer used or available. + * + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1443550 for more details. + */ + + +async function checkServerSupportsListWorkers() { + const root = await tabTarget.root; // root is not available on all debug targets. + + if (!root) { + return false; + } + + const deviceFront = await (0, _frontsDevice.getDeviceFront)(debuggerClient, root); + const description = await deviceFront.getDescription(); + const isFennec = description.apptype === "mobile/android"; + + if (!isFennec) { + // Explicitly return true early to avoid calling Services.vs.compare. + // This would force us to extent the Services shim provided by + // devtools-modules, used when this code runs in a tab. + return true; + } // We are only interested in Fennec release versions here. + // We assume that the server fix for Bug 1443550 will land in FF61. + + + const version = description.platformversion; + return _devtoolsModules.Services.vc.compare(version, "61.0") >= 0; +} + +async function fetchWorkers() { + // Temporary workaround for Bug 1443550 + // XXX: Remove when FF60 for Android is no longer used or available. + const supportsListWorkers = await checkServerSupportsListWorkers(); // NOTE: The Worker and Browser Content toolboxes do not have a parent + // with a listWorkers function + // TODO: there is a listWorkers property, but it is not a function on the + // parent. Investigate what it is + + if (!threadClient._parent || typeof threadClient._parent.listWorkers != "function" || !supportsListWorkers) { + return Promise.resolve({ + workers: [] + }); + } + + return threadClient._parent.listWorkers(); +} + +const clientCommands = { + autocomplete, + blackBox, + interrupt, + eventListeners, + pauseGrip, + resume, + stepIn, + stepOut, + stepOver, + rewind, + reverseStepIn, + reverseStepOut, + reverseStepOver, + breakOnNext, + sourceContents, + getBreakpointByLocation, + setBreakpoint, + removeBreakpoint, + setBreakpointCondition, + evaluate, + evaluateInFrame, + evaluateExpressions, + debuggeeCommand, + navigate, + reload, + getProperties, + getFrameScopes, + pauseOnExceptions, + prettyPrint, + disablePrettyPrint, + fetchSources, + fetchWorkers, + sendPacket, + setPausePoints, + setSkipPausing +}; +exports.setupCommands = setupCommands; +exports.clientCommands = clientCommands; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/client/firefox/create.js b/devtools/client/debugger/new/src/client/firefox/create.js new file mode 100644 index 000000000000..179bd68bfa10 --- /dev/null +++ b/devtools/client/debugger/new/src/client/firefox/create.js @@ -0,0 +1,85 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createFrame = createFrame; +exports.createSource = createSource; +exports.createPause = createPause; +exports.createBreakpointLocation = createBreakpointLocation; + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// This module converts Firefox specific types to the generic types +function createFrame(frame) { + if (!frame) { + return null; + } + + let title; + + if (frame.type == "call") { + const c = frame.callee; + title = c.name || c.userDisplayName || c.displayName || L10N.getStr("anonymous"); + } else { + title = `(${frame.type})`; + } + + const location = { + sourceId: frame.where.source.actor, + line: frame.where.line, + column: frame.where.column + }; + return { + id: frame.actor, + displayName: title, + location, + generatedLocation: location, + this: frame.this, + scope: frame.environment + }; +} + +function createSource(source, { + supportsWasm +}) { + return { + id: source.actor, + url: source.url, + isPrettyPrinted: false, + isWasm: supportsWasm && source.introductionType === "wasm", + sourceMapURL: source.sourceMapURL, + isBlackBoxed: false, + loadedState: "unloaded" + }; +} + +function createPause(packet, response) { + // NOTE: useful when the debugger is already paused + const frame = packet.frame || response.frames[0]; + return _objectSpread({}, packet, { + frame: createFrame(frame), + frames: response.frames.map(createFrame) + }); +} // Firefox only returns `actualLocation` if it actually changed, +// but we want it always to exist. Format `actualLocation` if it +// exists, otherwise use `location`. + + +function createBreakpointLocation(location, actualLocation) { + if (!actualLocation) { + return location; + } + + return { + sourceId: actualLocation.source.actor, + sourceUrl: actualLocation.source.url, + line: actualLocation.line, + column: actualLocation.column + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/client/firefox/events.js b/devtools/client/debugger/new/src/client/firefox/events.js new file mode 100644 index 000000000000..fadde881e2d2 --- /dev/null +++ b/devtools/client/debugger/new/src/client/firefox/events.js @@ -0,0 +1,104 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.clientEvents = exports.setupEvents = undefined; + +var _create = require("./create"); + +var _sourceQueue = require("../../utils/source-queue"); + +var _sourceQueue2 = _interopRequireDefault(_sourceQueue); + +var _prefs = require("../../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const CALL_STACK_PAGE_SIZE = 1000; +let threadClient; +let actions; +let supportsWasm; +let isInterrupted; + +function setupEvents(dependencies) { + threadClient = dependencies.threadClient; + actions = dependencies.actions; + supportsWasm = dependencies.supportsWasm; + + _sourceQueue2.default.initialize({ + actions, + supportsWasm, + createSource: _create.createSource + }); + + if (threadClient) { + Object.keys(clientEvents).forEach(eventName => { + threadClient.addListener(eventName, clientEvents[eventName]); + }); + + if (threadClient._parent) { + threadClient._parent.addListener("workerListChanged", workerListChanged); + } + } +} + +async function paused(_, packet) { + // If paused by an explicit interrupt, which are generated by the + // slow script dialog and internal events such as setting + // breakpoints, ignore the event. + const { + why + } = packet; + + if (why.type === "interrupted" && !packet.why.onNext) { + isInterrupted = true; + return; + } // Eagerly fetch the frames + + + const response = await threadClient.getFrames(0, CALL_STACK_PAGE_SIZE); + + if (why.type != "alreadyPaused") { + const pause = (0, _create.createPause)(packet, response); + await _sourceQueue2.default.flush(); + actions.paused(pause); + } +} + +function resumed(_, packet) { + // NOTE: the client suppresses resumed events while interrupted + // to prevent unintentional behavior. + // see [client docs](../README.md#interrupted) for more information. + if (isInterrupted) { + isInterrupted = false; + return; + } + + actions.resumed(packet); +} + +function newSource(_, { + source +}) { + _sourceQueue2.default.queue(source); + + if (_prefs.features.eventListeners) { + actions.fetchEventListeners(); + } +} + +function workerListChanged() { + actions.updateWorkers(); +} + +const clientEvents = { + paused, + resumed, + newSource +}; +exports.setupEvents = setupEvents; +exports.clientEvents = clientEvents; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/client/firefox/fronts-device.js b/devtools/client/debugger/new/src/client/firefox/fronts-device.js new file mode 100644 index 000000000000..1b7739f35e01 --- /dev/null +++ b/devtools/client/debugger/new/src/client/firefox/fronts-device.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getDeviceFront = getDeviceFront; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getDeviceFront() { + return { + getDescription: function () { + return { + // Return anything that will not match Fennec v60 + apptype: "apptype", + version: "version" + }; + } + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/client/firefox/moz.build b/devtools/client/debugger/new/src/client/firefox/moz.build new file mode 100644 index 000000000000..cd496cf2762c --- /dev/null +++ b/devtools/client/debugger/new/src/client/firefox/moz.build @@ -0,0 +1,15 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'commands.js', + 'create.js', + 'events.js', + 'fronts-device.js', +) diff --git a/devtools/client/debugger/new/src/client/index.js b/devtools/client/debugger/new/src/client/index.js new file mode 100644 index 000000000000..3a3a31e29fbc --- /dev/null +++ b/devtools/client/debugger/new/src/client/index.js @@ -0,0 +1,73 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.onConnect = undefined; + +var _firefox = require("./firefox"); + +var firefox = _interopRequireWildcard(_firefox); + +var _prefs = require("../utils/prefs"); + +var _dbg = require("../utils/dbg"); + +var _bootstrap = require("../utils/bootstrap"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function loadFromPrefs(actions) { + const { + pauseOnExceptions, + pauseOnCaughtExceptions + } = _prefs.prefs; + + if (pauseOnExceptions || pauseOnCaughtExceptions) { + return actions.pauseOnExceptions(pauseOnExceptions, pauseOnCaughtExceptions); + } +} + +async function onConnect(connection, { + services, + toolboxActions +}) { + // NOTE: the landing page does not connect to a JS process + if (!connection) { + return; + } + + const commands = firefox.clientCommands; + const { + store, + actions, + selectors + } = (0, _bootstrap.bootstrapStore)(commands, { + services, + toolboxActions + }); + const workers = (0, _bootstrap.bootstrapWorkers)(); + await firefox.onConnect(connection, actions); + await loadFromPrefs(actions); + (0, _dbg.setupHelper)({ + store, + actions, + selectors, + workers: _objectSpread({}, workers, services), + connection, + client: firefox.clientCommands + }); + (0, _bootstrap.bootstrapApp)(store); + return { + store, + actions, + selectors, + client: commands + }; +} + +exports.onConnect = onConnect; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/client/moz.build b/devtools/client/debugger/new/src/client/moz.build new file mode 100644 index 000000000000..89ac5957b616 --- /dev/null +++ b/devtools/client/debugger/new/src/client/moz.build @@ -0,0 +1,13 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'firefox', +] + +DevToolsModules( + 'firefox.js', + 'index.js', +) diff --git a/devtools/client/debugger/new/src/components/App.js b/devtools/client/debugger/new/src/components/App.js new file mode 100644 index 000000000000..3080967274a2 --- /dev/null +++ b/devtools/client/debugger/new/src/components/App.js @@ -0,0 +1,297 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _prefs = require("../utils/prefs"); + +var _actions = require("../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _ShortcutsModal = require("./ShortcutsModal"); + +var _selectors = require("../selectors/index"); + +var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; + +var _devtoolsSplitter = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-splitter"]; + +var _devtoolsSplitter2 = _interopRequireDefault(_devtoolsSplitter); + +var _ProjectSearch = require("./ProjectSearch"); + +var _ProjectSearch2 = _interopRequireDefault(_ProjectSearch); + +var _PrimaryPanes = require("./PrimaryPanes/index"); + +var _PrimaryPanes2 = _interopRequireDefault(_PrimaryPanes); + +var _Editor = require("./Editor/index"); + +var _Editor2 = _interopRequireDefault(_Editor); + +var _SecondaryPanes = require("./SecondaryPanes/index"); + +var _SecondaryPanes2 = _interopRequireDefault(_SecondaryPanes); + +var _WelcomeBox = require("./WelcomeBox"); + +var _WelcomeBox2 = _interopRequireDefault(_WelcomeBox); + +var _Tabs = require("./Editor/Tabs"); + +var _Tabs2 = _interopRequireDefault(_Tabs); + +var _QuickOpenModal = require("./QuickOpenModal"); + +var _QuickOpenModal2 = _interopRequireDefault(_QuickOpenModal); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const shortcuts = new _devtoolsModules.KeyShortcuts({ + window +}); +const { + appinfo +} = _devtoolsModules.Services; +const isMacOS = appinfo.OS === "Darwin"; +const horizontalLayoutBreakpoint = window.matchMedia("(min-width: 800px)"); +const verticalLayoutBreakpoint = window.matchMedia("(min-width: 10px) and (max-width: 800px)"); + +class App extends _react.Component { + constructor(props) { + super(props); + + this.getChildContext = () => { + return { + shortcuts + }; + }; + + this.onEscape = (_, e) => { + const { + activeSearch, + closeActiveSearch, + closeQuickOpen, + quickOpenEnabled + } = this.props; + + if (activeSearch) { + e.preventDefault(); + closeActiveSearch(); + } + + if (quickOpenEnabled) { + e.preventDefault(); + closeQuickOpen(); + } + }; + + this.onCommandSlash = () => { + this.toggleShortcutsModal(); + }; + + this.toggleQuickOpenModal = (_, e, query) => { + const { + quickOpenEnabled, + openQuickOpen, + closeQuickOpen + } = this.props; + e.preventDefault(); + e.stopPropagation(); + + if (quickOpenEnabled === true) { + closeQuickOpen(); + return; + } + + if (query != null) { + openQuickOpen(query); + return; + } + + openQuickOpen(); + return; + }; + + this.onLayoutChange = () => { + this.setOrientation(); + }; + + this.renderEditorPane = () => { + const { + startPanelCollapsed, + endPanelCollapsed + } = this.props; + const { + endPanelSize, + startPanelSize + } = this.state; + const horizontal = this.isHorizontal(); + return _react2.default.createElement("div", { + className: "editor-pane" + }, _react2.default.createElement("div", { + className: "editor-container" + }, _react2.default.createElement(_Tabs2.default, { + startPanelCollapsed: startPanelCollapsed, + endPanelCollapsed: endPanelCollapsed, + horizontal: horizontal, + startPanelSize: startPanelSize, + endPanelSize: endPanelSize + }), _react2.default.createElement(_Editor2.default, { + horizontal: horizontal, + startPanelSize: startPanelSize, + endPanelSize: endPanelSize + }), !this.props.selectedSource ? _react2.default.createElement(_WelcomeBox2.default, { + horizontal: horizontal + }) : null, _react2.default.createElement(_ProjectSearch2.default, null))); + }; + + this.renderLayout = () => { + const { + startPanelCollapsed, + endPanelCollapsed + } = this.props; + const horizontal = this.isHorizontal(); + const maxSize = horizontal ? "70%" : "95%"; + const primaryInitialSize = horizontal ? "250px" : "150px"; + return _react2.default.createElement(_devtoolsSplitter2.default, { + style: { + width: "100vw" + }, + initialHeight: 400, + initialWidth: 300, + minSize: 30, + maxSize: maxSize, + splitterSize: 1, + vert: horizontal, + startPanel: _react2.default.createElement(_devtoolsSplitter2.default, { + style: { + width: "100vw" + }, + initialSize: primaryInitialSize, + minSize: 30, + maxSize: "85%", + splitterSize: 1, + startPanelCollapsed: startPanelCollapsed, + startPanel: _react2.default.createElement(_PrimaryPanes2.default, { + horizontal: horizontal + }), + endPanel: this.renderEditorPane() + }), + endPanelControl: true, + endPanel: _react2.default.createElement(_SecondaryPanes2.default, { + horizontal: horizontal, + toggleShortcutsModal: () => this.toggleShortcutsModal() + }), + endPanelCollapsed: endPanelCollapsed + }); + }; + + this.state = { + shortcutsModalEnabled: false, + startPanelSize: 0, + endPanelSize: 0 + }; + } + + componentDidMount() { + horizontalLayoutBreakpoint.addListener(this.onLayoutChange); + verticalLayoutBreakpoint.addListener(this.onLayoutChange); + this.setOrientation(); + shortcuts.on(L10N.getStr("symbolSearch.search.key2"), (_, e) => this.toggleQuickOpenModal(_, e, "@")); + const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")]; + searchKeys.forEach(key => shortcuts.on(key, this.toggleQuickOpenModal)); + shortcuts.on(L10N.getStr("gotoLineModal.key2"), (_, e) => this.toggleQuickOpenModal(_, e, ":")); + shortcuts.on("Escape", this.onEscape); + shortcuts.on("Cmd+/", this.onCommandSlash); + } + + componentWillUnmount() { + horizontalLayoutBreakpoint.removeListener(this.onLayoutChange); + verticalLayoutBreakpoint.removeListener(this.onLayoutChange); + shortcuts.off(L10N.getStr("symbolSearch.search.key2"), this.toggleQuickOpenModal); + const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")]; + searchKeys.forEach(key => shortcuts.off(key, this.toggleQuickOpenModal)); + shortcuts.off(L10N.getStr("gotoLineModal.key2"), this.toggleQuickOpenModal); + shortcuts.off("Escape", this.onEscape); + } + + isHorizontal() { + return this.props.orientation === "horizontal"; + } + + setOrientation() { + // If the orientation does not match (if it is not visible) it will + // not setOrientation, or if it is the same as before, calling + // setOrientation will not cause a rerender. + if (horizontalLayoutBreakpoint.matches) { + this.props.setOrientation("horizontal"); + } else if (verticalLayoutBreakpoint.matches) { + this.props.setOrientation("vertical"); + } + } + + toggleShortcutsModal() { + this.setState(prevState => ({ + shortcutsModalEnabled: !prevState.shortcutsModalEnabled + })); + } + + renderShortcutsModal() { + const additionalClass = isMacOS ? "mac" : ""; + + if (!_prefs.features.shortcuts) { + return; + } + + return _react2.default.createElement(_ShortcutsModal.ShortcutsModal, { + additionalClass: additionalClass, + enabled: this.state.shortcutsModalEnabled, + handleClose: () => this.toggleShortcutsModal() + }); + } + + render() { + const { + quickOpenEnabled + } = this.props; + return _react2.default.createElement("div", { + className: "debugger" + }, this.renderLayout(), quickOpenEnabled === true && _react2.default.createElement(_QuickOpenModal2.default, { + shortcutsModalEnabled: this.state.shortcutsModalEnabled, + toggleShortcutsModal: () => this.toggleShortcutsModal() + }), this.renderShortcutsModal()); + } + +} + +App.childContextTypes = { + shortcuts: _propTypes2.default.object +}; + +const mapStateToProps = state => ({ + selectedSource: (0, _selectors.getSelectedSource)(state), + startPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "start"), + endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end"), + activeSearch: (0, _selectors.getActiveSearch)(state), + quickOpenEnabled: (0, _selectors.getQuickOpenEnabled)(state), + orientation: (0, _selectors.getOrientation)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(App); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Breakpoint.js b/devtools/client/debugger/new/src/components/Editor/Breakpoint.js new file mode 100644 index 000000000000..938ce4220343 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Breakpoint.js @@ -0,0 +1,138 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("devtools/client/shared/vendor/react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _editor = require("../../utils/editor/index"); + +var _prefs = require("../../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const breakpointSvg = document.createElement("div"); + +_reactDom2.default.render(_react2.default.createElement(_Svg2.default, { + name: "breakpoint" +}), breakpointSvg); + +function makeMarker(isDisabled) { + const bp = breakpointSvg.cloneNode(true); + bp.className = (0, _classnames2.default)("editor new-breakpoint", { + "breakpoint-disabled": isDisabled, + "folding-enabled": _prefs.features.codeFolding + }); + return bp; +} + +class Breakpoint extends _react.Component { + constructor() { + super(); + + this.addBreakpoint = () => { + const { + breakpoint, + editor, + selectedSource + } = this.props; // Hidden Breakpoints are never rendered on the client + + if (breakpoint.hidden) { + return; + } // NOTE: we need to wait for the breakpoint to be loaded + // to get the generated location + + + if (!selectedSource || breakpoint.loading) { + return; + } + + const sourceId = selectedSource.id; + const line = (0, _editor.toEditorLine)(sourceId, breakpoint.location.line); + editor.codeMirror.setGutterMarker(line, "breakpoints", makeMarker(breakpoint.disabled)); + editor.codeMirror.addLineClass(line, "line", "new-breakpoint"); + + if (breakpoint.condition) { + editor.codeMirror.addLineClass(line, "line", "has-condition"); + } else { + editor.codeMirror.removeLineClass(line, "line", "has-condition"); + } + }; + } + + shouldComponentUpdate(nextProps) { + const { + editor, + breakpoint, + selectedSource + } = this.props; + return editor !== nextProps.editor || breakpoint.disabled !== nextProps.breakpoint.disabled || breakpoint.hidden !== nextProps.breakpoint.hidden || breakpoint.condition !== nextProps.breakpoint.condition || breakpoint.loading !== nextProps.breakpoint.loading || selectedSource !== nextProps.selectedSource; + } + + componentDidMount() { + this.addBreakpoint(); + } + + componentDidUpdate() { + this.addBreakpoint(); + } + + componentWillUnmount() { + const { + editor, + breakpoint, + selectedSource + } = this.props; + + if (!selectedSource) { + return; + } + + if (breakpoint.loading) { + return; + } + + const sourceId = selectedSource.id; + const doc = (0, _editor.getDocument)(sourceId); + + if (!doc) { + return; + } + + const line = (0, _editor.toEditorLine)(sourceId, breakpoint.location.line); // NOTE: when we upgrade codemirror we can use `doc.setGutterMarker` + + if (doc.setGutterMarker) { + doc.setGutterMarker(line, "breakpoints", null); + } else { + editor.codeMirror.setGutterMarker(line, "breakpoints", null); + } + + doc.removeLineClass(line, "line", "new-breakpoint"); + doc.removeLineClass(line, "line", "has-condition"); + } + + render() { + return null; + } + +} + +exports.default = Breakpoint; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Breakpoints.js b/devtools/client/debugger/new/src/components/Editor/Breakpoints.js new file mode 100644 index 000000000000..e3f28c8ead13 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Breakpoints.js @@ -0,0 +1,63 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _Breakpoint = require("./Breakpoint"); + +var _Breakpoint2 = _interopRequireDefault(_Breakpoint); + +var _selectors = require("../../selectors/index"); + +var _breakpoint = require("../../utils/breakpoint/index"); + +var _source = require("../../utils/source"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Breakpoints extends _react.Component { + shouldComponentUpdate(nextProps) { + if (nextProps.selectedSource && !(0, _source.isLoaded)(nextProps.selectedSource)) { + return false; + } + + return true; + } + + render() { + const { + breakpoints, + selectedSource, + editor + } = this.props; + + if (!selectedSource || !breakpoints || selectedSource.get("isBlackBoxed")) { + return null; + } + + return _react2.default.createElement("div", null, breakpoints.valueSeq().map(bp => { + return _react2.default.createElement(_Breakpoint2.default, { + key: (0, _breakpoint.makeLocationId)(bp.location), + breakpoint: bp, + selectedSource: selectedSource, + editor: editor + }); + })); + } + +} + +exports.default = (0, _reactRedux.connect)(state => ({ + breakpoints: (0, _selectors.getVisibleBreakpoints)(state), + selectedSource: (0, _selectors.getSelectedSource)(state) +}))(Breakpoints); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/CallSite.js b/devtools/client/debugger/new/src/components/Editor/CallSite.js new file mode 100644 index 000000000000..f9464b30bff0 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/CallSite.js @@ -0,0 +1,99 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _editor = require("../../utils/editor/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class CallSite extends _react.Component { + constructor() { + super(); + + this.addCallSite = nextProps => { + const { + editor, + callSite, + breakpoint, + source + } = nextProps || this.props; + const className = !breakpoint ? "call-site" : "call-site-bp"; + const sourceId = source.get("id"); + const editorRange = (0, _editor.toEditorRange)(sourceId, callSite.location); + this.marker = (0, _editor.markText)(editor, className, editorRange); + }; + + this.clearCallSite = () => { + if (this.marker) { + this.marker.clear(); + this.marker = null; + } + }; + + this.marker = undefined; + } + + shouldComponentUpdate(nextProps) { + return this.props.editor !== nextProps.editor; + } + + componentDidMount() { + const { + breakpoint, + showCallSite + } = this.props; + + if (!breakpoint && !showCallSite) { + return; + } + + this.addCallSite(); + } + + componentWillReceiveProps(nextProps) { + const { + breakpoint, + showCallSite + } = this.props; + + if (nextProps.breakpoint !== breakpoint) { + if (this.marker) { + this.clearCallSite(); + } + + if (nextProps.showCallSite) { + this.addCallSite(nextProps); + } + } + + if (nextProps.showCallSite !== showCallSite) { + if (nextProps.showCallSite) { + if (!this.marker) { + this.addCallSite(); + } + } else if (!nextProps.breakpoint) { + this.clearCallSite(); + } + } + } + + componentWillUnmount() { + if (!this.marker) { + return; + } + + this.marker.clear(); + } + + render() { + return null; + } + +} + +exports.default = CallSite; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/CallSites.js b/devtools/client/debugger/new/src/components/Editor/CallSites.js new file mode 100644 index 000000000000..e2df8facca9c --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/CallSites.js @@ -0,0 +1,257 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _CallSite = require("./CallSite"); + +var _CallSite2 = _interopRequireDefault(_CallSite); + +var _selectors = require("../../selectors/index"); + +var _editor = require("../../utils/editor/index"); + +var _wasm = require("../../utils/wasm"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getCallSiteAtLocation(callSites, location) { + return callSites.find(callSite => (0, _lodash.isEqualWith)(callSite.location, location, (cloc, loc) => { + return loc.line === cloc.start.line && loc.column >= cloc.start.column && loc.column <= cloc.end.column; + })); +} + +class CallSites extends _react.Component { + constructor(props) { + super(props); + + this.onKeyUp = e => { + if (e.key === "Alt") { + e.preventDefault(); + this.setState({ + showCallSites: false + }); + } + }; + + this.onKeyDown = e => { + if (e.key === "Alt") { + e.preventDefault(); + this.setState({ + showCallSites: true + }); + } + }; + + this.state = { + showCallSites: false + }; + } + + componentDidMount() { + const { + editor + } = this.props; + const codeMirrorWrapper = editor.codeMirror.getWrapperElement(); + codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e)); + document.body.addEventListener("keydown", this.onKeyDown); + document.body.addEventListener("keyup", this.onKeyUp); + } + + componentWillUnmount() { + const { + editor + } = this.props; + const codeMirrorWrapper = editor.codeMirror.getWrapperElement(); + codeMirrorWrapper.removeEventListener("click", e => this.onTokenClick(e)); + document.body.removeEventListener("keydown", this.onKeyDown); + document.body.removeEventListener("keyup", this.onKeyUp); + } + + onTokenClick(e) { + const { + target + } = e; + const { + editor, + selectedLocation + } = this.props; + + if (!e.altKey && !target.classList.contains("call-site-bp") || !target.classList.contains("call-site") && !target.classList.contains("call-site-bp")) { + return; + } + + const { + sourceId + } = selectedLocation; + const { + line, + column + } = (0, _editor.getTokenLocation)(editor.codeMirror, target); + this.toggleBreakpoint(line, (0, _wasm.isWasm)(sourceId) ? undefined : column); + } + + toggleBreakpoint(line, column = undefined) { + const { + selectedSource, + selectedLocation, + addBreakpoint, + removeBreakpoint, + callSites + } = this.props; + const callSite = getCallSiteAtLocation(callSites, { + line, + column + }); + + if (!callSite) { + return; + } + + const bp = callSite.breakpoint; + + if (bp && bp.loading || !selectedLocation || !selectedSource) { + return; + } + + const { + sourceId + } = selectedLocation; + + if (bp) { + // NOTE: it's possible the breakpoint has slid to a column + column = column || bp.location.column; + removeBreakpoint({ + sourceId: sourceId, + line: line, + column + }); + } else { + addBreakpoint({ + sourceId: sourceId, + sourceUrl: selectedSource.get("url"), + line: line, + column: column + }); + } + } + + render() { + const { + editor, + callSites, + selectedSource + } = this.props; + const { + showCallSites + } = this.state; + let sites; + + if (!callSites) { + return null; + } + + editor.codeMirror.operation(() => { + const childCallSites = callSites.map((callSite, index) => { + const props = { + key: index, + callSite, + editor, + source: selectedSource, + breakpoint: callSite.breakpoint, + showCallSite: showCallSites + }; + return _react2.default.createElement(_CallSite2.default, props); + }); + sites = _react2.default.createElement("div", null, childCallSites); + }); + return sites; + } + +} + +function getCallSites(symbols, breakpoints) { + if (!symbols || !symbols.callExpressions) { + return; + } + + const callSites = symbols.callExpressions; // NOTE: we create a breakpoint map keyed on location + // to speed up the lookups. Hopefully we'll fix the + // inconsistency with column offsets so that we can expect + // a breakpoint to be added at the beginning of a call expression. + + const bpLocationMap = (0, _lodash.keyBy)(breakpoints.valueSeq().toJS(), ({ + location + }) => locationKey(location)); + + function locationKey({ + line, + column + }) { + return `${line}/${column}`; + } + + function findBreakpoint(callSite) { + const { + location: { + start, + end + } + } = callSite; + const breakpointId = (0, _lodash.range)(start.column - 1, end.column).map(column => locationKey({ + line: start.line, + column + })).find(key => bpLocationMap[key]); + + if (breakpointId) { + return bpLocationMap[breakpointId]; + } + } + + return callSites.filter(({ + location + }) => location.start.line === location.end.line).map(callSite => _objectSpread({}, callSite, { + breakpoint: findBreakpoint(callSite) + })); +} + +const mapStateToProps = state => { + const selectedLocation = (0, _selectors.getSelectedLocation)(state); + const selectedSource = (0, _selectors.getSelectedSource)(state); + const sourceId = selectedLocation && selectedLocation.sourceId; + const symbols = (0, _selectors.getSymbols)(state, selectedSource); + const breakpoints = (0, _selectors.getBreakpointsForSource)(state, sourceId); + return { + selectedLocation, + selectedSource, + callSites: getCallSites(symbols, breakpoints), + breakpoints: breakpoints + }; +}; + +const { + addBreakpoint, + removeBreakpoint +} = _actions2.default; +const mapDispatchToProps = { + addBreakpoint, + removeBreakpoint +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(CallSites); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/ConditionalPanel.js b/devtools/client/debugger/new/src/components/Editor/ConditionalPanel.js new file mode 100644 index 000000000000..d0d8b5f2b940 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/ConditionalPanel.js @@ -0,0 +1,213 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ConditionalPanel = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("devtools/client/shared/vendor/react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _editor = require("../../utils/editor/index"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class ConditionalPanel extends _react.PureComponent { + constructor() { + super(); + + this.saveAndClose = () => { + if (this.input) { + this.setBreakpoint(this.input.value); + } + + this.props.closeConditionalPanel(); + }; + + this.onKey = e => { + if (e.key === "Enter") { + this.saveAndClose(); + } else if (e.key === "Escape") { + this.props.closeConditionalPanel(); + } + }; + + this.repositionOnScroll = () => { + if (this.panelNode && this.scrollParent) { + const { + scrollLeft + } = this.scrollParent; + this.panelNode.style.transform = `translateX(${scrollLeft}px)`; + } + }; + + this.cbPanel = null; + } + + keepFocusOnInput() { + if (this.input) { + this.input.focus(); + } + } + + setBreakpoint(condition) { + const { + selectedLocation, + line + } = this.props; + const sourceId = selectedLocation ? selectedLocation.sourceId : ""; + const location = { + sourceId, + line + }; + return this.props.setBreakpointCondition(location, { + condition + }); + } + + clearConditionalPanel() { + if (this.cbPanel) { + this.cbPanel.clear(); + this.cbPanel = null; + } + + if (this.scrollParent) { + this.scrollParent.removeEventListener("scroll", this.repositionOnScroll); + } + } + + componentWillMount() { + if (this.props.line) { + return this.renderToWidget(this.props); + } + } + + componentWillUpdate(nextProps) { + if (nextProps.line) { + return this.renderToWidget(nextProps); + } + + return this.clearConditionalPanel(); + } + + componentWillUnmount() { + // This is called if CodeMirror is re-initializing itself before the + // user closes the conditional panel. Clear the widget, and re-render it + // as soon as this component gets remounted + return this.clearConditionalPanel(); + } + + renderToWidget(props) { + if (this.cbPanel) { + if (this.props.line && this.props.line == props.line) { + return props.closeConditionalPanel(); + } + + this.clearConditionalPanel(); + } + + const { + selectedLocation, + line, + editor + } = props; + const sourceId = selectedLocation ? selectedLocation.sourceId : ""; + const editorLine = (0, _editor.toEditorLine)(sourceId, line); + this.cbPanel = editor.codeMirror.addLineWidget(editorLine, this.renderConditionalPanel(props), { + coverGutter: true, + noHScroll: false + }); + + if (this.input) { + let parent = this.input.parentNode; + + while (parent) { + if (parent instanceof HTMLElement && parent.classList.contains("CodeMirror-scroll")) { + this.scrollParent = parent; + break; + } + + parent = parent.parentNode; + } + + if (this.scrollParent) { + this.scrollParent.addEventListener("scroll", this.repositionOnScroll); + this.repositionOnScroll(); + } + + this.input.focus(); + } + } + + renderConditionalPanel(props) { + const { + breakpoint + } = props; + const condition = breakpoint ? breakpoint.condition : ""; + const panel = document.createElement("div"); + + _reactDom2.default.render(_react2.default.createElement("div", { + className: "conditional-breakpoint-panel", + onClick: () => this.keepFocusOnInput(), + onBlur: this.props.closeConditionalPanel, + ref: node => this.panelNode = node + }, _react2.default.createElement("div", { + className: "prompt" + }, "\xBB"), _react2.default.createElement("input", { + defaultValue: condition, + placeholder: L10N.getStr("editor.conditionalPanel.placeholder"), + onKeyDown: this.onKey, + ref: input => { + this.input = input; + this.keepFocusOnInput(); + } + })), panel); + + return panel; + } + + render() { + return null; + } + +} + +exports.ConditionalPanel = ConditionalPanel; + +const mapStateToProps = state => { + const line = (0, _selectors.getConditionalPanelLine)(state); + const selectedLocation = (0, _selectors.getSelectedLocation)(state); + return { + selectedLocation, + breakpoint: (0, _selectors.getBreakpointForLine)(state, selectedLocation.sourceId, line), + line + }; +}; + +const { + setBreakpointCondition, + openConditionalPanel, + closeConditionalPanel +} = _actions2.default; +const mapDispatchToProps = { + setBreakpointCondition, + openConditionalPanel, + closeConditionalPanel +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(ConditionalPanel); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/DebugLine.js b/devtools/client/debugger/new/src/components/Editor/DebugLine.js new file mode 100644 index 000000000000..b0a2dc399083 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/DebugLine.js @@ -0,0 +1,134 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DebugLine = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _editor = require("../../utils/editor/index"); + +var _source = require("../../utils/source"); + +var _pause = require("../../utils/pause/index"); + +var _indentation = require("../../utils/indentation"); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function isDocumentReady(selectedSource, selectedFrame) { + return selectedFrame && (0, _source.isLoaded)(selectedSource) && (0, _editor.hasDocument)(selectedFrame.location.sourceId); +} + +class DebugLine extends _react.Component { + componentDidUpdate(prevProps) { + const { + why, + selectedFrame, + selectedSource + } = this.props; + this.setDebugLine(why, selectedFrame, selectedSource); + } + + componentWillUpdate() { + const { + why, + selectedFrame, + selectedSource + } = this.props; + this.clearDebugLine(selectedFrame, selectedSource, why); + } + + componentDidMount() { + const { + why, + selectedFrame, + selectedSource + } = this.props; + this.setDebugLine(why, selectedFrame, selectedSource); + } + + setDebugLine(why, selectedFrame, selectedSource) { + if (!isDocumentReady(selectedSource, selectedFrame)) { + return; + } + + const sourceId = selectedFrame.location.sourceId; + const doc = (0, _editor.getDocument)(sourceId); + let { + line, + column + } = (0, _editor.toEditorPosition)(selectedFrame.location); + const { + markTextClass, + lineClass + } = this.getTextClasses(why); + doc.addLineClass(line, "line", lineClass); + const lineText = doc.getLine(line); + column = Math.max(column, (0, _indentation.getIndentation)(lineText)); + this.debugExpression = doc.markText({ + ch: column, + line + }, { + ch: null, + line + }, { + className: markTextClass + }); + } + + clearDebugLine(selectedFrame, selectedSource, why) { + if (!isDocumentReady(selectedSource, selectedFrame)) { + return; + } + + if (this.debugExpression) { + this.debugExpression.clear(); + } + + const sourceId = selectedFrame.location.sourceId; + const { + line + } = (0, _editor.toEditorPosition)(selectedFrame.location); + const doc = (0, _editor.getDocument)(sourceId); + const { + lineClass + } = this.getTextClasses(why); + doc.removeLineClass(line, "line", lineClass); + } + + getTextClasses(why) { + if ((0, _pause.isException)(why)) { + return { + markTextClass: "debug-expression-error", + lineClass: "new-debug-line-error" + }; + } + + return { + markTextClass: "debug-expression", + lineClass: "new-debug-line" + }; + } + + render() { + return null; + } + +} + +exports.DebugLine = DebugLine; + +const mapStateToProps = state => ({ + selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state), + selectedSource: (0, _selectors.getSelectedSource)(state), + why: (0, _selectors.getPauseReason)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps)(DebugLine); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/EditorMenu.js b/devtools/client/debugger/new/src/components/Editor/EditorMenu.js new file mode 100644 index 000000000000..b237383db7b4 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/EditorMenu.js @@ -0,0 +1,242 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _clipboard = require("../../utils/clipboard"); + +var _function = require("../../utils/function"); + +var _ast = require("../../utils/ast"); + +var _editor = require("../../utils/editor/index"); + +var _source = require("../../utils/source"); + +var _selectors = require("../../selectors/index"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function getMenuItems(event, { + addExpression, + editor, + evaluateInConsole, + flashLineRange, + getFunctionLocation, + getFunctionText, + hasPrettyPrint, + jumpToMappedLocation, + onGutterContextMenu, + selectedLocation, + selectedSource, + showSource, + toggleBlackBox +}) { + // variables + const hasSourceMap = !!selectedSource.get("sourceMapURL"); + const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId); + const isPrettyPrinted = (0, _source.isPretty)(selectedSource); + const isPrettified = isPrettyPrinted || hasPrettyPrint; + const isMapped = isOriginal || hasSourceMap; + const { + line + } = editor.codeMirror.coordsChar({ + left: event.clientX, + top: event.clientY + }); + const selectionText = editor.codeMirror.getSelection().trim(); + const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(editor, selectedLocation, event); + const isTextSelected = editor.codeMirror.somethingSelected(); // localizations + + const blackboxKey = L10N.getStr("sourceFooter.blackbox.accesskey"); + const blackboxLabel = L10N.getStr("sourceFooter.blackbox"); + const unblackboxLabel = L10N.getStr("sourceFooter.unblackbox"); + const toggleBlackBoxLabel = selectedSource.isBlackBoxed ? unblackboxLabel : blackboxLabel; + const copyFunctionKey = L10N.getStr("copyFunction.accesskey"); + const copyFunctionLabel = L10N.getStr("copyFunction.label"); + const copySourceKey = L10N.getStr("copySource.accesskey"); + const copySourceLabel = L10N.getStr("copySource"); + const copyToClipboardKey = L10N.getStr("copyToClipboard.accesskey"); + const copyToClipboardLabel = L10N.getStr("copyToClipboard.label"); + const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey"); + const copySourceUri2Label = L10N.getStr("copySourceUri2"); + const evaluateInConsoleLabel = L10N.getStr("evaluateInConsole.label"); + const jumpToMappedLocKey = L10N.getStr("editor.jumpToMappedLocation1.accesskey"); + const jumpToMappedLocLabel = L10N.getFormatStr("editor.jumpToMappedLocation1", isOriginal ? L10N.getStr("generated") : L10N.getStr("original")); + const revealInTreeKey = L10N.getStr("sourceTabs.revealInTree.accesskey"); + const revealInTreeLabel = L10N.getStr("sourceTabs.revealInTree"); + const watchExpressionKey = L10N.getStr("expressions.accesskey"); + const watchExpressionLabel = L10N.getStr("expressions.label"); // menu items + + const copyToClipboardItem = { + id: "node-menu-copy-to-clipboard", + label: copyToClipboardLabel, + accesskey: copyToClipboardKey, + disabled: false, + click: () => (0, _clipboard.copyToTheClipboard)(selectedSource.text) + }; + const copySourceItem = { + id: "node-menu-copy-source", + label: copySourceLabel, + accesskey: copySourceKey, + disabled: selectionText.length === 0, + click: () => (0, _clipboard.copyToTheClipboard)(selectionText) + }; + const copySourceUri2Item = { + id: "node-menu-copy-source-url", + label: copySourceUri2Label, + accesskey: copySourceUri2Key, + disabled: false, + click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(selectedSource.url)) + }; + const sourceId = selectedSource.get("id"); + const sourceLine = (0, _editor.toSourceLine)(sourceId, line); + const functionText = getFunctionText(sourceLine); + const copyFunctionItem = { + id: "node-menu-copy-function", + label: copyFunctionLabel, + accesskey: copyFunctionKey, + disabled: !functionText, + click: () => { + const { + location: { + start, + end + } + } = getFunctionLocation(sourceLine); + flashLineRange({ + start: start.line, + end: end.line, + sourceId: selectedLocation.sourceId + }); + return (0, _clipboard.copyToTheClipboard)(functionText); + } + }; + const jumpToMappedLocationItem = { + id: "node-menu-jump", + label: jumpToMappedLocLabel, + accesskey: jumpToMappedLocKey, + disabled: !isMapped && !isPrettified, + click: () => jumpToMappedLocation(sourceLocation) + }; + const showSourceMenuItem = { + id: "node-menu-show-source", + label: revealInTreeLabel, + accesskey: revealInTreeKey, + disabled: false, + click: () => showSource(sourceId) + }; + const blackBoxMenuItem = { + id: "node-menu-blackbox", + label: toggleBlackBoxLabel, + accesskey: blackboxKey, + disabled: isOriginal || isPrettyPrinted || hasSourceMap, + click: () => toggleBlackBox(selectedSource.toJS()) + }; + const watchExpressionItem = { + id: "node-menu-add-watch-expression", + label: watchExpressionLabel, + accesskey: watchExpressionKey, + click: () => addExpression(editor.codeMirror.getSelection()) + }; + const evaluateInConsoleItem = { + id: "node-menu-evaluate-in-console", + label: evaluateInConsoleLabel, + click: () => evaluateInConsole(selectionText) + }; // construct menu + + const menuItems = [copyToClipboardItem, copySourceItem, copySourceUri2Item, copyFunctionItem, { + type: "separator" + }, jumpToMappedLocationItem, showSourceMenuItem, blackBoxMenuItem]; // conditionally added items + // TODO: Find a new way to only add this for mapped sources? + + if (isTextSelected) { + menuItems.push(watchExpressionItem, evaluateInConsoleItem); + } + + return menuItems; +} + +class EditorMenu extends _react.Component { + constructor() { + super(); + } + + shouldComponentUpdate(nextProps) { + return nextProps.contextMenu.type === "Editor"; + } + + componentWillUpdate(nextProps) { + // clear the context menu since it is open + this.props.setContextMenu("", null); + return this.showMenu(nextProps); + } + + showMenu(nextProps) { + const { + contextMenu + } = nextProps, + options = _objectWithoutProperties(nextProps, ["contextMenu"]); + + const { + event + } = contextMenu; + (0, _devtoolsContextmenu.showMenu)(event, getMenuItems(event, options)); + } + + render() { + return null; + } + +} + +const mapStateToProps = state => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + const symbols = (0, _selectors.getSymbols)(state, selectedSource); + return { + selectedLocation: (0, _selectors.getSelectedLocation)(state), + selectedSource, + hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")), + contextMenu: (0, _selectors.getContextMenu)(state), + getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), symbols), + getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, { + line, + column: Infinity + }) + }; +}; + +const { + addExpression, + evaluateInConsole, + flashLineRange, + jumpToMappedLocation, + setContextMenu, + showSource, + toggleBlackBox +} = _actions2.default; +const mapDispatchToProps = { + addExpression, + evaluateInConsole, + flashLineRange, + jumpToMappedLocation, + setContextMenu, + showSource, + toggleBlackBox +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(EditorMenu); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/EmptyLines.js b/devtools/client/debugger/new/src/components/Editor/EmptyLines.js new file mode 100644 index 000000000000..0a71012633ee --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/EmptyLines.js @@ -0,0 +1,80 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _react = require("devtools/client/shared/vendor/react"); + +var _selectors = require("../../selectors/index"); + +var _editor = require("../../utils/editor/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class EmptyLines extends _react.Component { + componentDidMount() { + this.disableEmptyLines(); + } + + componentDidUpdate() { + this.disableEmptyLines(); + } + + componentWillUnmount() { + const { + emptyLines, + selectedSource, + editor + } = this.props; + + if (!emptyLines) { + return; + } + + editor.codeMirror.operation(() => { + emptyLines.forEach(emptyLine => { + const line = (0, _editor.toEditorLine)(selectedSource.get("id"), emptyLine); + editor.codeMirror.removeLineClass(line, "line", "empty-line"); + }); + }); + } + + disableEmptyLines() { + const { + emptyLines, + selectedSource, + editor + } = this.props; + + if (!emptyLines) { + return; + } + + editor.codeMirror.operation(() => { + emptyLines.forEach(emptyLine => { + const line = (0, _editor.toEditorLine)(selectedSource.get("id"), emptyLine); + editor.codeMirror.addLineClass(line, "line", "empty-line"); + }); + }); + } + + render() { + return null; + } + +} + +const mapStateToProps = state => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS()); + return { + selectedSource, + emptyLines: selectedSource ? foundEmptyLines : [] + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps)(EmptyLines); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Footer.js b/devtools/client/debugger/new/src/components/Editor/Footer.js new file mode 100644 index 000000000000..bdf200e5786c --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Footer.js @@ -0,0 +1,202 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _prefs = require("../../utils/prefs"); + +var _source = require("../../utils/source"); + +var _sources = require("../../reducers/sources"); + +var _editor = require("../../utils/editor/index"); + +var _PaneToggle = require("../shared/Button/PaneToggle"); + +var _PaneToggle2 = _interopRequireDefault(_PaneToggle); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class SourceFooter extends _react.PureComponent { + prettyPrintButton() { + const { + selectedSource, + togglePrettyPrint + } = this.props; + const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource); + + if (!(0, _editor.shouldShowPrettyPrint)(selectedSource)) { + return; + } + + const tooltip = L10N.getStr("sourceTabs.prettyPrint"); + const type = "prettyPrint"; + return _react2.default.createElement("button", { + onClick: () => togglePrettyPrint(selectedSource.get("id")), + className: (0, _classnames2.default)("action", type, { + active: sourceLoaded, + pretty: (0, _source.isPretty)(selectedSource) + }), + key: type, + title: tooltip, + "aria-label": tooltip + }, _react2.default.createElement("img", { + className: type + })); + } + + blackBoxButton() { + const { + selectedSource, + toggleBlackBox + } = this.props; + const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource); + + if (!sourceLoaded) { + return; + } + + const blackboxed = selectedSource.isBlackBoxed; + const tooltip = L10N.getStr("sourceFooter.blackbox"); + const type = "black-box"; + return _react2.default.createElement("button", { + onClick: () => toggleBlackBox(selectedSource.toJS()), + className: (0, _classnames2.default)("action", type, { + active: sourceLoaded, + blackboxed: blackboxed + }), + key: type, + title: tooltip, + "aria-label": tooltip + }, _react2.default.createElement("img", { + className: "blackBox" + })); + } + + blackBoxSummary() { + const { + selectedSource + } = this.props; + + if (!selectedSource || !selectedSource.isBlackBoxed) { + return; + } + + return _react2.default.createElement("span", { + className: "blackbox-summary" + }, L10N.getStr("sourceFooter.blackboxed")); + } + + coverageButton() { + const { + recordCoverage + } = this.props; + + if (!_prefs.features.codeCoverage) { + return; + } + + return _react2.default.createElement("button", { + className: "coverage action", + title: L10N.getStr("sourceFooter.codeCoverage"), + onClick: () => recordCoverage(), + "aria-label": L10N.getStr("sourceFooter.codeCoverage") + }, "C"); + } + + renderToggleButton() { + if (this.props.horizontal) { + return; + } + + return _react2.default.createElement(_PaneToggle2.default, { + position: "end", + collapsed: !this.props.endPanelCollapsed, + horizontal: this.props.horizontal, + handleClick: this.props.togglePaneCollapse + }); + } + + renderCommands() { + return _react2.default.createElement("div", { + className: "commands" + }, this.prettyPrintButton(), this.blackBoxButton(), this.blackBoxSummary(), this.coverageButton()); + } + + renderSourceSummary() { + const { + mappedSource, + jumpToMappedLocation, + selectedSource + } = this.props; + + if (mappedSource) { + const bundleSource = mappedSource.toJS(); + const filename = (0, _source.getFilename)(bundleSource); + const tooltip = L10N.getFormatStr("sourceFooter.mappedSourceTooltip", filename); + const title = L10N.getFormatStr("sourceFooter.mappedSource", filename); + const mappedSourceLocation = { + sourceId: selectedSource.get("id"), + line: 1, + column: 1 + }; + return _react2.default.createElement("button", { + className: "mapped-source", + onClick: () => jumpToMappedLocation(mappedSourceLocation), + title: tooltip + }, _react2.default.createElement("span", null, title)); + } + + return null; + } + + render() { + const { + selectedSource, + horizontal + } = this.props; + + if (!(0, _editor.shouldShowFooter)(selectedSource, horizontal)) { + return null; + } + + return _react2.default.createElement("div", { + className: "source-footer" + }, this.renderCommands(), this.renderSourceSummary(), this.renderToggleButton()); + } + +} + +const mapStateToProps = state => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + const selectedId = selectedSource.get("id"); + const source = selectedSource.toJS(); + return { + selectedSource, + mappedSource: (0, _sources.getGeneratedSource)(state, source), + prettySource: (0, _selectors.getPrettySource)(state, selectedId), + endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end") + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SourceFooter); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/GutterMenu.js b/devtools/client/debugger/new/src/components/Editor/GutterMenu.js new file mode 100644 index 000000000000..15b75300a7cf --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/GutterMenu.js @@ -0,0 +1,176 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.gutterMenu = gutterMenu; + +var _react = require("devtools/client/shared/vendor/react"); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _editor = require("../../utils/editor/index"); + +var _selectors = require("../../selectors/index"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function gutterMenu({ + breakpoint, + line, + event, + isPaused, + toggleBreakpoint, + openConditionalPanel, + toggleDisabledBreakpoint, + isCbPanelOpen, + closeConditionalPanel, + continueToHere +}) { + event.stopPropagation(); + event.preventDefault(); + const gutterItems = { + addBreakpoint: { + id: "node-menu-add-breakpoint", + label: L10N.getStr("editor.addBreakpoint") + }, + addConditional: { + id: "node-menu-add-conditional-breakpoint", + label: L10N.getStr("editor.addConditionalBreakpoint") + }, + removeBreakpoint: { + id: "node-menu-remove-breakpoint", + label: L10N.getStr("editor.removeBreakpoint") + }, + editConditional: { + id: "node-menu-edit-conditional-breakpoint", + label: L10N.getStr("editor.editBreakpoint") + }, + enableBreakpoint: { + id: "node-menu-enable-breakpoint", + label: L10N.getStr("editor.enableBreakpoint") + }, + disableBreakpoint: { + id: "node-menu-disable-breakpoint", + label: L10N.getStr("editor.disableBreakpoint") + }, + continueToHere: { + id: "node-menu-continue-to-here", + label: L10N.getStr("editor.continueToHere.label") + } + }; + + const toggleBreakpointItem = _objectSpread({ + accesskey: L10N.getStr("shortcuts.toggleBreakpoint.accesskey"), + disabled: false, + click: () => { + toggleBreakpoint(line); + + if (isCbPanelOpen) { + closeConditionalPanel(); + } + } + }, breakpoint ? gutterItems.removeBreakpoint : gutterItems.addBreakpoint); + + const conditionalBreakpoint = _objectSpread({ + accesskey: L10N.getStr("editor.addConditionalBreakpoint.accesskey"), + disabled: false, + click: () => openConditionalPanel(line) + }, breakpoint && breakpoint.condition ? gutterItems.editConditional : gutterItems.addConditional); + + const items = [toggleBreakpointItem, conditionalBreakpoint]; + + if (isPaused) { + const continueToHereItem = _objectSpread({ + accesskey: L10N.getStr("editor.continueToHere.accesskey"), + disabled: false, + click: () => continueToHere(line) + }, gutterItems.continueToHere); + + items.push(continueToHereItem); + } + + if (breakpoint) { + const disableBreakpoint = _objectSpread({ + accesskey: L10N.getStr("editor.disableBreakpoint.accesskey"), + disabled: false, + click: () => toggleDisabledBreakpoint(line) + }, breakpoint.disabled ? gutterItems.enableBreakpoint : gutterItems.disableBreakpoint); + + items.push(disableBreakpoint); + } + + (0, _devtoolsContextmenu.showMenu)(event, items); +} + +class GutterContextMenuComponent extends _react.Component { + constructor() { + super(); + } + + shouldComponentUpdate(nextProps) { + return nextProps.contextMenu.type === "Gutter"; + } + + componentWillUpdate(nextProps) { + // clear the context menu since it is open + this.props.setContextMenu("", null); + return this.showMenu(nextProps); + } + + showMenu(nextProps) { + const { + contextMenu + } = nextProps, + props = _objectWithoutProperties(nextProps, ["contextMenu"]); + + const { + event + } = contextMenu; + const sourceId = props.selectedSource ? props.selectedSource.get("id") : ""; + const line = (0, _editor.lineAtHeight)(props.editor, sourceId, event); + const breakpoint = nextProps.breakpoints.find(bp => bp.location.line === line); + + if (props.emptyLines && props.emptyLines.includes(line)) { + return; + } + + gutterMenu(_objectSpread({ + event, + sourceId, + line, + breakpoint + }, props)); + } + + render() { + return null; + } + +} + +const mapStateToProps = state => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + return { + selectedLocation: (0, _selectors.getSelectedLocation)(state), + selectedSource: selectedSource, + breakpoints: (0, _selectors.getVisibleBreakpoints)(state), + isPaused: (0, _selectors.isPaused)(state), + contextMenu: (0, _selectors.getContextMenu)(state), + emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.toJS()) + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(GutterContextMenuComponent); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/HighlightLine.js b/devtools/client/debugger/new/src/components/Editor/HighlightLine.js new file mode 100644 index 000000000000..dd6ffcf28577 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/HighlightLine.js @@ -0,0 +1,132 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.HighlightLine = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _editor = require("../../utils/editor/index"); + +var _sourceDocuments = require("../../utils/editor/source-documents"); + +var _source = require("../../utils/source"); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function isDebugLine(selectedFrame, selectedLocation) { + if (!selectedFrame) { + return; + } + + return selectedFrame.location.sourceId == selectedLocation.sourceId && selectedFrame.location.line == selectedLocation.line; +} + +function isDocumentReady(selectedSource, selectedLocation) { + return selectedLocation && (0, _source.isLoaded)(selectedSource) && (0, _sourceDocuments.hasDocument)(selectedLocation.sourceId); +} + +class HighlightLine extends _react.Component { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.isStepping = false, this.previousEditorLine = null, _temp; + } + + shouldComponentUpdate(nextProps) { + const { + selectedLocation, + selectedSource + } = nextProps; + return this.shouldSetHighlightLine(selectedLocation, selectedSource); + } + + shouldSetHighlightLine(selectedLocation, selectedSource) { + const { + sourceId, + line + } = selectedLocation; + const editorLine = (0, _editor.toEditorLine)(sourceId, line); + + if (!isDocumentReady(selectedSource, selectedLocation)) { + return false; + } + + if (this.isStepping && editorLine === this.previousEditorLine) { + return false; + } + + return true; + } + + componentDidUpdate(prevProps) { + const { + pauseCommand, + selectedLocation, + selectedFrame, + selectedSource + } = this.props; + + if (pauseCommand) { + this.isStepping = true; + } + + this.clearHighlightLine(prevProps.selectedLocation, prevProps.selectedSource); + this.setHighlightLine(selectedLocation, selectedFrame, selectedSource); + } + + setHighlightLine(selectedLocation, selectedFrame, selectedSource) { + const { + sourceId, + line + } = selectedLocation; + + if (!this.shouldSetHighlightLine(selectedLocation, selectedSource)) { + return; + } + + this.isStepping = false; + const editorLine = (0, _editor.toEditorLine)(sourceId, line); + this.previousEditorLine = editorLine; + + if (!line || isDebugLine(selectedFrame, selectedLocation)) { + return; + } + + const doc = (0, _sourceDocuments.getDocument)(sourceId); + doc.addLineClass(editorLine, "line", "highlight-line"); + } + + clearHighlightLine(selectedLocation, selectedSource) { + if (!isDocumentReady(selectedSource, selectedLocation)) { + return; + } + + const { + line, + sourceId + } = selectedLocation; + const editorLine = (0, _editor.toEditorLine)(sourceId, line); + const doc = (0, _sourceDocuments.getDocument)(sourceId); + doc.removeLineClass(editorLine, "line", "highlight-line"); + } + + render() { + return null; + } + +} + +exports.HighlightLine = HighlightLine; +exports.default = (0, _reactRedux.connect)(state => ({ + pauseCommand: (0, _selectors.getPauseCommand)(state), + selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state), + selectedLocation: (0, _selectors.getSelectedLocation)(state), + selectedSource: (0, _selectors.getSelectedSource)(state) +}))(HighlightLine); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/HighlightLines.js b/devtools/client/debugger/new/src/components/Editor/HighlightLines.js new file mode 100644 index 000000000000..d343bb9a79f3 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/HighlightLines.js @@ -0,0 +1,96 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class HighlightLines extends _react.Component { + constructor() { + super(); + + this.highlightLineRange = () => { + const { + highlightedLineRange, + editor + } = this.props; + const { + codeMirror + } = editor; + + if ((0, _lodash.isEmpty)(highlightedLineRange) || !codeMirror) { + return; + } + + const { + start, + end + } = highlightedLineRange; + codeMirror.operation(() => { + editor.alignLine(start); + (0, _lodash.range)(start - 1, end).forEach(line => { + codeMirror.addLineClass(line, "line", "highlight-lines"); + }); + }); + }; + } + + componentDidMount() { + this.highlightLineRange(); + } + + componentWillUpdate() { + this.clearHighlightRange(); + } + + componentDidUpdate() { + this.highlightLineRange(); + } + + componentWillUnmount() { + this.clearHighlightRange(); + } + + clearHighlightRange() { + const { + highlightedLineRange, + editor + } = this.props; + const { + codeMirror + } = editor; + + if ((0, _lodash.isEmpty)(highlightedLineRange) || !codeMirror) { + return; + } + + const { + start, + end + } = highlightedLineRange; + codeMirror.operation(() => { + (0, _lodash.range)(start - 1, end).forEach(line => { + codeMirror.removeLineClass(line, "line", "highlight-lines"); + }); + }); + } + + render() { + return null; + } + +} + +exports.default = (0, _reactRedux.connect)(state => ({ + highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state) +}))(HighlightLines); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/HitMarker.js b/devtools/client/debugger/new/src/components/Editor/HitMarker.js new file mode 100644 index 000000000000..47f6244d1f12 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/HitMarker.js @@ -0,0 +1,53 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const markerEl = document.createElement("div"); + +function makeMarker() { + const marker = markerEl.cloneNode(true); + marker.className = "editor hit-marker"; + return marker; +} + +class HitMarker extends _react.Component { + addMarker() { + const hitData = this.props.hitData; + const line = hitData.line - 1; + this.props.editor.setGutterMarker(line, "hit-markers", makeMarker()); + this.props.editor.addLineClass(line, "line", "hit-marker"); + } + + shouldComponentUpdate(nextProps) { + return this.props.editor !== nextProps.editor || this.props.hitData !== nextProps.hitData; + } + + componentDidMount() { + this.addMarker(); + } + + componentDidUpdate() { + this.addMarker(); + } + + componentWillUnmount() { + const hitData = this.props.hitData; + const line = hitData.line - 1; + this.props.editor.setGutterMarker(line, "hit-markers", null); + this.props.editor.removeLineClass(line, "line", "hit-marker"); + } + + render() { + return null; + } + +} + +exports.default = HitMarker; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Preview/Popup.js b/devtools/client/debugger/new/src/components/Editor/Preview/Popup.js new file mode 100644 index 000000000000..86b10a9fa213 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Preview/Popup.js @@ -0,0 +1,336 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Popup = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _devtoolsReps = require("devtools/client/shared/components/reps/reps.js"); + +var _devtoolsReps2 = _interopRequireDefault(_devtoolsReps); + +var _actions = require("../../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../../selectors/index"); + +var _Popover = require("../../shared/Popover"); + +var _Popover2 = _interopRequireDefault(_Popover); + +var _PreviewFunction = require("../../shared/PreviewFunction"); + +var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction); + +var _editor = require("../../../utils/editor/index"); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _firefox = require("../../../client/firefox"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + REPS: { + Rep + }, + MODE, + ObjectInspector, + ObjectInspectorUtils +} = _devtoolsReps2.default; +const { + createNode, + getChildren, + getValue, + nodeIsPrimitive, + NODE_TYPES +} = ObjectInspectorUtils.node; +const { + loadItemProperties +} = ObjectInspectorUtils.loadProperties; + +class Popup extends _react.Component { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.onMouseLeave = e => { + const relatedTarget = e.relatedTarget; + + if (relatedTarget && (relatedTarget.classList.contains("popover") || relatedTarget.classList.contains("debug-expression") || relatedTarget.classList.contains("editor-mount"))) { + return; + } + + this.props.onClose(); + }, _temp; + } + + async componentWillMount() { + const { + value, + setPopupObjectProperties, + popupObjectProperties + } = this.props; + const root = this.getRoot(); + + if (!nodeIsPrimitive(root) && value && value.actor && !popupObjectProperties[value.actor]) { + const onLoadItemProperties = loadItemProperties(root, _firefox.createObjectClient); + + if (onLoadItemProperties !== null) { + const properties = await onLoadItemProperties; + setPopupObjectProperties(root.contents.value, properties); + } + } + } + + componentDidMount() { + const { + value, + editor, + range + } = this.props; + + if (!value || !value.type == "object") { + return; + } + + this.marker = (0, _editor.markText)(editor, "preview-selection", range); + } + + componentWillUnmount() { + if (this.marker) { + this.marker.clear(); + } + } + + getRoot() { + const { + expression, + value, + extra + } = this.props; + let rootValue = value; + + if (extra.immutable) { + rootValue = extra.immutable.entries; + } + + return createNode({ + name: expression, + path: expression, + contents: { + value: rootValue + } + }); + } + + getChildren() { + const { + popupObjectProperties + } = this.props; + const root = this.getRoot(); + const value = getValue(root); + const actor = value ? value.actor : null; + const loadedRootProperties = popupObjectProperties[actor]; + + if (!loadedRootProperties) { + return null; + } + + const children = getChildren({ + item: root, + loadedProperties: new Map([[root.path, loadedRootProperties]]) + }); + + if (children.length > 0) { + return children; + } + + return null; + } + + renderFunctionPreview() { + const { + selectSourceURL, + value + } = this.props; + + if (!value) { + return null; + } + + const { + location + } = value; + return _react2.default.createElement("div", { + className: "preview-popup", + onClick: () => selectSourceURL(location.url, { + line: location.line + }) + }, _react2.default.createElement(_PreviewFunction2.default, { + func: value + })); + } + + renderReact(react, roots) { + const reactHeader = react.displayName || "React Component"; + return _react2.default.createElement("div", { + className: "header-container" + }, _react2.default.createElement(_Svg2.default, { + name: "react", + className: "logo" + }), _react2.default.createElement("h3", null, reactHeader)); + } + + renderImmutable(immutable) { + const immutableHeader = immutable.type || "Immutable"; + return _react2.default.createElement("div", { + className: "header-container" + }, _react2.default.createElement(_Svg2.default, { + name: "immutable", + className: "logo" + }), _react2.default.createElement("h3", null, immutableHeader)); + } + + renderObjectPreview() { + const { + extra + } = this.props; + const root = this.getRoot(); + + if (nodeIsPrimitive(root)) { + return null; + } + + let roots = this.getChildren(); + + if (!Array.isArray(roots) || roots.length === 0) { + return null; + } + + let header = null; + + if (extra.immutable) { + header = this.renderImmutable(extra.immutable); + roots = roots.filter(r => r.type != NODE_TYPES.PROTOTYPE); + } + + if (extra.react) { + header = this.renderReact(extra.react); + roots = roots.filter(r => ["state", "props"].includes(r.name)); + } + + return _react2.default.createElement("div", { + className: "preview-popup" + }, header, this.renderObjectInspector(roots)); + } + + renderSimplePreview(value) { + const { + openLink + } = this.props; + return _react2.default.createElement("div", { + className: "preview-popup" + }, Rep({ + object: value, + mode: MODE.LONG, + openLink + })); + } + + renderObjectInspector(roots) { + const { + openLink + } = this.props; + return _react2.default.createElement(ObjectInspector, { + roots: roots, + autoExpandDepth: 0, + disableWrap: true, + focusable: false, + openLink: openLink, + createObjectClient: grip => (0, _firefox.createObjectClient)(grip) + }); + } + + renderPreview() { + const { + value + } = this.props; + + if (!value) { + return null; + } + + if (value.class === "Function") { + return this.renderFunctionPreview(); + } + + if (value.type === "object") { + return _react2.default.createElement("div", null, this.renderObjectPreview()); + } + + return this.renderSimplePreview(value); + } + + getPreviewType(value) { + if (typeof value == "number" || typeof value == "boolean" || typeof value == "string" && value.length < 10 || typeof value == "number" && value.toString().length < 10 || value.type == "null" || value.type == "undefined" || value.class === "Function") { + return "tooltip"; + } + + return "popover"; + } + + render() { + const { + popoverPos, + value, + editorRef + } = this.props; + const type = this.getPreviewType(value); + + if (value && value.type === "object" && !this.getChildren()) { + return null; + } + + return _react2.default.createElement(_Popover2.default, { + targetPosition: popoverPos, + onMouseLeave: this.onMouseLeave, + type: type, + editorRef: editorRef + }, this.renderPreview()); + } + +} + +exports.Popup = Popup; + +const mapStateToProps = state => ({ + popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state) +}); + +const { + addExpression, + selectSourceURL, + selectLocation, + setPopupObjectProperties, + openLink +} = _actions2.default; +const mapDispatchToProps = { + addExpression, + selectSourceURL, + selectLocation, + setPopupObjectProperties, + openLink +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Popup); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Preview/index.js b/devtools/client/debugger/new/src/components/Editor/Preview/index.js new file mode 100644 index 000000000000..e37029d5e75a --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Preview/index.js @@ -0,0 +1,161 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _Popup = require("./Popup"); + +var _Popup2 = _interopRequireDefault(_Popup); + +var _selectors = require("../../../selectors/index"); + +var _actions = require("../../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _editor = require("../../../utils/editor/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Preview extends _react.PureComponent { + constructor(props) { + super(props); + + this.onMouseOver = e => { + const { + target + } = e; + this.props.updatePreview(target, this.props.editor); + }; + + this.onMouseUp = () => { + this.setState({ + selecting: false + }); + return true; + }; + + this.onMouseDown = () => { + this.setState({ + selecting: true + }); + return true; + }; + + this.onMouseLeave = e => { + const target = e.target; + + if (target.classList.contains("CodeMirror")) { + return; + } + + this.props.clearPreview(); + }; + + this.onClose = () => { + this.props.clearPreview(); + }; + + this.state = { + selecting: false + }; + } + + componentDidMount() { + const { + codeMirror + } = this.props.editor; + const codeMirrorWrapper = codeMirror.getWrapperElement(); + codeMirrorWrapper.addEventListener("mouseover", this.onMouseOver); + codeMirrorWrapper.addEventListener("mouseup", this.onMouseUp); + codeMirrorWrapper.addEventListener("mousedown", this.onMouseDown); + codeMirrorWrapper.addEventListener("mouseleave", this.onMouseLeave); + + if (document.body) { + document.body.addEventListener("mouseleave", this.onMouseLeave); + } + } + + componentWillUnmount() { + const codeMirror = this.props.editor.codeMirror; + const codeMirrorWrapper = codeMirror.getWrapperElement(); + codeMirrorWrapper.removeEventListener("mouseover", this.onMouseOver); + codeMirrorWrapper.removeEventListener("mouseup", this.onMouseUp); + codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown); + codeMirrorWrapper.removeEventListener("mouseleave", this.onMouseLeave); + + if (document.body) { + document.body.removeEventListener("mouseleave", this.onMouseLeave); + } + } + + render() { + const { + selectedSource, + preview + } = this.props; + + if (!this.props.editor || !selectedSource || this.state.selecting) { + return null; + } + + if (!preview || preview.updating) { + return null; + } + + const { + result, + expression, + location, + cursorPos, + extra + } = preview; + const value = result; + + if (typeof value == "undefined" || value.optimizedOut) { + return null; + } + + const editorRange = (0, _editor.toEditorRange)(selectedSource.get("id"), location); + return _react2.default.createElement(_Popup2.default, { + value: value, + editor: this.props.editor, + editorRef: this.props.editorRef, + range: editorRange, + expression: expression, + popoverPos: cursorPos, + extra: extra, + onClose: this.onClose + }); + } + +} + +const mapStateToProps = state => ({ + preview: (0, _selectors.getPreview)(state), + selectedSource: (0, _selectors.getSelectedSource)(state) +}); + +const { + addExpression, + setPopupObjectProperties, + updatePreview, + clearPreview +} = _actions2.default; +const mapDispatchToProps = { + addExpression, + setPopupObjectProperties, + updatePreview, + clearPreview +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Preview); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Preview/moz.build b/devtools/client/debugger/new/src/components/Editor/Preview/moz.build new file mode 100644 index 000000000000..d226ed0887fc --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Preview/moz.build @@ -0,0 +1,13 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'index.js', + 'Popup.js', +) diff --git a/devtools/client/debugger/new/src/components/Editor/SearchBar.js b/devtools/client/debugger/new/src/components/Editor/SearchBar.js new file mode 100644 index 000000000000..c04525b76683 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/SearchBar.js @@ -0,0 +1,368 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _editor = require("../../utils/editor/index"); + +var _resultList = require("../../utils/result-list"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _SearchInput = require("../shared/SearchInput"); + +var _SearchInput2 = _interopRequireDefault(_SearchInput); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getShortcuts() { + const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2"); + const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2"); + const searchKey = L10N.getStr("sourceSearch.search.key2"); + return { + shiftSearchAgainShortcut: searchAgainPrevKey, + searchAgainShortcut: searchAgainKey, + searchShortcut: searchKey + }; +} + +class SearchBar extends _react.Component { + constructor(props) { + super(props); + + this.onEscape = e => { + this.closeSearch(e); + }; + + this.clearSearch = () => { + const { + editor: ed, + query + } = this.props; + + if (ed) { + const ctx = { + ed, + cm: ed.codeMirror + }; + (0, _editor.removeOverlay)(ctx, query); + } + }; + + this.closeSearch = e => { + const { + closeFileSearch, + editor, + searchOn + } = this.props; + + if (editor && searchOn) { + this.clearSearch(); + closeFileSearch(editor); + e.stopPropagation(); + e.preventDefault(); + } + + this.setState({ + query: "", + inputFocused: false + }); + }; + + this.toggleSearch = e => { + e.stopPropagation(); + e.preventDefault(); + const { + editor, + searchOn, + setActiveSearch + } = this.props; + + if (!searchOn) { + setActiveSearch("file"); + } + + if (searchOn && editor) { + const query = editor.codeMirror.getSelection() || this.state.query; + + if (query !== "") { + this.setState({ + query, + inputFocused: true + }); + this.doSearch(query); + } else { + this.setState({ + query: "", + inputFocused: true + }); + } + } + }; + + this.doSearch = query => { + const { + selectedSource + } = this.props; + + if (!selectedSource || !selectedSource.get("text")) { + return; + } + + this.props.doSearch(query, this.props.editor); + }; + + this.updateSearchResults = (characterIndex, line, matches) => { + const matchIndex = matches.findIndex(elm => elm.line === line && elm.ch === characterIndex); + this.props.updateSearchResults({ + matches, + matchIndex, + count: matches.length, + index: characterIndex + }); + }; + + this.traverseResults = (e, rev) => { + e.stopPropagation(); + e.preventDefault(); + const editor = this.props.editor; + + if (!editor) { + return; + } + + this.props.traverseResults(rev, editor); + }; + + this.onChange = e => { + this.setState({ + query: e.target.value + }); + return this.doSearch(e.target.value); + }; + + this.onBlur = e => { + this.setState({ + inputFocused: false + }); + }; + + this.onKeyDown = e => { + if (e.key !== "Enter" && e.key !== "F3") { + return; + } + + this.traverseResults(e, e.shiftKey); + e.preventDefault(); + }; + + this.renderSearchModifiers = () => { + const { + modifiers, + toggleFileSearchModifier, + query + } = this.props; + const { + doSearch + } = this; + + function SearchModBtn({ + modVal, + className, + svgName, + tooltip + }) { + const preppedClass = (0, _classnames2.default)(className, { + active: modifiers && modifiers.get(modVal) + }); + return _react2.default.createElement("button", { + className: preppedClass, + onClick: () => { + toggleFileSearchModifier(modVal); + doSearch(query); + }, + title: tooltip + }, _react2.default.createElement(_Svg2.default, { + name: svgName + })); + } + + return _react2.default.createElement("div", { + className: "search-modifiers" + }, _react2.default.createElement("span", { + className: "search-type-name" + }, L10N.getStr("symbolSearch.searchModifier.modifiersLabel")), _react2.default.createElement(SearchModBtn, { + modVal: "regexMatch", + className: "regex-match-btn", + svgName: "regex-match", + tooltip: L10N.getStr("symbolSearch.searchModifier.regex") + }), _react2.default.createElement(SearchModBtn, { + modVal: "caseSensitive", + className: "case-sensitive-btn", + svgName: "case-match", + tooltip: L10N.getStr("symbolSearch.searchModifier.caseSensitive") + }), _react2.default.createElement(SearchModBtn, { + modVal: "wholeWord", + className: "whole-word-btn", + svgName: "whole-word-match", + tooltip: L10N.getStr("symbolSearch.searchModifier.wholeWord") + })); + }; + + this.state = { + query: props.query, + selectedResultIndex: 0, + count: 0, + index: -1, + inputFocused: false + }; + } + + componentWillUnmount() { + const shortcuts = this.context.shortcuts; + const { + searchShortcut, + searchAgainShortcut, + shiftSearchAgainShortcut + } = getShortcuts(); + shortcuts.off(searchShortcut); + shortcuts.off("Escape"); + shortcuts.off(searchAgainShortcut); + shortcuts.off(shiftSearchAgainShortcut); + } + + componentDidMount() { + // overwrite this.doSearch with debounced version to + // reduce frequency of queries + this.doSearch = (0, _lodash.debounce)(this.doSearch, 100); + const shortcuts = this.context.shortcuts; + const { + searchShortcut, + searchAgainShortcut, + shiftSearchAgainShortcut + } = getShortcuts(); + shortcuts.on(searchShortcut, (_, e) => this.toggleSearch(e)); + shortcuts.on("Escape", (_, e) => this.onEscape(e)); + shortcuts.on(shiftSearchAgainShortcut, (_, e) => this.traverseResults(e, true)); + shortcuts.on(searchAgainShortcut, (_, e) => this.traverseResults(e, false)); + } + + componentDidUpdate(prevProps, prevState) { + if (this.refs.resultList && this.refs.resultList.refs) { + (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedResultIndex); + } + } + + // Renderers + buildSummaryMsg() { + const { + searchResults: { + matchIndex, + count, + index + }, + query + } = this.props; + + if (query.trim() == "") { + return ""; + } + + if (count == 0) { + return L10N.getStr("editor.noResults"); + } + + if (index == -1) { + return L10N.getFormatStr("sourceSearch.resultsSummary1", count); + } + + return L10N.getFormatStr("editor.searchResults", matchIndex + 1, count); + } + + shouldShowErrorEmoji() { + const { + query, + searchResults: { + count + } + } = this.props; + return !!query && !count; + } + + render() { + const { + searchResults: { + count + }, + searchOn + } = this.props; + + if (!searchOn) { + return _react2.default.createElement("div", null); + } + + return _react2.default.createElement("div", { + className: "search-bar" + }, _react2.default.createElement(_SearchInput2.default, { + query: this.state.query, + count: count, + placeholder: L10N.getStr("sourceSearch.search.placeholder"), + summaryMsg: this.buildSummaryMsg(), + onChange: this.onChange, + onBlur: this.onBlur, + showErrorEmoji: this.shouldShowErrorEmoji(), + onKeyDown: this.onKeyDown, + handleNext: e => this.traverseResults(e, false), + handlePrev: e => this.traverseResults(e, true), + handleClose: this.closeSearch, + shouldFocus: this.state.inputFocused + }), _react2.default.createElement("div", { + className: "search-bottom-bar" + }, this.renderSearchModifiers())); + } + +} + +SearchBar.contextTypes = { + shortcuts: _propTypes2.default.object +}; + +const mapStateToProps = state => ({ + searchOn: (0, _selectors.getActiveSearch)(state) === "file", + selectedSource: (0, _selectors.getSelectedSource)(state), + selectedLocation: (0, _selectors.getSelectedLocation)(state), + query: (0, _selectors.getFileSearchQuery)(state), + modifiers: (0, _selectors.getFileSearchModifiers)(state), + highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state), + searchResults: (0, _selectors.getFileSearchResults)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SearchBar); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Tab.js b/devtools/client/debugger/new/src/components/Editor/Tab.js new file mode 100644 index 000000000000..d789b1a7ed2e --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Tab.js @@ -0,0 +1,194 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _Close = require("../shared/Button/Close"); + +var _Close2 = _interopRequireDefault(_Close); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _source = require("../../utils/source"); + +var _clipboard = require("../../utils/clipboard"); + +var _tabs = require("../../utils/tabs"); + +var _selectors = require("../../selectors/index"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +class Tab extends _react.PureComponent { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.onTabContextMenu = (event, tab) => { + event.preventDefault(); + this.showContextMenu(event, tab); + }, _temp; + } + + showContextMenu(e, tab) { + const { + closeTab, + closeTabs, + tabSources, + showSource, + togglePrettyPrint, + selectedSource + } = this.props; + const otherTabs = tabSources.filter(t => t.get("id") !== tab); + const sourceTab = tabSources.find(t => t.get("id") == tab); + const tabURLs = tabSources.map(t => t.get("url")); + const otherTabURLs = otherTabs.map(t => t.get("url")); + + if (!sourceTab) { + return; + } + + const isPrettySource = (0, _source.isPretty)(sourceTab); + const tabMenuItems = (0, _tabs.getTabMenuItems)(); + const items = [{ + item: _objectSpread({}, tabMenuItems.closeTab, { + click: () => closeTab(sourceTab.get("url")) + }) + }, { + item: _objectSpread({}, tabMenuItems.closeOtherTabs, { + click: () => closeTabs(otherTabURLs) + }), + hidden: () => tabSources.size === 1 + }, { + item: _objectSpread({}, tabMenuItems.closeTabsToEnd, { + click: () => { + const tabIndex = tabSources.findIndex(t => t.get("id") == tab); + closeTabs(tabURLs.filter((t, i) => i > tabIndex)); + } + }), + hidden: () => tabSources.size === 1 || tabSources.some((t, i) => t === tab && tabSources.size - 1 === i) + }, { + item: _objectSpread({}, tabMenuItems.closeAllTabs, { + click: () => closeTabs(tabURLs) + }) + }, { + item: { + type: "separator" + } + }, { + item: _objectSpread({}, tabMenuItems.copyToClipboard, { + disabled: selectedSource.get("id") !== tab, + click: () => (0, _clipboard.copyToTheClipboard)(sourceTab.text) + }) + }, { + item: _objectSpread({}, tabMenuItems.copySourceUri2, { + click: () => (0, _clipboard.copyToTheClipboard)((0, _source.getRawSourceURL)(sourceTab.get("url"))) + }) + }]; + items.push({ + item: _objectSpread({}, tabMenuItems.showSource, { + click: () => showSource(tab) + }) + }); + + if (!isPrettySource) { + items.push({ + item: _objectSpread({}, tabMenuItems.prettyPrint, { + click: () => togglePrettyPrint(tab) + }) + }); + } + + (0, _devtoolsContextmenu.showMenu)(e, (0, _devtoolsContextmenu.buildMenu)(items)); + } + + isProjectSearchEnabled() { + return this.props.activeSearch === "project"; + } + + isSourceSearchEnabled() { + return this.props.activeSearch === "source"; + } + + render() { + const { + selectedSource, + selectSpecificSource, + closeTab, + source, + sourceMetaData + } = this.props; + const src = source.toJS(); + const filename = (0, _source.getFilename)(src); + const sourceId = source.id; + const active = selectedSource && sourceId == selectedSource.get("id") && !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled(); + const isPrettyCode = (0, _source.isPretty)(source); + const sourceAnnotation = (0, _tabs.getSourceAnnotation)(source, sourceMetaData); + + function onClickClose(e) { + e.stopPropagation(); + closeTab(source.url); + } + + function handleTabClick(e) { + e.preventDefault(); + e.stopPropagation(); // Accommodate middle click to close tab + + if (e.button === 1) { + return closeTab(source.url); + } + + return selectSpecificSource(sourceId); + } + + const className = (0, _classnames2.default)("source-tab", { + active, + pretty: isPrettyCode + }); + return _react2.default.createElement("div", { + className: className, + key: sourceId, + onMouseUp: handleTabClick, + onContextMenu: e => this.onTabContextMenu(e, sourceId), + title: (0, _source.getFileURL)(src) + }, sourceAnnotation, _react2.default.createElement("div", { + className: "filename" + }, filename), _react2.default.createElement(_Close2.default, { + handleClick: onClickClose, + tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip") + })); + } + +} + +const mapStateToProps = (state, { + source +}) => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + return { + tabSources: (0, _selectors.getSourcesForTabs)(state), + selectedSource: selectedSource, + sourceMetaData: (0, _selectors.getSourceMetaData)(state, source.id), + activeSearch: (0, _selectors.getActiveSearch)(state) + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tab); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/Tabs.js b/devtools/client/debugger/new/src/components/Editor/Tabs.js new file mode 100644 index 000000000000..861281f6f2f7 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/Tabs.js @@ -0,0 +1,216 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _selectors = require("../../selectors/index"); + +var _ui = require("../../utils/ui"); + +var _tabs = require("../../utils/tabs"); + +var _source = require("../../utils/source"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _Tab = require("./Tab"); + +var _Tab2 = _interopRequireDefault(_Tab); + +var _PaneToggle = require("../shared/Button/PaneToggle"); + +var _PaneToggle2 = _interopRequireDefault(_PaneToggle); + +var _Dropdown = require("../shared/Dropdown"); + +var _Dropdown2 = _interopRequireDefault(_Dropdown); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Tabs extends _react.PureComponent { + constructor(props) { + super(props); + + this.updateHiddenTabs = () => { + if (!this.refs.sourceTabs) { + return; + } + + const { + selectedSource, + tabSources, + moveTab + } = this.props; + const sourceTabEls = this.refs.sourceTabs.children; + const hiddenTabs = (0, _tabs.getHiddenTabs)(tabSources, sourceTabEls); + + if ((0, _ui.isVisible)() && hiddenTabs.indexOf(selectedSource) !== -1) { + return moveTab(selectedSource.url, 0); + } + + this.setState({ + hiddenTabs + }); + }; + + this.renderDropdownSource = source => { + const { + selectSpecificSource + } = this.props; + const filename = (0, _source.getFilename)(source.toJS()); + + const onClick = () => selectSpecificSource(source.id); + + return _react2.default.createElement("li", { + key: source.id, + onClick: onClick + }, _react2.default.createElement("img", { + className: `dropdown-icon ${this.getIconClass(source)}` + }), filename); + }; + + this.state = { + dropdownShown: false, + hiddenTabs: I.List() + }; + this.onResize = (0, _lodash.debounce)(() => { + this.updateHiddenTabs(); + }); + } + + componentDidUpdate(prevProps) { + if (!(prevProps === this.props)) { + this.updateHiddenTabs(); + } + } + + componentDidMount() { + window.requestIdleCallback(this.updateHiddenTabs); + window.addEventListener("resize", this.onResize); + } + + componentWillUnmount() { + window.removeEventListener("resize", this.onResize); + } + /* + * Updates the hiddenSourceTabs state, by + * finding the source tabs which are wrapped and are not on the top row. + */ + + + toggleSourcesDropdown(e) { + this.setState(prevState => ({ + dropdownShown: !prevState.dropdownShown + })); + } + + getIconClass(source) { + if ((0, _source.isPretty)(source)) { + return "prettyPrint"; + } + + if (source.isBlackBoxed) { + return "blackBox"; + } + + return "file"; + } + + renderTabs() { + const { + tabSources + } = this.props; + + if (!tabSources) { + return; + } + + return _react2.default.createElement("div", { + className: "source-tabs", + ref: "sourceTabs" + }, tabSources.map((source, index) => _react2.default.createElement(_Tab2.default, { + key: index, + source: source + }))); + } + + renderDropdown() { + const hiddenTabs = this.state.hiddenTabs; + + if (!hiddenTabs || hiddenTabs.size == 0) { + return null; + } + + const Panel = _react2.default.createElement("ul", null, hiddenTabs.map(this.renderDropdownSource)); + + const icon = _react2.default.createElement("img", { + className: "moreTabs" + }); + + return _react2.default.createElement(_Dropdown2.default, { + panel: Panel, + icon: icon + }); + } + + renderStartPanelToggleButton() { + return _react2.default.createElement(_PaneToggle2.default, { + position: "start", + collapsed: !this.props.startPanelCollapsed, + handleClick: this.props.togglePaneCollapse + }); + } + + renderEndPanelToggleButton() { + const { + horizontal, + endPanelCollapsed, + togglePaneCollapse + } = this.props; + + if (!horizontal) { + return; + } + + return _react2.default.createElement(_PaneToggle2.default, { + position: "end", + collapsed: !endPanelCollapsed, + handleClick: togglePaneCollapse, + horizontal: horizontal + }); + } + + render() { + return _react2.default.createElement("div", { + className: "source-header" + }, this.renderStartPanelToggleButton(), this.renderTabs(), this.renderDropdown(), this.renderEndPanelToggleButton()); + } + +} + +const mapStateToProps = state => ({ + selectedSource: (0, _selectors.getSelectedSource)(state), + tabSources: (0, _selectors.getSourcesForTabs)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tabs); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/index.js b/devtools/client/debugger/new/src/components/Editor/index.js new file mode 100644 index 000000000000..bff2ab62954a --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/index.js @@ -0,0 +1,638 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("devtools/client/shared/vendor/react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _source = require("../../utils/source"); + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +var _prefs = require("../../utils/prefs"); + +var _indentation = require("../../utils/indentation"); + +var _selectors = require("../../selectors/index"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _Footer = require("./Footer"); + +var _Footer2 = _interopRequireDefault(_Footer); + +var _SearchBar = require("./SearchBar"); + +var _SearchBar2 = _interopRequireDefault(_SearchBar); + +var _HighlightLines = require("./HighlightLines"); + +var _HighlightLines2 = _interopRequireDefault(_HighlightLines); + +var _Preview = require("./Preview/index"); + +var _Preview2 = _interopRequireDefault(_Preview); + +var _Breakpoints = require("./Breakpoints"); + +var _Breakpoints2 = _interopRequireDefault(_Breakpoints); + +var _HitMarker = require("./HitMarker"); + +var _HitMarker2 = _interopRequireDefault(_HitMarker); + +var _CallSites = require("./CallSites"); + +var _CallSites2 = _interopRequireDefault(_CallSites); + +var _DebugLine = require("./DebugLine"); + +var _DebugLine2 = _interopRequireDefault(_DebugLine); + +var _HighlightLine = require("./HighlightLine"); + +var _HighlightLine2 = _interopRequireDefault(_HighlightLine); + +var _EmptyLines = require("./EmptyLines"); + +var _EmptyLines2 = _interopRequireDefault(_EmptyLines); + +var _GutterMenu = require("./GutterMenu"); + +var _GutterMenu2 = _interopRequireDefault(_GutterMenu); + +var _EditorMenu = require("./EditorMenu"); + +var _EditorMenu2 = _interopRequireDefault(_EditorMenu); + +var _ConditionalPanel = require("./ConditionalPanel"); + +var _ConditionalPanel2 = _interopRequireDefault(_ConditionalPanel); + +var _editor = require("../../utils/editor/index"); + +var _ui = require("../../utils/ui"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Redux actions +const cssVars = { + searchbarHeight: "var(--editor-searchbar-height)", + secondSearchbarHeight: "var(--editor-second-searchbar-height)", + footerHeight: "var(--editor-footer-height)" +}; + +class Editor extends _react.PureComponent { + constructor(props) { + super(props); + + this.onToggleBreakpoint = (key, e) => { + e.preventDefault(); + e.stopPropagation(); + const { + selectedSource, + conditionalPanelLine + } = this.props; + + if (!selectedSource) { + return; + } + + const line = this.getCurrentLine(); + + if (e.shiftKey) { + this.toggleConditionalPanel(line); + } else if (!conditionalPanelLine) { + this.props.toggleBreakpoint(line); + } else { + this.toggleConditionalPanel(line); + this.props.toggleBreakpoint(line); + } + }; + + this.onToggleConditionalPanel = (key, e) => { + e.stopPropagation(); + e.preventDefault(); + const line = this.getCurrentLine(); + this.toggleConditionalPanel(line); + }; + + this.onEscape = (key, e) => { + if (!this.state.editor) { + return; + } + + const { + codeMirror + } = this.state.editor; + + if (codeMirror.listSelections().length > 1) { + codeMirror.execCommand("singleSelection"); + e.preventDefault(); + } + }; + + this.onSearchAgain = (_, e) => { + this.props.traverseResults(e.shiftKey, this.state.editor); + }; + + this.onGutterClick = (cm, line, gutter, ev) => { + const { + selectedSource, + conditionalPanelLine, + closeConditionalPanel, + addOrToggleDisabledBreakpoint, + toggleBreakpoint, + continueToHere + } = this.props; // ignore right clicks in the gutter + + if (ev.ctrlKey && ev.button === 0 || ev.which === 3 || selectedSource && selectedSource.isBlackBoxed || !selectedSource) { + return; + } + + if (conditionalPanelLine) { + return closeConditionalPanel(); + } + + if (gutter === "CodeMirror-foldgutter") { + return; + } + + const sourceLine = (0, _editor.toSourceLine)(selectedSource.get("id"), line); + + if (ev.altKey) { + return continueToHere(sourceLine); + } + + if (ev.shiftKey) { + return addOrToggleDisabledBreakpoint(sourceLine); + } + + return toggleBreakpoint(sourceLine); + }; + + this.onGutterContextMenu = event => { + event.stopPropagation(); + event.preventDefault(); + return this.props.setContextMenu("Gutter", event); + }; + + this.toggleConditionalPanel = line => { + const { + conditionalPanelLine, + closeConditionalPanel, + openConditionalPanel + } = this.props; + + if (conditionalPanelLine) { + return closeConditionalPanel(); + } + + return openConditionalPanel(line); + }; + + this.closeConditionalPanel = () => { + return this.props.closeConditionalPanel(); + }; + + this.state = { + highlightedLineRange: null, + editor: null + }; + } + + componentWillReceiveProps(nextProps) { + if (!this.state.editor) { + return; + } + + (0, _ui.resizeBreakpointGutter)(this.state.editor.codeMirror); + (0, _ui.resizeToggleButton)(this.state.editor.codeMirror); + } + + componentWillUpdate(nextProps) { + this.setText(nextProps); + this.setSize(nextProps); + this.scrollToLocation(nextProps); + } + + setupEditor() { + const editor = (0, _editor.createEditor)(); // disables the default search shortcuts + // $FlowIgnore + + editor._initShortcuts = () => {}; + + const node = _reactDom2.default.findDOMNode(this); + + if (node instanceof HTMLElement) { + editor.appendToLocalElement(node.querySelector(".editor-mount")); + } + + const { + codeMirror + } = editor; + const codeMirrorWrapper = codeMirror.getWrapperElement(); + (0, _ui.resizeBreakpointGutter)(codeMirror); + (0, _ui.resizeToggleButton)(codeMirror); + codeMirror.on("gutterClick", this.onGutterClick); // Set code editor wrapper to be focusable + + codeMirrorWrapper.tabIndex = 0; + codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e)); + codeMirrorWrapper.addEventListener("click", e => this.onClick(e)); + + const toggleFoldMarkerVisibility = e => { + if (node instanceof HTMLElement) { + node.querySelectorAll(".CodeMirror-guttermarker-subtle").forEach(elem => { + elem.classList.toggle("visible"); + }); + } + }; + + const codeMirrorGutter = codeMirror.getGutterElement(); + codeMirrorGutter.addEventListener("mouseleave", toggleFoldMarkerVisibility); + codeMirrorGutter.addEventListener("mouseenter", toggleFoldMarkerVisibility); + + if (!(0, _devtoolsEnvironment.isFirefox)()) { + codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => this.onGutterContextMenu(event)); + codeMirror.on("contextmenu", (cm, event) => this.openMenu(event)); + } else { + codeMirrorWrapper.addEventListener("contextmenu", event => this.openMenu(event)); + } + + this.setState({ + editor + }); + (0, _editor.setEditor)(editor); + return editor; + } + + componentDidMount() { + const { + shortcuts + } = this.context; + const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2"); + const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2"); + shortcuts.on(L10N.getStr("toggleBreakpoint.key"), this.onToggleBreakpoint); + shortcuts.on(L10N.getStr("toggleCondPanel.key"), this.onToggleConditionalPanel); + shortcuts.on("Esc", this.onEscape); + shortcuts.on(searchAgainPrevKey, this.onSearchAgain); + shortcuts.on(searchAgainKey, this.onSearchAgain); + } + + componentWillUnmount() { + if (this.state.editor) { + this.state.editor.destroy(); + this.setState({ + editor: null + }); + } + + const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2"); + const searchAgainPrevKey = L10N.getStr("sourceSearch.search.againPrev.key2"); + const shortcuts = this.context.shortcuts; + shortcuts.off(L10N.getStr("toggleBreakpoint.key")); + shortcuts.off(L10N.getStr("toggleCondPanel.key")); + shortcuts.off(searchAgainPrevKey); + shortcuts.off(searchAgainKey); + } + + componentDidUpdate(prevProps, prevState) { + const { + selectedSource + } = this.props; // NOTE: when devtools are opened, the editor is not set when + // the source loads so we need to wait until the editor is + // set to update the text and size. + + if (!prevState.editor && selectedSource) { + if (!this.state.editor) { + const editor = this.setupEditor(); + (0, _editor.updateDocument)(editor, selectedSource); + } else { + this.setText(this.props); + this.setSize(this.props); + } + } + } + + getCurrentLine() { + const { + codeMirror + } = this.state.editor; + const { + selectedSource + } = this.props; + const line = (0, _editor.getCursorLine)(codeMirror); + return (0, _editor.toSourceLine)(selectedSource.get("id"), line); + } + + onKeyDown(e) { + const { + codeMirror + } = this.state.editor; + const { + key, + target + } = e; + const codeWrapper = codeMirror.getWrapperElement(); + const textArea = codeWrapper.querySelector("textArea"); + + if (key === "Escape" && target == textArea) { + e.stopPropagation(); + e.preventDefault(); + codeWrapper.focus(); + } else if (key === "Enter" && target == codeWrapper) { + e.preventDefault(); // Focus into editor's text area + + textArea.focus(); + } + } + /* + * The default Esc command is overridden in the CodeMirror keymap to allow + * the Esc keypress event to be catched by the toolbox and trigger the + * split console. Restore it here, but preventDefault if and only if there + * is a multiselection. + */ + + + openMenu(event) { + event.stopPropagation(); + event.preventDefault(); + const { + setContextMenu + } = this.props; + + if (event.target.classList.contains("CodeMirror-linenumber")) { + return setContextMenu("Gutter", event); + } + + return setContextMenu("Editor", event); + } + + onClick(e) { + const { + selectedLocation, + jumpToMappedLocation + } = this.props; + + if (e.metaKey && e.altKey) { + const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(this.state.editor, selectedLocation, e); + jumpToMappedLocation(sourceLocation); + } + } + + shouldScrollToLocation(nextProps) { + const { + selectedLocation, + selectedSource + } = this.props; + const { + editor + } = this.state; + + if (!nextProps.selectedSource || !editor || !nextProps.selectedLocation) { + return false; + } + + if (!(0, _source.isLoaded)(nextProps.selectedSource)) { + return false; + } + + if (!nextProps.selectedLocation.line) { + return false; + } + + const isFirstLoad = (!selectedSource || !(0, _source.isLoaded)(selectedSource)) && (0, _source.isLoaded)(nextProps.selectedSource); + const locationChanged = selectedLocation !== nextProps.selectedLocation; + return isFirstLoad || locationChanged; + } + + scrollToLocation(nextProps) { + const { + editor + } = this.state; + + if (this.shouldScrollToLocation(nextProps)) { + let { + line, + column + } = (0, _editor.toEditorPosition)(nextProps.selectedLocation); + + if ((0, _editor.hasDocument)(nextProps.selectedSource.get("id"))) { + const doc = (0, _editor.getDocument)(nextProps.selectedSource.get("id")); + const lineText = doc.getLine(line); + column = Math.max(column, (0, _indentation.getIndentation)(lineText)); + } + + (0, _editor.scrollToColumn)(editor.codeMirror, line, column); + } + } + + setSize(nextProps) { + if (!this.state.editor) { + return; + } + + if (nextProps.startPanelSize !== this.props.startPanelSize || nextProps.endPanelSize !== this.props.endPanelSize) { + this.state.editor.codeMirror.setSize(); + } + } + + setText(props) { + const { + selectedSource, + symbols + } = props; + + if (!this.state.editor) { + return; + } // check if we previously had a selected source + + + if (!selectedSource) { + return this.clearEditor(); + } + + if (!(0, _source.isLoaded)(selectedSource)) { + return (0, _editor.showLoading)(this.state.editor); + } + + if (selectedSource.get("error")) { + return this.showErrorMessage(selectedSource.get("error")); + } + + if (selectedSource) { + return (0, _editor.showSourceText)(this.state.editor, selectedSource.toJS(), symbols); + } + } + + clearEditor() { + const { + editor + } = this.state; + + if (!editor) { + return; + } + + (0, _editor.clearEditor)(editor); + } + + showErrorMessage(msg) { + const { + editor + } = this.state; + + if (!editor) { + return; + } + + (0, _editor.showErrorMessage)(editor, msg); + } + + getInlineEditorStyles() { + const { + selectedSource, + horizontal, + searchOn + } = this.props; + const subtractions = []; + + if ((0, _editor.shouldShowFooter)(selectedSource, horizontal)) { + subtractions.push(cssVars.footerHeight); + } + + if (searchOn) { + subtractions.push(cssVars.searchbarHeight); + subtractions.push(cssVars.secondSearchbarHeight); + } + + return { + height: subtractions.length === 0 ? "100%" : `calc(100% - ${subtractions.join(" - ")})` + }; + } + + renderHitCounts() { + const { + hitCount, + selectedSource + } = this.props; + + if (!selectedSource || !(0, _source.isLoaded)(selectedSource) || !hitCount || !this.state.editor) { + return; + } + + return hitCount.filter(marker => marker.get("count") > 0).map(marker => _react2.default.createElement(_HitMarker2.default, { + key: marker.get("line"), + hitData: marker.toJS(), + editor: this.state.editor.codeMirror + })); + } + + renderItems() { + const { + horizontal, + selectedSource + } = this.props; + const { + editor + } = this.state; + + if (!editor || !selectedSource) { + return null; + } + + return _react2.default.createElement("div", null, _react2.default.createElement(_DebugLine2.default, null), _react2.default.createElement(_HighlightLine2.default, null), _react2.default.createElement(_EmptyLines2.default, { + editor: editor + }), _react2.default.createElement(_Breakpoints2.default, { + editor: editor + }), _react2.default.createElement(_Preview2.default, { + editor: editor, + editorRef: this.$editorWrapper + }), ";", _react2.default.createElement(_Footer2.default, { + editor: editor, + horizontal: horizontal + }), _react2.default.createElement(_HighlightLines2.default, { + editor: editor + }), _react2.default.createElement(_EditorMenu2.default, { + editor: editor + }), _react2.default.createElement(_GutterMenu2.default, { + editor: editor + }), _react2.default.createElement(_ConditionalPanel2.default, { + editor: editor + }), _prefs.features.columnBreakpoints ? _react2.default.createElement(_CallSites2.default, { + editor: editor + }) : null, this.renderHitCounts()); + } + + renderSearchBar() { + const { + editor + } = this.state; + + if (!editor) { + return null; + } + + return _react2.default.createElement(_SearchBar2.default, { + editor: editor + }); + } + + render() { + const { + coverageOn + } = this.props; + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("editor-wrapper", { + "coverage-on": coverageOn + }), + ref: c => this.$editorWrapper = c + }, this.renderSearchBar(), _react2.default.createElement("div", { + className: "editor-mount devtools-monospace", + style: this.getInlineEditorStyles() + }), this.renderItems()); + } + +} + +Editor.contextTypes = { + shortcuts: _propTypes2.default.object +}; + +const mapStateToProps = state => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + const sourceId = selectedSource ? selectedSource.get("id") : ""; + return { + selectedLocation: (0, _selectors.getSelectedLocation)(state), + selectedSource, + searchOn: (0, _selectors.getActiveSearch)(state) === "file", + hitCount: (0, _selectors.getHitCountForSource)(state, sourceId), + coverageOn: (0, _selectors.getCoverageEnabled)(state), + conditionalPanelLine: (0, _selectors.getConditionalPanelLine)(state), + symbols: (0, _selectors.getSymbols)(state, selectedSource && selectedSource.toJS()) + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Editor); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/Editor/moz.build b/devtools/client/debugger/new/src/components/Editor/moz.build new file mode 100644 index 000000000000..25a7f4c57fb2 --- /dev/null +++ b/devtools/client/debugger/new/src/components/Editor/moz.build @@ -0,0 +1,28 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'Preview', +] + +DevToolsModules( + 'Breakpoint.js', + 'Breakpoints.js', + 'CallSite.js', + 'CallSites.js', + 'ConditionalPanel.js', + 'DebugLine.js', + 'EditorMenu.js', + 'EmptyLines.js', + 'Footer.js', + 'GutterMenu.js', + 'HighlightLine.js', + 'HighlightLines.js', + 'HitMarker.js', + 'index.js', + 'SearchBar.js', + 'Tab.js', + 'Tabs.js', +) diff --git a/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js b/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js new file mode 100644 index 000000000000..76ad92b5b403 --- /dev/null +++ b/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js @@ -0,0 +1,205 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Outline = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _clipboard = require("../../utils/clipboard"); + +var _function = require("../../utils/function"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _PreviewFunction = require("../shared/PreviewFunction"); + +var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Outline extends _react.Component { + selectItem(location) { + const { + selectedSource, + selectLocation + } = this.props; + + if (!selectedSource) { + return; + } + + const selectedSourceId = selectedSource.get("id"); + const startLine = location.start.line; + selectLocation({ + sourceId: selectedSourceId, + line: startLine + }); + } + + onContextMenu(event, func) { + event.stopPropagation(); + event.preventDefault(); + const { + selectedSource, + getFunctionText, + flashLineRange, + selectedLocation + } = this.props; + const copyFunctionKey = L10N.getStr("copyFunction.accesskey"); + const copyFunctionLabel = L10N.getStr("copyFunction.label"); + + if (!selectedSource) { + return; + } + + const sourceLine = func.location.start.line; + const functionText = getFunctionText(sourceLine); + const copyFunctionItem = { + id: "node-menu-copy-function", + label: copyFunctionLabel, + accesskey: copyFunctionKey, + disabled: !functionText, + click: () => { + flashLineRange({ + start: func.location.start.line, + end: func.location.end.line, + sourceId: selectedLocation.sourceId + }); + return (0, _clipboard.copyToTheClipboard)(functionText); + } + }; + const menuOptions = [copyFunctionItem]; + (0, _devtoolsContextmenu.showMenu)(event, menuOptions); + } + + renderPlaceholder() { + const placeholderMessage = this.props.selectedSource ? L10N.getStr("outline.noFunctions") : L10N.getStr("outline.noFileSelected"); + return _react2.default.createElement("div", { + className: "outline-pane-info" + }, placeholderMessage); + } + + renderLoading() { + return _react2.default.createElement("div", { + className: "outline-pane-info" + }, L10N.getStr("loadingText")); + } + + renderFunction(func) { + const { + name, + location, + parameterNames + } = func; + return _react2.default.createElement("li", { + key: `${name}:${location.start.line}:${location.start.column}`, + className: "outline-list__element", + onClick: () => this.selectItem(location), + onContextMenu: e => this.onContextMenu(e, func) + }, _react2.default.createElement("span", { + className: "outline-list__element-icon" + }, "\u03BB"), _react2.default.createElement(_PreviewFunction2.default, { + func: { + name, + parameterNames + } + })); + } + + renderClassFunctions(klass, functions) { + if (klass == null || functions.length == 0) { + return null; + } + + const classFunc = functions.find(func => func.name === klass); + const classFunctions = functions.filter(func => func.klass === klass); + const classInfo = this.props.symbols.classes.find(c => c.name === klass); + const heading = classFunc ? _react2.default.createElement("h2", null, this.renderFunction(classFunc)) : _react2.default.createElement("h2", { + onClick: classInfo ? () => this.selectItem(classInfo.location) : null + }, _react2.default.createElement("span", { + className: "keyword" + }, "class"), " ", klass); + return _react2.default.createElement("div", { + className: "outline-list__class", + key: klass + }, heading, _react2.default.createElement("ul", { + className: "outline-list__class-list" + }, classFunctions.map(func => this.renderFunction(func)))); + } + + renderFunctions(functions) { + let classes = (0, _lodash.uniq)(functions.map(func => func.klass)); + let namedFunctions = functions.filter(func => func.name != "anonymous" && !func.klass && !classes.includes(func.name)); + let classFunctions = functions.filter(func => func.name != "anonymous" && !!func.klass); + + if (this.props.alphabetizeOutline) { + namedFunctions = (0, _lodash.sortBy)(namedFunctions, "name"); + classes = (0, _lodash.sortBy)(classes, "klass"); + classFunctions = (0, _lodash.sortBy)(classFunctions, "name"); + } + + return _react2.default.createElement("div", null, _react2.default.createElement("ul", { + className: "outline-list" + }, namedFunctions.map(func => this.renderFunction(func)), classes.map(klass => this.renderClassFunctions(klass, classFunctions))), _react2.default.createElement("div", { + className: "outline-footer bottom" + }, _react2.default.createElement("button", { + onClick: () => { + this.props.onAlphabetizeClick(); + }, + className: this.props.alphabetizeOutline ? "active" : "" + }, L10N.getStr("outline.sortLabel")))); + } + + render() { + const { + symbols, + selectedSource + } = this.props; + + if (!selectedSource) { + return this.renderPlaceholder(); + } + + if (!symbols || symbols.loading) { + return this.renderLoading(); + } + + const symbolsToDisplay = symbols.functions.filter(func => func.name != "anonymous"); + return _react2.default.createElement("div", { + className: "outline" + }, symbolsToDisplay.length > 0 ? this.renderFunctions(symbols.functions) : this.renderPlaceholder()); + } + +} + +exports.Outline = Outline; + +const mapStateToProps = state => { + const selectedSource = (0, _selectors.getSelectedSource)(state); + const symbols = (0, _selectors.getSymbols)(state, selectedSource); + return { + symbols, + selectedSource, + selectedLocation: (0, _selectors.getSelectedLocation)(state), + getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols) + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Outline); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js new file mode 100644 index 000000000000..387de02718f1 --- /dev/null +++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js @@ -0,0 +1,415 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _selectors = require("../../selectors/index"); + +var _sourceTree = require("../../actions/source-tree"); + +var _sources = require("../../actions/sources/index"); + +var _ui = require("../../actions/ui"); + +var _ManagedTree = require("../shared/ManagedTree"); + +var _ManagedTree2 = _interopRequireDefault(_ManagedTree); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _sourcesTree = require("../../utils/sources-tree/index"); + +var _source = require("../../utils/source"); + +var _clipboard = require("../../utils/clipboard"); + +var _prefs = require("../../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Dependencies +// Selectors +// Actions +// Components +// Utils +class SourcesTree extends _react.Component { + constructor(props) { + super(props); + + _initialiseProps.call(this); + + const { + debuggeeUrl, + sources, + projectRoot + } = this.props; + this.state = (0, _sourcesTree.createTree)({ + projectRoot, + debuggeeUrl, + sources + }); + } + + componentWillReceiveProps(nextProps) { + const { + projectRoot, + debuggeeUrl, + sources, + shownSource, + selectedSource + } = this.props; + const { + uncollapsedTree, + sourceTree + } = this.state; + + if (projectRoot != nextProps.projectRoot || debuggeeUrl != nextProps.debuggeeUrl || nextProps.sources.size === 0) { + // early recreate tree because of changes + // to project root, debugee url or lack of sources + return this.setState((0, _sourcesTree.createTree)({ + sources: nextProps.sources, + debuggeeUrl: nextProps.debuggeeUrl, + projectRoot: nextProps.projectRoot + })); + } + + if (nextProps.shownSource && nextProps.shownSource != shownSource) { + const listItems = (0, _sourcesTree.getDirectories)(nextProps.shownSource, sourceTree); + + if (listItems && listItems[0]) { + this.selectItem(listItems[0]); + } + + return this.setState({ + listItems + }); + } + + if (nextProps.selectedSource && nextProps.selectedSource != selectedSource) { + const highlightItems = (0, _sourcesTree.getDirectories)((0, _source.getRawSourceURL)(nextProps.selectedSource.get("url")), sourceTree); + return this.setState({ + highlightItems + }); + } // NOTE: do not run this every time a source is clicked, + // only when a new source is added + + + if (nextProps.sources != this.props.sources) { + this.setState((0, _sourcesTree.updateTree)({ + newSources: nextProps.sources, + prevSources: sources, + debuggeeUrl, + projectRoot, + uncollapsedTree, + sourceTree + })); + } + } + + renderItemName(name) { + const hosts = { + "ng://": "Angular", + "webpack://": "Webpack", + "moz-extension://": L10N.getStr("extensionsText") + }; + return hosts[name] || name; + } + + renderEmptyElement(message) { + return _react2.default.createElement("div", { + className: "no-sources-message" + }, message); + } + + render() { + const { + expanded, + projectRoot + } = this.props; + const { + focusedItem, + highlightItems, + listItems, + parentMap, + sourceTree + } = this.state; + + const onExpand = (item, expandedState) => { + this.props.setExpandedState(expandedState); + }; + + const onCollapse = (item, expandedState) => { + this.props.setExpandedState(expandedState); + }; + + const isEmpty = sourceTree.contents.length === 0; + const isCustomRoot = projectRoot !== ""; + + let roots = () => sourceTree.contents; + + let clearProjectRootButton = null; // The "sourceTree.contents[0]" check ensures that there are contents + // A custom root with no existing sources will be ignored + + if (isCustomRoot) { + const sourceContents = sourceTree.contents[0]; + let rootLabel = projectRoot.split("/").pop(); + + roots = () => sourceContents.contents; + + if (sourceContents && sourceContents.name !== rootLabel) { + rootLabel = sourceContents.contents[0].name; + + roots = () => sourceContents.contents[0].contents; + } + + clearProjectRootButton = _react2.default.createElement("button", { + className: "sources-clear-root", + onClick: () => this.props.clearProjectDirectoryRoot(), + title: L10N.getStr("removeDirectoryRoot.label") + }, _react2.default.createElement(_Svg2.default, { + name: "home" + }), _react2.default.createElement(_Svg2.default, { + name: "breadcrumb", + "class": true + }), _react2.default.createElement("span", { + className: "sources-clear-root-label" + }, rootLabel)); + } + + if (isEmpty && !isCustomRoot) { + return this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable")); + } + + const treeProps = { + autoExpandAll: false, + autoExpandDepth: expanded ? 0 : 1, + expanded, + getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [], + getParent: item => parentMap.get(item), + getPath: this.getPath, + getRoots: roots, + highlightItems, + itemHeight: 21, + key: isEmpty ? "empty" : "full", + listItems, + onCollapse, + onExpand, + onFocus: this.focusItem, + renderItem: this.renderItem + }; + + const tree = _react2.default.createElement(_ManagedTree2.default, treeProps); + + const onKeyDown = e => { + if (e.keyCode === 13 && focusedItem) { + this.selectItem(focusedItem); + } + }; + + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("sources-pane", { + "sources-list-custom-root": isCustomRoot + }) + }, isCustomRoot ? _react2.default.createElement("div", { + className: "sources-clear-root-container" + }, clearProjectRootButton) : null, isEmpty ? this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailableRoot")) : _react2.default.createElement("div", { + className: "sources-list", + onKeyDown: onKeyDown + }, tree)); + } + +} + +var _initialiseProps = function () { + this.focusItem = item => { + this.setState({ + focusedItem: item + }); + }; + + this.selectItem = item => { + if (!(0, _sourcesTree.nodeHasChildren)(item)) { + this.props.selectLocation({ + sourceId: item.contents.get("id") + }); + } + }; + + this.getPath = item => { + const { + sources + } = this.props; + const obj = item.contents.get && item.contents.get("id"); + let blackBoxedPart = ""; + + if (typeof obj !== "undefined" && sources.has(obj) && sources.get(obj).get("isBlackBoxed")) { + blackBoxedPart = "update"; + } + + return `${item.path}/${item.name}/${blackBoxedPart}`; + }; + + this.getIcon = (sources, item, depth) => { + const { + debuggeeUrl, + projectRoot + } = this.props; + + if (item.path === "webpack://") { + return _react2.default.createElement(_Svg2.default, { + name: "webpack" + }); + } else if (item.path === "ng://") { + return _react2.default.createElement(_Svg2.default, { + name: "angular" + }); + } else if (item.path === "moz-extension://") { + return _react2.default.createElement("img", { + className: "extension" + }); + } + + if (depth === 0 && projectRoot === "") { + return _react2.default.createElement("img", { + className: (0, _classnames2.default)("domain", { + debuggee: debuggeeUrl && debuggeeUrl.includes(item.name) + }) + }); + } + + if (!(0, _sourcesTree.nodeHasChildren)(item)) { + const obj = item.contents.get("id"); + const source = sources.get(obj); + const className = (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "source-icon"); + return _react2.default.createElement("img", { + className: className + }); + } + + return _react2.default.createElement("img", { + className: "folder" + }); + }; + + this.onContextMenu = (event, item) => { + const copySourceUri2Label = L10N.getStr("copySourceUri2"); + const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey"); + const setDirectoryRootLabel = L10N.getStr("setDirectoryRoot.label"); + const setDirectoryRootKey = L10N.getStr("setDirectoryRoot.accesskey"); + const removeDirectoryRootLabel = L10N.getStr("removeDirectoryRoot.label"); + event.stopPropagation(); + event.preventDefault(); + const menuOptions = []; + + if (!(0, _sourcesTree.isDirectory)(item)) { + const source = item.contents.get("url"); + const copySourceUri2 = { + id: "node-menu-copy-source", + label: copySourceUri2Label, + accesskey: copySourceUri2Key, + disabled: false, + click: () => (0, _clipboard.copyToTheClipboard)(source) + }; + menuOptions.push(copySourceUri2); + } + + if ((0, _sourcesTree.isDirectory)(item) && _prefs.features.root) { + const { + path + } = item; + const { + projectRoot + } = this.props; + + if (projectRoot.endsWith(path)) { + menuOptions.push({ + id: "node-remove-directory-root", + label: removeDirectoryRootLabel, + disabled: false, + click: () => this.props.clearProjectDirectoryRoot() + }); + } else { + menuOptions.push({ + id: "node-set-directory-root", + label: setDirectoryRootLabel, + accesskey: setDirectoryRootKey, + disabled: false, + click: () => this.props.setProjectDirectoryRoot(path) + }); + } + } + + (0, _devtoolsContextmenu.showMenu)(event, menuOptions); + }; + + this.renderItem = (item, depth, focused, _, expanded, { + setExpanded + }) => { + const arrow = (0, _sourcesTree.nodeHasChildren)(item) ? _react2.default.createElement("img", { + className: (0, _classnames2.default)("arrow", { + expanded: expanded + }) + }) : _react2.default.createElement("i", { + className: "no-arrow" + }); + const { + sources + } = this.props; + const icon = this.getIcon(sources, item, depth); + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("node", { + focused + }), + key: item.path, + onClick: e => { + this.focusItem(item); + + if ((0, _sourcesTree.isDirectory)(item)) { + setExpanded(item, !!expanded, e.altKey); + } else { + this.selectItem(item); + } + }, + onContextMenu: e => this.onContextMenu(e, item) + }, arrow, icon, _react2.default.createElement("span", { + className: "label" + }, " ", this.renderItemName(item.name), " ")); + }; +}; + +const mapStateToProps = state => { + return { + shownSource: (0, _selectors.getShownSource)(state), + selectedSource: (0, _selectors.getSelectedSource)(state), + debuggeeUrl: (0, _selectors.getDebuggeeUrl)(state), + expanded: (0, _selectors.getExpandedState)(state), + projectRoot: (0, _selectors.getProjectDirectoryRoot)(state), + sources: (0, _selectors.getSources)(state) + }; +}; + +const actionCreators = { + setExpandedState: _sourceTree.setExpandedState, + selectLocation: _sources.selectLocation, + setProjectDirectoryRoot: _ui.setProjectDirectoryRoot, + clearProjectDirectoryRoot: _ui.clearProjectDirectoryRoot +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, actionCreators)(SourcesTree); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/PrimaryPanes/index.js b/devtools/client/debugger/new/src/components/PrimaryPanes/index.js new file mode 100644 index 000000000000..3592f90e0c7e --- /dev/null +++ b/devtools/client/debugger/new/src/components/PrimaryPanes/index.js @@ -0,0 +1,127 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _text = require("../../utils/text"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _prefs = require("../../utils/prefs"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _Outline = require("./Outline"); + +var _Outline2 = _interopRequireDefault(_Outline); + +var _SourcesTree = require("./SourcesTree"); + +var _SourcesTree2 = _interopRequireDefault(_SourcesTree); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class PrimaryPanes extends _react.Component { + constructor(props) { + super(props); + + this.showPane = selectedPane => { + this.props.setPrimaryPaneTab(selectedPane); + }; + + this.onAlphabetizeClick = () => { + const alphabetizeOutline = !_prefs.prefs.alphabetizeOutline; + _prefs.prefs.alphabetizeOutline = alphabetizeOutline; + this.setState({ + alphabetizeOutline + }); + }; + + this.renderTabs = () => { + return _react2.default.createElement("div", { + className: "source-outline-tabs" + }, this.renderOutlineTabs()); + }; + + this.renderShortcut = () => { + if (this.props.horizontal) { + const onClick = () => { + if (this.props.sourceSearchOn) { + return this.props.closeActiveSearch(); + } + + this.props.setActiveSearch("source"); + }; + + return _react2.default.createElement("span", { + className: "sources-header-info", + dir: "ltr", + onClick: onClick + }, L10N.getFormatStr("sources.search", (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2")))); + } + }; + + this.state = { + alphabetizeOutline: _prefs.prefs.alphabetizeOutline + }; + } + + renderOutlineTabs() { + if (!_prefs.features.outline) { + return; + } + + const sources = (0, _text.formatKeyShortcut)(L10N.getStr("sources.header")); + const outline = (0, _text.formatKeyShortcut)(L10N.getStr("outline.header")); + return [_react2.default.createElement("div", { + className: (0, _classnames2.default)("tab sources-tab", { + active: this.props.selectedTab === "sources" + }), + onClick: () => this.showPane("sources"), + key: "sources-tab" + }, sources), _react2.default.createElement("div", { + className: (0, _classnames2.default)("tab outline-tab", { + active: this.props.selectedTab === "outline" + }), + onClick: () => this.showPane("outline"), + key: "outline-tab" + }, outline)]; + } + + render() { + const { + selectedTab + } = this.props; + return _react2.default.createElement("div", { + className: "sources-panel" + }, this.renderTabs(), selectedTab === "sources" ? _react2.default.createElement(_SourcesTree2.default, null) : _react2.default.createElement(_Outline2.default, { + alphabetizeOutline: this.state.alphabetizeOutline, + onAlphabetizeClick: this.onAlphabetizeClick + })); + } + +} + +const mapStateToProps = state => ({ + selectedTab: (0, _selectors.getSelectedPrimaryPaneTab)(state), + sources: (0, _selectors.getSources)(state), + sourceSearchOn: (0, _selectors.getActiveSearch)(state) === "source" +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(PrimaryPanes); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/PrimaryPanes/moz.build b/devtools/client/debugger/new/src/components/PrimaryPanes/moz.build new file mode 100644 index 000000000000..de2357010484 --- /dev/null +++ b/devtools/client/debugger/new/src/components/PrimaryPanes/moz.build @@ -0,0 +1,14 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'index.js', + 'Outline.js', + 'SourcesTree.js', +) diff --git a/devtools/client/debugger/new/src/components/ProjectSearch.js b/devtools/client/debugger/new/src/components/ProjectSearch.js new file mode 100644 index 000000000000..a99179246a45 --- /dev/null +++ b/devtools/client/debugger/new/src/components/ProjectSearch.js @@ -0,0 +1,324 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ProjectSearch = undefined; + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _actions = require("../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _editor = require("../utils/editor/index"); + +var _projectSearch = require("../utils/project-search"); + +var _projectTextSearch = require("../reducers/project-text-search"); + +var _sourcesTree = require("../utils/sources-tree/index"); + +var _selectors = require("../selectors/index"); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _ManagedTree = require("./shared/ManagedTree"); + +var _ManagedTree2 = _interopRequireDefault(_ManagedTree); + +var _SearchInput = require("./shared/SearchInput"); + +var _SearchInput2 = _interopRequireDefault(_SearchInput); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getFilePath(item, index) { + return item.type === "RESULT" ? `${item.sourceId}-${index || "$"}` : `${item.sourceId}-${item.line}-${item.column}-${index || "$"}`; +} + +function sanitizeQuery(query) { + // no '\' at end of query + return query.replace(/\\$/, ""); +} + +class ProjectSearch extends _react.Component { + constructor(props) { + super(props); + + this.toggleProjectTextSearch = (key, e) => { + const { + closeProjectSearch, + setActiveSearch + } = this.props; + + if (e) { + e.preventDefault(); + } + + if (this.isProjectSearchEnabled()) { + return closeProjectSearch(); + } + + return setActiveSearch("project"); + }; + + this.isProjectSearchEnabled = () => this.props.activeSearch === "project"; + + this.selectMatchItem = matchItem => { + this.props.selectLocation(_objectSpread({}, matchItem)); + this.props.doSearchForHighlight(this.state.inputValue, (0, _editor.getEditor)(), matchItem.line, matchItem.column); + }; + + this.getResults = () => { + const { + results + } = this.props; + return results.toJS().map(result => _objectSpread({ + type: "RESULT" + }, result, { + matches: result.matches.map(m => _objectSpread({ + type: "MATCH" + }, m)) + })).filter(result => result.filepath && result.matches.length > 0); + }; + + this.getResultCount = () => this.getResults().reduce((count, file) => count + file.matches.length, 0); + + this.onKeyDown = e => { + if (e.key === "Escape") { + return; + } + + e.stopPropagation(); + + if (e.key !== "Enter") { + return; + } + + this.focusedItem = null; + const query = sanitizeQuery(this.state.inputValue); + + if (query) { + this.props.searchSources(query); + } + }; + + this.onEnterPress = () => { + if (this.focusedItem && !this.state.inputFocused) { + const { + setExpanded, + file, + expanded, + match + } = this.focusedItem; + + if (setExpanded) { + setExpanded(file, !expanded); + } else if (match) { + this.selectMatchItem(match); + } + } + }; + + this.inputOnChange = e => { + const inputValue = e.target.value; + const { + clearSearch + } = this.props; + this.setState({ + inputValue + }); + + if (inputValue === "") { + clearSearch(); + } + }; + + this.renderFile = (file, focused, expanded, setExpanded) => { + if (focused) { + this.focusedItem = { + setExpanded, + file, + expanded + }; + } + + const matchesLength = file.matches.length; + const matches = ` (${matchesLength} match${matchesLength > 1 ? "es" : ""})`; + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("file-result", { + focused + }), + key: file.sourceId, + onClick: e => setExpanded(file, !expanded) + }, _react2.default.createElement(_Svg2.default, { + name: "arrow", + className: (0, _classnames2.default)({ + expanded + }) + }), _react2.default.createElement("img", { + className: "file" + }), _react2.default.createElement("span", { + className: "file-path" + }, (0, _sourcesTree.getRelativePath)(file.filepath)), _react2.default.createElement("span", { + className: "matches-summary" + }, matches)); + }; + + this.renderMatch = (match, focused) => { + if (focused) { + this.focusedItem = { + match + }; + } + + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("result", { + focused + }), + onClick: () => setTimeout(() => this.selectMatchItem(match), 50) + }, _react2.default.createElement("span", { + className: "line-number", + key: match.line + }, match.line), (0, _projectSearch.highlightMatches)(match)); + }; + + this.renderItem = (item, depth, focused, _, expanded, { + setExpanded + }) => { + if (item.type === "RESULT") { + return this.renderFile(item, focused, expanded, setExpanded); + } + + return this.renderMatch(item, focused); + }; + + this.renderResults = () => { + const results = this.getResults(); + const { + status + } = this.props; + + if (!this.props.query) { + return; + } + + if (results.length && status === _projectTextSearch.statusType.done) { + return _react2.default.createElement(_ManagedTree2.default, { + getRoots: () => results, + getChildren: file => file.matches || [], + itemHeight: 24, + autoExpandAll: true, + autoExpandDepth: 1, + getParent: item => null, + getPath: getFilePath, + renderItem: this.renderItem + }); + } + + const msg = status === _projectTextSearch.statusType.fetching ? L10N.getStr("loadingText") : L10N.getStr("projectTextSearch.noResults"); + return _react2.default.createElement("div", { + className: "no-result-msg absolute-center" + }, msg); + }; + + this.renderSummary = () => { + return this.props.query !== "" ? L10N.getFormatStr("sourceSearch.resultsSummary1", this.getResultCount()) : ""; + }; + + this.state = { + inputValue: this.props.query || "", + inputFocused: false + }; + } + + componentDidMount() { + const { + shortcuts + } = this.context; + shortcuts.on(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch); + shortcuts.on("Enter", this.onEnterPress); + } + + componentWillUnmount() { + const { + shortcuts + } = this.context; + shortcuts.off(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch); + shortcuts.off("Enter", this.onEnterPress); + } + + shouldShowErrorEmoji() { + return !this.getResultCount() && this.props.status === _projectTextSearch.statusType.done; + } + + renderInput() { + return _react2.default.createElement(_SearchInput2.default, { + query: this.state.inputValue, + count: this.getResultCount(), + placeholder: L10N.getStr("projectTextSearch.placeholder"), + size: "big", + showErrorEmoji: this.shouldShowErrorEmoji(), + summaryMsg: this.renderSummary(), + onChange: this.inputOnChange, + onFocus: () => this.setState({ + inputFocused: true + }), + onBlur: () => this.setState({ + inputFocused: false + }), + onKeyDown: this.onKeyDown, + handleClose: this.props.closeProjectSearch, + ref: "searchInput" + }); + } + + render() { + if (!this.isProjectSearchEnabled()) { + return null; + } + + return _react2.default.createElement("div", { + className: "search-container" + }, _react2.default.createElement("div", { + className: "project-text-search" + }, _react2.default.createElement("div", { + className: "header" + }, this.renderInput()), this.renderResults())); + } + +} + +exports.ProjectSearch = ProjectSearch; +ProjectSearch.contextTypes = { + shortcuts: _propTypes2.default.object +}; + +const mapStateToProps = state => ({ + sources: (0, _selectors.getSources)(state), + activeSearch: (0, _selectors.getActiveSearch)(state), + results: (0, _selectors.getTextSearchResults)(state), + query: (0, _selectors.getTextSearchQuery)(state), + status: (0, _selectors.getTextSearchStatus)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ProjectSearch); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/QuickOpenModal.js b/devtools/client/debugger/new/src/components/QuickOpenModal.js new file mode 100644 index 000000000000..a025713a4503 --- /dev/null +++ b/devtools/client/debugger/new/src/components/QuickOpenModal.js @@ -0,0 +1,484 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.QuickOpenModal = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _fuzzaldrinPlus = require("devtools/client/debugger/new/dist/vendors").vendored["fuzzaldrin-plus"]; + +var _fuzzaldrinPlus2 = _interopRequireDefault(_fuzzaldrinPlus); + +var _path = require("../utils/path"); + +var _actions = require("../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../selectors/index"); + +var _resultList = require("../utils/result-list"); + +var _quickOpen = require("../utils/quick-open"); + +var _Modal = require("./shared/Modal"); + +var _Modal2 = _interopRequireDefault(_Modal); + +var _SearchInput = require("./shared/SearchInput"); + +var _SearchInput2 = _interopRequireDefault(_SearchInput); + +var _ResultList = require("./shared/ResultList"); + +var _ResultList2 = _interopRequireDefault(_ResultList); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function filter(values, query) { + return _fuzzaldrinPlus2.default.filter(values, query, { + key: "value", + maxResults: 1000 + }); +} + +class QuickOpenModal extends _react.Component { + constructor(props) { + super(props); + + this.closeModal = () => { + this.props.closeQuickOpen(); + }; + + this.dropGoto = query => { + return query.split(":")[0]; + }; + + this.searchSources = query => { + const { + sources + } = this.props; + const results = query == "" ? sources : filter(sources, this.dropGoto(query)); + return this.setState({ + results + }); + }; + + this.searchSymbols = query => { + const { + symbols: { + functions, + variables + } + } = this.props; + let results = functions; + + if (this.isVariableQuery()) { + results = variables; + } else { + results = results.filter(result => result.title !== "anonymous"); + } + + if (query === "@" || query === "#") { + return this.setState({ + results + }); + } + + this.setState({ + results: filter(results, query.slice(1)) + }); + }; + + this.searchShortcuts = query => { + const results = (0, _quickOpen.formatShortcutResults)(); + + if (query == "?") { + this.setState({ + results + }); + } else { + this.setState({ + results: filter(results, query.slice(1)) + }); + } + }; + + this.showTopSources = () => { + const { + tabs, + sources + } = this.props; + + if (tabs.length > 0) { + this.setState({ + results: sources.filter(source => tabs.includes(source.url)) + }); + } else { + this.setState({ + results: sources.slice(0, 100) + }); + } + }; + + this.updateResults = query => { + if (this.isGotoQuery()) { + return; + } + + if (query == "" && !this.isShortcutQuery()) { + return this.showTopSources(); + } + + if (this.isSymbolSearch()) { + return this.searchSymbols(query); + } + + if (this.isShortcutQuery()) { + return this.searchShortcuts(query); + } + + return this.searchSources(query); + }; + + this.setModifier = item => { + if (["@", "#", ":"].includes(item.id)) { + this.props.setQuickOpenQuery(item.id); + } + }; + + this.selectResultItem = (e, item) => { + if (item == null) { + return; + } + + if (this.isShortcutQuery()) { + return this.setModifier(item); + } + + if (this.isGotoSourceQuery()) { + const location = (0, _quickOpen.parseLineColumn)(this.props.query); + return this.gotoLocation(_objectSpread({}, location, { + sourceId: item.id + })); + } + + if (this.isSymbolSearch()) { + return this.gotoLocation({ + line: item.location && item.location.start ? item.location.start.line : 0 + }); + } + + this.gotoLocation({ + sourceId: item.id, + line: 0 + }); + }; + + this.onSelectResultItem = item => { + const { + selectLocation, + selectedSource, + highlightLineRange + } = this.props; + + if (!this.isSymbolSearch() || selectedSource == null) { + return; + } + + if (this.isVariableQuery()) { + const line = item.location && item.location.start ? item.location.start.line : 0; + return selectLocation({ + sourceId: selectedSource.get("id"), + line, + column: null + }); + } + + if (this.isFunctionQuery()) { + return highlightLineRange(_objectSpread({}, item.location != null ? { + start: item.location.start.line, + end: item.location.end.line + } : {}, { + sourceId: selectedSource.get("id") + })); + } + }; + + this.traverseResults = e => { + const direction = e.key === "ArrowUp" ? -1 : 1; + const { + selectedIndex, + results + } = this.state; + const resultCount = this.getResultCount(); + const index = selectedIndex + direction; + const nextIndex = (index + resultCount) % resultCount; + this.setState({ + selectedIndex: nextIndex + }); + + if (results != null) { + this.onSelectResultItem(results[nextIndex]); + } + }; + + this.gotoLocation = location => { + const { + selectLocation, + selectedSource + } = this.props; + const selectedSourceId = selectedSource ? selectedSource.get("id") : ""; + + if (location != null) { + const sourceId = location.sourceId ? location.sourceId : selectedSourceId; + selectLocation({ + sourceId, + line: location.line, + column: location.column || null + }); + this.closeModal(); + } + }; + + this.onChange = e => { + const { + selectedSource, + setQuickOpenQuery + } = this.props; + setQuickOpenQuery(e.target.value); + const noSource = !selectedSource || !selectedSource.get("text"); + + if (this.isSymbolSearch() && noSource || this.isGotoQuery()) { + return; + } + + this.updateResults(e.target.value); + }; + + this.onKeyDown = e => { + const { + enabled, + query + } = this.props; + const { + results, + selectedIndex + } = this.state; + + if (!this.isGotoQuery() && (!enabled || !results)) { + return; + } + + if (e.key === "Enter") { + if (this.isGotoQuery()) { + const location = (0, _quickOpen.parseLineColumn)(query); + return this.gotoLocation(location); + } + + if (results) { + if (this.isShortcutQuery()) { + return this.setModifier(results[selectedIndex]); + } + + return this.selectResultItem(e, results[selectedIndex]); + } + } + + if (e.key === "Tab") { + return this.closeModal(); + } + + if (["ArrowUp", "ArrowDown"].includes(e.key)) { + e.preventDefault(); + return this.traverseResults(e); + } + }; + + this.getResultCount = () => { + const results = this.state.results; + return results && results.length ? results.length : 0; + }; + + this.isFunctionQuery = () => this.props.searchType === "functions"; + + this.isVariableQuery = () => this.props.searchType === "variables"; + + this.isSymbolSearch = () => this.isFunctionQuery() || this.isVariableQuery(); + + this.isGotoQuery = () => this.props.searchType === "goto"; + + this.isGotoSourceQuery = () => this.props.searchType === "gotoSource"; + + this.isShortcutQuery = () => this.props.searchType === "shortcuts"; + + this.isSourcesQuery = () => this.props.searchType === "sources"; + + this.isSourceSearch = () => this.isSourcesQuery() || this.isGotoSourceQuery(); + + this.renderHighlight = (candidateString, query, name) => { + const options = { + wrap: { + tagOpen: '', + tagClose: "" + } + }; + + const html = _fuzzaldrinPlus2.default.wrap(candidateString, query, options); + + return _react2.default.createElement("div", { + dangerouslySetInnerHTML: { + __html: html + } + }); + }; + + this.highlightMatching = (query, results) => { + let newQuery = query; + + if (newQuery === "") { + return results; + } + + newQuery = query.replace(/[@:#?]/gi, " "); + return results.map(result => { + return _objectSpread({}, result, { + title: this.renderHighlight(result.title, (0, _path.basename)(newQuery), "title") + }); + }); + }; + + this.renderLoading = () => { + const { + symbolsLoading + } = this.props; + + if ((this.isFunctionQuery() || this.isVariableQuery()) && symbolsLoading) { + return _react2.default.createElement("div", { + className: "loading-indicator" + }, L10N.getStr("loadingText")); + } + }; + + this.state = { + results: null, + selectedIndex: 0 + }; + } + + componentDidMount() { + const { + query, + shortcutsModalEnabled, + toggleShortcutsModal + } = this.props; + this.updateResults(query); + + if (shortcutsModalEnabled) { + toggleShortcutsModal(); + } + } + + componentDidUpdate(prevProps) { + const nowEnabled = !prevProps.enabled && this.props.enabled; + const queryChanged = prevProps.query !== this.props.query; + + if (this.refs.resultList && this.refs.resultList.refs) { + (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedIndex, nowEnabled || !queryChanged); + } + + if (nowEnabled || queryChanged) { + this.updateResults(this.props.query); + } + } + + shouldShowErrorEmoji() { + const { + query + } = this.props; + + if (this.isGotoQuery()) { + return !/^:\d*$/.test(query); + } + + return !this.getResultCount() && !!query; + } + + render() { + const { + enabled, + query + } = this.props; + const { + selectedIndex, + results + } = this.state; + + if (!enabled) { + return null; + } + + const newResults = results && results.slice(0, 100); + const items = this.highlightMatching(query, newResults || []); + const expanded = !!items && items.length > 0; + return _react2.default.createElement(_Modal2.default, { + "in": enabled, + handleClose: this.closeModal + }, _react2.default.createElement(_SearchInput2.default, { + query: query, + hasPrefix: true, + count: this.getResultCount(), + placeholder: L10N.getStr("sourceSearch.search"), + summaryMsg: "", + showErrorEmoji: this.shouldShowErrorEmoji(), + onChange: this.onChange, + onKeyDown: this.onKeyDown, + handleClose: this.closeModal, + expanded: expanded, + selectedItemId: expanded && items[selectedIndex] ? items[selectedIndex].id : "" + }), this.renderLoading(), newResults && _react2.default.createElement(_ResultList2.default, _extends({ + key: "results", + items: items, + selected: selectedIndex, + selectItem: this.selectResultItem, + ref: "resultList", + expanded: expanded + }, this.isSourceSearch() ? { + size: "big" + } : {}))); + } + +} + +exports.QuickOpenModal = QuickOpenModal; +/* istanbul ignore next: ignoring testing of redux connection stuff */ + +function mapStateToProps(state) { + const selectedSource = (0, _selectors.getSelectedSource)(state); + return { + enabled: (0, _selectors.getQuickOpenEnabled)(state), + sources: (0, _quickOpen.formatSources)((0, _selectors.getRelativeSources)(state), (0, _selectors.getTabs)(state).toArray()), + selectedSource, + symbols: (0, _quickOpen.formatSymbols)((0, _selectors.getSymbols)(state, selectedSource)), + symbolsLoading: (0, _selectors.isSymbolsLoading)(state, selectedSource), + query: (0, _selectors.getQuickOpenQuery)(state), + searchType: (0, _selectors.getQuickOpenType)(state), + tabs: (0, _selectors.getTabs)(state).toArray() + }; +} +/* istanbul ignore next: ignoring testing of redux connection stuff */ + + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(QuickOpenModal); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js new file mode 100644 index 000000000000..45f03ec8cdf2 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js @@ -0,0 +1,200 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("devtools/client/shared/vendor/react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _Close = require("../shared/Button/Close"); + +var _Close2 = _interopRequireDefault(_Close); + +var _breakpoint = require("../../utils/breakpoint/index"); + +var _prefs = require("../../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getBreakpointLocation(source, line, column) { + const isWasm = source && source.isWasm; + const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : ""; + const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`; + return bpLocation; +} + +function getBreakpointText(selectedSource, breakpoint) { + const { + condition, + text, + originalText + } = breakpoint; + + if (condition) { + return condition; + } + + if (!selectedSource || (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) || originalText.length == 0) { + return text; + } + + return originalText; +} + +class Breakpoint extends _react.Component { + componentDidMount() { + this.setupEditor(); + } + + componentDidUpdate(prevProps) { + if (getBreakpointText(this.props.selectedSource, this.props.breakpoint) != getBreakpointText(prevProps.selectedSource, prevProps.breakpoint)) { + this.destroyEditor(); + } + + this.setupEditor(); + } + + componentWillUnmount() { + this.destroyEditor(); + } + + shouldComponentUpdate(nextProps) { + const prevBreakpoint = this.props.breakpoint; + const nextBreakpoint = nextProps.breakpoint; + return !prevBreakpoint || this.props.selectedSource != nextProps.selectedSource || prevBreakpoint.text != nextBreakpoint.text || prevBreakpoint.disabled != nextBreakpoint.disabled || prevBreakpoint.condition != nextBreakpoint.condition || prevBreakpoint.hidden != nextBreakpoint.hidden || prevBreakpoint.isCurrentlyPaused != nextBreakpoint.isCurrentlyPaused; + } + + destroyEditor() { + if (this.editor) { + this.editor.destroy(); + this.editor = null; + } + } + + setupEditor() { + if (this.editor) { + return; + } + + const { + selectedSource, + breakpoint + } = this.props; + this.editor = (0, _breakpoint.createEditor)(getBreakpointText(selectedSource, breakpoint)); // disables the default search shortcuts + // $FlowIgnore + + this.editor._initShortcuts = () => {}; + + const node = _reactDom2.default.findDOMNode(this); + + if (node instanceof HTMLElement) { + const mountNode = node.querySelector(".breakpoint-label"); + + if (node instanceof HTMLElement) { + // $FlowIgnore + mountNode.innerHTML = ""; + this.editor.appendToLocalElement(mountNode); + this.editor.codeMirror.on("mousedown", (_, e) => e.preventDefault()); + } + } + } + + renderCheckbox() { + const { + onChange, + breakpoint + } = this.props; + const { + disabled + } = breakpoint; + return _react2.default.createElement("input", { + type: "checkbox", + className: "breakpoint-checkbox", + checked: !disabled, + onChange: onChange, + onClick: ev => ev.stopPropagation() + }); + } + + renderText() { + const { + selectedSource, + breakpoint + } = this.props; + const text = getBreakpointText(selectedSource, breakpoint); + return _react2.default.createElement("label", { + className: "breakpoint-label", + title: text + }, text); + } + + renderLineClose() { + const { + breakpoint, + onCloseClick, + selectedSource + } = this.props; + const { + location + } = breakpoint; + let { + line, + column + } = location; + + if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) && breakpoint.generatedLocation) { + line = breakpoint.generatedLocation.line; + column = breakpoint.generatedLocation.column; + } + + return _react2.default.createElement("div", { + className: "breakpoint-line-close" + }, _react2.default.createElement("div", { + className: "breakpoint-line" + }, getBreakpointLocation(breakpoint.source, line, column)), _react2.default.createElement(_Close2.default, { + handleClick: onCloseClick, + tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip") + })); + } + + render() { + const { + breakpoint, + onClick, + onContextMenu + } = this.props; + const locationId = breakpoint.locationId; + const isCurrentlyPaused = breakpoint.isCurrentlyPaused; + const isDisabled = breakpoint.disabled; + const isConditional = !!breakpoint.condition; + return _react2.default.createElement("div", { + className: (0, _classnames2.default)({ + breakpoint, + paused: isCurrentlyPaused, + disabled: isDisabled, + "is-conditional": isConditional + }), + key: locationId, + onClick: onClick, + onContextMenu: onContextMenu + }, this.renderCheckbox(), this.renderText(), this.renderLineClose()); + } + +} + +exports.default = Breakpoint; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js new file mode 100644 index 000000000000..f0d6a5c1a3ae --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js @@ -0,0 +1,204 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _Breakpoint = require("./Breakpoint"); + +var _Breakpoint2 = _interopRequireDefault(_Breakpoint); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _source = require("../../utils/source"); + +var _selectors = require("../../selectors/index"); + +var _pause = require("../../utils/pause/index"); + +var _breakpoint = require("../../utils/breakpoint/index"); + +var _BreakpointsContextMenu = require("./BreakpointsContextMenu"); + +var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function isCurrentlyPausedAtBreakpoint(frame, why, breakpoint) { + if (!frame || !(0, _pause.isInterrupted)(why)) { + return false; + } + + const bpId = (0, _breakpoint.makeLocationId)(breakpoint.location); + const pausedId = (0, _breakpoint.makeLocationId)(frame.location); + return bpId === pausedId; +} + +function createExceptionOption(label, value, onChange, className) { + return _react2.default.createElement("div", { + className: className, + onClick: onChange + }, _react2.default.createElement("input", { + type: "checkbox", + checked: value ? "checked" : "", + onChange: e => e.stopPropagation() && onChange() + }), _react2.default.createElement("div", { + className: "breakpoint-exceptions-label" + }, label)); +} + +function sortFilenames(urlA, urlB) { + const filenameA = (0, _source.getFilenameFromURL)(urlA); + const filenameB = (0, _source.getFilenameFromURL)(urlB); + + if (filenameA > filenameB) { + return 1; + } + + if (filenameA < filenameB) { + return -1; + } + + return 0; +} + +class Breakpoints extends _react.Component { + handleBreakpointCheckbox(breakpoint) { + if (breakpoint.loading) { + return; + } + + if (breakpoint.disabled) { + this.props.enableBreakpoint(breakpoint.location); + } else { + this.props.disableBreakpoint(breakpoint.location); + } + } + + selectBreakpoint(breakpoint) { + this.props.selectLocation(breakpoint.location); + } + + removeBreakpoint(event, breakpoint) { + event.stopPropagation(); + this.props.removeBreakpoint(breakpoint.location); + } + + renderBreakpoint(breakpoint) { + const { + selectedSource + } = this.props; + return _react2.default.createElement(_Breakpoint2.default, { + key: breakpoint.locationId, + breakpoint: breakpoint, + selectedSource: selectedSource, + onClick: () => this.selectBreakpoint(breakpoint), + onContextMenu: e => (0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, { + breakpoint, + contextMenuEvent: e + })), + onChange: () => this.handleBreakpointCheckbox(breakpoint), + onCloseClick: ev => this.removeBreakpoint(ev, breakpoint) + }); + } + + renderExceptionsOptions() { + const { + breakpoints, + shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions, + pauseOnExceptions + } = this.props; + const isEmpty = breakpoints.size == 0; + const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions"); + const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught"); + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("breakpoints-exceptions-options", { + empty: isEmpty + }) + }, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null); + } + + renderBreakpoints() { + const { + breakpoints + } = this.props; + + if (breakpoints.size == 0) { + return; + } + + const groupedBreakpoints = (0, _lodash.groupBy)((0, _lodash.sortBy)([...breakpoints.valueSeq()], bp => bp.location.line), bp => (0, _source.getRawSourceURL)(bp.source.url)); + return [...Object.keys(groupedBreakpoints).sort(sortFilenames).map(url => { + const file = (0, _source.getFilenameFromURL)(url); + const groupBreakpoints = groupedBreakpoints[url].filter(bp => !bp.hidden && (bp.text || bp.originalText)); + + if (!groupBreakpoints.length) { + return null; + } + + return [_react2.default.createElement("div", { + className: "breakpoint-heading", + title: url, + key: url, + onClick: () => this.props.selectSource(groupBreakpoints[0].source.id) + }, file), ...groupBreakpoints.map(bp => this.renderBreakpoint(bp))]; + })]; + } + + render() { + return _react2.default.createElement("div", { + className: "pane breakpoints-list" + }, this.renderExceptionsOptions(), this.renderBreakpoints()); + } + +} + +function updateLocation(sources, frame, why, bp) { + const source = (0, _selectors.getSourceInSources)(sources, bp.location.sourceId); + const isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(frame, why, bp); + const locationId = (0, _breakpoint.makeLocationId)(bp.location); + + const localBP = _objectSpread({}, bp, { + locationId, + isCurrentlyPaused, + source + }); + + return localBP; +} + +const _getBreakpoints = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _selectors.getTopFrame, _selectors.getPauseReason, (breakpoints, sources, frame, why) => breakpoints.map(bp => updateLocation(sources, frame, why, bp)).filter(bp => bp.source && !bp.source.isBlackBoxed)); + +const mapStateToProps = state => ({ + breakpoints: _getBreakpoints(state), + selectedSource: (0, _selectors.getSelectedSource)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/BreakpointsContextMenu.js b/devtools/client/debugger/new/src/components/SecondaryPanes/BreakpointsContextMenu.js new file mode 100644 index 000000000000..32aa0d850938 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/BreakpointsContextMenu.js @@ -0,0 +1,201 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = showContextMenu; + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function showContextMenu(props) { + const { + removeBreakpoint, + removeBreakpoints, + removeAllBreakpoints, + toggleBreakpoints, + toggleAllBreakpoints, + toggleDisabledBreakpoint, + selectLocation, + setBreakpointCondition, + openConditionalPanel, + breakpoints, + breakpoint, + contextMenuEvent + } = props; + contextMenuEvent.preventDefault(); + const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label"); + const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label"); + const deleteOthersLabel = L10N.getStr("breakpointMenuItem.deleteOthers2.label"); + const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label"); + const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label"); + const enableOthersLabel = L10N.getStr("breakpointMenuItem.enableOthers2.label"); + const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label"); + const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label"); + const disableOthersLabel = L10N.getStr("breakpointMenuItem.disableOthers2.label"); + const removeConditionLabel = L10N.getStr("breakpointMenuItem.removeCondition2.label"); + const addConditionLabel = L10N.getStr("breakpointMenuItem.addCondition2.label"); + const editConditionLabel = L10N.getStr("breakpointMenuItem.editCondition2.label"); + const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey"); + const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey"); + const deleteOthersKey = L10N.getStr("breakpointMenuItem.deleteOthers2.accesskey"); + const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey"); + const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey"); + const enableOthersKey = L10N.getStr("breakpointMenuItem.enableOthers2.accesskey"); + const disableSelfKey = L10N.getStr("breakpointMenuItem.disableSelf2.accesskey"); + const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey"); + const disableOthersKey = L10N.getStr("breakpointMenuItem.disableOthers2.accesskey"); + const removeConditionKey = L10N.getStr("breakpointMenuItem.removeCondition2.accesskey"); + const editConditionKey = L10N.getStr("breakpointMenuItem.editCondition2.accesskey"); + const addConditionKey = L10N.getStr("breakpointMenuItem.addCondition2.accesskey"); + const otherBreakpoints = breakpoints.filter(b => b !== breakpoint); + const enabledBreakpoints = breakpoints.filter(b => !b.disabled); + const disabledBreakpoints = breakpoints.filter(b => b.disabled); + const otherEnabledBreakpoints = breakpoints.filter(b => !b.disabled && b !== breakpoint); + const otherDisabledBreakpoints = breakpoints.filter(b => b.disabled && b !== breakpoint); + const deleteSelfItem = { + id: "node-menu-delete-self", + label: deleteSelfLabel, + accesskey: deleteSelfKey, + disabled: false, + click: () => removeBreakpoint(breakpoint.location) + }; + const deleteAllItem = { + id: "node-menu-delete-all", + label: deleteAllLabel, + accesskey: deleteAllKey, + disabled: false, + click: () => removeAllBreakpoints() + }; + const deleteOthersItem = { + id: "node-menu-delete-other", + label: deleteOthersLabel, + accesskey: deleteOthersKey, + disabled: false, + click: () => removeBreakpoints(otherBreakpoints) + }; + const enableSelfItem = { + id: "node-menu-enable-self", + label: enableSelfLabel, + accesskey: enableSelfKey, + disabled: false, + click: () => toggleDisabledBreakpoint(breakpoint.location.line) + }; + const enableAllItem = { + id: "node-menu-enable-all", + label: enableAllLabel, + accesskey: enableAllKey, + disabled: false, + click: () => toggleAllBreakpoints(false) + }; + const enableOthersItem = { + id: "node-menu-enable-others", + label: enableOthersLabel, + accesskey: enableOthersKey, + disabled: false, + click: () => toggleBreakpoints(false, otherDisabledBreakpoints) + }; + const disableSelfItem = { + id: "node-menu-disable-self", + label: disableSelfLabel, + accesskey: disableSelfKey, + disabled: false, + click: () => toggleDisabledBreakpoint(breakpoint.location.line) + }; + const disableAllItem = { + id: "node-menu-disable-all", + label: disableAllLabel, + accesskey: disableAllKey, + disabled: false, + click: () => toggleAllBreakpoints(true) + }; + const disableOthersItem = { + id: "node-menu-disable-others", + label: disableOthersLabel, + accesskey: disableOthersKey, + click: () => toggleBreakpoints(true, otherEnabledBreakpoints) + }; + const removeConditionItem = { + id: "node-menu-remove-condition", + label: removeConditionLabel, + accesskey: removeConditionKey, + disabled: false, + click: () => setBreakpointCondition(breakpoint.location) + }; + const addConditionItem = { + id: "node-menu-add-condition", + label: addConditionLabel, + accesskey: addConditionKey, + click: () => { + selectLocation(breakpoint.location); + openConditionalPanel(breakpoint.location.line); + } + }; + const editConditionItem = { + id: "node-menu-edit-condition", + label: editConditionLabel, + accesskey: editConditionKey, + click: () => { + selectLocation(breakpoint.location); + openConditionalPanel(breakpoint.location.line); + } + }; + const hideEnableSelfItem = !breakpoint.disabled; + const hideEnableAllItem = disabledBreakpoints.size === 0; + const hideEnableOthersItem = otherDisabledBreakpoints.size === 0; + const hideDisableAllItem = enabledBreakpoints.size === 0; + const hideDisableOthersItem = otherEnabledBreakpoints.size === 0; + const hideDisableSelfItem = breakpoint.disabled; + const items = [{ + item: enableSelfItem, + hidden: () => hideEnableSelfItem + }, { + item: enableAllItem, + hidden: () => hideEnableAllItem + }, { + item: enableOthersItem, + hidden: () => hideEnableOthersItem + }, { + item: { + type: "separator" + }, + hidden: () => hideEnableSelfItem && hideEnableAllItem && hideEnableOthersItem + }, { + item: deleteSelfItem + }, { + item: deleteAllItem + }, { + item: deleteOthersItem, + hidden: () => breakpoints.size === 1 + }, { + item: { + type: "separator" + }, + hidden: () => hideDisableSelfItem && hideDisableAllItem && hideDisableOthersItem + }, { + item: disableSelfItem, + hidden: () => hideDisableSelfItem + }, { + item: disableAllItem, + hidden: () => hideDisableAllItem + }, { + item: disableOthersItem, + hidden: () => hideDisableOthersItem + }, { + item: { + type: "separator" + } + }, { + item: addConditionItem, + hidden: () => breakpoint.condition + }, { + item: editConditionItem, + hidden: () => !breakpoint.condition + }, { + item: removeConditionItem, + hidden: () => !breakpoint.condition + }]; + (0, _devtoolsContextmenu.showMenu)(contextMenuEvent, (0, _devtoolsContextmenu.buildMenu)(items)); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js b/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js new file mode 100644 index 000000000000..30e26c9ee357 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js @@ -0,0 +1,294 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _prefs = require("../../utils/prefs"); + +var _selectors = require("../../selectors/index"); + +var _text = require("../../utils/text"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _CommandBarButton = require("../shared/Button/CommandBarButton"); + +var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + appinfo +} = _devtoolsModules.Services; +const isMacOS = appinfo.OS === "Darwin"; +const COMMANDS = ["resume", "stepOver", "stepIn", "stepOut"]; +const KEYS = { + WINNT: { + resume: "F8", + pause: "F8", + stepOver: "F10", + stepIn: "F11", + stepOut: "Shift+F11" + }, + Darwin: { + resume: "Cmd+\\", + pause: "Cmd+\\", + stepOver: "Cmd+'", + stepIn: "Cmd+;", + stepOut: "Cmd+Shift+:", + stepOutDisplay: "Cmd+Shift+;" + }, + Linux: { + resume: "F8", + pause: "F8", + stepOver: "F10", + stepIn: "Ctrl+F11", + stepOut: "Ctrl+Shift+F11" + } +}; + +function getKey(action) { + return getKeyForOS(appinfo.OS, action); +} + +function getKeyForOS(os, action) { + const osActions = KEYS[os] || KEYS.Linux; + return osActions[action]; +} + +function formatKey(action) { + const key = getKey(`${action}Display`) || getKey(action); + + if (isMacOS) { + const winKey = getKeyForOS("WINNT", `${action}Display`) || getKeyForOS("WINNT", action); // display both Windows type and Mac specific keys + + return (0, _text.formatKeyShortcut)([key, winKey].join(" ")); + } + + return (0, _text.formatKeyShortcut)(key); +} + +class CommandBar extends _react.Component { + componentWillUnmount() { + const shortcuts = this.context.shortcuts; + COMMANDS.forEach(action => shortcuts.off(getKey(action))); + + if (isMacOS) { + COMMANDS.forEach(action => shortcuts.off(getKeyForOS("WINNT", action))); + } + } + + componentDidMount() { + const shortcuts = this.context.shortcuts; + COMMANDS.forEach(action => shortcuts.on(getKey(action), (_, e) => this.handleEvent(e, action))); + + if (isMacOS) { + // The Mac supports both the Windows Function keys + // as well as the Mac non-Function keys + COMMANDS.forEach(action => shortcuts.on(getKeyForOS("WINNT", action), (_, e) => this.handleEvent(e, action))); + } + } + + handleEvent(e, action) { + e.preventDefault(); + e.stopPropagation(); + this.props[action](); + } + + setHistory(offset) { + this.props.timeTravelTo(this.props.historyPosition + offset); + } + + renderStepButtons() { + const { + isPaused, + canRewind + } = this.props; + const className = isPaused ? "active" : "disabled"; + const isDisabled = !isPaused; + + if (canRewind || !isPaused && _prefs.features.removeCommandBarOptions) { + return; + } + + return [(0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", className, L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled)]; + } + + resume() { + this.props.resume(); + this.props.clearHistory(); + } + + renderPauseButton() { + const { + isPaused, + breakOnNext, + isWaitingOnBreak, + canRewind + } = this.props; + + if (canRewind) { + return; + } + + if (isPaused) { + return (0, _CommandBarButton.debugBtn)(() => this.resume(), "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))); + } + + if (_prefs.features.removeCommandBarOptions && !this.props.canRewind) { + return; + } + + if (isWaitingOnBreak) { + return (0, _CommandBarButton.debugBtn)(null, "pause", "disabled", L10N.getStr("pausePendingButtonTooltip"), true); + } + + return (0, _CommandBarButton.debugBtn)(breakOnNext, "pause", "active", L10N.getFormatStr("pauseButtonTooltip", formatKey("pause"))); + } + + renderTimeTravelButtons() { + const { + isPaused, + canRewind + } = this.props; + + if (!canRewind || !isPaused) { + return null; + } + + const isDisabled = !isPaused; + return [(0, _CommandBarButton.debugBtn)(this.props.rewind, "rewind", "active", "Rewind Execution"), (0, _CommandBarButton.debugBtn)(() => this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", { + className: "divider" + }), (0, _CommandBarButton.debugBtn)(this.props.reverseStepOver, "reverseStepOver", "active", "Reverse step over"), (0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", "active", L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), _react2.default.createElement("div", { + className: "divider" + }), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", "active", L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", "active", L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled)]; + } + + replayPreviousButton() { + const { + history, + historyPosition, + canRewind + } = this.props; + const historyLength = history.length; + + if (canRewind || !historyLength || historyLength <= 1 || !_prefs.features.replay) { + return null; + } + + const enabled = historyPosition === 0; + const activeClass = enabled ? "replay-inactive" : ""; + return (0, _CommandBarButton.debugBtn)(() => this.setHistory(-1), `replay-previous ${activeClass}`, "active", L10N.getStr("replayPrevious"), enabled); + } + + replayNextButton() { + const { + history, + historyPosition, + canRewind + } = this.props; + const historyLength = history.length; + + if (canRewind || !historyLength || historyLength <= 1 || !_prefs.features.replay) { + return null; + } + + const enabled = historyPosition + 1 === historyLength; + const activeClass = enabled ? "replay-inactive" : ""; + return (0, _CommandBarButton.debugBtn)(() => this.setHistory(1), `replay-next ${activeClass}`, "active", L10N.getStr("replayNext"), enabled); + } + + renderStepPosition() { + const { + history, + historyPosition, + canRewind + } = this.props; + const historyLength = history.length; + + if (canRewind || !historyLength || !_prefs.features.replay) { + return null; + } + + const position = historyPosition + 1; + const total = historyLength; + const activePrev = position > 1 ? "replay-active" : "replay-inactive"; + const activeNext = position < total ? "replay-active" : "replay-inactive"; + return _react2.default.createElement("div", { + className: "step-position" + }, _react2.default.createElement("span", { + className: activePrev + }, position), _react2.default.createElement("span", null, " | "), _react2.default.createElement("span", { + className: activeNext + }, total)); + } + + renderSkipPausingButton() { + const { + skipPausing, + toggleSkipPausing + } = this.props; + + if (!_prefs.features.skipPausing) { + return null; + } + + return _react2.default.createElement("button", { + className: (0, _classnames2.default)("command-bar-button", { + active: skipPausing + }), + title: L10N.getStr("skipPausingTooltip"), + onClick: toggleSkipPausing + }, _react2.default.createElement("img", { + className: "skipPausing" + })); + } + + render() { + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("command-bar", { + vertical: !this.props.horizontal + }) + }, this.renderPauseButton(), this.renderStepButtons(), this.renderTimeTravelButtons(), _react2.default.createElement("div", { + className: "filler" + }), this.replayPreviousButton(), this.renderStepPosition(), this.replayNextButton(), this.renderSkipPausingButton()); + } + +} + +CommandBar.contextTypes = { + shortcuts: _propTypes2.default.object +}; + +const mapStateToProps = state => ({ + isPaused: (0, _selectors.isPaused)(state), + history: (0, _selectors.getHistory)(state), + historyPosition: (0, _selectors.getHistoryPosition)(state), + isWaitingOnBreak: (0, _selectors.getIsWaitingOnBreak)(state), + canRewind: (0, _selectors.getCanRewind)(state), + skipPausing: (0, _selectors.getSkipPausing)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(CommandBar); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js b/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js new file mode 100644 index 000000000000..5f6915d02f60 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js @@ -0,0 +1,117 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _Close = require("../shared/Button/Close"); + +var _Close2 = _interopRequireDefault(_Close); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +class EventListeners extends _react.Component { + constructor(...args) { + super(...args); + + this.renderListener = ({ + type, + selector, + line, + sourceId, + breakpoint + }) => { + const checked = breakpoint && !breakpoint.disabled; + const location = { + sourceId, + line + }; + return _react2.default.createElement("div", { + className: "listener", + onClick: () => this.props.selectLocation({ + sourceId, + line + }), + key: `${type}.${selector}.${sourceId}.${line}` + }, _react2.default.createElement("input", { + type: "checkbox", + className: "listener-checkbox", + checked: checked, + onChange: () => this.handleCheckbox(breakpoint, location) + }), _react2.default.createElement("span", { + className: "type" + }, type), _react2.default.createElement("span", { + className: "selector" + }, selector), breakpoint ? _react2.default.createElement(_Close2.default, { + handleClick: ev => this.removeBreakpoint(ev, breakpoint) + }) : ""); + }; + } + + handleCheckbox(breakpoint, location) { + if (!breakpoint) { + return this.props.addBreakpoint(location); + } + + if (breakpoint.loading) { + return; + } + + if (breakpoint.disabled) { + this.props.enableBreakpoint(breakpoint.location); + } else { + this.props.disableBreakpoint(breakpoint.location); + } + } + + removeBreakpoint(event, breakpoint) { + event.stopPropagation(); + + if (breakpoint) { + this.props.removeBreakpoint(breakpoint.location); + } + } + + render() { + const { + listeners + } = this.props; + return _react2.default.createElement("div", { + className: "pane event-listeners" + }, listeners.map(this.renderListener)); + } + +} + +const mapStateToProps = state => { + const listeners = (0, _selectors.getEventListeners)(state).map(listener => { + return _objectSpread({}, listener, { + breakpoint: (0, _selectors.getBreakpoint)(state, { + sourceId: listener.sourceId, + line: listener.line, + column: null + }) + }); + }); + return { + listeners + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(EventListeners); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js new file mode 100644 index 000000000000..49fff1fd5707 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js @@ -0,0 +1,326 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _devtoolsReps = require("devtools/client/shared/components/reps/reps.js"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _expressions = require("../../utils/expressions"); + +var _firefox = require("../../client/firefox"); + +var _Close = require("../shared/Button/Close"); + +var _Close2 = _interopRequireDefault(_Close); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Expressions extends _react.Component { + constructor(props) { + super(props); + + this.clear = () => { + this.setState(() => { + this.props.clearExpressionError(); + return { + editing: false, + editIndex: -1, + inputValue: "" + }; + }); + }; + + this.handleChange = e => { + this.setState({ + inputValue: e.target.value + }); + }; + + this.handleKeyDown = e => { + if (e.key === "Escape") { + this.clear(); + } + }; + + this.hideInput = () => { + this.setState({ + focused: false + }); + this.props.onExpressionAdded(); + }; + + this.onFocus = () => { + this.setState({ + focused: true + }); + }; + + this.handleExistingSubmit = async (e, expression) => { + e.preventDefault(); + e.stopPropagation(); + this.props.updateExpression(this.state.inputValue, expression); + this.hideInput(); + }; + + this.handleNewSubmit = async e => { + const { + inputValue + } = this.state; + e.preventDefault(); + e.stopPropagation(); + this.props.clearExpressionError(); + await this.props.addExpression(this.state.inputValue); + this.setState({ + editing: false, + editIndex: -1, + inputValue: this.props.expressionError ? inputValue : "" + }); + + if (!this.props.expressionError) { + this.hideInput(); + } + }; + + this.renderExpression = (expression, index) => { + const { + expressionError, + openLink + } = this.props; + const { + editing, + editIndex + } = this.state; + const { + input, + updating + } = expression; + const isEditingExpr = editing && editIndex === index; + + if (isEditingExpr || isEditingExpr && expressionError) { + return this.renderExpressionEditInput(expression); + } + + if (updating) { + return; + } + + const { + value + } = (0, _expressions.getValue)(expression); + const root = { + name: expression.input, + path: input, + contents: { + value + } + }; + return _react2.default.createElement("li", { + className: "expression-container", + key: input, + onDoubleClick: (items, options) => this.editExpression(expression, index) + }, _react2.default.createElement("div", { + className: "expression-content" + }, _react2.default.createElement(_devtoolsReps.ObjectInspector, { + roots: [root], + autoExpandDepth: 0, + disableWrap: true, + focusable: false, + openLink: openLink, + createObjectClient: grip => (0, _firefox.createObjectClient)(grip) + }), _react2.default.createElement("div", { + className: "expression-container__close-btn" + }, _react2.default.createElement(_Close2.default, { + handleClick: e => this.deleteExpression(e, expression) + })))); + }; + + this.state = { + editing: false, + editIndex: -1, + inputValue: "", + focused: false + }; + } + + componentDidMount() { + const { + expressions, + evaluateExpressions + } = this.props; + + if (expressions.size > 0) { + evaluateExpressions(); + } + } + + componentWillReceiveProps(nextProps) { + if (this.state.editing && !nextProps.expressionError) { + this.clear(); + } + } + + shouldComponentUpdate(nextProps, nextState) { + const { + editing, + inputValue, + focused + } = this.state; + const { + expressions, + expressionError, + showInput + } = this.props; + return expressions !== nextProps.expressions || expressionError !== nextProps.expressionError || editing !== nextState.editing || inputValue !== nextState.inputValue || nextProps.showInput !== showInput || focused !== nextState.focused; + } + + componentDidUpdate(prevProps, prevState) { + const input = this._input; + + if (!input) { + return; + } + + if (!prevState.editing && this.state.editing) { + input.setSelectionRange(0, input.value.length); + input.focus(); + } else if (this.props.showInput && !this.state.focused) { + input.focus(); + } + } + + editExpression(expression, index) { + this.setState({ + inputValue: expression.input, + editing: true, + editIndex: index + }); + } + + deleteExpression(e, expression) { + e.stopPropagation(); + const { + deleteExpression + } = this.props; + deleteExpression(expression); + } + + onBlur() { + this.clear(); + this.hideInput(); + } + + renderNewExpressionInput() { + const { + expressionError, + showInput + } = this.props; + const { + editing, + inputValue, + focused + } = this.state; + const error = editing === false && expressionError === true; + const placeholder = error ? L10N.getStr("expressions.errorMsg") : L10N.getStr("expressions.placeholder"); + return _react2.default.createElement("li", { + className: (0, _classnames2.default)("expression-input-container", { + focused, + error + }) + }, _react2.default.createElement("form", { + className: "expression-input-form", + onSubmit: this.handleNewSubmit + }, _react2.default.createElement("input", { + className: "input-expression", + type: "text", + placeholder: placeholder, + onChange: this.handleChange, + onBlur: this.hideInput, + onKeyDown: this.handleKeyDown, + onFocus: this.onFocus, + autoFocus: showInput, + value: !editing ? inputValue : "", + ref: c => this._input = c + }), _react2.default.createElement("input", { + type: "submit", + style: { + display: "none" + } + }))); + } + + renderExpressionEditInput(expression) { + const { + expressionError + } = this.props; + const { + inputValue, + editing, + focused + } = this.state; + const error = editing === true && expressionError === true; + return _react2.default.createElement("span", { + className: (0, _classnames2.default)("expression-input-container", { + focused, + error + }), + key: expression.input + }, _react2.default.createElement("form", { + className: "expression-input-form", + onSubmit: e => this.handleExistingSubmit(e, expression) + }, _react2.default.createElement("input", { + className: (0, _classnames2.default)("input-expression", { + error + }), + type: "text", + onChange: this.handleChange, + onBlur: this.clear, + onKeyDown: this.handleKeyDown, + onFocus: this.onFocus, + value: editing ? inputValue : expression.input, + ref: c => this._input = c + }), _react2.default.createElement("input", { + type: "submit", + style: { + display: "none" + } + }))); + } + + render() { + const { + expressions, + showInput + } = this.props; + return _react2.default.createElement("ul", { + className: "pane expressions-list" + }, expressions.map(this.renderExpression), (showInput || !expressions.size) && this.renderNewExpressionInput()); + } + +} + +const mapStateToProps = state => ({ + expressions: (0, _selectors.getExpressions)(state), + expressionError: (0, _selectors.getExpressionError)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Expressions); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js new file mode 100644 index 000000000000..bc2e3258d70a --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js @@ -0,0 +1,132 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _frames = require("../../../utils/pause/frames/index"); + +var _source = require("../../../utils/source"); + +var _FrameMenu = require("./FrameMenu"); + +var _FrameMenu2 = _interopRequireDefault(_FrameMenu); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function FrameTitle({ + frame, + options +}) { + const displayName = (0, _frames.formatDisplayName)(frame, options); + return _react2.default.createElement("div", { + className: "title" + }, displayName); +} + +function FrameLocation({ + frame +}) { + if (!frame.source) { + return; + } + + if (frame.library) { + return _react2.default.createElement("div", { + className: "location" + }, frame.library, _react2.default.createElement(_Svg2.default, { + name: frame.library.toLowerCase(), + className: "annotation-logo" + })); + } + + const filename = (0, _source.getFilename)(frame.source); + return _react2.default.createElement("div", { + className: "location" + }, `${filename}: ${frame.location.line}`); +} + +FrameLocation.displayName = "FrameLocation"; + +class FrameComponent extends _react.Component { + onContextMenu(event) { + const { + frame, + copyStackTrace, + toggleFrameworkGrouping, + toggleBlackBox, + frameworkGroupingOn + } = this.props; + (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { + copyStackTrace, + toggleFrameworkGrouping, + toggleBlackBox + }, event); + } + + onMouseDown(e, frame, selectedFrame) { + if (e.nativeEvent.which == 3) { + return; + } + + this.props.selectFrame(frame); + } + + onKeyUp(event, frame, selectedFrame) { + if (event.key != "Enter") { + return; + } + + this.props.selectFrame(frame); + } + + render() { + const { + frame, + selectedFrame, + hideLocation, + shouldMapDisplayName + } = this.props; + const className = (0, _classnames2.default)("frame", { + selected: selectedFrame && selectedFrame.id === frame.id + }); + return _react2.default.createElement("li", { + key: frame.id, + className: className, + onMouseDown: e => this.onMouseDown(e, frame, selectedFrame), + onKeyUp: e => this.onKeyUp(e, frame, selectedFrame), + onContextMenu: e => this.onContextMenu(e), + tabIndex: 0 + }, _react2.default.createElement(FrameTitle, { + frame: frame, + options: { + shouldMapDisplayName + } + }), !hideLocation && _react2.default.createElement(FrameLocation, { + frame: frame + })); + } + +} + +exports.default = FrameComponent; +FrameComponent.defaultProps = { + hideLocation: false, + shouldMapDisplayName: true +}; +FrameComponent.displayName = "Frame"; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.js new file mode 100644 index 000000000000..4be2c7b2e71f --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.js @@ -0,0 +1,68 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = FrameMenu; + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _clipboard = require("../../../utils/clipboard"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const blackboxString = "sourceFooter.blackbox"; +const unblackboxString = "sourceFooter.unblackbox"; + +function formatMenuElement(labelString, click, disabled = false) { + const label = L10N.getStr(labelString); + const accesskey = L10N.getStr(`${labelString}.accesskey`); + const id = `node-menu-${(0, _lodash.kebabCase)(label)}`; + return { + id, + label, + accesskey, + disabled, + click + }; +} + +function copySourceElement(url) { + return formatMenuElement("copySourceUri2", () => (0, _clipboard.copyToTheClipboard)(url)); +} + +function copyStackTraceElement(copyStackTrace) { + return formatMenuElement("copyStackTrace", () => copyStackTrace()); +} + +function toggleFrameworkGroupingElement(toggleFrameworkGrouping, frameworkGroupingOn) { + const actionType = frameworkGroupingOn ? "framework.disableGrouping" : "framework.enableGrouping"; + return formatMenuElement(actionType, () => toggleFrameworkGrouping()); +} + +function blackBoxSource(source, toggleBlackBox) { + const toggleBlackBoxString = source.isBlackBoxed ? unblackboxString : blackboxString; + return formatMenuElement(toggleBlackBoxString, () => toggleBlackBox(source)); +} + +function FrameMenu(frame, frameworkGroupingOn, callbacks, event) { + event.stopPropagation(); + event.preventDefault(); + const menuOptions = []; + const source = frame.source; + const toggleFrameworkElement = toggleFrameworkGroupingElement(callbacks.toggleFrameworkGrouping, frameworkGroupingOn); + menuOptions.push(toggleFrameworkElement); + + if (source) { + const copySourceUri2 = copySourceElement(source.url); + menuOptions.push(copySourceUri2); + menuOptions.push(blackBoxSource(source, callbacks.toggleBlackBox)); + } + + const copyStackTraceItem = copyStackTraceElement(callbacks.copyStackTrace); + menuOptions.push(copyStackTraceItem); + (0, _devtoolsContextmenu.showMenu)(event, menuOptions); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js new file mode 100644 index 000000000000..1bba2c39a3c0 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js @@ -0,0 +1,154 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _frames = require("../../../utils/pause/frames/index"); + +var _FrameMenu = require("./FrameMenu"); + +var _FrameMenu2 = _interopRequireDefault(_FrameMenu); + +var _Frame = require("./Frame"); + +var _Frame2 = _interopRequireDefault(_Frame); + +var _Badge = require("../../shared/Badge"); + +var _Badge2 = _interopRequireDefault(_Badge); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function FrameLocation({ + frame +}) { + const library = frame.library || (0, _frames.getLibraryFromUrl)(frame); + + if (!library) { + return null; + } + + return _react2.default.createElement("div", { + className: "location" + }, library, _react2.default.createElement(_Svg2.default, { + name: library.toLowerCase(), + className: "annotation-logo" + })); +} + +FrameLocation.displayName = "FrameLocation"; + +class Group extends _react.Component { + constructor(...args) { + super(...args); + + this.toggleFrames = () => { + this.setState(prevState => ({ + expanded: !prevState.expanded + })); + }; + + this.state = { + expanded: false + }; + } + + onContextMenu(event) { + const { + group, + copyStackTrace, + toggleFrameworkGrouping, + toggleBlackBox, + frameworkGroupingOn + } = this.props; + const frame = group[0]; + (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { + copyStackTrace, + toggleFrameworkGrouping, + toggleBlackBox + }, event); + } + + renderFrames() { + const { + group, + selectFrame, + selectedFrame, + toggleFrameworkGrouping, + frameworkGroupingOn, + toggleBlackBox, + copyStackTrace + } = this.props; + const { + expanded + } = this.state; + + if (!expanded) { + return null; + } + + return _react2.default.createElement("div", { + className: "frames-list" + }, group.map(frame => _react2.default.createElement(_Frame2.default, { + copyStackTrace: copyStackTrace, + frame: frame, + frameworkGroupingOn: frameworkGroupingOn, + hideLocation: true, + key: frame.id, + selectedFrame: selectedFrame, + selectFrame: selectFrame, + shouldMapDisplayName: false, + toggleBlackBox: toggleBlackBox, + toggleFrameworkGrouping: toggleFrameworkGrouping + }))); + } + + renderDescription() { + const frame = this.props.group[0]; + const displayName = (0, _frames.formatDisplayName)(frame); + return _react2.default.createElement("li", { + key: frame.id, + className: (0, _classnames2.default)("group"), + onClick: this.toggleFrames, + tabIndex: 0 + }, _react2.default.createElement("div", { + className: "d-flex align-items-center min-width-0" + }, _react2.default.createElement("div", { + className: "title" + }, displayName), _react2.default.createElement(_Badge2.default, null, this.props.group.length)), _react2.default.createElement(FrameLocation, { + frame: frame + })); + } + + render() { + const { + expanded + } = this.state; + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("frames-group", { + expanded + }), + onContextMenu: e => this.onContextMenu(e) + }, this.renderDescription(), this.renderFrames()); + } + +} + +exports.default = Group; +Group.displayName = "Group"; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/WhyPaused.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/WhyPaused.js new file mode 100644 index 000000000000..1795648c180a --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/WhyPaused.js @@ -0,0 +1,61 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = renderWhyPaused; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _pause = require("../../../utils/pause/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function renderExceptionSummary(exception) { + if (typeof exception === "string") { + return exception; + } + + const preview = exception.preview; + + if (!preview) { + return; + } + + return `${preview.name}: ${preview.message}`; +} + +function renderMessage(why) { + if (why.type == "exception" && why.exception) { + return _react2.default.createElement("div", { + className: "message warning" + }, renderExceptionSummary(why.exception)); + } + + if (typeof why.message == "string") { + return _react2.default.createElement("div", { + className: "message" + }, why.message); + } + + return null; +} + +function renderWhyPaused(why) { + const reason = (0, _pause.getPauseReason)(why); + + if (!reason) { + return null; + } + + return _react2.default.createElement("div", { + className: "pane why-paused" + }, _react2.default.createElement("div", null, L10N.getStr(reason)), renderMessage(why)); +} + +renderWhyPaused.displayName = "whyPaused"; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js new file mode 100644 index 000000000000..ab317631097a --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js @@ -0,0 +1,177 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _Frame = require("./Frame"); + +var _Frame2 = _interopRequireDefault(_Frame); + +var _Group = require("./Group"); + +var _Group2 = _interopRequireDefault(_Group); + +var _WhyPaused = require("./WhyPaused"); + +var _WhyPaused2 = _interopRequireDefault(_WhyPaused); + +var _actions = require("../../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _frames = require("../../../utils/pause/frames/index"); + +var _clipboard = require("../../../utils/clipboard"); + +var _selectors = require("../../../selectors/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const NUM_FRAMES_SHOWN = 7; + +class Frames extends _react.Component { + constructor(props) { + super(props); + + this.toggleFramesDisplay = () => { + this.setState(prevState => ({ + showAllFrames: !prevState.showAllFrames + })); + }; + + this.copyStackTrace = () => { + const { + frames + } = this.props; + const framesToCopy = frames.map(f => (0, _frames.formatCopyName)(f)).join("\n"); + (0, _clipboard.copyToTheClipboard)(framesToCopy); + }; + + this.toggleFrameworkGrouping = () => { + const { + toggleFrameworkGrouping, + frameworkGroupingOn + } = this.props; + toggleFrameworkGrouping(!frameworkGroupingOn); + }; + + this.state = { + showAllFrames: !!props.disableFrameTruncate + }; + } + + shouldComponentUpdate(nextProps, nextState) { + const { + frames, + selectedFrame, + frameworkGroupingOn + } = this.props; + const { + showAllFrames + } = this.state; + return frames !== nextProps.frames || selectedFrame !== nextProps.selectedFrame || showAllFrames !== nextState.showAllFrames || frameworkGroupingOn !== nextProps.frameworkGroupingOn; + } + + collapseFrames(frames) { + const { + frameworkGroupingOn + } = this.props; + + if (!frameworkGroupingOn) { + return frames; + } + + return (0, _frames.collapseFrames)(frames); + } + + truncateFrames(frames) { + const numFramesToShow = this.state.showAllFrames ? frames.length : NUM_FRAMES_SHOWN; + return frames.slice(0, numFramesToShow); + } + + renderFrames(frames) { + const { + selectFrame, + selectedFrame, + toggleBlackBox, + frameworkGroupingOn + } = this.props; + const framesOrGroups = this.truncateFrames(this.collapseFrames(frames)); + return _react2.default.createElement("ul", null, framesOrGroups.map(frameOrGroup => frameOrGroup.id ? _react2.default.createElement(_Frame2.default, { + frame: frameOrGroup, + toggleFrameworkGrouping: this.toggleFrameworkGrouping, + copyStackTrace: this.copyStackTrace, + frameworkGroupingOn: frameworkGroupingOn, + selectFrame: selectFrame, + selectedFrame: selectedFrame, + toggleBlackBox: toggleBlackBox, + key: String(frameOrGroup.id) + }) : _react2.default.createElement(_Group2.default, { + group: frameOrGroup, + toggleFrameworkGrouping: this.toggleFrameworkGrouping, + copyStackTrace: this.copyStackTrace, + frameworkGroupingOn: frameworkGroupingOn, + selectFrame: selectFrame, + selectedFrame: selectedFrame, + toggleBlackBox: toggleBlackBox, + key: frameOrGroup[0].id + }))); + } + + renderToggleButton(frames) { + const buttonMessage = this.state.showAllFrames ? L10N.getStr("callStack.collapse") : L10N.getStr("callStack.expand"); + frames = this.collapseFrames(frames); + + if (frames.length <= NUM_FRAMES_SHOWN) { + return null; + } + + return _react2.default.createElement("div", { + className: "show-more-container" + }, _react2.default.createElement("button", { + className: "show-more", + onClick: this.toggleFramesDisplay + }, buttonMessage)); + } + + render() { + const { + frames, + disableFrameTruncate, + why + } = this.props; + + if (!frames) { + return _react2.default.createElement("div", { + className: "pane frames" + }, _react2.default.createElement("div", { + className: "pane-info empty" + }, L10N.getStr("callStack.notPaused"))); + } + + return _react2.default.createElement("div", { + className: "pane frames" + }, this.renderFrames(frames), (0, _WhyPaused2.default)(why), disableFrameTruncate ? null : this.renderToggleButton(frames)); + } + +} + +const mapStateToProps = state => ({ + frames: (0, _selectors.getCallStackFrames)(state), + why: (0, _selectors.getPauseReason)(state), + frameworkGroupingOn: (0, _selectors.getFrameworkGroupingState)(state), + selectedFrame: (0, _selectors.getSelectedFrame)(state), + pause: (0, _selectors.isPaused)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Frames); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/moz.build b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/moz.build new file mode 100644 index 000000000000..375908b624f4 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/moz.build @@ -0,0 +1,16 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'Frame.js', + 'FrameMenu.js', + 'Group.js', + 'index.js', + 'WhyPaused.js', +) diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/FrameworkComponent.js b/devtools/client/debugger/new/src/components/SecondaryPanes/FrameworkComponent.js new file mode 100644 index 000000000000..ec77a5f2cfa3 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/FrameworkComponent.js @@ -0,0 +1,116 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _firefox = require("../../client/firefox"); + +var _selectors = require("../../selectors/index"); + +var _devtoolsReps = require("devtools/client/shared/components/reps/reps.js"); + +var _preview = require("../../utils/preview"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + createNode, + getChildren +} = _devtoolsReps.ObjectInspectorUtils.node; +const { + loadItemProperties +} = _devtoolsReps.ObjectInspectorUtils.loadProperties; + +class FrameworkComponent extends _react.PureComponent { + async componentWillMount() { + const expression = "this;"; + const { + selectedFrame, + setPopupObjectProperties + } = this.props; + const value = selectedFrame.this; + const root = createNode({ + name: expression, + contents: { + value + } + }); + const properties = await loadItemProperties(root, _firefox.createObjectClient); + + if (properties) { + setPopupObjectProperties(value, properties); + } + } + + renderReactComponent() { + const { + selectedFrame, + popupObjectProperties + } = this.props; + const expression = "this;"; + const value = selectedFrame.this; + const root = { + name: expression, + path: expression, + contents: { + value + } + }; + const loadedRootProperties = popupObjectProperties[value.actor]; + + if (!loadedRootProperties) { + return null; + } + + let roots = getChildren({ + item: root, + loadedProperties: new Map([[root.path, loadedRootProperties]]) + }); + roots = roots.filter(r => ["state", "props"].includes(r.name)); + return _react2.default.createElement("div", { + className: "pane framework-component" + }, _react2.default.createElement(_devtoolsReps.ObjectInspector, { + roots: roots, + autoExpandAll: false, + autoExpandDepth: 0, + disableWrap: true, + focusable: false, + dimTopLevelWindow: true, + createObjectClient: grip => (0, _firefox.createObjectClient)(grip) + })); + } + + render() { + const { + selectedFrame + } = this.props; + + if (selectedFrame && (0, _preview.isReactComponent)(selectedFrame.this)) { + return this.renderReactComponent(); + } + + return null; + } + +} + +const mapStateToProps = state => ({ + selectedFrame: (0, _selectors.getSelectedFrame)(state), + popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(FrameworkComponent); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/ReactComponentStack.js b/devtools/client/debugger/new/src/components/SecondaryPanes/ReactComponentStack.js new file mode 100644 index 000000000000..2ce3226ade4a --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/ReactComponentStack.js @@ -0,0 +1,42 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class ReactComponentStack extends _react.PureComponent { + render() { + const { + componentStack + } = this.props.extra.react; + return _react2.default.createElement("div", { + className: "pane frames" + }, _react2.default.createElement("ul", null, componentStack.slice().reverse().map((component, index) => _react2.default.createElement("li", { + key: index + }, component)))); + } + +} + +const mapStateToProps = state => ({ + extra: (0, _selectors.getExtra)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ReactComponentStack); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js new file mode 100644 index 000000000000..41bdae84e63a --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js @@ -0,0 +1,148 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _firefox = require("../../client/firefox"); + +var _selectors = require("../../selectors/index"); + +var _scopes = require("../../utils/pause/scopes/index"); + +var _devtoolsReps = require("devtools/client/shared/components/reps/reps.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Scopes extends _react.PureComponent { + constructor(props, ...args) { + const { + why, + selectedFrame, + originalFrameScopes, + generatedFrameScopes + } = props; + super(props, ...args); + this.state = { + originalScopes: (0, _scopes.getScopes)(why, selectedFrame, originalFrameScopes), + generatedScopes: (0, _scopes.getScopes)(why, selectedFrame, generatedFrameScopes), + showOriginal: true + }; + } + + componentWillReceiveProps(nextProps) { + const { + isPaused, + selectedFrame, + originalFrameScopes, + generatedFrameScopes + } = this.props; + const isPausedChanged = isPaused !== nextProps.isPaused; + const selectedFrameChanged = selectedFrame !== nextProps.selectedFrame; + const originalFrameScopesChanged = originalFrameScopes !== nextProps.originalFrameScopes; + const generatedFrameScopesChanged = generatedFrameScopes !== nextProps.generatedFrameScopes; + + if (isPausedChanged || selectedFrameChanged || originalFrameScopesChanged || generatedFrameScopesChanged) { + this.setState({ + originalScopes: (0, _scopes.getScopes)(nextProps.why, nextProps.selectedFrame, nextProps.originalFrameScopes), + generatedScopes: (0, _scopes.getScopes)(nextProps.why, nextProps.selectedFrame, nextProps.generatedFrameScopes) + }); + } + } + + render() { + const { + isPaused, + isLoading + } = this.props; + const { + originalScopes, + generatedScopes, + showOriginal + } = this.state; + const scopes = showOriginal && originalScopes || generatedScopes; + + if (scopes && !isLoading) { + return _react2.default.createElement("div", { + className: "pane scopes-list" + }, _react2.default.createElement(_devtoolsReps.ObjectInspector, { + roots: scopes, + autoExpandAll: false, + autoExpandDepth: 1, + disableWrap: true, + focusable: false, + dimTopLevelWindow: true, + createObjectClient: grip => (0, _firefox.createObjectClient)(grip) + }), originalScopes ? _react2.default.createElement("div", { + className: "scope-type-toggle" + }, _react2.default.createElement("a", { + href: "", + onClick: e => { + e.preventDefault(); + this.setState({ + showOriginal: !showOriginal + }); + } + }, showOriginal ? L10N.getStr("scopes.toggleToGenerated") : L10N.getStr("scopes.toggleToOriginal"))) : null); + } + + let stateText = L10N.getStr("scopes.notPaused"); + + if (isPaused) { + if (isLoading) { + stateText = L10N.getStr("loadingText"); + } else { + stateText = L10N.getStr("scopes.notAvailable"); + } + } + + return _react2.default.createElement("div", { + className: "pane scopes-list" + }, _react2.default.createElement("div", { + className: "pane-info" + }, stateText)); + } + +} + +const mapStateToProps = state => { + const selectedFrame = (0, _selectors.getSelectedFrame)(state); + const selectedSource = (0, _selectors.getSelectedSource)(state); + const { + scope: originalFrameScopes, + pending: originalPending + } = (0, _selectors.getOriginalFrameScope)(state, selectedSource && selectedSource.get("id"), selectedFrame && selectedFrame.id) || { + scope: null, + pending: false + }; + const { + scope: generatedFrameScopes, + pending: generatedPending + } = (0, _selectors.getGeneratedFrameScope)(state, selectedFrame && selectedFrame.id) || { + scope: null, + pending: false + }; + return { + selectedFrame, + isPaused: (0, _selectors.isPaused)(state), + isLoading: generatedPending || originalPending, + why: (0, _selectors.getPauseReason)(state), + originalFrameScopes, + generatedFrameScopes + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Scopes); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/UtilsBar.js b/devtools/client/debugger/new/src/components/SecondaryPanes/UtilsBar.js new file mode 100644 index 000000000000..4c1d8d7eaf2e --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/UtilsBar.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _CommandBarButton = require("../shared/Button/CommandBarButton"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class UtilsBar extends _react.Component { + renderUtilButtons() { + return [(0, _CommandBarButton.debugBtn)(this.props.toggleShortcutsModal, "shortcuts", "active", L10N.getStr("shortcuts.buttonName"), false)]; + } + + render() { + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("command-bar bottom", { + vertical: !this.props.horizontal + }) + }, this.renderUtilButtons()); + } + +} + +exports.default = UtilsBar; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Workers.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Workers.js new file mode 100644 index 000000000000..400d96a9b20f --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Workers.js @@ -0,0 +1,64 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Workers = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _path = require("../../utils/path"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Workers extends _react.PureComponent { + renderWorkers(workers) { + const { + openWorkerToolbox + } = this.props; + return workers.map(worker => _react2.default.createElement("div", { + className: "worker", + key: worker.actor, + onClick: () => openWorkerToolbox(worker) + }, _react2.default.createElement("img", { + className: "domain" + }), (0, _path.basename)(worker.url))); + } + + renderNoWorkersPlaceholder() { + return _react2.default.createElement("div", { + className: "pane-info" + }, L10N.getStr("noWorkersText")); + } + + render() { + const { + workers + } = this.props; + return _react2.default.createElement("div", { + className: "pane workers-list" + }, workers && workers.size > 0 ? this.renderWorkers(workers) : this.renderNoWorkersPlaceholder()); + } + +} + +exports.Workers = Workers; + +const mapStateToProps = state => ({ + workers: (0, _selectors.getWorkers)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Workers); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/index.js b/devtools/client/debugger/new/src/components/SecondaryPanes/index.js new file mode 100644 index 000000000000..22eddae2ce3c --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/index.js @@ -0,0 +1,411 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var _actions = require("../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../../selectors/index"); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _prefs = require("../../utils/prefs"); + +var _Breakpoints = require("./Breakpoints"); + +var _Breakpoints2 = _interopRequireDefault(_Breakpoints); + +var _Expressions = require("./Expressions"); + +var _Expressions2 = _interopRequireDefault(_Expressions); + +var _devtoolsSplitter = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-splitter"]; + +var _devtoolsSplitter2 = _interopRequireDefault(_devtoolsSplitter); + +var _Frames = require("./Frames/index"); + +var _Frames2 = _interopRequireDefault(_Frames); + +var _EventListeners = require("./EventListeners"); + +var _EventListeners2 = _interopRequireDefault(_EventListeners); + +var _Workers = require("./Workers"); + +var _Workers2 = _interopRequireDefault(_Workers); + +var _Accordion = require("../shared/Accordion"); + +var _Accordion2 = _interopRequireDefault(_Accordion); + +var _CommandBar = require("./CommandBar"); + +var _CommandBar2 = _interopRequireDefault(_CommandBar); + +var _UtilsBar = require("./UtilsBar"); + +var _UtilsBar2 = _interopRequireDefault(_UtilsBar); + +var _FrameworkComponent = require("./FrameworkComponent"); + +var _FrameworkComponent2 = _interopRequireDefault(_FrameworkComponent); + +var _ReactComponentStack = require("./ReactComponentStack"); + +var _ReactComponentStack2 = _interopRequireDefault(_ReactComponentStack); + +var _Scopes = require("./Scopes"); + +var _Scopes2 = _interopRequireDefault(_Scopes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function debugBtn(onClick, type, className, tooltip) { + return _react2.default.createElement("button", { + onClick: onClick, + className: `${type} ${className}`, + key: type, + title: tooltip + }, _react2.default.createElement(_Svg2.default, { + name: type, + title: tooltip, + "aria-label": tooltip + })); +} + +class SecondaryPanes extends _react.Component { + constructor(props) { + super(props); + + this.onExpressionAdded = () => { + this.setState({ + showExpressionsInput: false + }); + }; + + this.state = { + showExpressionsInput: false + }; + } + + renderBreakpointsToggle() { + const { + toggleAllBreakpoints, + breakpoints, + breakpointsDisabled, + breakpointsLoading + } = this.props; + const isIndeterminate = !breakpointsDisabled && breakpoints.some(x => x.disabled); + + if (_prefs.features.skipPausing || breakpoints.size == 0) { + return null; + } + + const inputProps = { + type: "checkbox", + "aria-label": breakpointsDisabled ? L10N.getStr("breakpoints.enable") : L10N.getStr("breakpoints.disable"), + className: "breakpoints-toggle", + disabled: breakpointsLoading, + key: "breakpoints-toggle", + onChange: e => { + e.stopPropagation(); + toggleAllBreakpoints(!breakpointsDisabled); + }, + onClick: e => e.stopPropagation(), + checked: !breakpointsDisabled && !isIndeterminate, + ref: input => { + if (input) { + input.indeterminate = isIndeterminate; + } + }, + title: breakpointsDisabled ? L10N.getStr("breakpoints.enable") : L10N.getStr("breakpoints.disable") + }; + return _react2.default.createElement("input", inputProps); + } + + watchExpressionHeaderButtons() { + const { + expressions + } = this.props; + const buttons = []; + + if (expressions.size) { + buttons.push(debugBtn(evt => { + evt.stopPropagation(); + this.props.evaluateExpressions(); + }, "refresh", "refresh", L10N.getStr("watchExpressions.refreshButton"))); + } + + buttons.push(debugBtn(evt => { + if (_prefs.prefs.expressionsVisible) { + evt.stopPropagation(); + } + + this.setState({ + showExpressionsInput: true + }); + }, "plus", "plus", L10N.getStr("expressions.placeholder"))); + return buttons; + } + + getScopeItem() { + return { + header: L10N.getStr("scopes.header"), + className: "scopes-pane", + component: _react2.default.createElement(_Scopes2.default, null), + opened: _prefs.prefs.scopesVisible, + onToggle: opened => { + _prefs.prefs.scopesVisible = opened; + } + }; + } + + getComponentStackItem() { + return { + header: L10N.getStr("components.header"), + component: _react2.default.createElement(_ReactComponentStack2.default, null), + opened: _prefs.prefs.componentStackVisible, + onToggle: opened => { + _prefs.prefs.componentStackVisible = opened; + } + }; + } + + getComponentItem() { + const { + extra: { + react + } + } = this.props; + return { + header: react.displayName, + className: "component-pane", + component: _react2.default.createElement(_FrameworkComponent2.default, null), + opened: _prefs.prefs.componentVisible, + onToggle: opened => { + _prefs.prefs.componentVisible = opened; + } + }; + } + + getWatchItem() { + return { + header: L10N.getStr("watchExpressions.header"), + className: "watch-expressions-pane", + buttons: this.watchExpressionHeaderButtons(), + component: _react2.default.createElement(_Expressions2.default, { + showInput: this.state.showExpressionsInput, + onExpressionAdded: this.onExpressionAdded + }), + opened: _prefs.prefs.expressionsVisible, + onToggle: opened => { + _prefs.prefs.expressionsVisible = opened; + } + }; + } + + getCallStackItem() { + return { + header: L10N.getStr("callStack.header"), + className: "call-stack-pane", + component: _react2.default.createElement(_Frames2.default, null), + opened: _prefs.prefs.callStackVisible, + onToggle: opened => { + _prefs.prefs.callStackVisible = opened; + } + }; + } + + getWorkersItem() { + return { + header: L10N.getStr("workersHeader"), + className: "workers-pane", + component: _react2.default.createElement(_Workers2.default, null), + opened: _prefs.prefs.workersVisible, + onToggle: opened => { + _prefs.prefs.workersVisible = opened; + } + }; + } + + getBreakpointsItem() { + const { + shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions, + pauseOnExceptions + } = this.props; + return { + header: L10N.getStr("breakpoints.header"), + className: "breakpoints-pane", + buttons: [this.renderBreakpointsToggle()], + component: _react2.default.createElement(_Breakpoints2.default, { + shouldPauseOnExceptions: shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions: shouldPauseOnCaughtExceptions, + pauseOnExceptions: pauseOnExceptions + }), + opened: _prefs.prefs.breakpointsVisible, + onToggle: opened => { + _prefs.prefs.breakpointsVisible = opened; + } + }; + } + + getStartItems() { + const { + extra, + workers + } = this.props; + const items = []; + + if (this.props.horizontal) { + if (_prefs.features.workers && workers.size > 0) { + items.push(this.getWorkersItem()); + } + + items.push(this.getWatchItem()); + } + + items.push(this.getBreakpointsItem()); + + if (this.props.hasFrames) { + items.push(this.getCallStackItem()); + + if (this.props.horizontal) { + if (extra && extra.react) { + if (_prefs.features.componentStack && extra.react.componentStack.length > 1) { + items.push(this.getComponentStackItem()); + } + + items.push(this.getComponentItem()); + } + + items.push(this.getScopeItem()); + } + } + + if (_prefs.features.eventListeners) { + items.push({ + header: L10N.getStr("eventListenersHeader"), + className: "event-listeners-pane", + component: _react2.default.createElement(_EventListeners2.default, null) + }); + } + + return items.filter(item => item); + } + + renderHorizontalLayout() { + return _react2.default.createElement(_Accordion2.default, { + items: this.getItems() + }); + } + + getEndItems() { + const { + extra, + workers + } = this.props; + let items = []; + + if (this.props.horizontal) { + return []; + } + + if (_prefs.features.workers && workers.size > 0) { + items.push(this.getWorkersItem()); + } + + items.push(this.getWatchItem()); + + if (extra && extra.react) { + items.push(this.getComponentItem()); + } + + if (this.props.hasFrames) { + items = [...items, this.getScopeItem()]; + } + + return items; + } + + getItems() { + return [...this.getStartItems(), ...this.getEndItems()]; + } + + renderVerticalLayout() { + return _react2.default.createElement(_devtoolsSplitter2.default, { + initialSize: "300px", + minSize: 10, + maxSize: "50%", + splitterSize: 1, + startPanel: _react2.default.createElement(_Accordion2.default, { + items: this.getStartItems() + }), + endPanel: _react2.default.createElement(_Accordion2.default, { + items: this.getEndItems() + }) + }); + } + + renderUtilsBar() { + if (!_prefs.features.shortcuts) { + return; + } + + return _react2.default.createElement(_UtilsBar2.default, { + horizontal: this.props.horizontal, + toggleShortcutsModal: this.props.toggleShortcutsModal + }); + } + + render() { + return _react2.default.createElement("div", { + className: "secondary-panes-wrapper" + }, _react2.default.createElement(_CommandBar2.default, { + horizontal: this.props.horizontal + }), _react2.default.createElement("div", { + className: "secondary-panes" + }, this.props.horizontal ? this.renderHorizontalLayout() : this.renderVerticalLayout()), this.renderUtilsBar()); + } + +} + +SecondaryPanes.contextTypes = { + shortcuts: _propTypes2.default.object +}; + +const mapStateToProps = state => ({ + expressions: (0, _selectors.getExpressions)(state), + extra: (0, _selectors.getExtra)(state), + hasFrames: !!(0, _selectors.getTopFrame)(state), + breakpoints: (0, _selectors.getBreakpoints)(state), + breakpointsDisabled: (0, _selectors.getBreakpointsDisabled)(state), + breakpointsLoading: (0, _selectors.getBreakpointsLoading)(state), + isWaitingOnBreak: (0, _selectors.getIsWaitingOnBreak)(state), + shouldPauseOnExceptions: (0, _selectors.getShouldPauseOnExceptions)(state), + shouldPauseOnCaughtExceptions: (0, _selectors.getShouldPauseOnCaughtExceptions)(state), + workers: (0, _selectors.getWorkers)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SecondaryPanes); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build b/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build new file mode 100644 index 000000000000..7d1d54afab6b --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build @@ -0,0 +1,23 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'Frames', +] + +DevToolsModules( + 'Breakpoint.js', + 'Breakpoints.js', + 'BreakpointsContextMenu.js', + 'CommandBar.js', + 'EventListeners.js', + 'Expressions.js', + 'FrameworkComponent.js', + 'index.js', + 'ReactComponentStack.js', + 'Scopes.js', + 'UtilsBar.js', + 'Workers.js', +) diff --git a/devtools/client/debugger/new/src/components/ShortcutsModal.js b/devtools/client/debugger/new/src/components/ShortcutsModal.js new file mode 100644 index 000000000000..3621d0a6802d --- /dev/null +++ b/devtools/client/debugger/new/src/components/ShortcutsModal.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ShortcutsModal = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _Modal = require("./shared/Modal"); + +var _Modal2 = _interopRequireDefault(_Modal); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _text = require("../utils/text"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class ShortcutsModal extends _react.Component { + renderPrettyCombos(combo) { + return combo.split(" ").map(c => _react2.default.createElement("span", { + key: c, + className: "keystroke" + }, c)).reduce((prev, curr) => [prev, " + ", curr]); + } + + renderShorcutItem(title, combo) { + return _react2.default.createElement("li", null, _react2.default.createElement("span", null, title), _react2.default.createElement("span", null, this.renderPrettyCombos(combo))); + } + + renderEditorShortcuts() { + return _react2.default.createElement("ul", { + className: "shortcuts-list" + }, this.renderShorcutItem(L10N.getStr("shortcuts.toggleBreakpoint"), (0, _text.formatKeyShortcut)(L10N.getStr("toggleBreakpoint.key"))), this.renderShorcutItem(L10N.getStr("shortcuts.toggleCondPanel"), (0, _text.formatKeyShortcut)(L10N.getStr("toggleCondPanel.key")))); + } + + renderSteppingShortcuts() { + return _react2.default.createElement("ul", { + className: "shortcuts-list" + }, this.renderShorcutItem(L10N.getStr("shortcuts.pauseOrResume"), "F8"), this.renderShorcutItem(L10N.getStr("shortcuts.stepOver"), "F10"), this.renderShorcutItem(L10N.getStr("shortcuts.stepIn"), "F11"), this.renderShorcutItem(L10N.getStr("shortcuts.stepOut"), (0, _text.formatKeyShortcut)(L10N.getStr("stepOut.key")))); + } + + renderSearchShortcuts() { + return _react2.default.createElement("ul", { + className: "shortcuts-list" + }, this.renderShorcutItem(L10N.getStr("shortcuts.fileSearch"), (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"))), this.renderShorcutItem(L10N.getStr("shortcuts.searchAgain"), (0, _text.formatKeyShortcut)(L10N.getStr("sourceSearch.search.again.key2"))), this.renderShorcutItem(L10N.getStr("shortcuts.projectSearch"), (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key"))), this.renderShorcutItem(L10N.getStr("shortcuts.functionSearch"), (0, _text.formatKeyShortcut)(L10N.getStr("functionSearch.key"))), this.renderShorcutItem(L10N.getStr("shortcuts.gotoLine"), (0, _text.formatKeyShortcut)(L10N.getStr("gotoLineModal.key2")))); + } + + renderShortcutsContent() { + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("shortcuts-content", this.props.additionalClass) + }, _react2.default.createElement("div", { + className: "shortcuts-section" + }, _react2.default.createElement("h2", null, L10N.getStr("shortcuts.header.editor")), this.renderEditorShortcuts()), _react2.default.createElement("div", { + className: "shortcuts-section" + }, _react2.default.createElement("h2", null, L10N.getStr("shortcuts.header.stepping")), this.renderSteppingShortcuts()), _react2.default.createElement("div", { + className: "shortcuts-section" + }, _react2.default.createElement("h2", null, L10N.getStr("shortcuts.header.search")), this.renderSearchShortcuts())); + } + + render() { + const { + enabled + } = this.props; + + if (!enabled) { + return null; + } + + return _react2.default.createElement(_Modal2.default, { + "in": enabled, + additionalClass: "shortcuts-modal", + handleClose: this.props.handleClose + }, this.renderShortcutsContent()); + } + +} + +exports.ShortcutsModal = ShortcutsModal; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/WelcomeBox.js b/devtools/client/debugger/new/src/components/WelcomeBox.js new file mode 100644 index 000000000000..531d31be11ab --- /dev/null +++ b/devtools/client/debugger/new/src/components/WelcomeBox.js @@ -0,0 +1,91 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WelcomeBox = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _actions = require("../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../selectors/index"); + +var _text = require("../utils/text"); + +var _PaneToggle = require("./shared/Button/PaneToggle"); + +var _PaneToggle2 = _interopRequireDefault(_PaneToggle); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class WelcomeBox extends _react.Component { + renderToggleButton() { + const { + horizontal, + endPanelCollapsed, + togglePaneCollapse + } = this.props; + + if (horizontal) { + return; + } + + return _react2.default.createElement(_PaneToggle2.default, { + position: "end", + collapsed: !endPanelCollapsed, + horizontal: horizontal, + handleClick: togglePaneCollapse + }); + } + + render() { + const searchSourcesShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2")); + const searchProjectShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key")); + const searchSourcesLabel = L10N.getStr("welcome.search").substring(2); + const searchProjectLabel = L10N.getStr("welcome.findInFiles").substring(2); + const { + setActiveSearch, + openQuickOpen + } = this.props; + return _react2.default.createElement("div", { + className: "welcomebox" + }, _react2.default.createElement("div", { + className: "alignlabel" + }, _react2.default.createElement("div", { + className: "shortcutFunction" + }, _react2.default.createElement("p", { + className: "welcomebox__searchSources", + onClick: () => openQuickOpen() + }, _react2.default.createElement("span", { + className: "shortcutKey" + }, searchSourcesShortcut), _react2.default.createElement("span", { + className: "shortcutLabel" + }, searchSourcesLabel)), _react2.default.createElement("p", { + className: "welcomebox__searchProject", + onClick: setActiveSearch.bind(null, "project") + }, _react2.default.createElement("span", { + className: "shortcutKey" + }, searchProjectShortcut), _react2.default.createElement("span", { + className: "shortcutLabel" + }, searchProjectLabel))), this.renderToggleButton())); + } + +} + +exports.WelcomeBox = WelcomeBox; + +const mapStateToProps = state => ({ + endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end") +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(WelcomeBox); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/moz.build b/devtools/client/debugger/new/src/components/moz.build new file mode 100644 index 000000000000..7e2bdaa1e7dc --- /dev/null +++ b/devtools/client/debugger/new/src/components/moz.build @@ -0,0 +1,20 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'Editor', + 'PrimaryPanes', + 'SecondaryPanes', + 'shared', + 'test', +] + +DevToolsModules( + 'App.js', + 'ProjectSearch.js', + 'QuickOpenModal.js', + 'ShortcutsModal.js', + 'WelcomeBox.js', +) diff --git a/devtools/client/debugger/new/src/components/shared/Accordion.js b/devtools/client/debugger/new/src/components/shared/Accordion.js new file mode 100644 index 000000000000..76c1ba620290 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Accordion.js @@ -0,0 +1,76 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Accordion extends _react.Component { + constructor(props) { + super(props); + + this.renderContainer = (item, i) => { + const { + opened + } = item; + return _react2.default.createElement("li", { + role: "listitem", + className: item.className, + key: i + }, _react2.default.createElement("h2", { + className: "_header", + tabIndex: "0", + onClick: () => this.handleHeaderClick(i) + }, _react2.default.createElement(_Svg2.default, { + name: "arrow", + className: opened ? "expanded" : "" + }), item.header, item.buttons ? _react2.default.createElement("div", { + className: "header-buttons", + tabIndex: "-1" + }, item.buttons) : null), opened && _react2.default.createElement("div", { + className: "_content" + }, (0, _react.cloneElement)(item.component, item.componentProps || {}))); + }; + + this.state = { + opened: props.items.map(item => item.opened), + created: [] + }; + } + + handleHeaderClick(i) { + const item = this.props.items[i]; + const opened = !item.opened; + item.opened = opened; + + if (item.onToggle) { + item.onToggle(opened); + } // We force an update because otherwise the accordion + // would not re-render + + + this.forceUpdate(); + } + + render() { + return _react2.default.createElement("ul", { + role: "list", + className: "accordion" + }, this.props.items.map(this.renderContainer)); + } + +} + +exports.default = Accordion; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Badge.js b/devtools/client/debugger/new/src/components/shared/Badge.js new file mode 100644 index 000000000000..f4d4dcc75e4c --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Badge.js @@ -0,0 +1,22 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const Badge = ({ + children +}) => _react2.default.createElement("div", { + className: "badge text-white text-center" +}, children); + +exports.default = Badge; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/BracketArrow.js b/devtools/client/debugger/new/src/components/shared/BracketArrow.js new file mode 100644 index 000000000000..fdc32b0e94f6 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/BracketArrow.js @@ -0,0 +1,36 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const BracketArrow = ({ + orientation, + left, + top, + bottom +}) => { + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("bracket-arrow", orientation || "up"), + style: { + left, + top, + bottom + } + }); +}; + +exports.default = BracketArrow; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Button/Close.js b/devtools/client/debugger/new/src/components/shared/Button/Close.js new file mode 100644 index 000000000000..a64c4c084541 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Button/Close.js @@ -0,0 +1,30 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function CloseButton({ + handleClick, + buttonClass, + tooltip +}) { + return _react2.default.createElement("button", { + className: buttonClass ? `close-btn ${buttonClass}` : "close-btn", + onClick: handleClick, + title: tooltip + }, _react2.default.createElement("img", { + className: "close" + })); +} + +exports.default = CloseButton; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Button/CommandBarButton.js b/devtools/client/debugger/new/src/components/shared/Button/CommandBarButton.js new file mode 100644 index 000000000000..1f24f922f66a --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Button/CommandBarButton.js @@ -0,0 +1,49 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.debugBtn = debugBtn; + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function debugBtn(onClick, type, className, tooltip, disabled = false, ariaPressed = false) { + return _react2.default.createElement(CommandBarButton, { + className: (0, _classnames2.default)(type, className), + disabled: disabled, + key: type, + onClick: onClick, + pressed: ariaPressed, + title: tooltip + }, _react2.default.createElement("img", { + className: type + })); +} + +const CommandBarButton = props => { + const { + children, + className, + pressed = false + } = props, + rest = _objectWithoutProperties(props, ["children", "className", "pressed"]); + + return _react2.default.createElement("button", _extends({ + "aria-pressed": pressed, + className: (0, _classnames2.default)("command-bar-button", className) + }, rest), children); +}; + +exports.default = CommandBarButton; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js b/devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js new file mode 100644 index 000000000000..efabc748e6dd --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js @@ -0,0 +1,54 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _CommandBarButton = require("./CommandBarButton"); + +var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class PaneToggleButton extends _react.PureComponent { + render() { + const { + position, + collapsed, + horizontal, + handleClick + } = this.props; + const title = !collapsed ? L10N.getStr("expandPanes") : L10N.getStr("collapsePanes"); + return _react2.default.createElement(_CommandBarButton2.default, { + className: (0, _classnames2.default)("toggle-button", position, { + collapsed, + vertical: !horizontal + }), + onClick: () => handleClick(position, collapsed), + title: title + }, _react2.default.createElement(_Svg2.default, { + name: "togglePanes" + })); + } + +} + +PaneToggleButton.defaultProps = { + horizontal: false +}; +exports.default = PaneToggleButton; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Button/moz.build b/devtools/client/debugger/new/src/components/shared/Button/moz.build new file mode 100644 index 000000000000..62a3f6e69043 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Button/moz.build @@ -0,0 +1,14 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'Close.js', + 'CommandBarButton.js', + 'PaneToggle.js', +) diff --git a/devtools/client/debugger/new/src/components/shared/Dropdown.js b/devtools/client/debugger/new/src/components/shared/Dropdown.js new file mode 100644 index 000000000000..cda04f636649 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Dropdown.js @@ -0,0 +1,68 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Dropdown = undefined; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Dropdown extends _react.Component { + constructor(props) { + super(props); + + this.toggleDropdown = e => { + this.setState(prevState => ({ + dropdownShown: !prevState.dropdownShown + })); + }; + + this.state = { + dropdownShown: false + }; + } + + renderPanel() { + return _react2.default.createElement("div", { + className: "dropdown", + onClick: this.toggleDropdown, + style: { + display: this.state.dropdownShown ? "block" : "none" + } + }, this.props.panel); + } + + renderButton() { + return _react2.default.createElement("button", { + className: "dropdown-button", + onClick: this.toggleDropdown + }, this.props.icon); + } + + renderMask() { + return _react2.default.createElement("div", { + className: "dropdown-mask", + onClick: this.toggleDropdown, + style: { + display: this.state.dropdownShown ? "block" : "none" + } + }); + } + + render() { + return _react2.default.createElement("div", { + className: "dropdown-block" + }, this.renderPanel(), this.renderButton(), this.renderMask()); + } + +} + +exports.Dropdown = Dropdown; +exports.default = Dropdown; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/ManagedTree.js b/devtools/client/debugger/new/src/components/shared/ManagedTree.js new file mode 100644 index 000000000000..d67c39c1590e --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/ManagedTree.js @@ -0,0 +1,155 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +const { + Tree +} = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-components"]; + +class ManagedTree extends _react.Component { + constructor(props) { + super(props); + + this.setExpanded = (item, isExpanded, shouldIncludeChildren) => { + const expandItem = i => { + const path = this.props.getPath(i); + + if (isExpanded) { + expanded.add(path); + } else { + expanded.delete(path); + } + }; + + const { + expanded + } = this.state; + expandItem(item); + + if (shouldIncludeChildren) { + let parents = [item]; + + while (parents.length) { + const children = []; + + for (const parent of parents) { + if (parent.contents && parent.contents.length) { + for (const child of parent.contents) { + expandItem(child); + children.push(child); + } + } + } + + parents = children; + } + } + + this.setState({ + expanded + }); + + if (isExpanded && this.props.onExpand) { + this.props.onExpand(item, expanded); + } else if (!isExpanded && this.props.onCollapse) { + this.props.onCollapse(item, expanded); + } + }; + + this.focusItem = item => { + if (!this.props.disabledFocus && this.state.focusedItem !== item) { + this.setState({ + focusedItem: item + }); + + if (this.props.onFocus) { + this.props.onFocus(item); + } + } + }; + + this.state = { + expanded: props.expanded || new Set(), + focusedItem: null + }; + } + + componentWillReceiveProps(nextProps) { + const { + listItems, + highlightItems, + focused + } = this.props; + + if (nextProps.listItems && nextProps.listItems != listItems && nextProps.listItems.length) { + this.expandListItems(nextProps.listItems); + } + + if (nextProps.highlightItems && nextProps.highlightItems != highlightItems && nextProps.highlightItems.length) { + this.highlightItem(nextProps.highlightItems); + } + + if (nextProps.focused && nextProps.focused !== focused) { + this.focusItem(nextProps.focused); + } + } + + expandListItems(listItems) { + const { + expanded + } = this.state; + listItems.forEach(item => expanded.add(this.props.getPath(item))); + this.focusItem(listItems[0]); + this.setState({ + expanded + }); + } + + highlightItem(highlightItems) { + const { + expanded + } = this.state; // This file is visible, so we highlight it. + + if (expanded.has(this.props.getPath(highlightItems[0]))) { + this.focusItem(highlightItems[0]); + } else { + // Look at folders starting from the top-level until finds a + // closed folder and highlights this folder + const index = highlightItems.reverse().findIndex(item => !expanded.has(this.props.getPath(item))); + this.focusItem(highlightItems[index]); + } + } + + render() { + const { + expanded, + focusedItem + } = this.state; + return _react2.default.createElement("div", { + className: "managed-tree" + }, _react2.default.createElement(Tree, _extends({}, this.props, { + isExpanded: item => expanded.has(this.props.getPath(item)), + focused: focusedItem, + getKey: this.props.getPath, + onExpand: item => this.setExpanded(item, true, false), + onCollapse: item => this.setExpanded(item, false, false), + onFocus: this.focusItem, + renderItem: (...args) => this.props.renderItem(...args, { + setExpanded: this.setExpanded + }) + }))); + } + +} + +exports.default = ManagedTree; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Modal.js b/devtools/client/debugger/new/src/components/shared/Modal.js new file mode 100644 index 000000000000..6149adaa3d40 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Modal.js @@ -0,0 +1,79 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Modal = exports.transitionTimeout = undefined; +exports.default = Slide; + +var _propTypes = require("devtools/client/shared/vendor/react-prop-types"); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _Transition = require("devtools/client/debugger/new/dist/vendors").vendored["react-transition-group/Transition"]; + +var _Transition2 = _interopRequireDefault(_Transition); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const transitionTimeout = exports.transitionTimeout = 175; + +class Modal extends _react2.default.Component { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.onClick = e => { + e.stopPropagation(); + }, _temp; + } + + render() { + const { + additionalClass, + children, + handleClose, + status + } = this.props; + return _react2.default.createElement("div", { + className: "modal-wrapper", + onClick: handleClose + }, _react2.default.createElement("div", { + className: (0, _classnames2.default)("modal", additionalClass, status), + onClick: this.onClick + }, children)); + } + +} + +exports.Modal = Modal; +Modal.contextTypes = { + shortcuts: _propTypes2.default.object +}; + +function Slide({ + in: inProp, + children, + additionalClass, + handleClose +}) { + return _react2.default.createElement(_Transition2.default, { + "in": inProp, + timeout: transitionTimeout, + appear: true + }, status => _react2.default.createElement(Modal, { + status: status, + additionalClass: additionalClass, + handleClose: handleClose + }, children)); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Popover.js b/devtools/client/debugger/new/src/components/shared/Popover.js new file mode 100644 index 000000000000..1d9ee2c2cab9 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Popover.js @@ -0,0 +1,309 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _BracketArrow = require("./BracketArrow"); + +var _BracketArrow2 = _interopRequireDefault(_BracketArrow); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class Popover extends _react.Component { + constructor(props) { + super(props); + + this.calculateTopForRightOrientation = (target, editor, popover) => { + if (popover.height < editor.height) { + const rightOrientationTop = target.top - popover.height / 2; + + if (rightOrientationTop < editor.top) { + return editor.top; + } + + const rightOrientationBottom = rightOrientationTop + popover.height; + + if (rightOrientationBottom > editor.bottom) { + return editor.bottom - popover.height; + } + + return rightOrientationTop; + } + + return 0; + }; + + this.calculateTop = (target, editor, popover, orientation) => { + if (orientation === "down") { + return target.bottom; + } + + if (orientation === "up") { + return target.top - popover.height; + } + + return this.calculateTopForRightOrientation(target, editor, popover); + }; + + this.onMouseLeave = e => { + const { + onMouseLeave + } = this.props; + + if (/^(bracket-arrow|gap)$/.test(e.currentTarget.className)) { + return; + } + + onMouseLeave(e); + }; + + this.state = { + left: 0, + top: 0, + targetMid: { + x: 0, + y: 0 + }, + orientation: "up" + }; + } + + componentDidMount() { + const { + type + } = this.props; + const { + left, + top, + orientation, + targetMid + } = type == "popover" ? this.getPopoverCoords() : this.getTooltipCoords(); // eslint-disable-next-line react/no-did-mount-set-state + + this.setState({ + left, + top, + orientation, + targetMid + }); + } + + calculateLeft(target, editor, popover, orientation) { + const estimatedLeft = target.left; + const estimatedRight = estimatedLeft + popover.width; + const isOverflowingRight = estimatedRight > editor.right; + + if (orientation === "right") { + return target.left + target.width + 10; + } + + if (isOverflowingRight) { + const adjustedLeft = editor.right - popover.width - 8; + return adjustedLeft; + } + + return estimatedLeft; + } + + calculateOrientation(target, editor, popover) { + const estimatedBottom = target.bottom + popover.height; + + if (editor.bottom > estimatedBottom) { + return "down"; + } + + const upOrientationTop = target.top - popover.height; + + if (upOrientationTop > editor.top) { + return "up"; + } + + return "right"; + } + + getPopoverCoords() { + if (this.$popover && this.props.editorRef) { + const popover = this.$popover; + const editor = this.props.editorRef; + const popoverRect = popover.getBoundingClientRect(); + const editorRect = editor.getBoundingClientRect(); + const targetRect = this.props.targetPosition; + const orientation = this.calculateOrientation(targetRect, editorRect, popoverRect); + const top = this.calculateTop(targetRect, editorRect, popoverRect, orientation); + const popoverLeft = this.calculateLeft(targetRect, editorRect, popoverRect, orientation); + let targetMid; + + if (orientation === "right") { + targetMid = { + x: -14, + y: targetRect.top - top - 2 + }; + } else { + targetMid = { + x: targetRect.left - popoverLeft + targetRect.width / 2 - 8, + y: 0 + }; + } + + return { + left: popoverLeft, + top, + orientation, + targetMid + }; + } + + return { + left: 0, + top: 0, + orientation: "down", + targetMid: { + x: 0, + y: 0 + } + }; + } + + getTooltipCoords() { + if (this.$tooltip && this.props.editorRef) { + const tooltip = this.$tooltip; + const editor = this.props.editorRef; + const tooltipRect = tooltip.getBoundingClientRect(); + const editorRect = editor.getBoundingClientRect(); + const targetRect = this.props.targetPosition; + const left = this.calculateLeft(targetRect, editorRect, tooltipRect); + const top = targetRect.top - tooltipRect.height; + return { + left, + top, + orientation: "up", + targetMid: { + x: 0, + y: 0 + } + }; + } + + return { + left: 0, + top: 0, + orientation: "up", + targetMid: { + x: 0, + y: 0 + } + }; + } + + getChildren() { + const { + children + } = this.props; + const { + orientation + } = this.state; + + const gap = _react2.default.createElement("div", { + className: "gap", + key: "gap" + }); + + return orientation === "up" ? [children, gap] : [gap, children]; + } + + getPopoverArrow(orientation, left, top) { + const arrowProps = {}; + + if (orientation === "up") { + Object.assign(arrowProps, { + orientation: "down", + bottom: 5, + left + }); + } else if (orientation === "down") { + Object.assign(arrowProps, { + orientation: "up", + top: -7, + left + }); + } else { + Object.assign(arrowProps, { + orientation: "left", + top, + left: -14 + }); + } + + return _react2.default.createElement(_BracketArrow2.default, arrowProps); + } + + renderPopover() { + const { + top, + left, + orientation, + targetMid + } = this.state; + const arrow = this.getPopoverArrow(orientation, targetMid.x, targetMid.y); + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("popover", `orientation-${orientation}`, { + up: orientation === "up" + }), + onMouseLeave: this.onMouseLeave, + style: { + top, + left + }, + ref: c => this.$popover = c + }, arrow, this.getChildren()); + } + + renderTooltip() { + const { + onMouseLeave + } = this.props; + const { + top, + left + } = this.state; + return _react2.default.createElement("div", { + className: "tooltip", + onMouseLeave: onMouseLeave, + style: { + top, + left + }, + ref: c => this.$tooltip = c + }, this.getChildren()); + } + + render() { + const { + type + } = this.props; + + if (type === "tooltip") { + return this.renderTooltip(); + } + + return this.renderPopover(); + } + +} + +Popover.defaultProps = { + onMouseLeave: () => {}, + type: "popover" +}; +exports.default = Popover; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/PreviewFunction.js b/devtools/client/debugger/new/src/components/shared/PreviewFunction.js new file mode 100644 index 000000000000..b9e1bc184b2b --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/PreviewFunction.js @@ -0,0 +1,60 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _frames = require("../../utils/pause/frames/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getFunctionName(func) { + const name = func.userDisplayName || func.displayName || func.name; + return (0, _frames.simplifyDisplayName)(name); +} + +class PreviewFunction extends _react.Component { + renderFunctionName(func) { + const name = getFunctionName(func); + return _react2.default.createElement("span", { + className: "function-name" + }, name); + } + + renderParams(func) { + const { + parameterNames = [] + } = func; + const params = parameterNames.filter(i => i).map(param => _react2.default.createElement("span", { + className: "param", + key: param + }, param)); + const commas = (0, _lodash.times)(params.length - 1).map((_, i) => _react2.default.createElement("span", { + className: "delimiter", + key: i + }, ", ")); + return (0, _lodash.flatten)((0, _lodash.zip)(params, commas)); + } + + render() { + return _react2.default.createElement("span", { + className: "function-signature" + }, this.renderFunctionName(this.props.func), _react2.default.createElement("span", { + className: "paren" + }, "("), this.renderParams(this.props.func), _react2.default.createElement("span", { + className: "paren" + }, ")")); + } + +} + +exports.default = PreviewFunction; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/ResultList.js b/devtools/client/debugger/new/src/components/shared/ResultList.js new file mode 100644 index 000000000000..5d889b1900d0 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/ResultList.js @@ -0,0 +1,81 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +class ResultList extends _react.Component { + constructor(props) { + super(props); + + _initialiseProps.call(this); + } + + render() { + const { + size, + items, + role + } = this.props; + return _react2.default.createElement("ul", { + className: (0, _classnames2.default)("result-list", size), + id: "result-list", + role: role, + "aria-live": "polite" + }, items.map(this.renderListItem)); + } + +} + +exports.default = ResultList; +ResultList.defaultProps = { + size: "small", + role: "listbox" +}; + +var _initialiseProps = function () { + this.renderListItem = (item, index) => { + if (item.value === "/" && item.title === "") { + item.title = "(index)"; + } + + const { + selectItem, + selected + } = this.props; + const props = { + onClick: event => selectItem(event, item, index), + key: `${item.id}${item.value}${index}`, + ref: String(index), + title: item.value, + "aria-labelledby": `${item.id}-title`, + "aria-describedby": `${item.id}-subtitle`, + role: "option", + className: (0, _classnames2.default)("result-item", { + selected: index === selected + }) + }; + return _react2.default.createElement("li", props, item.icon && _react2.default.createElement("div", null, _react2.default.createElement("img", { + className: item.icon + })), _react2.default.createElement("div", { + id: `${item.id}-title`, + className: "title" + }, item.title), _react2.default.createElement("div", { + id: `${item.id}-subtitle`, + className: "subtitle" + }, item.subtitle)); + }; +}; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/SearchInput.js b/devtools/client/debugger/new/src/components/shared/SearchInput.js new file mode 100644 index 000000000000..ed8f25bb46f0 --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/SearchInput.js @@ -0,0 +1,189 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _Close = require("./Button/Close"); + +var _Close2 = _interopRequireDefault(_Close); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const arrowBtn = (onClick, type, className, tooltip) => { + const props = { + className, + key: type, + onClick, + title: tooltip, + type + }; + return _react2.default.createElement("button", props, _react2.default.createElement(_Svg2.default, { + name: type + })); +}; + +class SearchInput extends _react.Component { + constructor(props) { + super(props); + + this.onFocus = e => { + const { + onFocus + } = this.props; + this.setState({ + inputFocused: true + }); + + if (onFocus) { + onFocus(e); + } + }; + + this.onBlur = e => { + const { + onBlur + } = this.props; + this.setState({ + inputFocused: false + }); + + if (onBlur) { + onBlur(e); + } + }; + + this.state = { + inputFocused: false + }; + } + + componentDidMount() { + this.setFocus(); + } + + componentDidUpdate(prevProps) { + if (this.props.shouldFocus && !prevProps.shouldFocus) { + this.setFocus(); + } + } + + setFocus() { + if (this.$input) { + const input = this.$input; + input.focus(); + + if (!input.value) { + return; + } // omit prefix @:# from being selected + + + const selectStartPos = this.props.hasPrefix ? 1 : 0; + input.setSelectionRange(selectStartPos, input.value.length + 1); + } + } + + renderSvg() { + const svgName = this.props.showErrorEmoji ? "sad-face" : "magnifying-glass"; + return _react2.default.createElement(_Svg2.default, { + name: svgName + }); + } + + renderArrowButtons() { + const { + handleNext, + handlePrev + } = this.props; + return [arrowBtn(handleNext, "arrow-down", (0, _classnames2.default)("nav-btn", "next"), L10N.getFormatStr("editor.searchResults.nextResult")), arrowBtn(handlePrev, "arrow-up", (0, _classnames2.default)("nav-btn", "prev"), L10N.getFormatStr("editor.searchResults.prevResult"))]; + } + + renderNav() { + const { + count, + handleNext, + handlePrev + } = this.props; + + if (!handleNext && !handlePrev || !count || count == 1) { + return; + } + + return _react2.default.createElement("div", { + className: "search-nav-buttons" + }, this.renderArrowButtons()); + } + + render() { + const { + expanded, + handleClose, + onChange, + onKeyDown, + onKeyUp, + placeholder, + query, + selectedItemId, + showErrorEmoji, + size, + summaryMsg + } = this.props; + const inputProps = { + className: (0, _classnames2.default)({ + empty: showErrorEmoji + }), + onChange, + onKeyDown, + onKeyUp, + onFocus: e => this.onFocus(e), + onBlur: e => this.onBlur(e), + "aria-autocomplete": "list", + "aria-controls": "result-list", + "aria-activedescendant": expanded && selectedItemId ? `${selectedItemId}-title` : "", + placeholder, + value: query, + spellCheck: false, + ref: c => this.$input = c + }; + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("search-shadow", { + focused: this.state.inputFocused + }) + }, _react2.default.createElement("div", { + className: (0, _classnames2.default)("search-field", size), + role: "combobox", + "aria-haspopup": "listbox", + "aria-owns": "result-list", + "aria-expanded": expanded + }, this.renderSvg(), _react2.default.createElement("input", inputProps), summaryMsg && _react2.default.createElement("div", { + className: "summary" + }, summaryMsg), this.renderNav(), _react2.default.createElement(_Close2.default, { + handleClick: handleClose, + buttonClass: size + }))); + } + +} + +SearchInput.defaultProps = { + expanded: false, + hasPrefix: false, + selectedItemId: "", + size: "" +}; +exports.default = SearchInput; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Svg.js b/devtools/client/debugger/new/src/components/shared/Svg.js new file mode 100644 index 000000000000..e5b418cb128d --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/Svg.js @@ -0,0 +1,20 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; + +var _Svg2 = _interopRequireDefault(_Svg); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * This file maps the SVG React Components in the assets/images directory. + */ +exports.default = _Svg2.default; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/moz.build b/devtools/client/debugger/new/src/components/shared/moz.build new file mode 100644 index 000000000000..cc8b0f240c0b --- /dev/null +++ b/devtools/client/debugger/new/src/components/shared/moz.build @@ -0,0 +1,22 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'Button', +] + +DevToolsModules( + 'Accordion.js', + 'Badge.js', + 'BracketArrow.js', + 'Dropdown.js', + 'ManagedTree.js', + 'Modal.js', + 'Popover.js', + 'PreviewFunction.js', + 'ResultList.js', + 'SearchInput.js', + 'Svg.js', +) diff --git a/devtools/client/debugger/new/src/components/test/Outline.spec.js b/devtools/client/debugger/new/src/components/test/Outline.spec.js new file mode 100644 index 000000000000..22f73dc7368e --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/Outline.spec.js @@ -0,0 +1,316 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _enzyme = require("enzyme/index"); + +var _Outline = require("../../components/PrimaryPanes/Outline"); + +var _Outline2 = _interopRequireDefault(_Outline); + +var _testHead = require("../../utils/test-head"); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _clipboard = require("../../utils/clipboard"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +jest.mock("devtools-contextmenu", () => ({ + showMenu: jest.fn() +})); +jest.mock("../../utils/clipboard", () => ({ + copyToTheClipboard: jest.fn() +})); +const sourceId = "id"; +const mockFunctionText = "mock function text"; + +function generateDefaults(overrides) { + return _objectSpread({ + selectLocation: jest.genMockFunction(), + selectedSource: { + get: () => sourceId + }, + getFunctionText: jest.fn().mockReturnValue(mockFunctionText), + flashLineRange: jest.fn(), + isHidden: false, + symbols: {}, + selectedLocation: { + sourceId: sourceId + }, + onAlphabetizeClick: jest.fn() + }, overrides); +} + +function render(overrides = {}) { + const props = generateDefaults(overrides); + const component = (0, _enzyme.shallow)(_react2.default.createElement(_Outline2.default.WrappedComponent, props)); + const instance = component.instance(); + return { + component, + props, + instance + }; +} + +describe("Outline", () => { + afterEach(() => { + _clipboard.copyToTheClipboard.mockClear(); + + _devtoolsContextmenu.showMenu.mockClear(); + }); + it("renders a list of functions when properties change", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("my_example_function1", 21), (0, _testHead.makeSymbolDeclaration)("my_example_function2", 22)] + }; + const { + component + } = render({ + symbols + }); + expect(component).toMatchSnapshot(); + }); + it("selects a line of code in the current file on click", async () => { + const startLine = 12; + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("my_example_function", startLine)] + }; + const { + component, + props + } = render({ + symbols + }); + const { + selectLocation + } = props; + const listItem = component.find("li").first(); + listItem.simulate("click"); + expect(selectLocation).toHaveBeenCalledWith({ + line: startLine, + sourceId + }); + }); + describe("renders outline", () => { + describe("renders loading", () => { + it("if symbols is not defined", () => { + const { + component + } = render({ + symbols: null + }); + expect(component).toMatchSnapshot(); + }); + it("if symbols are loading", () => { + const { + component + } = render({ + symbols: { + loading: true + } + }); + expect(component).toMatchSnapshot(); + }); + }); + it("renders ignore anonymous functions", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("my_example_function1", 21), (0, _testHead.makeSymbolDeclaration)("anonymous", 25)] + }; + const { + component + } = render({ + symbols + }); + expect(component).toMatchSnapshot(); + }); + describe("renders placeholder", () => { + it("`No File Selected` if selectedSource is not defined", async () => { + const { + component + } = render({ + selectedSource: null + }); + expect(component).toMatchSnapshot(); + }); + it("`No functions` if all func are anonymous", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("anonymous", 25), (0, _testHead.makeSymbolDeclaration)("anonymous", 30)] + }; + const { + component + } = render({ + symbols + }); + expect(component).toMatchSnapshot(); + }); + it("`No functions` if symbols has no func", async () => { + const symbols = { + functions: [] + }; + const { + component + } = render({ + symbols + }); + expect(component).toMatchSnapshot(); + }); + }); + it("sorts functions alphabetically by function name", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("c_function", 25), (0, _testHead.makeSymbolDeclaration)("x_function", 30), (0, _testHead.makeSymbolDeclaration)("a_function", 70)] + }; + const { + component + } = render({ + symbols: symbols, + alphabetizeOutline: true + }); + expect(component).toMatchSnapshot(); + }); + it("calls onAlphabetizeClick when sort button is clicked", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("example_function", 25)] + }; + const { + component, + props + } = render({ + symbols + }); + await component.find(".outline-footer").find("button").simulate("click", {}); + expect(props.onAlphabetizeClick).toHaveBeenCalled(); + }); + it("renders functions by function class", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("x_function", 25, 26, "x_klass"), (0, _testHead.makeSymbolDeclaration)("a2_function", 30, 31, "a_klass"), (0, _testHead.makeSymbolDeclaration)("a1_function", 70, 71, "a_klass")], + classes: [(0, _testHead.makeSymbolDeclaration)("x_klass", 24, 27), (0, _testHead.makeSymbolDeclaration)("a_klass", 29, 72)] + }; + const { + component + } = render({ + symbols: symbols + }); + expect(component).toMatchSnapshot(); + }); + it("renders functions by function class, alphabetically", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("x_function", 25, 26, "x_klass"), (0, _testHead.makeSymbolDeclaration)("a2_function", 30, 31, "a_klass"), (0, _testHead.makeSymbolDeclaration)("a1_function", 70, 71, "a_klass")], + classes: [(0, _testHead.makeSymbolDeclaration)("x_klass", 24, 27), (0, _testHead.makeSymbolDeclaration)("a_klass", 29, 72)] + }; + const { + component + } = render({ + symbols: symbols, + alphabetizeOutline: true + }); + expect(component).toMatchSnapshot(); + }); + it("selects class on click on class headline", async () => { + const symbols = { + functions: [(0, _testHead.makeSymbolDeclaration)("x_function", 25, 26, "x_klass")], + classes: [(0, _testHead.makeSymbolDeclaration)("x_klass", 24, 27)] + }; + const { + component, + props + } = render({ + symbols: symbols + }); + await component.find("h2").simulate("click", {}); + expect(props.selectLocation).toHaveBeenCalledWith({ + line: 24, + sourceId: sourceId + }); + }); + it("does not select an item if selectedSource is not defined", async () => { + const { + instance, + props + } = render({ + selectedSource: null + }); + await instance.selectItem({}); + expect(props.selectLocation).not.toHaveBeenCalled(); + }); + }); + describe("onContextMenu of Outline", () => { + it("is called onContextMenu for each item", async () => { + const event = { + event: "oncontextmenu" + }; + const fn = (0, _testHead.makeSymbolDeclaration)("exmple_function", 2); + const symbols = { + functions: [fn] + }; + const { + component, + instance + } = render({ + symbols + }); + instance.onContextMenu = jest.fn(() => {}); + await component.find(".outline-list__element").simulate("contextmenu", event); + expect(instance.onContextMenu).toHaveBeenCalledWith(event, fn); + }); + it("does not show menu with no selected source", async () => { + const mockEvent = { + preventDefault: jest.fn(), + stopPropagation: jest.fn() + }; + const { + instance + } = render({ + selectedSource: null + }); + await instance.onContextMenu(mockEvent, {}); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + expect(mockEvent.stopPropagation).toHaveBeenCalled(); + expect(_devtoolsContextmenu.showMenu).not.toHaveBeenCalled(); + }); + it("shows menu to copy func, copies to clipboard on click", async () => { + const startLine = 12; + const endLine = 21; + const func = (0, _testHead.makeSymbolDeclaration)("my_example_function", startLine, endLine); + const symbols = { + functions: [func] + }; + const mockEvent = { + preventDefault: jest.fn(), + stopPropagation: jest.fn() + }; + const { + instance, + props + } = render({ + symbols + }); + await instance.onContextMenu(mockEvent, func); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + expect(mockEvent.stopPropagation).toHaveBeenCalled(); + const expectedMenuOptions = [{ + accesskey: "F", + click: expect.any(Function), + disabled: false, + id: "node-menu-copy-function", + label: "Copy function" + }]; + expect(props.getFunctionText).toHaveBeenCalledWith(12); + expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, expectedMenuOptions); + + _devtoolsContextmenu.showMenu.mock.calls[0][1][0].click(); + + expect(_clipboard.copyToTheClipboard).toHaveBeenCalledWith(mockFunctionText); + expect(props.flashLineRange).toHaveBeenCalledWith({ + end: endLine, + sourceId: sourceId, + start: startLine + }); + }); + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js b/devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js new file mode 100644 index 000000000000..c5bf9a2c66bd --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js @@ -0,0 +1,248 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _enzyme = require("enzyme/index"); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var _ProjectSearch = require("../ProjectSearch"); + +var _projectTextSearch = require("../../reducers/project-text-search"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const hooks = { + on: [], + off: [] +}; +const shortcuts = { + dispatch(eventName) { + hooks.on.forEach(hook => { + if (hook.event === eventName) { + hook.cb(); + } + }); + hooks.off.forEach(hook => { + if (hook.event === eventName) { + hook.cb(); + } + }); + }, + + on: jest.fn((event, cb) => hooks.on.push({ + event, + cb + })), + off: jest.fn((event, cb) => hooks.off.push({ + event, + cb + })) +}; +const context = { + shortcuts +}; +const testResults = (0, _immutable.List)([{ + filepath: "testFilePath1", + matches: [{ + match: "match1", + value: "some thing match1", + column: 30 + }, { + match: "match2", + value: "some thing match2", + column: 60 + }, { + match: "match3", + value: "some thing match3", + column: 90 + }] +}, { + filepath: "testFilePath2", + matches: [{ + match: "match4", + value: "some thing match4", + column: 80 + }, { + match: "match5", + value: "some thing match5", + column: 40 + }] +}]); +const testMatch = { + match: "match1", + value: "some thing match1", + column: 30 +}; + +function render(overrides = {}, mounted = false) { + const props = _objectSpread({ + status: "DONE", + sources: {}, + results: (0, _immutable.List)([]), + query: "foo", + activeSearch: "project", + closeProjectSearch: jest.fn(), + searchSources: jest.fn(), + clearSearch: jest.fn(), + updateSearchStatus: jest.fn(), + selectLocation: jest.fn(), + doSearchForHighlight: jest.fn() + }, overrides); + + return mounted ? (0, _enzyme.mount)(_react2.default.createElement(_ProjectSearch.ProjectSearch, props), { + context + }) : (0, _enzyme.shallow)(_react2.default.createElement(_ProjectSearch.ProjectSearch, props), { + context + }); +} + +describe("ProjectSearch", () => { + beforeEach(() => { + context.shortcuts.on.mockClear(); + context.shortcuts.off.mockClear(); + }); + it("renders nothing when disabled", () => { + const component = render({ + activeSearch: null + }); + expect(component).toMatchSnapshot(); + }); + it("where has not been pressed", () => { + const component = render({ + query: "" + }); + expect(component).toMatchSnapshot(); + }); + it("found no search results", () => { + const component = render(); + expect(component).toMatchSnapshot(); + }); + it("should display loading message while search is in progress", () => { + const component = render({ + query: "match", + status: _projectTextSearch.statusType.fetching + }); + expect(component).toMatchSnapshot(); + }); + it("found search results", () => { + const component = render({ + query: "match", + results: testResults + }, true); + expect(component).toMatchSnapshot(); + }); + it("turns off shortcuts on unmount", () => { + const component = render({ + query: "" + }); + expect(component).toMatchSnapshot(); + component.unmount(); + expect(context.shortcuts.off).toHaveBeenCalled(); + }); + it("calls inputOnChange", () => { + const component = render({ + results: testResults + }, true); + component.find("SearchInput input").simulate("change", { + target: { + value: "bar" + } + }); + expect(component.state().inputValue).toEqual("bar"); + }); + it("onKeyDown Escape/Other", () => { + const searchSources = jest.fn(); + const component = render({ + results: testResults, + searchSources + }, true); + component.find("SearchInput input").simulate("keydown", { + key: "Escape" + }); + expect(searchSources).not.toHaveBeenCalled(); + searchSources.mockClear(); + component.find("SearchInput input").simulate("keydown", { + key: "Other", + stopPropagation: jest.fn() + }); + expect(searchSources).not.toHaveBeenCalled(); + }); + it("onKeyDown Enter", () => { + const searchSources = jest.fn(); + const component = render({ + results: testResults, + searchSources + }, true); + component.find("SearchInput input").simulate("keydown", { + key: "Enter", + stopPropagation: jest.fn() + }); + expect(searchSources).toHaveBeenCalledWith("foo"); + }); + it("onEnterPress shortcut no match or setExpanded", () => { + const selectLocation = jest.fn(); + const component = render({ + results: testResults, + selectLocation + }, true); + component.instance().focusedItem = {}; + shortcuts.dispatch("Enter"); + expect(selectLocation).not.toHaveBeenCalled(); + }); + it("onEnterPress shortcut match", () => { + const selectLocation = jest.fn(); + const component = render({ + results: testResults, + selectLocation + }, true); + component.instance().focusedItem = { + match: testMatch + }; + shortcuts.dispatch("Enter"); + expect(selectLocation).toHaveBeenCalledWith(testMatch); + }); + it("onEnterPress shortcut setExpanded", () => { + const selectLocation = jest.fn(); + const component = render({ + results: testResults, + selectLocation + }, true); + const setExpanded = jest.fn(); + const testFile = { + filepath: "testFilePath1", + matches: [testMatch] + }; + component.instance().focusedItem = { + setExpanded, + file: testFile, + expanded: true + }; + shortcuts.dispatch("Enter"); + expect(setExpanded).toHaveBeenCalledWith(testFile, false); + }); + describe("showErrorEmoji", () => { + it("false if not done & results", () => { + const component = render({ + status: _projectTextSearch.statusType.fetching, + results: testResults + }); + expect(component).toMatchSnapshot(); + }); + it("false if not done & no results", () => { + const component = render({ + status: _projectTextSearch.statusType.fetching + }); + expect(component).toMatchSnapshot(); + }); // "false if done & has results" + // is the same test as "found search results" + // "true if done & has no results" + // is the same test as "found no search results" + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/QuickOpenModal.spec.js b/devtools/client/debugger/new/src/components/test/QuickOpenModal.spec.js new file mode 100644 index 000000000000..c2466c80745a --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/QuickOpenModal.spec.js @@ -0,0 +1,277 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _enzyme = require("enzyme/index"); + +var _QuickOpenModal = require("../QuickOpenModal"); + +var _fuzzaldrinPlus = require("devtools/client/debugger/new/dist/vendors").vendored["fuzzaldrin-plus"]; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +jest.mock("fuzzaldrin-plus"); + +function generateModal(propOverrides, renderType = "shallow") { + const props = _objectSpread({ + enabled: false, + query: "", + searchType: "sources", + sources: [], + tabs: [], + selectLocation: jest.fn(), + setQuickOpenQuery: jest.fn(), + highlightLineRange: jest.fn(), + clearHighlightLineRange: jest.fn(), + closeQuickOpen: jest.fn() + }, propOverrides); + + return { + wrapper: renderType === "shallow" ? (0, _enzyme.shallow)(_react2.default.createElement(_QuickOpenModal.QuickOpenModal, props)) : (0, _enzyme.mount)(_react2.default.createElement(_QuickOpenModal.QuickOpenModal, props)), + props + }; +} + +describe("QuickOpenModal", () => { + beforeEach(() => { + _fuzzaldrinPlus.filter.mockClear(); + }); + test("Doesn't render when disabled", () => { + const { + wrapper + } = generateModal(); + expect(wrapper).toMatchSnapshot(); + }); + test("Renders when enabled", () => { + const { + wrapper + } = generateModal({ + enabled: true + }); + expect(wrapper).toMatchSnapshot(); + }); + test("Basic render with mount", () => { + const { + wrapper + } = generateModal({ + enabled: true + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + test("Basic render with mount & searchType = functions", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "@", + searchType: "functions", + symbols: { + functions: [], + variables: [] + } + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + test("Ensure anonymous functions do not render in QuickOpenModal", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "@", + searchType: "functions", + symbols: { + functions: [{ + title: "anonymous" + }, { + title: "c" + }, { + title: "anonymous" + }], + variables: [] + } + }, "mount"); + expect(wrapper.find("ResultList")).toHaveLength(1); + expect(wrapper.find("li")).toHaveLength(1); + }); + test("Basic render with mount & searchType = variables", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "#", + searchType: "variables", + symbols: { + functions: [], + variables: [] + } + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + test("Basic render with mount & searchType = shortcuts", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "?", + searchType: "shortcuts", + symbols: { + functions: [], + variables: [] + } + }, "mount"); + expect(wrapper.find("ResultList")).toHaveLength(1); + expect(wrapper.find("li")).toHaveLength(3); + }); + test("updateResults on enable", () => { + const { + wrapper + } = generateModal({}, "mount"); + expect(wrapper).toMatchSnapshot(); + wrapper.setProps({ + enabled: true + }); + expect(wrapper).toMatchSnapshot(); + }); + test("basic source search", () => { + const { + wrapper + } = generateModal({ + enabled: true, + symbols: { + functions: [], + variables: [] + } + }, "mount"); + wrapper.find("input").simulate("change", { + target: { + value: "somefil" + } + }); + expect(_fuzzaldrinPlus.filter).toHaveBeenCalledWith([], "somefil", { + key: "value", + maxResults: 1000 + }); + }); + test("basic gotoSource search", () => { + const { + wrapper + } = generateModal({ + enabled: true, + searchType: "gotoSource", + symbols: { + functions: [], + variables: [] + } + }, "mount"); + wrapper.find("input").simulate("change", { + target: { + value: "somefil:33" + } + }); + expect(_fuzzaldrinPlus.filter).toHaveBeenCalledWith([], "somefil", { + key: "value", + maxResults: 1000 + }); + }); + test("basic symbol seach", () => { + const { + wrapper + } = generateModal({ + enabled: true, + searchType: "functions", + symbols: { + functions: [], + variables: [] + }, + // symbol searching relies on a source being selected. + // So we dummy out the source and the API. + selectedSource: { + get: jest.fn(() => true) + } + }, "mount"); + wrapper.find("input").simulate("change", { + target: { + value: "@someFunc" + } + }); + expect(_fuzzaldrinPlus.filter).toHaveBeenCalledWith([], "someFunc", { + key: "value", + maxResults: 1000 + }); + }); + test("Simple goto search query = :abc & searchType = goto", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: ":abc", + searchType: "goto", + symbols: { + functions: [], + variables: [] + } + }, "mount"); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.state().results).toEqual(null); + }); + describe("showErrorEmoji", () => { + it("true when no count + query", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "test", + searchType: "" + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + it("false when count + query", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "dasdasdas" + }, "mount"); + wrapper.setState(() => ({ + results: [1, 2] + })); + expect(wrapper).toMatchSnapshot(); + }); + it("false when no query", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: "", + searchType: "" + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + it("false when goto numeric ':2222'", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: ":2222", + searchType: "goto" + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + it("true when goto not numeric ':22k22'", () => { + const { + wrapper + } = generateModal({ + enabled: true, + query: ":22k22", + searchType: "goto" + }, "mount"); + expect(wrapper).toMatchSnapshot(); + }); + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/ShortcutsModal.spec.js b/devtools/client/debugger/new/src/components/test/ShortcutsModal.spec.js new file mode 100644 index 000000000000..2e488dea8a4a --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/ShortcutsModal.spec.js @@ -0,0 +1,28 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _enzyme = require("enzyme/index"); + +var _ShortcutsModal = require("../ShortcutsModal"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +describe("ShortcutsModal", () => { + it("renders when enabled", () => { + const enabled = true; + const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_ShortcutsModal.ShortcutsModal, { + enabled: enabled + })); + expect(wrapper).toMatchSnapshot(); + }); + it("renders nothing when not enabled", () => { + const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_ShortcutsModal.ShortcutsModal, null)); + expect(wrapper.text()).toBe(""); + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/SourcesTree.spec.js b/devtools/client/debugger/new/src/components/test/SourcesTree.spec.js new file mode 100644 index 000000000000..2e8af4f99480 --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/SourcesTree.spec.js @@ -0,0 +1,639 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _enzyme = require("enzyme/index"); + +var _SourcesTree = require("../../components/PrimaryPanes/SourcesTree"); + +var _SourcesTree2 = _interopRequireDefault(_SourcesTree); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"]; + +var _clipboard = require("../../utils/clipboard"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +jest.mock("devtools-contextmenu", () => ({ + showMenu: jest.fn() +})); +jest.mock("../../utils/clipboard", () => ({ + copyToTheClipboard: jest.fn() +})); +describe("SourcesTree", () => { + afterEach(() => { + _clipboard.copyToTheClipboard.mockClear(); + + _devtoolsContextmenu.showMenu.mockClear(); + }); + it("Should show the tree with nothing expanded", async () => { + const { + component + } = render(); + expect(component).toMatchSnapshot(); + }); + describe("When loading initial source", () => { + it("Shows the tree with one.js, two.js and three.js expanded", async () => { + const { + component, + props + } = render(); + await component.setProps(_objectSpread({}, props, { + expanded: ["one.js", "two.js", "three.js"] + })); + expect(component).toMatchSnapshot(); + }); + }); + describe("After changing expanded nodes", () => { + it("Shows the tree with four.js, five.js and six.js expanded", async () => { + const { + component, + props + } = render(); + await component.setProps(_objectSpread({}, props, { + expanded: ["four.js", "five.js", "six.js"] + })); + expect(component).toMatchSnapshot(); + }); + }); + describe("on receiving new props", () => { + describe("recreates tree", () => { + it("does not recreate tree if no new source is added", async () => { + const { + component, + props, + defaultState + } = render(); + const mockSource = I.Map({ + "server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js") + }); + await component.setProps(_objectSpread({}, props, { + sources: mockSource + })); + expect(component.state("uncollapsedTree")).toEqual(defaultState.uncollapsedTree); + }); + it("updates tree with a new item", async () => { + const { + component, + props + } = render(); + const sources = props.sources.merge({ + "server1.conn13.child1/42": createMockSource("server1.conn13.child1/42", "http://mdn.com/four.js") + }); + await component.setProps(_objectSpread({}, props, { + sources: sources + })); + expect(component.state("uncollapsedTree").contents[0].contents).toHaveLength(4); + }); + it("updates sources if sources are emptied", async () => { + const { + component, + props, + defaultState + } = render(); + expect(defaultState.uncollapsedTree.contents).toHaveLength(1); + await component.setProps(_objectSpread({}, props, { + sources: I.Map({}) + })); + expect(component.state("uncollapsedTree").contents).toHaveLength(0); + }); + it("recreates tree if projectRoot is changed", async () => { + const { + component, + props, + defaultState + } = render(); + const sources = I.Map({ + "server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mozilla.com/three.js") + }); + expect(defaultState.uncollapsedTree.contents[0].contents).toHaveLength(3); + await component.setProps(_objectSpread({}, props, { + sources: sources, + projectRoot: "mozilla" + })); + expect(component.state("uncollapsedTree").contents[0].contents).toHaveLength(1); + }); + it("recreates tree if debugeeUrl is changed", async () => { + const { + component, + props, + defaultState + } = render(); + const mockSource = I.Map({ + "server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js") + }); + expect(defaultState.uncollapsedTree.contents[0].contents).toHaveLength(3); + await component.setProps(_objectSpread({}, props, { + debuggeeUrl: "mozilla", + sources: mockSource + })); + expect(component.state("uncollapsedTree").contents[0].contents).toHaveLength(1); + }); + }); + describe("updates list items", () => { + it("updates list items if shownSource changes", async () => { + const { + component, + props + } = render(); + await component.setProps(_objectSpread({}, props, { + shownSource: "http://mdn.com/three.js" + })); + expect(component).toMatchSnapshot(); + expect(props.selectLocation).toHaveBeenCalledWith({ + sourceId: "server1.conn13.child1/41" + }); + }); + }); + describe("updates highlighted items", () => { + it("updates highlightItems if selectedSource changes", async () => { + const { + component, + props + } = render(); + const mockSource = I.Map({ + "server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js") + }); + await component.setProps(_objectSpread({}, props, { + selectedSource: mockSource + })); + expect(component).toMatchSnapshot(); + }); + }); + }); + describe("focusItem", () => { + it("update the focused item", async () => { + const { + component, + instance, + props + } = render(); + const item = createMockItem(); + await instance.focusItem(item); + await component.update(); + await component.find(".sources-list").simulate("keydown", { + keyCode: 13 + }); + expect(props.selectLocation).toHaveBeenCalledWith({ + sourceId: item.contents.get("id") + }); + }); + }); + describe("with custom root", () => { + it("renders custom root source list", async () => { + const { + component + } = render({ + projectRoot: "mdn.com" + }); + expect(component).toMatchSnapshot(); + }); + it("calls clearProjectDirectoryRoot on click", async () => { + const { + component, + props + } = render({ + projectRoot: "mdn" + }); + component.find(".sources-clear-root").simulate("click"); + expect(props.clearProjectDirectoryRoot).toHaveBeenCalled(); + }); + it("renders empty custom root source list", async () => { + const { + component + } = render({ + projectRoot: "custom", + sources: I.Map() + }); + expect(component).toMatchSnapshot(); + }); + }); + describe("onContextMenu of the tree", () => { + it("shows context menu on directory to set as root", async () => { + const menuOptions = [{ + accesskey: "r", + click: expect.any(Function), + disabled: false, + id: "node-set-directory-root", + label: "Set directory root" + }]; + const mockEvent = { + preventDefault: jest.fn(), + stopPropagation: jest.fn() + }; + const { + props, + instance + } = render({ + projectRoot: "root/" + }); + await instance.onContextMenu(mockEvent, createMockDirectory()); + expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, menuOptions); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + expect(mockEvent.stopPropagation).toHaveBeenCalled(); + + _devtoolsContextmenu.showMenu.mock.calls[0][1][0].click(); + + expect(props.setProjectDirectoryRoot).toHaveBeenCalled(); + expect(props.clearProjectDirectoryRoot).not.toHaveBeenCalled(); + expect(_clipboard.copyToTheClipboard).not.toHaveBeenCalled(); + }); + it("shows context menu on file to copy source uri", async () => { + const menuOptions = [{ + accesskey: "u", + click: expect.any(Function), + disabled: false, + id: "node-menu-copy-source", + label: "Copy source URI" + }]; + const mockEvent = { + preventDefault: jest.fn(), + stopPropagation: jest.fn() + }; + const { + props, + instance + } = render({ + projectRoot: "root/" + }); + await instance.onContextMenu(mockEvent, createMockItem()); + expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, menuOptions); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + expect(mockEvent.stopPropagation).toHaveBeenCalled(); + + _devtoolsContextmenu.showMenu.mock.calls[0][1][0].click(); + + expect(props.setProjectDirectoryRoot).not.toHaveBeenCalled(); + expect(props.clearProjectDirectoryRoot).not.toHaveBeenCalled(); + expect(_clipboard.copyToTheClipboard).toHaveBeenCalled(); + }); + it("shows context menu on root to remove directory root", async () => { + const menuOptions = [{ + click: expect.any(Function), + disabled: false, + id: "node-remove-directory-root", + label: "Remove directory root" + }]; + const { + props, + instance + } = render({ + projectRoot: "root/" + }); + const mockEvent = { + preventDefault: jest.fn(), + stopPropagation: jest.fn() + }; + await instance.onContextMenu(mockEvent, createMockDirectory("root/", "root")); + expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, menuOptions); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + expect(mockEvent.stopPropagation).toHaveBeenCalled(); + + _devtoolsContextmenu.showMenu.mock.calls[0][1][0].click(); + + expect(props.setProjectDirectoryRoot).not.toHaveBeenCalled(); + expect(props.clearProjectDirectoryRoot).toHaveBeenCalled(); + expect(_clipboard.copyToTheClipboard).not.toHaveBeenCalled(); + }); + }); + describe("renderItem", () => { + it("should show icon for webpack item", async () => { + const { + instance + } = render(); + const item = createMockDirectory("webpack://", "webpack://"); + const node = renderItem(instance, item); + expect(node).toMatchSnapshot(); + }); + it("should show icon for angular item", async () => { + const { + instance + } = render(); + const item = createMockDirectory("ng://", "ng://"); + const node = renderItem(instance, item); + expect(node).toMatchSnapshot(); + }); + it("should show icon for moz-extension item", async () => { + const { + instance + } = render(); + const item = createMockDirectory("moz-extension://", "moz-extension://"); + const node = renderItem(instance, item); + expect(node).toMatchSnapshot(); + }); + it("should show icon for folder with arrow", async () => { + const { + instance + } = render(); + const node = renderItem(instance, createMockDirectory()); + expect(node).toMatchSnapshot(); + }); + it("should show icon for folder with expanded arrow", async () => { + const { + instance + } = render(); + const node = renderItem(instance, createMockDirectory(), 1, false, true); + expect(node).toMatchSnapshot(); + }); + it("should show focused item for folder with expanded arrow", async () => { + const { + instance + } = render(); + const node = renderItem(instance, createMockDirectory(), 1, true, true); + expect(node).toMatchSnapshot(); + }); + it("should show source item with source icon", async () => { + const { + instance + } = render(); + const node = renderItem(instance, createMockItem()); + expect(node).toMatchSnapshot(); + }); + it("should show source item with source icon with focus", async () => { + const { + instance + } = render(); + const node = renderItem(instance, createMockItem(), 1, true, false); + expect(node).toMatchSnapshot(); + }); + it("should show domain item", async () => { + const { + instance + } = render(); + const item = createMockItem("root", "root"); + const node = renderItem(instance, item, 0); + expect(node).toMatchSnapshot(); + }); + it("should show domain item as debuggee", async () => { + const { + instance + } = render(); + const item = createMockItem("root", "http://mdn.com"); + const node = renderItem(instance, item, 0); + expect(node).toMatchSnapshot(); + }); + it("should show domain item as debuggee with focus and arrow", async () => { + const { + instance + } = render(); + const item = createMockDirectory("root", "http://mdn.com"); + const node = renderItem(instance, item, 0, true); + expect(node).toMatchSnapshot(); + }); + it("should not show domain item when the projectRoot exists", async () => { + const { + instance + } = render({ + projectRoot: "root/" + }); + const node = renderItem(instance, createMockItem(), 0); + expect(node).toMatchSnapshot(); + }); + it("should show menu on contextmenu of an item", async () => { + const { + instance + } = render(); + const item = createMockItem(); + instance.onContextMenu = jest.fn(() => {}); + const event = { + event: "contextmenu" + }; + const node = (0, _enzyme.shallow)(renderItem(instance, item, 1, true)); + node.simulate("contextmenu", event); + expect(instance.onContextMenu).toHaveBeenCalledWith(event, item); + }); + it("should focus on and select item on click", async () => { + const { + component, + instance, + props + } = render(); + const item = createMockItem(); + const event = { + event: "click" + }; + const setExpanded = jest.fn(); + const node = (0, _enzyme.shallow)(renderItem(instance, item, 1, true, false, setExpanded)); + node.simulate("click", event); + await component.find(".sources-list").simulate("keydown", { + keyCode: 13 + }); + expect(props.selectLocation).toHaveBeenCalledWith({ + sourceId: item.contents.get("id") + }); + expect(setExpanded).not.toHaveBeenCalled(); + }); + it("should focus on and expand directory on click", async () => { + const { + component, + instance, + props + } = render(); + const event = { + event: "click" + }; + const setExpanded = jest.fn(); + const mockDirectory = createMockDirectory(); + const node = (0, _enzyme.shallow)(renderItem(instance, mockDirectory, 1, true, false, setExpanded)); + node.simulate("click", event); + expect(component.state("focusedItem")).toEqual(mockDirectory); + expect(setExpanded).toHaveBeenCalled(); + expect(props.selectLocation).not.toHaveBeenCalledWith(); + }); + }); + describe("selectItem", () => { + it("should select item with no children", async () => { + const { + instance, + props + } = render(); + instance.selectItem(createMockItem()); + expect(props.selectLocation).toHaveBeenCalledWith({ + sourceId: "server1.conn13.child1/39" + }); + }); + it("should not select item with children", async () => { + const { + props, + instance + } = render(); + instance.selectItem(createMockDirectory()); + expect(props.selectLocation).not.toHaveBeenCalled(); + }); + it("should select item on enter onKeyDown event", async () => { + const { + component, + props, + instance + } = render(); + await instance.focusItem(createMockItem()); + await component.update(); + await component.find(".sources-list").simulate("keydown", { + keyCode: 13 + }); + expect(props.selectLocation).toHaveBeenCalledWith({ + sourceId: "server1.conn13.child1/39" + }); + }); + it("does not select if no item is focused on", async () => { + const { + component, + props + } = render(); + await component.find(".sources-list").simulate("keydown", { + keyCode: 13 + }); + expect(props.selectLocation).not.toHaveBeenCalled(); + }); + }); + describe("handles items", () => { + it("getChildren from directory", async () => { + const { + component + } = render(); + const item = createMockDirectory("http://mdn.com/views", "views", ["a", "b"]); + const children = component.find("ManagedTree").props().getChildren(item); + expect(children).toEqual(["a", "b"]); + }); + it("getChildren from non directory", async () => { + const { + component + } = render(); + const children = component.find("ManagedTree").props().getChildren(createMockItem()); + expect(children).toEqual([]); + }); + it("onExpand", async () => { + const { + component, + props + } = render(); + const expandedState = ["x", "y"]; + await component.find("ManagedTree").props().onExpand({}, expandedState); + expect(props.setExpandedState).toHaveBeenCalledWith(expandedState); + }); + it("onCollapse", async () => { + const { + component, + props + } = render(); + const expandedState = ["y", "z"]; + await component.find("ManagedTree").props().onCollapse({}, expandedState); + expect(props.setExpandedState).toHaveBeenCalledWith(expandedState); + }); + it("getParent", async () => { + const { + component + } = render(); + const item = component.state("sourceTree").contents[0].contents[0]; + const parent = component.find("ManagedTree").props().getParent(item); + expect(parent.path).toEqual("mdn.com"); + expect(parent.contents).toHaveLength(3); + }); + }); + describe("getPath", () => { + it("should return path for item", async () => { + const { + instance + } = render(); + const path = instance.getPath(createMockItem()); + expect(path).toEqual("http://mdn.com/one.js/one.js/"); + }); + it("should return path for blackboxedboxed item", async () => { + const item = createMockItem("http://mdn.com/blackboxed.js", "blackboxed.js", I.Map({ + id: "server1.conn13.child1/59" + })); + const source = I.Map({ + "server1.conn13.child1/59": createMockSource("server1.conn13.child1/59", "http://mdn.com/blackboxed.js", true) + }); + const { + instance + } = render({ + sources: source + }); + const path = instance.getPath(item); + expect(path).toEqual("http://mdn.com/blackboxed.js/blackboxed.js/update"); + }); + }); +}); + +function generateDefaults(overrides) { + const defaultSources = I.Map({ + "server1.conn13.child1/39": createMockSource("server1.conn13.child1/39", "http://mdn.com/one.js"), + "server1.conn13.child1/40": createMockSource("server1.conn13.child1/40", "http://mdn.com/two.js"), + "server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js") + }); + return _objectSpread({ + autoExpandAll: true, + selectLocation: jest.fn(), + setExpandedState: jest.fn(), + sources: defaultSources, + debuggeeUrl: "http://mdn.com", + clearProjectDirectoryRoot: jest.fn(), + setProjectDirectoryRoot: jest.fn(), + projectRoot: "" + }, overrides); +} + +function renderItem(instance, item = createMockItem(), depth = 1, focused = false, expanded = false, setExpanded = jest.fn()) { + return instance.renderItem(item, depth, focused, null, expanded, { + setExpanded: setExpanded + }); +} + +function render(overrides = {}) { + const props = generateDefaults(overrides); + const component = (0, _enzyme.shallow)(_react2.default.createElement(_SourcesTree2.default.WrappedComponent, props)); + const defaultState = component.state(); + const instance = component.instance(); + + instance.shouldComponentUpdate = () => true; + + return { + component, + props, + defaultState, + instance + }; +} + +function createMockSource(id, url, isBlackBoxed = false) { + return I.Map({ + id: id, + url: url, + isPrettyPrinted: false, + isWasm: false, + sourceMapURL: null, + isBlackBoxed: isBlackBoxed, + loadedState: "unloaded" + }); +} + +function createMockDirectory(path = "folder/", name = "folder", contents = []) { + return { + name, + path, + contents + }; +} + +function createMockItem(path = "http://mdn.com/one.js", name = "one.js", contents = I.Map({ + id: "server1.conn13.child1/39" +})) { + return { + name, + path, + contents + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/WelcomeBox.spec.js b/devtools/client/debugger/new/src/components/test/WelcomeBox.spec.js new file mode 100644 index 000000000000..b2ee913f67b2 --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/WelcomeBox.spec.js @@ -0,0 +1,50 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _enzyme = require("enzyme/index"); + +var _WelcomeBox = require("../WelcomeBox"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +describe("WelomeBox", () => { + const setActiveSearch = () => null; + + it("renders with default values", () => { + const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, { + setActiveSearch: setActiveSearch + })); + expect(wrapper).toMatchSnapshot(); + }); + it("doesn't render toggle button in horizontal mode", () => { + const horizontal = true; + const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, { + horizontal: horizontal, + setActiveSearch: setActiveSearch + })); + expect(wrapper.find("PaneToggleButton")).toHaveLength(0); + }); + it("calls correct function on searchSources click", () => { + const openQuickOpen = jest.fn(); + const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, { + setActiveSearch: setActiveSearch, + openQuickOpen: openQuickOpen + })); + wrapper.find(".welcomebox__searchSources").simulate("click"); + expect(openQuickOpen).toBeCalled(); + }); + it("calls correct function on searchProject click", () => { + const setActiveSearchSpy = jest.fn(); + const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, { + setActiveSearch: setActiveSearchSpy + })); + wrapper.find(".welcomebox__searchProject").simulate("click"); + expect(setActiveSearchSpy).toBeCalled(); + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/WhyPaused.spec.js b/devtools/client/debugger/new/src/components/test/WhyPaused.spec.js new file mode 100644 index 000000000000..fcc7bf3706c7 --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/WhyPaused.spec.js @@ -0,0 +1,45 @@ +"use strict"; + +var _enzyme = require("enzyme/index"); + +var _WhyPaused = require("../SecondaryPanes/Frames/WhyPaused.js/index"); + +var _WhyPaused2 = _interopRequireDefault(_WhyPaused); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +describe("WhyPaused", () => { + it("should pause reason with message", () => { + const why = { + type: "breakpoint", + message: "bla is hit" + }; + const component = (0, _enzyme.shallow)((0, _WhyPaused2.default)(why)); + expect(component).toMatchSnapshot(); + }); + it("should show pause reason with exception details", () => { + const why = { + type: "exception", + exception: { + class: "Error", + preview: { + name: "ReferenceError", + message: "o is not defined" + } + } + }; + const component = (0, _enzyme.shallow)((0, _WhyPaused2.default)(why)); + expect(component).toMatchSnapshot(); + }); + it("should show pause reason with exception string", () => { + const why = { + type: "exception", + exception: "Not Available" + }; + const component = (0, _enzyme.shallow)((0, _WhyPaused2.default)(why)); + expect(component).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/test/moz.build b/devtools/client/debugger/new/src/components/test/moz.build new file mode 100644 index 000000000000..301a8c2d426f --- /dev/null +++ b/devtools/client/debugger/new/src/components/test/moz.build @@ -0,0 +1,18 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'Outline.spec.js', + 'ProjectSearch.spec.js', + 'QuickOpenModal.spec.js', + 'ShortcutsModal.spec.js', + 'SourcesTree.spec.js', + 'WelcomeBox.spec.js', + 'WhyPaused.spec.js', +) diff --git a/devtools/client/debugger/new/src/main.js b/devtools/client/debugger/new/src/main.js new file mode 100644 index 000000000000..896292de96be --- /dev/null +++ b/devtools/client/debugger/new/src/main.js @@ -0,0 +1,82 @@ +"use strict"; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("devtools/client/shared/vendor/react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +var _client = require("./client/index"); + +var _bootstrap = require("./utils/bootstrap"); + +var _sourceQueue = require("./utils/source-queue"); + +var _sourceQueue2 = _interopRequireDefault(_sourceQueue); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function unmountRoot() { + const mount = document.querySelector("#mount .launchpad-root"); + + _reactDom2.default.unmountComponentAtNode(mount); +} + +if ((0, _devtoolsEnvironment.isFirefoxPanel)()) { + module.exports = { + bootstrap: ({ + threadClient, + tabTarget, + debuggerClient, + sourceMaps, + toolboxActions + }) => { + return (0, _client.onConnect)({ + tab: { + clientType: "firefox" + }, + tabConnection: { + tabTarget, + threadClient, + debuggerClient + } + }, { + services: { + sourceMaps + }, + toolboxActions + }); + }, + destroy: () => { + unmountRoot(); + + _sourceQueue2.default.clear(); + + (0, _bootstrap.teardownWorkers)(); + } + }; +} else { + const { + bootstrap, + L10N + } = require("devtools/shared/flags"); + + window.L10N = L10N; // $FlowIgnore: + + window.L10N.setBundle(require("devtools/shared/flags")); + bootstrap(_react2.default, _reactDom2.default).then(connection => { + (0, _client.onConnect)(connection, { + services: { + sourceMaps: require("devtools/client/shared/source-map/index.js") + }, + toolboxActions: {} + }); + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/moz.build b/devtools/client/debugger/new/src/moz.build new file mode 100644 index 000000000000..3634f3b6d6f3 --- /dev/null +++ b/devtools/client/debugger/new/src/moz.build @@ -0,0 +1,18 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'actions', + 'client', + 'components', + 'reducers', + 'selectors', + 'utils', + 'workers', +] + +DevToolsModules( + 'main.js', +) diff --git a/devtools/client/debugger/new/src/reducers/ast.js b/devtools/client/debugger/new/src/reducers/ast.js new file mode 100644 index 000000000000..f79ce1b9eb0b --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/ast.js @@ -0,0 +1,233 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.initialASTState = initialASTState; +exports.getSymbols = getSymbols; +exports.hasSymbols = hasSymbols; +exports.isSymbolsLoading = isSymbolsLoading; +exports.isEmptyLineInSource = isEmptyLineInSource; +exports.getEmptyLines = getEmptyLines; +exports.getPausePoints = getPausePoints; +exports.getPausePoint = getPausePoint; +exports.hasPausePoints = hasPausePoints; +exports.getOutOfScopeLocations = getOutOfScopeLocations; +exports.getPreview = getPreview; +exports.getSourceMetaData = getSourceMetaData; +exports.hasSourceMetaData = hasSourceMetaData; +exports.getInScopeLines = getInScopeLines; +exports.isLineInScope = isLineInScope; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _ast = require("../utils/ast"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function initialASTState() { + return (0, _makeRecord2.default)({ + symbols: I.Map(), + emptyLines: I.Map(), + outOfScopeLocations: null, + inScopeLines: null, + preview: null, + pausePoints: I.Map(), + sourceMetaData: I.Map() + })(); +} + +function update(state = initialASTState(), action) { + switch (action.type) { + case "SET_SYMBOLS": + { + const { + sourceId + } = action; + + if (action.status === "start") { + return state.setIn(["symbols", sourceId], { + loading: true + }); + } + + const value = action.value; + return state.setIn(["symbols", sourceId], value); + } + + case "SET_PAUSE_POINTS": + { + const { + source, + pausePoints + } = action; + const emptyLines = (0, _ast.findEmptyLines)(source, pausePoints); + return state.setIn(["pausePoints", source.id], pausePoints).setIn(["emptyLines", source.id], emptyLines); + } + + case "OUT_OF_SCOPE_LOCATIONS": + { + return state.set("outOfScopeLocations", action.locations); + } + + case "IN_SCOPE_LINES": + { + return state.set("inScopeLines", action.lines); + } + + case "CLEAR_SELECTION": + { + return state.set("preview", null); + } + + case "SET_PREVIEW": + { + if (action.status == "start") { + return state.set("preview", { + updating: true + }); + } + + if (!action.value) { + return state.set("preview", null); + } + + return state.set("preview", _objectSpread({}, action.value, { + updating: false + })); + } + + case "RESUME": + { + return state.set("outOfScopeLocations", null); + } + + case "NAVIGATE": + { + return initialASTState(); + } + + case "SET_SOURCE_METADATA": + { + return state.setIn(["sourceMetaData", action.sourceId], action.sourceMetaData); + } + + default: + { + return state; + } + } +} // NOTE: we'd like to have the app state fully typed +// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 + + +function getSymbols(state, source) { + if (!source) { + return null; + } + + return state.ast.symbols.get(source.id) || null; +} + +function hasSymbols(state, source) { + const symbols = getSymbols(state, source); + + if (!symbols) { + return false; + } + + return !symbols.hasOwnProperty("loading"); +} + +function isSymbolsLoading(state, source) { + const symbols = getSymbols(state, source); + + if (!symbols) { + return false; + } + + return symbols.hasOwnProperty("loading"); +} + +function isEmptyLineInSource(state, line, selectedSource) { + const emptyLines = getEmptyLines(state, selectedSource); + return emptyLines && emptyLines.includes(line); +} + +function getEmptyLines(state, source) { + if (!source) { + return null; + } + + return state.ast.emptyLines.get(source.id); +} + +function getPausePoints(state, sourceId) { + return state.ast.pausePoints.get(sourceId); +} + +function getPausePoint(state, location) { + if (!location) { + return; + } + + const { + column, + line, + sourceId + } = location; + const pausePoints = getPausePoints(state, sourceId); + + if (!pausePoints) { + return; + } + + const linePoints = pausePoints[line]; + return linePoints && linePoints[column]; +} + +function hasPausePoints(state, sourceId) { + const pausePoints = getPausePoints(state, sourceId); + return !!pausePoints; +} + +function getOutOfScopeLocations(state) { + return state.ast.get("outOfScopeLocations"); +} + +function getPreview(state) { + return state.ast.get("preview"); +} + +const emptySourceMetaData = {}; + +function getSourceMetaData(state, sourceId) { + return state.ast.sourceMetaData.get(sourceId) || emptySourceMetaData; +} + +function hasSourceMetaData(state, sourceId) { + return state.ast.hasIn(["sourceMetaData", sourceId]); +} + +function getInScopeLines(state) { + return state.ast.get("inScopeLines"); +} + +function isLineInScope(state, line) { + const linesInScope = state.ast.get("inScopeLines"); + return linesInScope && linesInScope.includes(line); +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/async-requests.js b/devtools/client/debugger/new/src/reducers/async-requests.js new file mode 100644 index 000000000000..68f1ef305192 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/async-requests.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Async request reducer + * @module reducers/async-request + */ +const initialAsyncRequestState = []; + +function update(state = initialAsyncRequestState, action) { + const { + seqId + } = action; + + if (action.type === "NAVIGATE") { + return initialAsyncRequestState; + } else if (seqId) { + let newState; + + if (action.status === "start") { + newState = [...state, seqId]; + } else if (action.status === "error" || action.status === "done") { + newState = state.filter(id => id !== seqId); + } + + return newState; + } + + return state; +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/breakpoints.js b/devtools/client/debugger/new/src/reducers/breakpoints.js new file mode 100644 index 000000000000..ef2fc8ef1741 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/breakpoints.js @@ -0,0 +1,237 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.initialBreakpointsState = initialBreakpointsState; +exports.getBreakpoints = getBreakpoints; +exports.getBreakpoint = getBreakpoint; +exports.getBreakpointsDisabled = getBreakpointsDisabled; +exports.getBreakpointsLoading = getBreakpointsLoading; +exports.getBreakpointsForSource = getBreakpointsForSource; +exports.getBreakpointForLine = getBreakpointForLine; +exports.getHiddenBreakpoint = getHiddenBreakpoint; +exports.getHiddenBreakpointLocation = getHiddenBreakpointLocation; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _breakpoint = require("../utils/breakpoint/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function initialBreakpointsState() { + return (0, _makeRecord2.default)({ + breakpoints: I.Map(), + breakpointsDisabled: false + })(); +} + +function update(state = initialBreakpointsState(), action) { + switch (action.type) { + case "ADD_BREAKPOINT": + { + return addBreakpoint(state, action); + } + + case "SYNC_BREAKPOINT": + { + return syncBreakpoint(state, action); + } + + case "ENABLE_BREAKPOINT": + { + return addBreakpoint(state, action); + } + + case "DISABLE_BREAKPOINT": + { + return updateBreakpoint(state, action); + } + + case "DISABLE_ALL_BREAKPOINTS": + { + return updateAllBreakpoints(state, action); + } + + case "ENABLE_ALL_BREAKPOINTS": + { + return updateAllBreakpoints(state, action); + } + + case "SET_BREAKPOINT_CONDITION": + { + return updateBreakpoint(state, action); + } + + case "REMOVE_BREAKPOINT": + { + return removeBreakpoint(state, action); + } + + case "REMAP_BREAKPOINTS": + { + return remapBreakpoints(state, action); + } + + case "NAVIGATE": + { + return initialBreakpointsState(); + } + } + + return state; +} + +function addBreakpoint(state, action) { + if (action.status === "start" && action.breakpoint) { + const { + breakpoint + } = action; + const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); + return state.setIn(["breakpoints", locationId], breakpoint); + } // when the action completes, we can commit the breakpoint + + + if (action.status === "done") { + const { + value + } = action; + return syncBreakpoint(state, value); + } // Remove the optimistic update + + + if (action.status === "error" && action.breakpoint) { + const locationId = (0, _breakpoint.makeLocationId)(action.breakpoint.location); + return state.deleteIn(["breakpoints", locationId]); + } + + return state; +} + +function syncBreakpoint(state, data) { + const { + breakpoint, + previousLocation + } = data; + + if (previousLocation) { + state = state.deleteIn(["breakpoints", (0, _breakpoint.makeLocationId)(previousLocation)]); + } + + if (!breakpoint) { + return state; + } + + const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); + return state.setIn(["breakpoints", locationId], breakpoint); +} + +function updateBreakpoint(state, action) { + const { + breakpoint + } = action; + const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); + return state.setIn(["breakpoints", locationId], breakpoint); +} + +function updateAllBreakpoints(state, action) { + const { + breakpoints + } = action; + breakpoints.forEach(breakpoint => { + const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); + state = state.setIn(["breakpoints", locationId], breakpoint); + }); + return state; +} + +function remapBreakpoints(state, action) { + const breakpoints = action.breakpoints.reduce((updatedBreakpoints, breakpoint) => { + const locationId = (0, _breakpoint.makeLocationId)(breakpoint.location); + return _objectSpread({}, updatedBreakpoints, { + [locationId]: breakpoint + }); + }, {}); + return state.set("breakpoints", I.Map(breakpoints)); +} + +function removeBreakpoint(state, action) { + const { + breakpoint + } = action; + const id = (0, _breakpoint.makeLocationId)(breakpoint.location); + return state.deleteIn(["breakpoints", id]); +} // Selectors +// TODO: these functions should be moved out of the reducer + + +function getBreakpoints(state) { + return state.breakpoints.breakpoints; +} + +function getBreakpoint(state, location) { + const breakpoints = getBreakpoints(state); + return breakpoints.get((0, _breakpoint.makeLocationId)(location)); +} + +function getBreakpointsDisabled(state) { + return state.breakpoints.breakpoints.every(x => x.disabled); +} + +function getBreakpointsLoading(state) { + const breakpoints = getBreakpoints(state); + const isLoading = !!breakpoints.valueSeq().filter(bp => bp.loading).first(); + return breakpoints.size > 0 && isLoading; +} + +function getBreakpointsForSource(state, sourceId) { + if (!sourceId) { + return I.Map(); + } + + const isGeneratedSource = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); + const breakpoints = getBreakpoints(state); + return breakpoints.filter(bp => { + const location = isGeneratedSource ? bp.generatedLocation || bp.location : bp.location; + return location.sourceId === sourceId; + }); +} + +function getBreakpointForLine(state, sourceId, line) { + if (!sourceId) { + return I.Map(); + } + + const breakpoints = getBreakpointsForSource(state, sourceId); + return breakpoints.find(breakpoint => breakpoint.location.line === line); +} + +function getHiddenBreakpoint(state) { + return getBreakpoints(state).valueSeq().filter(breakpoint => breakpoint.hidden).first(); +} + +function getHiddenBreakpointLocation(state) { + const hiddenBreakpoint = getHiddenBreakpoint(state); + + if (!hiddenBreakpoint) { + return null; + } + + return hiddenBreakpoint.location; +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/coverage.js b/devtools/client/debugger/new/src/reducers/coverage.js new file mode 100644 index 000000000000..6dbf15ab5f7c --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/coverage.js @@ -0,0 +1,62 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createCoverageState = undefined; +exports.getHitCountForSource = getHitCountForSource; +exports.getCoverageEnabled = getCoverageEnabled; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _fromJS = require("../utils/fromJS"); + +var _fromJS2 = _interopRequireDefault(_fromJS); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Code coverage reducer + * @module reducers/coverage + */ +const createCoverageState = exports.createCoverageState = (0, _makeRecord2.default)({ + coverageOn: false, + hitCount: I.Map() +}); + +function update(state = createCoverageState(), action) { + switch (action.type) { + case "RECORD_COVERAGE": + return state.mergeIn(["hitCount"], (0, _fromJS2.default)(action.value.coverage)).setIn(["coverageOn"], true); + + default: + { + return state; + } + } +} // NOTE: we'd like to have the app state fully typed +// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 + + +function getHitCountForSource(state, sourceId) { + const hitCount = state.coverage.get("hitCount"); + return hitCount.get(sourceId); +} + +function getCoverageEnabled(state) { + return state.coverage.get("coverageOn"); +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/debuggee.js b/devtools/client/debugger/new/src/reducers/debuggee.js new file mode 100644 index 000000000000..14334e459893 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/debuggee.js @@ -0,0 +1,48 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getWorkers = exports.createDebuggeeState = undefined; +exports.default = debuggee; +exports.getWorker = getWorker; + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Debuggee reducer + * @module reducers/debuggee + */ +const createDebuggeeState = exports.createDebuggeeState = (0, _makeRecord2.default)({ + workers: (0, _immutable.List)() +}); + +function debuggee(state = createDebuggeeState(), action) { + switch (action.type) { + case "SET_WORKERS": + return state.set("workers", (0, _immutable.List)(action.workers)); + + default: + return state; + } +} + +const getDebuggeeWrapper = state => state.debuggee; + +const getWorkers = exports.getWorkers = (0, _reselect.createSelector)(getDebuggeeWrapper, debuggeeState => debuggeeState.get("workers")); + +function getWorker(state, url) { + return getWorkers(state).find(value => url); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/event-listeners.js b/devtools/client/debugger/new/src/reducers/event-listeners.js new file mode 100644 index 000000000000..6487d08279a0 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/event-listeners.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getEventListeners = getEventListeners; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Event listeners reducer + * @module reducers/event-listeners + */ +const initialEventListenersState = { + activeEventNames: [], + listeners: [], + fetchingListeners: false +}; + +function update(state = initialEventListenersState, action, emit) { + switch (action.type) { + case "UPDATE_EVENT_BREAKPOINTS": + state.activeEventNames = action.eventNames; // emit("activeEventNames", state.activeEventNames); + + break; + + case "FETCH_EVENT_LISTENERS": + if (action.status === "begin") { + state.fetchingListeners = true; + } else if (action.status === "done") { + state.fetchingListeners = false; + state.listeners = action.listeners; + } + + break; + + case "NAVIGATE": + return initialEventListenersState; + } + + return state; +} + +function getEventListeners(state) { + return state.eventListeners.listeners; +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/expressions.js b/devtools/client/debugger/new/src/reducers/expressions.js new file mode 100644 index 000000000000..081d990d911b --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/expressions.js @@ -0,0 +1,171 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getExpressionError = exports.getAutocompleteMatches = exports.getExpressions = exports.createExpressionState = undefined; +exports.getExpression = getExpression; +exports.getAutocompleteMatchset = getAutocompleteMatchset; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +var _prefs = require("../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Expressions reducer + * @module reducers/expressions + */ +const createExpressionState = exports.createExpressionState = (0, _makeRecord2.default)({ + expressions: (0, _immutable.List)(restoreExpressions()), + expressionError: false, + autocompleteMatches: (0, _immutable.Map)({}) +}); + +function update(state = createExpressionState(), action) { + switch (action.type) { + case "ADD_EXPRESSION": + if (action.expressionError) { + return state.set("expressionError", !!action.expressionError); + } + + return appendExpressionToList(state, { + input: action.input, + value: null, + updating: true + }); + + case "UPDATE_EXPRESSION": + const key = action.expression.input; + return updateExpressionInList(state, key, { + input: action.input, + value: null, + updating: true + }).set("expressionError", !!action.expressionError); + + case "EVALUATE_EXPRESSION": + return updateExpressionInList(state, action.input, { + input: action.input, + value: action.value, + updating: false + }); + + case "EVALUATE_EXPRESSIONS": + const { + inputs, + results + } = action; + return (0, _lodash.zip)(inputs, results).reduce((newState, [input, result]) => updateExpressionInList(newState, input, { + input: input, + value: result, + updating: false + }), state); + + case "DELETE_EXPRESSION": + return deleteExpression(state, action.input); + + case "CLEAR_EXPRESSION_ERROR": + return state.set("expressionError", false); + // respond to time travel + + case "TRAVEL_TO": + return travelTo(state, action); + + case "AUTOCOMPLETE": + const { + matchProp, + matches + } = action.result; + return state.updateIn(["autocompleteMatches", matchProp], list => matches); + } + + return state; +} + +function travelTo(state, action) { + const { + expressions + } = action.data; + + if (!expressions) { + return state; + } + + return expressions.reduce((finalState, previousState) => updateExpressionInList(finalState, previousState.input, { + input: previousState.input, + value: previousState.value, + updating: false + }), state); +} + +function restoreExpressions() { + const exprs = _prefs.prefs.expressions; + + if (exprs.length == 0) { + return; + } + + return exprs; +} + +function storeExpressions({ + expressions +}) { + _prefs.prefs.expressions = expressions.map(expression => (0, _lodash.omit)(expression, "value")).toJS(); +} + +function appendExpressionToList(state, value) { + const newState = state.update("expressions", () => { + return state.expressions.push(value); + }); + storeExpressions(newState); + return newState; +} + +function updateExpressionInList(state, key, value) { + const newState = state.update("expressions", () => { + const list = state.expressions; + const index = list.findIndex(e => e.input == key); + return list.update(index, () => value); + }); + storeExpressions(newState); + return newState; +} + +function deleteExpression(state, input) { + const index = getExpressions({ + expressions: state + }).findIndex(e => e.input == input); + const newState = state.deleteIn(["expressions", index]); + storeExpressions(newState); + return newState; +} + +const getExpressionsWrapper = state => state.expressions; + +const getExpressions = exports.getExpressions = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.expressions); +const getAutocompleteMatches = exports.getAutocompleteMatches = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.autocompleteMatches); + +function getExpression(state, input) { + return getExpressions(state).find(exp => exp.input == input); +} + +function getAutocompleteMatchset(state, input) { + return getAutocompleteMatches(state).get(input); +} + +const getExpressionError = exports.getExpressionError = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.expressionError); +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/file-search.js b/devtools/client/debugger/new/src/reducers/file-search.js new file mode 100644 index 000000000000..68c428fc6360 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/file-search.js @@ -0,0 +1,94 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createFileSearchState = undefined; +exports.getFileSearchQuery = getFileSearchQuery; +exports.getFileSearchModifiers = getFileSearchModifiers; +exports.getFileSearchResults = getFileSearchResults; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _prefs = require("../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * File Search reducer + * @module reducers/fileSearch + */ +const createFileSearchState = exports.createFileSearchState = (0, _makeRecord2.default)({ + query: "", + searchResults: { + matches: [], + matchIndex: -1, + index: -1, + count: 0 + }, + modifiers: (0, _makeRecord2.default)({ + caseSensitive: _prefs.prefs.fileSearchCaseSensitive, + wholeWord: _prefs.prefs.fileSearchWholeWord, + regexMatch: _prefs.prefs.fileSearchRegexMatch + })() +}); + +function update(state = createFileSearchState(), action) { + switch (action.type) { + case "UPDATE_FILE_SEARCH_QUERY": + { + return state.set("query", action.query); + } + + case "UPDATE_SEARCH_RESULTS": + { + return state.set("searchResults", action.results); + } + + case "TOGGLE_FILE_SEARCH_MODIFIER": + { + const actionVal = !state.modifiers[action.modifier]; + + if (action.modifier == "caseSensitive") { + _prefs.prefs.fileSearchCaseSensitive = actionVal; + } + + if (action.modifier == "wholeWord") { + _prefs.prefs.fileSearchWholeWord = actionVal; + } + + if (action.modifier == "regexMatch") { + _prefs.prefs.fileSearchRegexMatch = actionVal; + } + + return state.setIn(["modifiers", action.modifier], actionVal); + } + + default: + { + return state; + } + } +} // NOTE: we'd like to have the app state fully typed +// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 + + +function getFileSearchQuery(state) { + return state.fileSearch.query; +} + +function getFileSearchModifiers(state) { + return state.fileSearch.modifiers; +} + +function getFileSearchResults(state) { + return state.fileSearch.searchResults; +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/index.js b/devtools/client/debugger/new/src/reducers/index.js new file mode 100644 index 000000000000..6eee1f60f397 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/index.js @@ -0,0 +1,98 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _expressions = require("./expressions"); + +var _expressions2 = _interopRequireDefault(_expressions); + +var _eventListeners = require("./event-listeners"); + +var _eventListeners2 = _interopRequireDefault(_eventListeners); + +var _sources = require("./sources"); + +var _sources2 = _interopRequireDefault(_sources); + +var _breakpoints = require("./breakpoints"); + +var _breakpoints2 = _interopRequireDefault(_breakpoints); + +var _pendingBreakpoints = require("./pending-breakpoints"); + +var _pendingBreakpoints2 = _interopRequireDefault(_pendingBreakpoints); + +var _asyncRequests = require("./async-requests"); + +var _asyncRequests2 = _interopRequireDefault(_asyncRequests); + +var _pause = require("./pause"); + +var _pause2 = _interopRequireDefault(_pause); + +var _ui = require("./ui"); + +var _ui2 = _interopRequireDefault(_ui); + +var _fileSearch = require("./file-search"); + +var _fileSearch2 = _interopRequireDefault(_fileSearch); + +var _ast = require("./ast"); + +var _ast2 = _interopRequireDefault(_ast); + +var _coverage = require("./coverage"); + +var _coverage2 = _interopRequireDefault(_coverage); + +var _projectTextSearch = require("./project-text-search"); + +var _projectTextSearch2 = _interopRequireDefault(_projectTextSearch); + +var _replay = require("./replay"); + +var _replay2 = _interopRequireDefault(_replay); + +var _quickOpen = require("./quick-open"); + +var _quickOpen2 = _interopRequireDefault(_quickOpen); + +var _sourceTree = require("./source-tree"); + +var _sourceTree2 = _interopRequireDefault(_sourceTree); + +var _debuggee = require("./debuggee"); + +var _debuggee2 = _interopRequireDefault(_debuggee); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Reducer index + * @module reducers/index + */ +exports.default = { + expressions: _expressions2.default, + eventListeners: _eventListeners2.default, + sources: _sources2.default, + breakpoints: _breakpoints2.default, + pendingBreakpoints: _pendingBreakpoints2.default, + asyncRequests: _asyncRequests2.default, + pause: _pause2.default, + ui: _ui2.default, + fileSearch: _fileSearch2.default, + ast: _ast2.default, + coverage: _coverage2.default, + projectTextSearch: _projectTextSearch2.default, + replay: _replay2.default, + quickOpen: _quickOpen2.default, + sourceTree: _sourceTree2.default, + debuggee: _debuggee2.default +}; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/moz.build b/devtools/client/debugger/new/src/reducers/moz.build new file mode 100644 index 000000000000..53d4ddf44609 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/moz.build @@ -0,0 +1,28 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'ast.js', + 'async-requests.js', + 'breakpoints.js', + 'coverage.js', + 'debuggee.js', + 'event-listeners.js', + 'expressions.js', + 'file-search.js', + 'index.js', + 'pause.js', + 'pending-breakpoints.js', + 'project-text-search.js', + 'quick-open.js', + 'replay.js', + 'source-tree.js', + 'sources.js', + 'ui.js', +) diff --git a/devtools/client/debugger/new/src/reducers/pause.js b/devtools/client/debugger/new/src/reducers/pause.js new file mode 100644 index 000000000000..769e741d49ef --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/pause.js @@ -0,0 +1,416 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getSelectedFrame = exports.getAllPopupObjectProperties = exports.createPauseState = undefined; +exports.getPauseReason = getPauseReason; +exports.getPauseCommand = getPauseCommand; +exports.isStepping = isStepping; +exports.isPaused = isPaused; +exports.getPreviousPauseFrameLocation = getPreviousPauseFrameLocation; +exports.isEvaluatingExpression = isEvaluatingExpression; +exports.getPopupObjectProperties = getPopupObjectProperties; +exports.getIsWaitingOnBreak = getIsWaitingOnBreak; +exports.getShouldPauseOnExceptions = getShouldPauseOnExceptions; +exports.getShouldPauseOnCaughtExceptions = getShouldPauseOnCaughtExceptions; +exports.getCanRewind = getCanRewind; +exports.getExtra = getExtra; +exports.getFrames = getFrames; +exports.getGeneratedFrameScope = getGeneratedFrameScope; +exports.getOriginalFrameScope = getOriginalFrameScope; +exports.getFrameScopes = getFrameScopes; +exports.getFrameScope = getFrameScope; +exports.getSelectedScope = getSelectedScope; +exports.getSelectedScopeMappings = getSelectedScopeMappings; +exports.getSelectedFrameId = getSelectedFrameId; +exports.getTopFrame = getTopFrame; +exports.getDebuggeeUrl = getDebuggeeUrl; +exports.getSkipPausing = getSkipPausing; +exports.getChromeScopes = getChromeScopes; + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _prefs = require("../utils/prefs"); + +var _sources = require("./sources"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const createPauseState = exports.createPauseState = () => ({ + extra: {}, + why: null, + isWaitingOnBreak: false, + frames: undefined, + selectedFrameId: undefined, + frameScopes: { + generated: {}, + original: {}, + mappings: {} + }, + loadedObjects: {}, + shouldPauseOnExceptions: _prefs.prefs.pauseOnExceptions, + shouldPauseOnCaughtExceptions: _prefs.prefs.pauseOnCaughtExceptions, + canRewind: false, + debuggeeUrl: "", + command: null, + previousLocation: null, + skipPausing: _prefs.prefs.skipPausing +}); + +const emptyPauseState = { + frames: null, + frameScopes: { + generated: {}, + original: {}, + mappings: {} + }, + selectedFrameId: null, + loadedObjects: {}, + why: null +}; + +function update(state = createPauseState(), action) { + switch (action.type) { + case "PAUSED": + { + const { + selectedFrameId, + frames, + loadedObjects, + why + } = action; // turn this into an object keyed by object id + + const objectMap = {}; + loadedObjects.forEach(obj => { + objectMap[obj.value.objectId] = obj; + }); + return _objectSpread({}, state, { + isWaitingOnBreak: false, + selectedFrameId, + frames, + frameScopes: _objectSpread({}, emptyPauseState.frameScopes), + loadedObjects: objectMap, + why + }); + } + + case "MAP_FRAMES": + { + return _objectSpread({}, state, { + frames: action.frames + }); + } + + case "ADD_EXTRA": + { + return _objectSpread({}, state, { + extra: action.extra + }); + } + + case "ADD_SCOPES": + { + const { + frame, + status, + value + } = action; + const selectedFrameId = frame.id; + + const generated = _objectSpread({}, state.frameScopes.generated, { + [selectedFrameId]: { + pending: status !== "done", + scope: value + } + }); + + return _objectSpread({}, state, { + frameScopes: _objectSpread({}, state.frameScopes, { + generated + }) + }); + } + + case "TRAVEL_TO": + return _objectSpread({}, state, action.data.paused); + + case "MAP_SCOPES": + { + const { + frame, + status, + value + } = action; + const selectedFrameId = frame.id; + + const original = _objectSpread({}, state.frameScopes.original, { + [selectedFrameId]: { + pending: status !== "done", + scope: value && value.scope + } + }); + + const mappings = _objectSpread({}, state.frameScopes.mappings, { + [selectedFrameId]: value && value.mappings + }); + + return _objectSpread({}, state, { + frameScopes: _objectSpread({}, state.frameScopes, { + original, + mappings + }) + }); + } + + case "BREAK_ON_NEXT": + return _objectSpread({}, state, { + isWaitingOnBreak: true + }); + + case "SELECT_FRAME": + return _objectSpread({}, state, { + selectedFrameId: action.frame.id + }); + + case "SET_POPUP_OBJECT_PROPERTIES": + if (!action.properties) { + return _objectSpread({}, state); + } + + return _objectSpread({}, state, { + loadedObjects: _objectSpread({}, state.loadedObjects, { + [action.objectId]: action.properties + }) + }); + + case "CONNECT": + return _objectSpread({}, createPauseState(), { + debuggeeUrl: action.url, + canRewind: action.canRewind + }); + + case "PAUSE_ON_EXCEPTIONS": + const { + shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions + } = action; + _prefs.prefs.pauseOnExceptions = shouldPauseOnExceptions; + _prefs.prefs.pauseOnCaughtExceptions = shouldPauseOnCaughtExceptions; // Preserving for the old debugger + + _prefs.prefs.ignoreCaughtExceptions = !shouldPauseOnCaughtExceptions; + return _objectSpread({}, state, { + shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions + }); + + case "COMMAND": + { + return action.status === "start" ? _objectSpread({}, state, emptyPauseState, { + command: action.command, + previousLocation: buildPreviousLocation(state, action) + }) : _objectSpread({}, state, { + command: null + }); + } + + case "RESUME": + return _objectSpread({}, state, emptyPauseState); + + case "EVALUATE_EXPRESSION": + return _objectSpread({}, state, { + command: action.status === "start" ? "expression" : null + }); + + case "NAVIGATE": + return _objectSpread({}, state, emptyPauseState, { + debuggeeUrl: action.url + }); + + case "TOGGLE_SKIP_PAUSING": + { + const { + skipPausing + } = action; + _prefs.prefs.skipPausing = skipPausing; + return _objectSpread({}, state, { + skipPausing + }); + } + } + + return state; +} + +function buildPreviousLocation(state, action) { + const { + frames, + previousLocation + } = state; + + if (action.command !== "stepOver") { + return null; + } + + const frame = frames && frames.length > 0 ? frames[0] : null; + + if (!frame) { + return previousLocation; + } + + return { + location: frame.location, + generatedLocation: frame.generatedLocation + }; +} // Selectors +// Unfortunately, it's really hard to make these functions accept just +// the state that we care about and still type it with Flow. The +// problem is that we want to re-export all selectors from a single +// module for the UI, and all of those selectors should take the +// top-level app state, so we'd have to "wrap" them to automatically +// pick off the piece of state we're interested in. It's impossible +// (right now) to type those wrapped functions. + + +const getPauseState = state => state.pause; + +const getAllPopupObjectProperties = exports.getAllPopupObjectProperties = (0, _reselect.createSelector)(getPauseState, pauseWrapper => pauseWrapper.loadedObjects); + +function getPauseReason(state) { + return state.pause.why; +} + +function getPauseCommand(state) { + return state.pause && state.pause.command; +} + +function isStepping(state) { + return ["stepIn", "stepOver", "stepOut"].includes(getPauseCommand(state)); +} + +function isPaused(state) { + return !!getFrames(state); +} + +function getPreviousPauseFrameLocation(state) { + return state.pause.previousLocation; +} + +function isEvaluatingExpression(state) { + return state.pause.command === "expression"; +} + +function getPopupObjectProperties(state, objectId) { + return getAllPopupObjectProperties(state)[objectId]; +} + +function getIsWaitingOnBreak(state) { + return state.pause.isWaitingOnBreak; +} + +function getShouldPauseOnExceptions(state) { + return state.pause.shouldPauseOnExceptions; +} + +function getShouldPauseOnCaughtExceptions(state) { + return state.pause.shouldPauseOnCaughtExceptions; +} + +function getCanRewind(state) { + return state.pause.canRewind; +} + +function getExtra(state) { + return state.pause.extra; +} + +function getFrames(state) { + return state.pause.frames; +} + +function getGeneratedFrameScope(state, frameId) { + if (!frameId) { + return null; + } + + return getFrameScopes(state).generated[frameId]; +} + +function getOriginalFrameScope(state, sourceId, frameId) { + if (!frameId || !sourceId) { + return null; + } + + const isGenerated = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); + const original = getFrameScopes(state).original[frameId]; + + if (!isGenerated && original && (original.pending || original.scope)) { + return original; + } + + return null; +} + +function getFrameScopes(state) { + return state.pause.frameScopes; +} + +function getFrameScope(state, sourceId, frameId) { + return getOriginalFrameScope(state, sourceId, frameId) || getGeneratedFrameScope(state, frameId); +} + +function getSelectedScope(state) { + const sourceRecord = (0, _sources.getSelectedSource)(state); + const frameId = getSelectedFrameId(state); + const { + scope + } = getFrameScope(state, sourceRecord && sourceRecord.get("id"), frameId) || {}; + return scope || null; +} + +function getSelectedScopeMappings(state) { + const frameId = getSelectedFrameId(state); + + if (!frameId) { + return null; + } + + return getFrameScopes(state).mappings[frameId]; +} + +function getSelectedFrameId(state) { + return state.pause.selectedFrameId; +} + +function getTopFrame(state) { + const frames = getFrames(state); + return frames && frames[0]; +} + +const getSelectedFrame = exports.getSelectedFrame = (0, _reselect.createSelector)(getSelectedFrameId, getFrames, (selectedFrameId, frames) => { + if (!frames) { + return null; + } + + return frames.find(frame => frame.id == selectedFrameId); +}); + +function getDebuggeeUrl(state) { + return state.pause.debuggeeUrl; +} + +function getSkipPausing(state) { + return state.pause.skipPausing; +} // NOTE: currently only used for chrome + + +function getChromeScopes(state) { + const frame = getSelectedFrame(state); + return frame ? frame.scopeChain : undefined; +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/pending-breakpoints.js b/devtools/client/debugger/new/src/reducers/pending-breakpoints.js new file mode 100644 index 000000000000..bfa0a1680ed4 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/pending-breakpoints.js @@ -0,0 +1,176 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.initialPendingBreakpointsState = initialPendingBreakpointsState; +exports.getPendingBreakpoints = getPendingBreakpoints; +exports.getPendingBreakpointsForSource = getPendingBreakpointsForSource; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _breakpoint = require("../utils/breakpoint/index"); + +var _prefs = require("../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Pending breakpoints reducer + * @module reducers/pending-breakpoints + */ +function initialPendingBreakpointsState() { + return (0, _makeRecord2.default)({ + pendingBreakpoints: restorePendingBreakpoints() + })(); +} + +function update(state = initialPendingBreakpointsState(), action) { + switch (action.type) { + case "ADD_BREAKPOINT": + { + if (action.breakpoint.hidden) { + return state; + } + + return addBreakpoint(state, action); + } + + case "SYNC_BREAKPOINT": + { + return syncBreakpoint(state, action); + } + + case "ENABLE_BREAKPOINT": + { + return addBreakpoint(state, action); + } + + case "DISABLE_BREAKPOINT": + { + return updateBreakpoint(state, action); + } + + case "DISABLE_ALL_BREAKPOINTS": + { + return updateAllBreakpoints(state, action); + } + + case "ENABLE_ALL_BREAKPOINTS": + { + return updateAllBreakpoints(state, action); + } + + case "SET_BREAKPOINT_CONDITION": + { + return updateBreakpoint(state, action); + } + + case "REMOVE_BREAKPOINT": + { + if (action.breakpoint.hidden) { + return state; + } + + return removeBreakpoint(state, action); + } + } + + return state; +} + +function addBreakpoint(state, action) { + if (action.status !== "done") { + return state; + } // when the action completes, we can commit the breakpoint + + + const { + breakpoint + } = action.value; + const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); + const pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint); + return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint); +} + +function syncBreakpoint(state, action) { + const { + breakpoint, + previousLocation + } = action; + + if (previousLocation) { + state = state.deleteIn(["pendingBreakpoints", (0, _breakpoint.makePendingLocationId)(previousLocation)]); + } + + if (!breakpoint) { + return state; + } + + const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); + const pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint); + return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint); +} + +function updateBreakpoint(state, action) { + const { + breakpoint + } = action; + const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); + const pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint); + return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint); +} + +function updateAllBreakpoints(state, action) { + const { + breakpoints + } = action; + breakpoints.forEach(breakpoint => { + const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); + state = state.setIn(["pendingBreakpoints", locationId], breakpoint); + }); + return state; +} + +function removeBreakpoint(state, action) { + const { + breakpoint + } = action; + const locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location); + const pendingBp = state.pendingBreakpoints.get(locationId); + + if (!pendingBp && action.status == "start") { + return state.set("pendingBreakpoints", I.Map()); + } + + return state.deleteIn(["pendingBreakpoints", locationId]); +} // Selectors +// TODO: these functions should be moved out of the reducer + + +function getPendingBreakpoints(state) { + return state.pendingBreakpoints.pendingBreakpoints; +} + +function getPendingBreakpointsForSource(state, sourceUrl) { + const pendingBreakpoints = state.pendingBreakpoints.pendingBreakpoints || I.Map(); + return pendingBreakpoints.filter(pendingBreakpoint => pendingBreakpoint.location.sourceUrl === sourceUrl); +} + +function restorePendingBreakpoints() { + return I.Map(_prefs.prefs.pendingBreakpoints); +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/project-text-search.js b/devtools/client/debugger/new/src/reducers/project-text-search.js new file mode 100644 index 000000000000..d2f23e7e0ac4 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/project-text-search.js @@ -0,0 +1,100 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.statusType = undefined; +exports.initialProjectTextSearchState = initialProjectTextSearchState; +exports.getTextSearchResults = getTextSearchResults; +exports.getTextSearchStatus = getTextSearchStatus; +exports.getTextSearchQuery = getTextSearchQuery; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// @format + +/** + * Project text search reducer + * @module reducers/project-text-search + */ +const statusType = exports.statusType = { + initial: "INITIAL", + fetching: "FETCHING", + done: "DONE", + error: "ERROR" +}; + +function initialProjectTextSearchState() { + return (0, _makeRecord2.default)({ + query: "", + results: I.List(), + status: statusType.initial + })(); +} + +function update(state = initialProjectTextSearchState(), action) { + switch (action.type) { + case "ADD_QUERY": + const actionCopy = action; + return state.update("query", value => actionCopy.query); + + case "CLEAR_QUERY": + return state.merge({ + query: "", + status: statusType.initial + }); + + case "ADD_SEARCH_RESULT": + const results = state.get("results"); + return state.merge({ + results: results.push(action.result) + }); + + case "UPDATE_STATUS": + return state.merge({ + status: action.status + }); + + case "CLEAR_SEARCH_RESULTS": + return state.merge({ + results: state.get("results").clear() + }); + + case "CLEAR_SEARCH": + case "CLOSE_PROJECT_SEARCH": + return state.merge({ + query: "", + results: state.get("results").clear(), + status: statusType.initial + }); + } + + return state; +} + +function getTextSearchResults(state) { + return state.projectTextSearch.get("results"); +} + +function getTextSearchStatus(state) { + return state.projectTextSearch.get("status"); +} + +function getTextSearchQuery(state) { + return state.projectTextSearch.get("query"); +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/quick-open.js b/devtools/client/debugger/new/src/reducers/quick-open.js new file mode 100644 index 000000000000..c7bba2a86072 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/quick-open.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createQuickOpenState = undefined; +exports.default = update; +exports.getQuickOpenEnabled = getQuickOpenEnabled; +exports.getQuickOpenQuery = getQuickOpenQuery; +exports.getQuickOpenType = getQuickOpenType; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _quickOpen = require("../utils/quick-open"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Quick Open reducer + * @module reducers/quick-open + */ +const createQuickOpenState = exports.createQuickOpenState = (0, _makeRecord2.default)({ + enabled: false, + query: "", + searchType: "sources" +}); + +function update(state = createQuickOpenState(), action) { + switch (action.type) { + case "OPEN_QUICK_OPEN": + if (action.query != null) { + return state.merge({ + enabled: true, + query: action.query, + searchType: (0, _quickOpen.parseQuickOpenQuery)(action.query) + }); + } + + return state.set("enabled", true); + + case "CLOSE_QUICK_OPEN": + return createQuickOpenState(); + + case "SET_QUICK_OPEN_QUERY": + return state.merge({ + query: action.query, + searchType: (0, _quickOpen.parseQuickOpenQuery)(action.query) + }); + + default: + return state; + } +} + +function getQuickOpenEnabled(state) { + return state.quickOpen.get("enabled"); +} + +function getQuickOpenQuery(state) { + return state.quickOpen.get("query"); +} + +function getQuickOpenType(state) { + return state.quickOpen.get("searchType"); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/replay.js b/devtools/client/debugger/new/src/reducers/replay.js new file mode 100644 index 000000000000..d32c22c5d39d --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/replay.js @@ -0,0 +1,216 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.initialState = initialState; +exports.getHistory = getHistory; +exports.getHistoryFrame = getHistoryFrame; +exports.getHistoryPosition = getHistoryPosition; + +var _prefs = require("../utils/prefs"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function initialState() { + return { + history: [], + position: -1 + }; +} + +const defaultFrameScopes = { + original: {}, + generated: {} +}; + +function update(state = initialState(), action) { + if (!_prefs.features.replay) { + return state; + } + + switch (action.type) { + case "TRAVEL_TO": + { + return _objectSpread({}, state, { + position: action.position + }); + } + + case "ADD_SCOPES": + { + return addScopes(state, action); + } + + case "MAP_SCOPES": + { + return mapScopes(state, action); + } + + case "CLEAR_HISTORY": + { + return { + history: [], + position: -1 + }; + } + + case "PAUSED": + { + return paused(state, action); + } + + case "EVALUATE_EXPRESSION": + { + return evaluateExpression(state, action); + } + } + + return state; +} + +function addScopes(state, action) { + const { + frame, + status, + value + } = action; + const selectedFrameId = frame.id; + const instance = state.history[state.position]; + + if (!instance) { + return state; + } + + const pausedInst = instance.paused; + + const generated = _objectSpread({}, pausedInst.frameScopes.generated, { + [selectedFrameId]: { + pending: status !== "done", + scope: value + } + }); + + const newPaused = _objectSpread({}, pausedInst, { + frameScopes: _objectSpread({}, pausedInst.frameScopes, { + generated + }) + }); + + const history = [...state.history]; + history[state.position] = _objectSpread({}, instance, { + paused: newPaused + }); + return _objectSpread({}, state, { + history + }); +} + +function mapScopes(state, action) { + const { + frame, + status, + value + } = action; + const selectedFrameId = frame.id; + const instance = state.history[state.position]; + + if (!instance) { + return state; + } + + const pausedInst = instance.paused; + + const original = _objectSpread({}, pausedInst.frameScopes.original, { + [selectedFrameId]: { + pending: status !== "done", + scope: value + } + }); + + const newPaused = _objectSpread({}, pausedInst, { + frameScopes: _objectSpread({}, pausedInst.frameScopes, { + original + }) + }); + + const history = [...state.history]; + history[state.position] = _objectSpread({}, instance, { + paused: newPaused + }); + return _objectSpread({}, state, { + history + }); +} + +function evaluateExpression(state, action) { + const { + input, + value + } = action; + const instance = state.history[state.position]; + + if (!instance) { + return state; + } + + const prevExpressions = instance.expressions || []; + const expression = { + input, + value + }; + const expressions = [...prevExpressions, expression]; + const history = [...state.history]; + history[state.position] = _objectSpread({}, instance, { + expressions + }); + return _objectSpread({}, state, { + history + }); +} + +function paused(state, action) { + const { + selectedFrameId, + frames, + loadedObjects, + why + } = action; // turn this into an object keyed by object id + + const objectMap = {}; + loadedObjects.forEach(obj => { + objectMap[obj.value.objectId] = obj; + }); + const pausedInfo = { + isWaitingOnBreak: false, + selectedFrameId, + frames, + frameScopes: defaultFrameScopes, + loadedObjects: objectMap, + why + }; + const history = [...state.history, { + paused: pausedInfo + }]; + const position = state.position + 1; + return _objectSpread({}, state, { + history, + position + }); +} + +function getHistory(state) { + return state.replay.history; +} + +function getHistoryFrame(state, position) { + return state.replay.history[position]; +} + +function getHistoryPosition(state) { + return state.replay.position; +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/source-tree.js b/devtools/client/debugger/new/src/reducers/source-tree.js new file mode 100644 index 000000000000..f9de236264fa --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/source-tree.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.InitialState = InitialState; +exports.default = update; +exports.getExpandedState = getExpandedState; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Source tree reducer + * @module reducers/source-tree + */ +function InitialState() { + return (0, _makeRecord2.default)({ + expanded: null + })(); +} + +function update(state = InitialState(), action) { + switch (action.type) { + case "SET_EXPANDED_STATE": + return state.set("expanded", action.expanded); + } + + return state; +} + +function getExpandedState(state) { + return state.sourceTree.get("expanded"); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/sources.js b/devtools/client/debugger/new/src/reducers/sources.js new file mode 100644 index 000000000000..93dc324ca8f3 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/sources.js @@ -0,0 +1,408 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getSelectedSourceText = exports.getSelectedSource = exports.getSelectedLocation = exports.getSourcesForTabs = exports.getSourceTabs = exports.getTabs = exports.getSources = exports.SourceRecordClass = undefined; +exports.initialSourcesState = initialSourcesState; +exports.removeSourceFromTabList = removeSourceFromTabList; +exports.removeSourcesFromTabList = removeSourcesFromTabList; +exports.getBlackBoxList = getBlackBoxList; +exports.getNewSelectedSourceId = getNewSelectedSourceId; +exports.getSource = getSource; +exports.getSourceByURL = getSourceByURL; +exports.getGeneratedSource = getGeneratedSource; +exports.getPendingSelectedLocation = getPendingSelectedLocation; +exports.getPrettySource = getPrettySource; +exports.hasPrettySource = hasPrettySource; +exports.getSourceInSources = getSourceInSources; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _source = require("../utils/source"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _prefs = require("../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function initialSourcesState() { + return (0, _makeRecord2.default)({ + sources: I.Map(), + selectedLocation: undefined, + pendingSelectedLocation: _prefs.prefs.pendingSelectedLocation, + sourcesText: I.Map(), + tabs: I.List(restoreTabs()) + })(); +} + +const SourceRecordClass = exports.SourceRecordClass = new I.Record({ + id: undefined, + url: undefined, + sourceMapURL: undefined, + isBlackBoxed: false, + isPrettyPrinted: false, + isWasm: false, + text: undefined, + contentType: "", + error: undefined, + loadedState: "unloaded" +}); + +function update(state = initialSourcesState(), action) { + let location = null; + + switch (action.type) { + case "UPDATE_SOURCE": + { + const source = action.source; + return updateSource(state, source); + } + + case "ADD_SOURCE": + { + const source = action.source; + return updateSource(state, source); + } + + case "ADD_SOURCES": + { + return action.sources.reduce((newState, source) => updateSource(newState, source), state); + } + + case "SELECT_SOURCE": + location = _objectSpread({}, action.location, { + url: action.source.url + }); + _prefs.prefs.pendingSelectedLocation = location; + return state.set("selectedLocation", _objectSpread({ + sourceId: action.source.id + }, action.location)).set("pendingSelectedLocation", location); + + case "CLEAR_SELECTED_SOURCE": + location = { + url: "" + }; + _prefs.prefs.pendingSelectedLocation = location; + return state.set("selectedLocation", { + sourceId: "" + }).set("pendingSelectedLocation", location); + + case "SELECT_SOURCE_URL": + location = { + url: action.url, + line: action.line + }; + _prefs.prefs.pendingSelectedLocation = location; + return state.set("pendingSelectedLocation", location); + + case "ADD_TAB": + return state.merge({ + tabs: updateTabList({ + sources: state + }, action.source.url) + }); + + case "MOVE_TAB": + return state.merge({ + tabs: updateTabList({ + sources: state + }, action.url, action.tabIndex) + }); + + case "CLOSE_TAB": + _prefs.prefs.tabs = action.tabs; + return state.merge({ + tabs: action.tabs + }); + + case "CLOSE_TABS": + _prefs.prefs.tabs = action.tabs; + return state.merge({ + tabs: action.tabs + }); + + case "LOAD_SOURCE_TEXT": + return setSourceTextProps(state, action); + + case "BLACKBOX": + if (action.status === "done") { + const url = action.source.url; + const { + isBlackBoxed + } = action.value; + updateBlackBoxList(url, isBlackBoxed); + return state.setIn(["sources", action.source.id, "isBlackBoxed"], isBlackBoxed); + } + + break; + + case "NAVIGATE": + const source = getSelectedSource({ + sources: state + }); + const url = source && source.url; + + if (!url) { + return initialSourcesState(); + } + + return initialSourcesState().set("pendingSelectedLocation", { + url + }); + } + + return state; +} + +function getTextPropsFromAction(action) { + const { + value, + sourceId + } = action; + + if (action.status === "start") { + return { + id: sourceId, + loadedState: "loading" + }; + } else if (action.status === "error") { + return { + id: sourceId, + error: action.error, + loadedState: "loaded" + }; + } + + return { + text: value.text, + id: sourceId, + contentType: value.contentType, + loadedState: "loaded" + }; +} // TODO: Action is coerced to `any` unfortunately because how we type +// asynchronous actions is wrong. The `value` may be null for the +// "start" and "error" states but we don't type it like that. We need +// to rethink how we type async actions. + + +function setSourceTextProps(state, action) { + const text = getTextPropsFromAction(action); + return updateSource(state, text); +} + +function updateSource(state, source) { + if (!source.id) { + return state; + } + + const existingSource = state.sources.get(source.id); + + if (existingSource) { + const updatedSource = existingSource.merge(source); + return state.setIn(["sources", source.id], updatedSource); + } + + return state.setIn(["sources", source.id], new SourceRecordClass(source)); +} + +function removeSourceFromTabList(tabs, url) { + return tabs.filter(tab => tab != url); +} + +function removeSourcesFromTabList(tabs, urls) { + return urls.reduce((t, url) => removeSourceFromTabList(t, url), tabs); +} + +function restoreTabs() { + const prefsTabs = _prefs.prefs.tabs || []; + + if (prefsTabs.length == 0) { + return; + } + + return prefsTabs; +} +/** + * Adds the new source to the tab list if it is not already there + * @memberof reducers/sources + * @static + */ + + +function updateTabList(state, url, tabIndex) { + let tabs = state.sources.tabs; + const urlIndex = tabs.indexOf(url); + const includesUrl = !!tabs.find(tab => tab == url); + + if (includesUrl) { + if (tabIndex != undefined) { + tabs = tabs.delete(urlIndex).insert(tabIndex, url); + } + } else { + tabs = tabs.insert(0, url); + } + + _prefs.prefs.tabs = tabs.toJS(); + return tabs; +} + +function updateBlackBoxList(url, isBlackBoxed) { + const tabs = getBlackBoxList(); + const i = tabs.indexOf(url); + + if (i >= 0) { + if (!isBlackBoxed) { + tabs.splice(i, 1); + } + } else if (isBlackBoxed) { + tabs.push(url); + } + + _prefs.prefs.tabsBlackBoxed = tabs; +} + +function getBlackBoxList() { + return _prefs.prefs.tabsBlackBoxed || []; +} +/** + * Gets the next tab to select when a tab closes. Heuristics: + * 1. if the selected tab is available, it remains selected + * 2. if it is gone, the next available tab to the left should be active + * 3. if the first tab is active and closed, select the second tab + * + * @memberof reducers/sources + * @static + */ + + +function getNewSelectedSourceId(state, availableTabs) { + const selectedLocation = state.sources.selectedLocation; + + if (!selectedLocation) { + return ""; + } + + const selectedTab = state.sources.sources.get(selectedLocation.sourceId); + const selectedTabUrl = selectedTab ? selectedTab.url : ""; + + if (availableTabs.includes(selectedTabUrl)) { + const sources = state.sources.sources; + + if (!sources) { + return ""; + } + + const selectedSource = sources.find(source => source.url == selectedTabUrl); + + if (selectedSource) { + return selectedSource.id; + } + + return ""; + } + + const tabUrls = state.sources.tabs; + const leftNeighborIndex = Math.max(tabUrls.indexOf(selectedTabUrl) - 1, 0); + const lastAvailbleTabIndex = availableTabs.size - 1; + const newSelectedTabIndex = Math.min(leftNeighborIndex, lastAvailbleTabIndex); + const availableTab = availableTabs.get(newSelectedTabIndex); + const tabSource = getSourceByUrlInSources(state.sources.sources, availableTab); + + if (tabSource) { + return tabSource.id; + } + + return ""; +} // Selectors +// Unfortunately, it's really hard to make these functions accept just +// the state that we care about and still type it with Flow. The +// problem is that we want to re-export all selectors from a single +// module for the UI, and all of those selectors should take the +// top-level app state, so we'd have to "wrap" them to automatically +// pick off the piece of state we're interested in. It's impossible +// (right now) to type those wrapped functions. + + +const getSourcesState = state => state.sources; + +function getSource(state, id) { + return getSourceInSources(getSources(state), id); +} + +function getSourceByURL(state, url) { + return getSourceByUrlInSources(state.sources.sources, url); +} + +function getGeneratedSource(state, source) { + if (!source || !(0, _devtoolsSourceMap.isOriginalId)(source.id)) { + return null; + } + + return getSource(state, (0, _devtoolsSourceMap.originalToGeneratedId)(source.id)); +} + +function getPendingSelectedLocation(state) { + return state.sources.pendingSelectedLocation; +} + +function getPrettySource(state, id) { + const source = getSource(state, id); + + if (!source) { + return; + } + + return getSourceByURL(state, (0, _source.getPrettySourceURL)(source.url)); +} + +function hasPrettySource(state, id) { + return !!getPrettySource(state, id); +} + +function getSourceByUrlInSources(sources, url) { + if (!url) { + return null; + } + + return sources.find(source => source.url === url); +} + +function getSourceInSources(sources, id) { + return sources.get(id); +} + +const getSources = exports.getSources = (0, _reselect.createSelector)(getSourcesState, sources => sources.sources); +const getTabs = exports.getTabs = (0, _reselect.createSelector)(getSourcesState, sources => sources.tabs); +const getSourceTabs = exports.getSourceTabs = (0, _reselect.createSelector)(getTabs, getSources, (tabs, sources) => tabs.filter(tab => getSourceByUrlInSources(sources, tab))); +const getSourcesForTabs = exports.getSourcesForTabs = (0, _reselect.createSelector)(getSourceTabs, getSources, (tabs, sources) => { + return tabs.map(tab => getSourceByUrlInSources(sources, tab)).filter(source => source); +}); +const getSelectedLocation = exports.getSelectedLocation = (0, _reselect.createSelector)(getSourcesState, sources => sources.selectedLocation); +const getSelectedSource = exports.getSelectedSource = (0, _reselect.createSelector)(getSelectedLocation, getSources, (selectedLocation, sources) => { + if (!selectedLocation) { + return; + } + + return sources.get(selectedLocation.sourceId); +}); +const getSelectedSourceText = exports.getSelectedSourceText = (0, _reselect.createSelector)(getSelectedSource, getSourcesState, (selectedSource, sources) => { + const id = selectedSource.id; + return id ? sources.sourcesText.get(id) : null; +}); +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/ui.js b/devtools/client/debugger/new/src/reducers/ui.js new file mode 100644 index 000000000000..05f86a618a69 --- /dev/null +++ b/devtools/client/debugger/new/src/reducers/ui.js @@ -0,0 +1,184 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createUIState = undefined; +exports.getSelectedPrimaryPaneTab = getSelectedPrimaryPaneTab; +exports.getActiveSearch = getActiveSearch; +exports.getContextMenu = getContextMenu; +exports.getFrameworkGroupingState = getFrameworkGroupingState; +exports.getShownSource = getShownSource; +exports.getPaneCollapse = getPaneCollapse; +exports.getHighlightedLineRange = getHighlightedLineRange; +exports.getConditionalPanelLine = getConditionalPanelLine; +exports.getProjectDirectoryRoot = getProjectDirectoryRoot; +exports.getOrientation = getOrientation; + +var _makeRecord = require("../utils/makeRecord"); + +var _makeRecord2 = _interopRequireDefault(_makeRecord); + +var _prefs = require("../utils/prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * UI reducer + * @module reducers/ui + */ +const createUIState = exports.createUIState = (0, _makeRecord2.default)({ + selectedPrimaryPaneTab: "sources", + activeSearch: null, + contextMenu: {}, + shownSource: "", + projectDirectoryRoot: _prefs.prefs.projectDirectoryRoot, + startPanelCollapsed: _prefs.prefs.startPanelCollapsed, + endPanelCollapsed: _prefs.prefs.endPanelCollapsed, + frameworkGroupingOn: _prefs.prefs.frameworkGroupingOn, + highlightedLineRange: undefined, + conditionalPanelLine: null, + orientation: "horizontal" +}); + +function update(state = createUIState(), action) { + switch (action.type) { + case "TOGGLE_ACTIVE_SEARCH": + { + return state.set("activeSearch", action.value); + } + + case "TOGGLE_FRAMEWORK_GROUPING": + { + _prefs.prefs.frameworkGroupingOn = action.value; + return state.set("frameworkGroupingOn", action.value); + } + + case "SET_CONTEXT_MENU": + { + return state.set("contextMenu", action.contextMenu); + } + + case "SET_ORIENTATION": + { + return state.set("orientation", action.orientation); + } + + case "SHOW_SOURCE": + { + return state.set("shownSource", action.sourceUrl); + } + + case "TOGGLE_PANE": + { + if (action.position == "start") { + _prefs.prefs.startPanelCollapsed = action.paneCollapsed; + return state.set("startPanelCollapsed", action.paneCollapsed); + } + + _prefs.prefs.endPanelCollapsed = action.paneCollapsed; + return state.set("endPanelCollapsed", action.paneCollapsed); + } + + case "HIGHLIGHT_LINES": + const { + start, + end, + sourceId + } = action.location; + let lineRange = {}; + + if (start && end && sourceId) { + lineRange = { + start, + end, + sourceId + }; + } + + return state.set("highlightedLineRange", lineRange); + + case "CLOSE_QUICK_OPEN": + case "CLEAR_HIGHLIGHT_LINES": + return state.set("highlightedLineRange", {}); + + case "OPEN_CONDITIONAL_PANEL": + return state.set("conditionalPanelLine", action.line); + + case "CLOSE_CONDITIONAL_PANEL": + return state.set("conditionalPanelLine", null); + + case "SET_PROJECT_DIRECTORY_ROOT": + _prefs.prefs.projectDirectoryRoot = action.url; + return state.set("projectDirectoryRoot", action.url); + + case "SET_PRIMARY_PANE_TAB": + return state.set("selectedPrimaryPaneTab", action.tabName); + + case "CLOSE_PROJECT_SEARCH": + { + if (state.get("activeSearch") === "project") { + return state.set("activeSearch", null); + } + + return state; + } + + default: + { + return state; + } + } +} // NOTE: we'd like to have the app state fully typed +// https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185 + + +function getSelectedPrimaryPaneTab(state) { + return state.ui.get("selectedPrimaryPaneTab"); +} + +function getActiveSearch(state) { + return state.ui.get("activeSearch"); +} + +function getContextMenu(state) { + return state.ui.get("contextMenu"); +} + +function getFrameworkGroupingState(state) { + return state.ui.get("frameworkGroupingOn"); +} + +function getShownSource(state) { + return state.ui.get("shownSource"); +} + +function getPaneCollapse(state, position) { + if (position == "start") { + return state.ui.get("startPanelCollapsed"); + } + + return state.ui.get("endPanelCollapsed"); +} + +function getHighlightedLineRange(state) { + return state.ui.get("highlightedLineRange"); +} + +function getConditionalPanelLine(state) { + return state.ui.get("conditionalPanelLine"); +} + +function getProjectDirectoryRoot(state) { + return state.ui.get("projectDirectoryRoot"); +} + +function getOrientation(state) { + return state.ui.get("orientation"); +} + +exports.default = update; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/breakpointAtLocation.js b/devtools/client/debugger/new/src/selectors/breakpointAtLocation.js new file mode 100644 index 000000000000..a528d58dd744 --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/breakpointAtLocation.js @@ -0,0 +1,74 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getBreakpointAtLocation = getBreakpointAtLocation; + +var _sources = require("../reducers/sources"); + +var _breakpoints = require("../reducers/breakpoints"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function isGenerated(selectedSource) { + const sourceId = selectedSource.get("id"); + return (0, _devtoolsSourceMap.isGeneratedId)(sourceId); +} + +function getColumn(column, selectedSource) { + if (column) { + return column; + } + + return isGenerated(selectedSource) ? undefined : 0; +} + +function getLocation(bp, selectedSource) { + return isGenerated(selectedSource) ? bp.generatedLocation || bp.location : bp.location; +} + +function getBreakpointsForSource(state, selectedSource) { + const breakpoints = (0, _breakpoints.getBreakpoints)(state); + return breakpoints.filter(bp => { + const location = getLocation(bp, selectedSource); + return location.sourceId === selectedSource.get("id"); + }); +} + +function findBreakpointAtLocation(breakpoints, selectedSource, { + line, + column +}) { + return breakpoints.find(breakpoint => { + const location = getLocation(breakpoint, selectedSource); + const sameLine = location.line === line; + + if (!sameLine) { + return false; + } + + if (column === undefined) { + return true; + } + + return location.column === getColumn(column, selectedSource); + }); +} +/* + * Finds a breakpoint at a location (line, column) of the + * selected source. + * + * This is useful for finding a breakpoint when the + * user clicks in the gutter or on a token. + */ + + +function getBreakpointAtLocation(state, location) { + const selectedSource = (0, _sources.getSelectedSource)(state); + const breakpoints = getBreakpointsForSource(state, selectedSource); + return findBreakpointAtLocation(breakpoints, selectedSource, location); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/getCallStackFrames.js b/devtools/client/debugger/new/src/selectors/getCallStackFrames.js new file mode 100644 index 000000000000..32d5f345d2c5 --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/getCallStackFrames.js @@ -0,0 +1,51 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getCallStackFrames = undefined; +exports.formatCallStackFrames = formatCallStackFrames; + +var _sources = require("../reducers/sources"); + +var _pause = require("../reducers/pause"); + +var _frames = require("../utils/pause/frames/index"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getLocation(frame, isGeneratedSource) { + return isGeneratedSource ? frame.generatedLocation || frame.location : frame.location; +} + +function getSourceForFrame(sources, frame, isGeneratedSource) { + const sourceId = getLocation(frame, isGeneratedSource).sourceId; + return (0, _sources.getSourceInSources)(sources, sourceId); +} + +function appendSource(sources, frame, selectedSource) { + const isGeneratedSource = selectedSource && !(0, _devtoolsSourceMap.isOriginalId)(selectedSource.get("id")); + return _objectSpread({}, frame, { + location: getLocation(frame, isGeneratedSource), + source: getSourceForFrame(sources, frame, isGeneratedSource).toJS() + }); +} + +function formatCallStackFrames(frames, sources, selectedSource) { + if (!frames) { + return null; + } + + const formattedFrames = frames.filter(frame => getSourceForFrame(sources, frame)).map(frame => appendSource(sources, frame, selectedSource)).filter(frame => !(0, _lodash.get)(frame, "source.isBlackBoxed")); + return (0, _frames.annotateFrames)(formattedFrames); +} + +const getCallStackFrames = exports.getCallStackFrames = (0, _reselect.createSelector)(_pause.getFrames, _sources.getSources, _sources.getSelectedSource, formatCallStackFrames); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/getRelativeSources.js b/devtools/client/debugger/new/src/selectors/getRelativeSources.js new file mode 100644 index 000000000000..fd9b268509c3 --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/getRelativeSources.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getRelativeSources = getRelativeSources; + +var _selectors = require("../selectors/index"); + +var _source = require("../utils/source"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getRelativeUrl(url, root) { + if (!root) { + return (0, _source.getSourcePath)(url); + } // + 1 removes the leading "/" + + + return url.slice(url.indexOf(root) + root.length + 1); +} + +function formatSource(source, root) { + return _objectSpread({}, source, { + relativeUrl: getRelativeUrl(source.url, root) + }); +} +/* + * Gets the sources that are below a project root + */ + + +function getRelativeSources(state) { + const sources = (0, _selectors.getSources)(state); + const root = (0, _selectors.getProjectDirectoryRoot)(state); + return sources.valueSeq().toJS().filter(({ + url + }) => url && url.includes(root)).map(source => formatSource(source, root)); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/index.js b/devtools/client/debugger/new/src/selectors/index.js new file mode 100644 index 000000000000..98e7ef5589c8 --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/index.js @@ -0,0 +1,245 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _expressions = require("../reducers/expressions"); + +Object.keys(_expressions).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _expressions[key]; + } + }); +}); + +var _sources = require("../reducers/sources"); + +Object.keys(_sources).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _sources[key]; + } + }); +}); + +var _pause = require("../reducers/pause"); + +Object.keys(_pause).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _pause[key]; + } + }); +}); + +var _debuggee = require("../reducers/debuggee"); + +Object.keys(_debuggee).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _debuggee[key]; + } + }); +}); + +var _breakpoints = require("../reducers/breakpoints"); + +Object.keys(_breakpoints).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _breakpoints[key]; + } + }); +}); + +var _pendingBreakpoints = require("../reducers/pending-breakpoints"); + +Object.keys(_pendingBreakpoints).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _pendingBreakpoints[key]; + } + }); +}); + +var _ui = require("../reducers/ui"); + +Object.keys(_ui).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _ui[key]; + } + }); +}); + +var _fileSearch = require("../reducers/file-search"); + +Object.keys(_fileSearch).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _fileSearch[key]; + } + }); +}); + +var _ast = require("../reducers/ast"); + +Object.keys(_ast).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _ast[key]; + } + }); +}); + +var _coverage = require("../reducers/coverage"); + +Object.keys(_coverage).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _coverage[key]; + } + }); +}); + +var _projectTextSearch = require("../reducers/project-text-search"); + +Object.keys(_projectTextSearch).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _projectTextSearch[key]; + } + }); +}); + +var _replay = require("../reducers/replay"); + +Object.keys(_replay).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _replay[key]; + } + }); +}); + +var _sourceTree = require("../reducers/source-tree"); + +Object.keys(_sourceTree).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _sourceTree[key]; + } + }); +}); + +var _eventListeners = require("../reducers/event-listeners"); + +Object.defineProperty(exports, "getEventListeners", { + enumerable: true, + get: function () { + return _eventListeners.getEventListeners; + } +}); + +var _quickOpen = require("../reducers/quick-open"); + +Object.defineProperty(exports, "getQuickOpenEnabled", { + enumerable: true, + get: function () { + return _quickOpen.getQuickOpenEnabled; + } +}); +Object.defineProperty(exports, "getQuickOpenQuery", { + enumerable: true, + get: function () { + return _quickOpen.getQuickOpenQuery; + } +}); +Object.defineProperty(exports, "getQuickOpenType", { + enumerable: true, + get: function () { + return _quickOpen.getQuickOpenType; + } +}); + +var _breakpointAtLocation = require("./breakpointAtLocation"); + +Object.defineProperty(exports, "getBreakpointAtLocation", { + enumerable: true, + get: function () { + return _breakpointAtLocation.getBreakpointAtLocation; + } +}); + +var _visibleBreakpoints = require("./visibleBreakpoints"); + +Object.defineProperty(exports, "getVisibleBreakpoints", { + enumerable: true, + get: function () { + return _visibleBreakpoints.getVisibleBreakpoints; + } +}); + +var _isSelectedFrameVisible = require("./isSelectedFrameVisible"); + +Object.defineProperty(exports, "isSelectedFrameVisible", { + enumerable: true, + get: function () { + return _isSelectedFrameVisible.isSelectedFrameVisible; + } +}); + +var _getCallStackFrames = require("./getCallStackFrames"); + +Object.defineProperty(exports, "getCallStackFrames", { + enumerable: true, + get: function () { + return _getCallStackFrames.getCallStackFrames; + } +}); + +var _visibleSelectedFrame = require("./visibleSelectedFrame"); + +Object.defineProperty(exports, "getVisibleSelectedFrame", { + enumerable: true, + get: function () { + return _visibleSelectedFrame.getVisibleSelectedFrame; + } +}); + +var _getRelativeSources = require("./getRelativeSources"); + +Object.defineProperty(exports, "getRelativeSources", { + enumerable: true, + get: function () { + return _getRelativeSources.getRelativeSources; + } +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js b/devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js new file mode 100644 index 000000000000..c536c822f71f --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js @@ -0,0 +1,43 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isSelectedFrameVisible = isSelectedFrameVisible; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _pause = require("../reducers/pause"); + +var _sources = require("../reducers/sources"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getGeneratedId(sourceId) { + if ((0, _devtoolsSourceMap.isOriginalId)(sourceId)) { + return (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId); + } + + return sourceId; +} +/* + * Checks to if the selected frame's source is currently + * selected. + */ + + +function isSelectedFrameVisible(state) { + const selectedLocation = (0, _sources.getSelectedLocation)(state); + const selectedFrame = (0, _pause.getSelectedFrame)(state); + + if (!selectedFrame || !selectedLocation) { + return false; + } + + if ((0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId)) { + return selectedLocation.sourceId === selectedFrame.location.sourceId; + } + + return selectedLocation.sourceId === getGeneratedId(selectedFrame.location.sourceId); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/moz.build b/devtools/client/debugger/new/src/selectors/moz.build new file mode 100644 index 000000000000..39cdff3309fc --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/moz.build @@ -0,0 +1,18 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'test', +] + +DevToolsModules( + 'breakpointAtLocation.js', + 'getCallStackFrames.js', + 'getRelativeSources.js', + 'index.js', + 'isSelectedFrameVisible.js', + 'visibleBreakpoints.js', + 'visibleSelectedFrame.js', +) diff --git a/devtools/client/debugger/new/src/selectors/test/getCallStackFrames.spec.js b/devtools/client/debugger/new/src/selectors/test/getCallStackFrames.spec.js new file mode 100644 index 000000000000..1df8ec30a6e3 --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/test/getCallStackFrames.spec.js @@ -0,0 +1,189 @@ +"use strict"; + +var _getCallStackFrames = require("../getCallStackFrames"); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +describe("getCallStackFrames selector", () => { + describe("library annotation", () => { + it("annotates React frames", () => { + const state = { + frames: [{ + location: { + sourceId: "source1" + } + }, { + location: { + sourceId: "source2" + } + }, { + location: { + sourceId: "source2" + } + }], + sources: (0, _immutable.fromJS)({ + source1: { + id: "source1", + url: "webpack:///src/App.js" + }, + source2: { + id: "source2", + url: "webpack:///~/react-dom/lib/ReactCompositeComponent.js" + } + }), + selectedSource: (0, _immutable.fromJS)({ + id: "sourceId-originalSource" + }) + }; + + const frames = _getCallStackFrames.getCallStackFrames.resultFunc(state.frames, state.sources, state.selectedSource, true); + + expect(frames[0]).not.toHaveProperty("library"); + expect(frames[1]).toHaveProperty("library", "React"); + expect(frames[2]).toHaveProperty("library", "React"); + }); // Multiple Babel async frame groups occur when you have an async function + // calling another async function (a common case). + // + // There are two possible frame groups that can occur depending on whether + // one sets a breakpoint before or after an await + + it("annotates frames related to Babel async transforms", () => { + const preAwaitGroup = [{ + displayName: "asyncAppFunction", + location: { + sourceId: "bundle" + } + }, { + displayName: "tryCatch", + location: { + sourceId: "regenerator" + } + }, { + displayName: "invoke", + location: { + sourceId: "regenerator" + } + }, { + displayName: "defineIteratorMethods/. */ +function getLocation(breakpoint, isGeneratedSource) { + return isGeneratedSource ? breakpoint.generatedLocation || breakpoint.location : breakpoint.location; +} + +function formatBreakpoint(breakpoint, selectedSource) { + const { + condition, + loading, + disabled, + hidden + } = breakpoint; + const sourceId = selectedSource.get("id"); + const isGeneratedSource = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); + return { + location: getLocation(breakpoint, isGeneratedSource), + condition, + loading, + disabled, + hidden + }; +} + +function isVisible(breakpoint, selectedSource) { + const sourceId = selectedSource.get("id"); + const isGeneratedSource = (0, _devtoolsSourceMap.isGeneratedId)(sourceId); + const location = getLocation(breakpoint, isGeneratedSource); + return location.sourceId === sourceId; +} +/* + * Finds the breakpoints, which appear in the selected source. + * + * This + */ + + +function getVisibleBreakpoints(state) { + const selectedSource = (0, _sources.getSelectedSource)(state); + + if (!selectedSource) { + return null; + } + + return (0, _breakpoints.getBreakpoints)(state).filter(bp => isVisible(bp, selectedSource)).map(bp => formatBreakpoint(bp, selectedSource)); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js b/devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js new file mode 100644 index 000000000000..8b18dc8caee5 --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getVisibleSelectedFrame = undefined; + +var _sources = require("../reducers/sources"); + +var _pause = require("../reducers/pause"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getLocation(frame, location) { + if (!location) { + return frame.location; + } + + return !(0, _devtoolsSourceMap.isOriginalId)(location.sourceId) ? frame.generatedLocation || frame.location : frame.location; +} + +const getVisibleSelectedFrame = exports.getVisibleSelectedFrame = (0, _reselect.createSelector)(_sources.getSelectedLocation, _pause.getSelectedFrame, (selectedLocation, selectedFrame) => { + if (!selectedFrame) { + return null; + } + + const { + id + } = selectedFrame; + return { + id, + location: getLocation(selectedFrame, selectedLocation) + }; +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/DevToolsUtils.js b/devtools/client/debugger/new/src/utils/DevToolsUtils.js new file mode 100644 index 000000000000..40efdc310ab6 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/DevToolsUtils.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.reportException = reportException; +exports.executeSoon = executeSoon; + +var _assert = require("./assert"); + +var _assert2 = _interopRequireDefault(_assert); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function reportException(who, exception) { + const msg = `${who} threw an exception: `; + console.error(msg, exception); +} + +function executeSoon(fn) { + setTimeout(fn, 0); +} + +exports.default = _assert2.default; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/assert.js b/devtools/client/debugger/new/src/utils/assert.js new file mode 100644 index 000000000000..854c805f983c --- /dev/null +++ b/devtools/client/debugger/new/src/utils/assert.js @@ -0,0 +1,17 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = assert; + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function assert(condition, message) { + if ((0, _devtoolsEnvironment.isDevelopment)() && !condition) { + throw new Error(`Assertion failure: ${message}`); + } +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/ast.js b/devtools/client/debugger/new/src/utils/ast.js new file mode 100644 index 000000000000..4dec1514470d --- /dev/null +++ b/devtools/client/debugger/new/src/utils/ast.js @@ -0,0 +1,114 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findBestMatchExpression = findBestMatchExpression; +exports.findEmptyLines = findEmptyLines; +exports.containsPosition = containsPosition; +exports.findClosestFunction = findClosestFunction; +exports.findClosestClass = findClosestClass; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _pausePoints = require("./pause/pausePoints"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function findBestMatchExpression(symbols, tokenPos) { + if (symbols.loading) { + return null; + } + + const { + line, + column + } = tokenPos; + const { + memberExpressions, + identifiers, + literals + } = symbols; + const members = memberExpressions.filter(({ + computed + }) => !computed); + return [].concat(identifiers, members, literals).reduce((found, expression) => { + const overlaps = expression.location.start.line == line && expression.location.start.column <= column && expression.location.end.column >= column; + + if (overlaps) { + return expression; + } + + return found; + }, null); +} + +function findEmptyLines(selectedSource, pausePoints) { + if (!pausePoints || !selectedSource) { + return []; + } + + const pausePointsList = (0, _pausePoints.convertToList)(pausePoints); + const breakpoints = pausePointsList.filter(point => point.types.break); + const breakpointLines = breakpoints.map(point => point.location.line); + + if (!selectedSource.text || breakpointLines.length == 0) { + return []; + } + + const lineCount = selectedSource.text.split("\n").length; + const sourceLines = (0, _lodash.range)(1, lineCount + 1); + return (0, _lodash.xor)(sourceLines, breakpointLines); +} + +function containsPosition(a, b) { + const startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column; + const endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column; + return startsBefore && endsAfter; +} + +function findClosestofSymbol(declarations, location) { + if (!declarations) { + return null; + } + + return declarations.reduce((found, currNode) => { + if (currNode.name === "anonymous" || !containsPosition(currNode.location, { + line: location.line, + column: location.column || 0 + })) { + return found; + } + + if (!found) { + return currNode; + } + + if (found.location.start.line > currNode.location.start.line) { + return found; + } + + if (found.location.start.line === currNode.location.start.line && found.location.start.column > currNode.location.start.column) { + return found; + } + + return currNode; + }, null); +} + +function findClosestFunction(symbols, location) { + if (!symbols || symbols.loading) { + return null; + } + + return findClosestofSymbol(symbols.functions, location); +} + +function findClosestClass(symbols, location) { + if (!symbols || symbols.loading) { + return null; + } + + return findClosestofSymbol(symbols.functions, location); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/bootstrap.js b/devtools/client/debugger/new/src/utils/bootstrap.js new file mode 100644 index 000000000000..21fa7c09cb04 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/bootstrap.js @@ -0,0 +1,154 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.bootstrapStore = bootstrapStore; +exports.bootstrapWorkers = bootstrapWorkers; +exports.teardownWorkers = teardownWorkers; +exports.bootstrapApp = bootstrapApp; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _redux = require("devtools/client/shared/vendor/redux"); + +var _reactDom = require("devtools/client/shared/vendor/react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _search = require("../workers/search/index"); + +var search = _interopRequireWildcard(_search); + +var _prettyPrint = require("../workers/pretty-print/index"); + +var prettyPrint = _interopRequireWildcard(_prettyPrint); + +var _parser = require("../workers/parser/index"); + +var parser = _interopRequireWildcard(_parser); + +var _createStore = require("../actions/utils/create-store"); + +var _createStore2 = _interopRequireDefault(_createStore); + +var _reducers = require("../reducers/index"); + +var _reducers2 = _interopRequireDefault(_reducers); + +var _selectors = require("../selectors/index"); + +var selectors = _interopRequireWildcard(_selectors); + +var _App = require("../components/App"); + +var _App2 = _interopRequireDefault(_App); + +var _prefs = require("./prefs"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const { + Provider +} = require("devtools/client/shared/vendor/react-redux"); + +function renderPanel(component, store) { + const root = document.createElement("div"); + root.className = "launchpad-root theme-body"; + root.style.setProperty("flex", "1"); + const mount = document.querySelector("#mount"); + + if (!mount) { + return; + } + + mount.appendChild(root); + + _reactDom2.default.render(_react2.default.createElement(Provider, { + store + }, _react2.default.createElement(component)), root); +} + +function bootstrapStore(client, { + services, + toolboxActions +}) { + const createStore = (0, _createStore2.default)({ + log: (0, _devtoolsEnvironment.isTesting)(), + timing: (0, _devtoolsEnvironment.isDevelopment)(), + makeThunkArgs: (args, state) => { + return _objectSpread({}, args, { + client + }, services, toolboxActions); + } + }); + const store = createStore((0, _redux.combineReducers)(_reducers2.default)); + store.subscribe(() => updatePrefs(store.getState())); + const actions = (0, _redux.bindActionCreators)(require("../actions/index").default, store.dispatch); + return { + store, + actions, + selectors + }; +} + +function bootstrapWorkers() { + const workerPath = (0, _devtoolsEnvironment.isDevelopment)() ? "assets/build" : "resource://devtools/client/debugger/new/dist"; + + if ((0, _devtoolsEnvironment.isDevelopment)()) { + // When used in Firefox, the toolbox manages the source map worker. + (0, _devtoolsSourceMap.startSourceMapWorker)(`${workerPath}/source-map-worker.js`); + } + + prettyPrint.start(`${workerPath}/pretty-print-worker.js`); + parser.start(`${workerPath}/parser-worker.js`); + search.start(`${workerPath}/search-worker.js`); + return { + prettyPrint, + parser, + search + }; +} + +function teardownWorkers() { + if (!(0, _devtoolsEnvironment.isFirefoxPanel)()) { + // When used in Firefox, the toolbox manages the source map worker. + (0, _devtoolsSourceMap.stopSourceMapWorker)(); + } + + prettyPrint.stop(); + parser.stop(); + search.stop(); +} + +function bootstrapApp(store) { + if ((0, _devtoolsEnvironment.isFirefoxPanel)()) { + renderPanel(_App2.default, store); + } else { + const { + renderRoot + } = require("devtools/shared/flags"); + + renderRoot(_react2.default, _reactDom2.default, _App2.default, store); + } +} + +function updatePrefs(state) { + const pendingBreakpoints = selectors.getPendingBreakpoints(state); + + if (_prefs.prefs.pendingBreakpoints !== pendingBreakpoints) { + _prefs.prefs.pendingBreakpoints = pendingBreakpoints; + } +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/breakpoint/astBreakpointLocation.js b/devtools/client/debugger/new/src/utils/breakpoint/astBreakpointLocation.js new file mode 100644 index 000000000000..253756d1256e --- /dev/null +++ b/devtools/client/debugger/new/src/utils/breakpoint/astBreakpointLocation.js @@ -0,0 +1,49 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getASTLocation = getASTLocation; +exports.findScopeByName = findScopeByName; + +var _parser = require("../../workers/parser/index"); + +var _ast = require("../ast"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getASTLocation(source, symbols, location) { + if (source.isWasm || !symbols || symbols.loading) { + return { + name: undefined, + offset: location + }; + } + + const scope = (0, _ast.findClosestFunction)(symbols, location); + + if (scope) { + // we only record the line, but at some point we may + // also do column offsets + const line = location.line - scope.location.start.line; + return { + name: scope.name, + offset: { + line, + column: undefined + } + }; + } + + return { + name: undefined, + offset: location + }; +} + +async function findScopeByName(source, name) { + const symbols = await (0, _parser.getSymbols)(source.id); + const functions = symbols.functions; + return functions.find(node => node.name === name); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/breakpoint/create-editor.js b/devtools/client/debugger/new/src/utils/breakpoint/create-editor.js new file mode 100644 index 000000000000..9b29b1bd1f86 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/breakpoint/create-editor.js @@ -0,0 +1,33 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createEditor = createEditor; + +var _sourceEditor = require("devtools/client/sourceeditor/editor"); + +var _sourceEditor2 = _interopRequireDefault(_sourceEditor); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function createEditor(value) { + return new _sourceEditor2.default({ + mode: "javascript", + foldGutter: false, + enableCodeFolding: false, + readOnly: "nocursor", + lineNumbers: false, + theme: "mozilla mozilla-breakpoint", + styleActiveLine: false, + lineWrapping: false, + matchBrackets: false, + showAnnotationRuler: false, + gutters: false, + value: value || "", + scrollbarStyle: null + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/breakpoint/index.js b/devtools/client/debugger/new/src/utils/breakpoint/index.js new file mode 100644 index 000000000000..2e0345f2a29a --- /dev/null +++ b/devtools/client/debugger/new/src/utils/breakpoint/index.js @@ -0,0 +1,202 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findScopeByName = exports.getASTLocation = exports.createEditor = undefined; + +var _createEditor = require("./create-editor"); + +Object.defineProperty(exports, "createEditor", { + enumerable: true, + get: function () { + return _createEditor.createEditor; + } +}); + +var _astBreakpointLocation = require("./astBreakpointLocation"); + +Object.defineProperty(exports, "getASTLocation", { + enumerable: true, + get: function () { + return _astBreakpointLocation.getASTLocation; + } +}); +Object.defineProperty(exports, "findScopeByName", { + enumerable: true, + get: function () { + return _astBreakpointLocation.findScopeByName; + } +}); +exports.firstString = firstString; +exports.locationMoved = locationMoved; +exports.makeLocationId = makeLocationId; +exports.makePendingLocationId = makePendingLocationId; +exports.assertBreakpoint = assertBreakpoint; +exports.assertPendingBreakpoint = assertPendingBreakpoint; +exports.assertLocation = assertLocation; +exports.assertPendingLocation = assertPendingLocation; +exports.breakpointAtLocation = breakpointAtLocation; +exports.breakpointExists = breakpointExists; +exports.createBreakpoint = createBreakpoint; +exports.createPendingBreakpoint = createPendingBreakpoint; + +var _selectors = require("../../selectors/index"); + +var _assert = require("../assert"); + +var _assert2 = _interopRequireDefault(_assert); + +var _prefs = require("../prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Return the first argument that is a string, or null if nothing is a +// string. +function firstString(...args) { + for (const arg of args) { + if (typeof arg === "string") { + return arg; + } + } + + return null; +} + +function locationMoved(location, newLocation) { + return location.line !== newLocation.line || location.column !== newLocation.column; +} + +function makeLocationId(location) { + const { + sourceId, + line, + column + } = location; + const columnString = column || ""; + return `${sourceId}:${line}:${columnString}`; +} + +function makePendingLocationId(location) { + assertPendingLocation(location); + const { + sourceUrl, + line, + column + } = location; + const sourceUrlString = sourceUrl || ""; + const columnString = column || ""; + return `${sourceUrlString}:${line}:${columnString}`; +} + +function assertBreakpoint(breakpoint) { + assertLocation(breakpoint.location); + assertLocation(breakpoint.generatedLocation); +} + +function assertPendingBreakpoint(pendingBreakpoint) { + assertPendingLocation(pendingBreakpoint.location); + assertPendingLocation(pendingBreakpoint.generatedLocation); +} + +function assertLocation(location) { + assertPendingLocation(location); + const { + sourceId + } = location; + (0, _assert2.default)(!!sourceId, "location must have a source id"); +} + +function assertPendingLocation(location) { + (0, _assert2.default)(!!location, "location must exist"); + const { + sourceUrl + } = location; // sourceUrl is null when the source does not have a url + + (0, _assert2.default)(sourceUrl !== undefined, "location must have a source url"); + (0, _assert2.default)(location.hasOwnProperty("line"), "location must have a line"); + (0, _assert2.default)(location.hasOwnProperty("column") != null, "location must have a column"); +} // syncing + + +function breakpointAtLocation(breakpoints, { + line, + column +}) { + return breakpoints.find(breakpoint => { + const sameLine = breakpoint.location.line === line; + + if (!sameLine) { + return false; + } // NOTE: when column breakpoints are disabled we want to find + // the first breakpoint + + + if (!_prefs.features.columnBreakpoints) { + return true; + } + + return breakpoint.location.column === column; + }); +} + +function breakpointExists(state, location) { + const currentBp = (0, _selectors.getBreakpoint)(state, location); + return currentBp && !currentBp.disabled; +} + +function createBreakpoint(location, overrides = {}) { + const { + condition, + disabled, + hidden, + generatedLocation, + astLocation, + id, + text, + originalText + } = overrides; + const defaultASTLocation = { + name: undefined, + offset: location + }; + const properties = { + id, + condition: condition || null, + disabled: disabled || false, + hidden: hidden || false, + loading: false, + astLocation: astLocation || defaultASTLocation, + generatedLocation: generatedLocation || location, + location, + text, + originalText + }; + return properties; +} + +function createPendingLocation(location) { + const { + sourceUrl, + line, + column + } = location; + return { + sourceUrl, + line, + column + }; +} + +function createPendingBreakpoint(bp) { + const pendingLocation = createPendingLocation(bp.location); + const pendingGeneratedLocation = createPendingLocation(bp.generatedLocation); + assertPendingLocation(pendingLocation); + return { + condition: bp.condition, + disabled: bp.disabled, + location: pendingLocation, + astLocation: bp.astLocation, + generatedLocation: pendingGeneratedLocation + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/breakpoint/moz.build b/devtools/client/debugger/new/src/utils/breakpoint/moz.build new file mode 100644 index 000000000000..06b7115e91b5 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/breakpoint/moz.build @@ -0,0 +1,14 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'astBreakpointLocation.js', + 'create-editor.js', + 'index.js', +) diff --git a/devtools/client/debugger/new/src/utils/clipboard.js b/devtools/client/debugger/new/src/utils/clipboard.js new file mode 100644 index 000000000000..310f21c2015a --- /dev/null +++ b/devtools/client/debugger/new/src/utils/clipboard.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.copyToTheClipboard = copyToTheClipboard; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Clipboard function taken from + * https://dxr.mozilla.org/mozilla-central/source/devtools/shared/platform/content/clipboard.js + */ +function copyToTheClipboard(string) { + const doCopy = function (e) { + e.clipboardData.setData("text/plain", string); + e.preventDefault(); + }; + + document.addEventListener("copy", doCopy); + document.execCommand("copy", false, null); + document.removeEventListener("copy", doCopy); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/dbg.js b/devtools/client/debugger/new/src/utils/dbg.js new file mode 100644 index 000000000000..711d561c4cd3 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/dbg.js @@ -0,0 +1,98 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setupHelper = setupHelper; + +var _timings = require("./timings"); + +var timings = _interopRequireWildcard(_timings); + +var _prefs = require("./prefs"); + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +var _pausePoints = require("./pause/pausePoints"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function findSource(dbg, url) { + const sources = dbg.selectors.getSources(); + const source = sources.find(s => (s.get("url") || "").includes(url)); + + if (!source) { + return; + } + + return source.toJS(); +} + +function sendPacket(dbg, packet, callback) { + dbg.client.sendPacket(packet, callback || console.log); +} + +function sendPacketToThread(dbg, packet, callback) { + sendPacket(dbg, _objectSpread({ + to: dbg.connection.tabConnection.threadClient.actor + }, packet), callback); +} + +function evaluate(dbg, expression, callback) { + dbg.client.evaluate(expression).then(callback || console.log); +} + +function bindSelectors(obj) { + return Object.keys(obj.selectors).reduce((bound, selector) => { + bound[selector] = (a, b, c) => obj.selectors[selector](obj.store.getState(), a, b, c); + + return bound; + }, {}); +} + +function getCM() { + const cm = document.querySelector(".CodeMirror"); + return cm && cm.CodeMirror; +} + +function _formatPausePoints(dbg, url) { + const source = dbg.helpers.findSource(url); + const pausePoints = dbg.selectors.getPausePoints(source); + console.log((0, _pausePoints.formatPausePoints)(source.text, pausePoints)); +} + +function setupHelper(obj) { + const selectors = bindSelectors(obj); + + const dbg = _objectSpread({}, obj, { + selectors, + prefs: _prefs.prefs, + features: _prefs.features, + timings, + getCM, + helpers: { + findSource: url => findSource(dbg, url), + evaluate: (expression, cbk) => evaluate(dbg, expression, cbk), + sendPacketToThread: (packet, cbk) => sendPacketToThread(dbg, packet, cbk), + sendPacket: (packet, cbk) => sendPacket(dbg, packet, cbk) + }, + formatters: { + pausePoints: url => _formatPausePoints(dbg, url) + } + }); + + window.dbg = dbg; + + if ((0, _devtoolsEnvironment.isDevelopment)()) { + console.group("Development Notes"); + const baseUrl = "https://devtools-html.github.io/debugger.html"; + const localDevelopmentUrl = `${baseUrl}/docs/dbg.html`; + console.log("Debugging Tips", localDevelopmentUrl); + console.log("dbg", window.dbg); + console.groupEnd(); + } +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/defer.js b/devtools/client/debugger/new/src/utils/defer.js new file mode 100644 index 000000000000..6b632c726a8b --- /dev/null +++ b/devtools/client/debugger/new/src/utils/defer.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = defer; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function defer() { + let resolve = () => {}; + + let reject = () => {}; + + const promise = new Promise((_res, _rej) => { + resolve = _res; + reject = _rej; + }); + return { + resolve, + reject, + promise + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/create-editor.js b/devtools/client/debugger/new/src/utils/editor/create-editor.js new file mode 100644 index 000000000000..b7a9457aea09 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/create-editor.js @@ -0,0 +1,48 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createEditor = createEditor; + +var _sourceEditor = require("devtools/client/sourceeditor/editor"); + +var _sourceEditor2 = _interopRequireDefault(_sourceEditor); + +var _prefs = require("../prefs"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function createEditor() { + const gutters = ["breakpoints", "hit-markers", "CodeMirror-linenumbers"]; + + if (_prefs.features.codeFolding) { + gutters.push("CodeMirror-foldgutter"); + } + + return new _sourceEditor2.default({ + mode: "javascript", + foldGutter: _prefs.features.codeFolding, + enableCodeFolding: _prefs.features.codeFolding, + readOnly: true, + lineNumbers: true, + theme: "mozilla", + styleActiveLine: false, + lineWrapping: false, + matchBrackets: true, + showAnnotationRuler: true, + gutters, + value: " ", + extraKeys: { + // Override code mirror keymap to avoid conflicts with split console. + Esc: false, + "Cmd-F": false, + "Ctrl-F": false, + "Cmd-G": false, + "Ctrl-G": false + } + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/get-expression.js b/devtools/client/debugger/new/src/utils/editor/get-expression.js new file mode 100644 index 000000000000..92b7269f7706 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/get-expression.js @@ -0,0 +1,83 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.tokenAtTextPosition = tokenAtTextPosition; +exports.getExpressionFromCoords = getExpressionFromCoords; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function tokenAtTextPosition(cm, { + line, + column +}) { + if (line < 0 || line >= cm.lineCount()) { + return null; + } + + const token = cm.getTokenAt({ + line: line - 1, + ch: column + }); + + if (!token) { + return null; + } + + return { + startColumn: token.start, + endColumn: token.end, + type: token.type + }; +} // The strategy of querying codeMirror tokens was borrowed +// from Chrome's inital implementation in JavaScriptSourceFrame.js#L414 + + +function getExpressionFromCoords(cm, coord) { + const token = tokenAtTextPosition(cm, coord); + + if (!token) { + return null; + } + + let startHighlight = token.startColumn; + const endHighlight = token.endColumn; + const lineNumber = coord.line; + const line = cm.doc.getLine(coord.line - 1); + + while (startHighlight > 1 && line.charAt(startHighlight - 1) === ".") { + const tokenBefore = tokenAtTextPosition(cm, { + line: coord.line, + column: startHighlight - 2 + }); + + if (!tokenBefore || !tokenBefore.type) { + return null; + } + + startHighlight = tokenBefore.startColumn; + } + + const expression = line.substring(startHighlight, endHighlight) || ""; + + if (!expression) { + return null; + } + + const location = { + start: { + line: lineNumber, + column: startHighlight + }, + end: { + line: lineNumber, + column: endHighlight + } + }; + return { + expression, + location + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/get-token-location.js b/devtools/client/debugger/new/src/utils/editor/get-token-location.js new file mode 100644 index 000000000000..a23c93587139 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/get-token-location.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getTokenLocation = getTokenLocation; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getTokenLocation(codeMirror, tokenEl) { + const { + left, + top, + width, + height + } = tokenEl.getBoundingClientRect(); + const { + line, + ch + } = codeMirror.coordsChar({ + left: left + width / 2, + top: top + height / 2 + }); + return { + line: line + 1, + column: ch + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/index.js b/devtools/client/debugger/new/src/utils/editor/index.js new file mode 100644 index 000000000000..3d8260770f36 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/index.js @@ -0,0 +1,265 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _sourceDocuments = require("./source-documents"); + +Object.keys(_sourceDocuments).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _sourceDocuments[key]; + } + }); +}); + +var _getTokenLocation = require("./get-token-location"); + +Object.keys(_getTokenLocation).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _getTokenLocation[key]; + } + }); +}); + +var _sourceSearch = require("./source-search"); + +Object.keys(_sourceSearch).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _sourceSearch[key]; + } + }); +}); + +var _ui = require("../ui"); + +Object.keys(_ui).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _ui[key]; + } + }); +}); + +var _createEditor = require("./create-editor"); + +Object.keys(_createEditor).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _createEditor[key]; + } + }); +}); +exports.setEditor = setEditor; +exports.getEditor = getEditor; +exports.removeEditor = removeEditor; +exports.shouldShowPrettyPrint = shouldShowPrettyPrint; +exports.shouldShowFooter = shouldShowFooter; +exports.traverseResults = traverseResults; +exports.toEditorLine = toEditorLine; +exports.toEditorPosition = toEditorPosition; +exports.toEditorRange = toEditorRange; +exports.toSourceLine = toSourceLine; +exports.scrollToColumn = scrollToColumn; +exports.markText = markText; +exports.lineAtHeight = lineAtHeight; +exports.getSourceLocationFromMouseEvent = getSourceLocationFromMouseEvent; +exports.forEachLine = forEachLine; +exports.removeLineClass = removeLineClass; +exports.clearLineClass = clearLineClass; +exports.getTextForLine = getTextForLine; +exports.getCursorLine = getCursorLine; + +var _source = require("../source"); + +var _wasm = require("../wasm"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +let editor; + +function setEditor(_editor) { + editor = _editor; +} + +function getEditor() { + return editor; +} + +function removeEditor() { + editor = null; +} + +function shouldShowPrettyPrint(selectedSource) { + if (!selectedSource) { + return false; + } + + return (0, _source.shouldPrettyPrint)(selectedSource); +} + +function shouldShowFooter(selectedSource, horizontal) { + if (!horizontal) { + return true; + } + + if (!selectedSource) { + return false; + } + + return shouldShowPrettyPrint(selectedSource) || (0, _devtoolsSourceMap.isOriginalId)(selectedSource.get("id")); +} + +function traverseResults(e, ctx, query, dir, modifiers) { + e.stopPropagation(); + e.preventDefault(); + + if (dir == "prev") { + (0, _sourceSearch.findPrev)(ctx, query, true, modifiers); + } else if (dir == "next") { + (0, _sourceSearch.findNext)(ctx, query, true, modifiers); + } +} + +function toEditorLine(sourceId, lineOrOffset) { + if ((0, _wasm.isWasm)(sourceId)) { + // TODO ensure offset is always "mappable" to edit line. + return (0, _wasm.wasmOffsetToLine)(sourceId, lineOrOffset) || 0; + } + + return lineOrOffset ? lineOrOffset - 1 : 1; +} + +function toEditorPosition(location) { + return { + line: toEditorLine(location.sourceId, location.line), + column: (0, _wasm.isWasm)(location.sourceId) || !location.column ? 0 : location.column + }; +} + +function toEditorRange(sourceId, location) { + const { + start, + end + } = location; + return { + start: toEditorPosition(_objectSpread({}, start, { + sourceId + })), + end: toEditorPosition(_objectSpread({}, end, { + sourceId + })) + }; +} + +function toSourceLine(sourceId, line) { + return (0, _wasm.isWasm)(sourceId) ? (0, _wasm.lineToWasmOffset)(sourceId, line) : line + 1; +} + +function scrollToColumn(codeMirror, line, column) { + const { + top, + left + } = codeMirror.charCoords({ + line: line, + ch: column + }, "local"); + + if (!isVisible(codeMirror, top, left)) { + const scroller = codeMirror.getScrollerElement(); + const centeredX = Math.max(left - scroller.offsetWidth / 2, 0); + const centeredY = Math.max(top - scroller.offsetHeight / 2, 0); + codeMirror.scrollTo(centeredX, centeredY); + } +} + +function isVisible(codeMirror, top, left) { + function withinBounds(x, min, max) { + return x >= min && x <= max; + } + + const scrollArea = codeMirror.getScrollInfo(); + const charWidth = codeMirror.defaultCharWidth(); + const inXView = withinBounds(left, scrollArea.left, scrollArea.left + (scrollArea.clientWidth - 30) - charWidth); + const fontHeight = codeMirror.defaultTextHeight(); + const inYView = withinBounds(top, scrollArea.top, scrollArea.top + scrollArea.clientHeight - fontHeight); + return inXView && inYView; +} + +function markText(_editor, className, { + start, + end +}) { + return _editor.codeMirror.markText({ + ch: start.column, + line: start.line + }, { + ch: end.column, + line: end.line + }, { + className + }); +} + +function lineAtHeight(_editor, sourceId, event) { + const _editorLine = _editor.codeMirror.lineAtHeight(event.clientY); + + return toSourceLine(sourceId, _editorLine); +} + +function getSourceLocationFromMouseEvent(_editor, selectedLocation, e) { + const { + line, + ch + } = _editor.codeMirror.coordsChar({ + left: e.clientX, + top: e.clientY + }); + + return { + sourceId: selectedLocation.sourceId, + line: line + 1, + column: ch + 1 + }; +} + +function forEachLine(codeMirror, iter) { + codeMirror.operation(() => { + codeMirror.doc.iter(0, codeMirror.lineCount(), iter); + }); +} + +function removeLineClass(codeMirror, line, className) { + codeMirror.removeLineClass(line, "line", className); +} + +function clearLineClass(codeMirror, className) { + forEachLine(codeMirror, line => { + removeLineClass(codeMirror, line, className); + }); +} + +function getTextForLine(codeMirror, line) { + return codeMirror.getLine(line - 1).trim(); +} + +function getCursorLine(codeMirror) { + return codeMirror.getCursor().line; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/moz.build b/devtools/client/debugger/new/src/utils/editor/moz.build new file mode 100644 index 000000000000..5197e883430f --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/moz.build @@ -0,0 +1,18 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'create-editor.js', + 'get-expression.js', + 'get-token-location.js', + 'index.js', + 'source-documents.js', + 'source-editor.js', + 'source-search.js', +) diff --git a/devtools/client/debugger/new/src/utils/editor/source-documents.js b/devtools/client/debugger/new/src/utils/editor/source-documents.js new file mode 100644 index 000000000000..cf3e248406b2 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/source-documents.js @@ -0,0 +1,183 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.showLoading = exports.showErrorMessage = exports.showSourceText = exports.clearEditor = exports.updateDocument = exports.updateLineNumberFormat = exports.clearDocuments = exports.removeDocument = exports.hasDocument = exports.setDocument = exports.getDocument = undefined; + +var _source = require("../source"); + +var _wasm = require("../wasm"); + +var _ui = require("../ui"); + +var _sourceEditor = require("devtools/client/sourceeditor/editor"); + +var _sourceEditor2 = _interopRequireDefault(_sourceEditor); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let sourceDocs = {}; + +function getDocument(key) { + return sourceDocs[key]; +} + +function hasDocument(key) { + return !!getDocument(key); +} + +function setDocument(key, doc) { + sourceDocs[key] = doc; +} + +function removeDocument(key) { + delete sourceDocs[key]; +} + +function clearDocuments() { + sourceDocs = {}; +} + +function resetLineNumberFormat(editor) { + const cm = editor.codeMirror; + cm.setOption("lineNumberFormatter", number => number); + (0, _ui.resizeBreakpointGutter)(cm); + (0, _ui.resizeToggleButton)(cm); +} + +function updateLineNumberFormat(editor, sourceId) { + if (!(0, _wasm.isWasm)(sourceId)) { + return resetLineNumberFormat(editor); + } + + const cm = editor.codeMirror; + const lineNumberFormatter = (0, _wasm.getWasmLineNumberFormatter)(sourceId); + cm.setOption("lineNumberFormatter", lineNumberFormatter); + (0, _ui.resizeBreakpointGutter)(cm); + (0, _ui.resizeToggleButton)(cm); +} + +function updateDocument(editor, source) { + if (!source) { + return; + } + + const sourceId = source.get("id"); + const doc = getDocument(sourceId) || editor.createDocument(); + editor.replaceDocument(doc); + updateLineNumberFormat(editor, sourceId); +} + +function clearEditor(editor) { + const doc = editor.createDocument(); + editor.replaceDocument(doc); + editor.setText(""); + editor.setMode({ + name: "text" + }); + resetLineNumberFormat(editor); +} + +function showLoading(editor) { + if (hasDocument("loading")) { + return; + } + + const doc = editor.createDocument(); + setDocument("loading", doc); + editor.replaceDocument(doc); + editor.setText(L10N.getStr("loadingText")); + editor.setMode({ + name: "text" + }); +} + +function showErrorMessage(editor, msg) { + let error; + + if (msg.includes("WebAssembly binary source is not available")) { + error = L10N.getStr("wasmIsNotAvailable"); + } else { + error = L10N.getFormatStr("errorLoadingText3", msg); + } + + const doc = editor.createDocument(); + editor.replaceDocument(doc); + editor.setText(error); + editor.setMode({ + name: "text" + }); + resetLineNumberFormat(editor); +} + +function setEditorText(editor, source) { + const { + text, + id: sourceId + } = source; + + if (source.isWasm) { + const wasmLines = (0, _wasm.renderWasmText)(sourceId, text); // cm will try to split into lines anyway, saving memory + + const wasmText = { + split: () => wasmLines, + match: () => false + }; + editor.setText(wasmText); + } else { + editor.setText(text); + } +} +/** + * Handle getting the source document or creating a new + * document with the correct mode and text. + */ + + +function showSourceText(editor, source, symbols) { + if (!source) { + return; + } + + if (hasDocument(source.id)) { + const doc = getDocument(source.id); + + if (editor.codeMirror.doc === doc) { + const mode = (0, _source.getMode)(source, symbols); + + if (doc.mode.name !== mode.name) { + editor.setMode(mode); + } + + return; + } + + editor.replaceDocument(doc); + updateLineNumberFormat(editor, source.id); + editor.setMode((0, _source.getMode)(source, symbols)); + return doc; + } + + const doc = editor.createDocument(); + setDocument(source.id, doc); + editor.replaceDocument(doc); + setEditorText(editor, source); + editor.setMode((0, _source.getMode)(source, symbols)); + updateLineNumberFormat(editor, source.id); +} + +exports.getDocument = getDocument; +exports.setDocument = setDocument; +exports.hasDocument = hasDocument; +exports.removeDocument = removeDocument; +exports.clearDocuments = clearDocuments; +exports.updateLineNumberFormat = updateLineNumberFormat; +exports.updateDocument = updateDocument; +exports.clearEditor = clearEditor; +exports.showSourceText = showSourceText; +exports.showErrorMessage = showErrorMessage; +exports.showLoading = showLoading; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/source-editor.js b/devtools/client/debugger/new/src/utils/editor/source-editor.js new file mode 100644 index 000000000000..f4d9c3aab86c --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/source-editor.js @@ -0,0 +1,157 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * CodeMirror source editor utils + * @module utils/source-editor + */ +const CodeMirror = require("codemirror/index"); + +require("codemirror/lib/codemirror.css/index"); + +require("codemirror/mode/javascript/javascript/index"); + +require("codemirror/mode/htmlmixed/htmlmixed/index"); + +require("codemirror/mode/coffeescript/coffeescript/index"); + +require("codemirror/mode/jsx/jsx/index"); + +require("codemirror/mode/elm/elm/index"); + +require("codemirror/mode/clojure/clojure/index"); + +require("codemirror/addon/search/searchcursor/index"); + +require("codemirror/addon/fold/foldcode/index"); + +require("codemirror/addon/fold/brace-fold/index"); + +require("codemirror/addon/fold/indent-fold/index"); + +require("codemirror/addon/fold/foldgutter/index"); + +require("codemirror/addon/selection/active-line/index"); + +require("codemirror/addon/edit/matchbrackets/index"); + +require("codemirror/mode/clike/clike/index"); + +require("codemirror/mode/rust/rust/index"); + +require("./source-editor.css/index"); // NOTE: we should eventually use debugger-html context type mode + + +// Maximum allowed margin (in number of lines) from top or bottom of the editor +// while shifting to a line which was initially out of view. +const MAX_VERTICAL_OFFSET = 3; + +class SourceEditor { + constructor(opts) { + this.opts = opts; + } + + appendToLocalElement(node) { + this.editor = CodeMirror(node, this.opts); + } + + destroy() { + // Unlink the current document. + if (this.editor.doc) { + this.editor.doc.cm = null; + } + } + + get codeMirror() { + return this.editor; + } + + setText(str) { + this.editor.setValue(str); + } + + getText() { + return this.editor.getValue(); + } + + setMode(value) { + this.editor.setOption("mode", value); + } + /** + * Replaces the current document with a new source document + * @memberof utils/source-editor + */ + + + replaceDocument(doc) { + this.editor.swapDoc(doc); + } + /** + * Creates a CodeMirror Document + * @returns CodeMirror.Doc + * @memberof utils/source-editor + */ + + + createDocument() { + return new CodeMirror.Doc(""); + } + /** + * Aligns the provided line to either "top", "center" or "bottom" of the + * editor view with a maximum margin of MAX_VERTICAL_OFFSET lines from top or + * bottom. + * @memberof utils/source-editor + */ + + + alignLine(line, align = "top") { + const cm = this.editor; + const editorClientRect = cm.getWrapperElement().getBoundingClientRect(); + const from = cm.lineAtHeight(editorClientRect.top, "page"); + const to = cm.lineAtHeight(editorClientRect.height + editorClientRect.top, "page"); + const linesVisible = to - from; + const halfVisible = Math.round(linesVisible / 2); // If the target line is in view, skip the vertical alignment part. + + if (line <= to && line >= from) { + return; + } // Setting the offset so that the line always falls in the upper half + // of visible lines (lower half for bottom aligned). + // MAX_VERTICAL_OFFSET is the maximum allowed value. + + + const offset = Math.min(halfVisible, MAX_VERTICAL_OFFSET); + let topLine = { + center: Math.max(line - halfVisible, 0), + bottom: Math.max(line - linesVisible + offset, 0), + top: Math.max(line - offset, 0) + }[align || "top"] || offset; // Bringing down the topLine to total lines in the editor if exceeding. + + topLine = Math.min(topLine, cm.lineCount()); + this.setFirstVisibleLine(topLine); + } + /** + * Scrolls the view such that the given line number is the first visible line. + * @memberof utils/source-editor + */ + + + setFirstVisibleLine(line) { + const { + top + } = this.editor.charCoords({ + line: line, + ch: 0 + }, "local"); + this.editor.scrollTo(0, top); + } + +} + +exports.default = SourceEditor; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/editor/source-search.js b/devtools/client/debugger/new/src/utils/editor/source-search.js new file mode 100644 index 000000000000..0b5352d8ae6a --- /dev/null +++ b/devtools/client/debugger/new/src/utils/editor/source-search.js @@ -0,0 +1,375 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.buildQuery = undefined; +exports.getMatchIndex = getMatchIndex; +exports.searchSourceForHighlight = searchSourceForHighlight; +exports.removeOverlay = removeOverlay; +exports.find = find; +exports.findNext = findNext; +exports.findPrev = findPrev; + +var _buildQuery = require("../../workers/search/build-query"); + +var _buildQuery2 = _interopRequireDefault(_buildQuery); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * @memberof utils/source-search + * @static + */ +function getSearchCursor(cm, query, pos, modifiers) { + const regexQuery = (0, _buildQuery2.default)(query, modifiers, { + isGlobal: true + }); + return cm.getSearchCursor(regexQuery, pos); +} +/** + * @memberof utils/source-search + * @static + */ + + +function SearchState() { + this.posFrom = this.posTo = this.query = null; + this.overlay = null; + this.results = []; +} +/** + * @memberof utils/source-search + * @static + */ + + +function getSearchState(cm, query) { + const state = cm.state.search || (cm.state.search = new SearchState()); + return state; +} + +function isWhitespace(query) { + return !query.match(/\S/); +} +/** + * This returns a mode object used by CoeMirror's addOverlay function + * to parse and style tokens in the file. + * The mode object contains a tokenizer function (token) which takes + * a character stream as input, advances it a character at a time, + * and returns style(s) for that token. For more details see + * https://codemirror.net/doc/manual.html#modeapi + * + * Also the token function code is mainly based of work done + * by the chrome devtools team. Thanks guys! :) + * + * @memberof utils/source-search + * @static + */ + + +function searchOverlay(query, modifiers) { + const regexQuery = (0, _buildQuery2.default)(query, modifiers, { + ignoreSpaces: true, + // regex must be global for the overlay + isGlobal: true + }); + return { + token: function (stream, state) { + // set the last index to be the current stream position + // this acts as an offset + regexQuery.lastIndex = stream.pos; + const match = regexQuery.exec(stream.string); + + if (match && match.index === stream.pos) { + // if we have a match at the current stream position + // set the class for a match + stream.pos += match[0].length || 1; + return "highlight highlight-full"; + } else if (match) { + // if we have a match somewhere in the line, go to that point in the + // stream + stream.pos = match.index; + } else { + // if we have no matches in this line, skip to the end of the line + stream.skipToEnd(); + } + } + }; +} +/** + * @memberof utils/source-search + * @static + */ + + +function updateOverlay(cm, state, query, modifiers) { + cm.removeOverlay(state.overlay); + state.overlay = searchOverlay(query, modifiers); + cm.addOverlay(state.overlay, { + opaque: false + }); +} + +function updateCursor(cm, state, keepSelection) { + state.posTo = cm.getCursor("anchor"); + state.posFrom = cm.getCursor("head"); + + if (!keepSelection) { + state.posTo = { + line: 0, + ch: 0 + }; + state.posFrom = { + line: 0, + ch: 0 + }; + } +} + +function getMatchIndex(count, currentIndex, rev) { + if (!rev) { + if (currentIndex == count - 1) { + return 0; + } + + return currentIndex + 1; + } + + if (currentIndex == 0) { + return count - 1; + } + + return currentIndex - 1; +} +/** + * If there's a saved search, selects the next results. + * Otherwise, creates a new search and selects the first + * result. + * + * @memberof utils/source-search + * @static + */ + + +function doSearch(ctx, rev, query, keepSelection, modifiers) { + const { + cm + } = ctx; + + if (!cm) { + return; + } + + const defaultIndex = { + line: -1, + ch: -1 + }; + return cm.operation(function () { + if (!query || isWhitespace(query)) { + clearSearch(cm, query); + return; + } + + const state = getSearchState(cm, query); + const isNewQuery = state.query !== query; + state.query = query; + updateOverlay(cm, state, query, modifiers); + updateCursor(cm, state, keepSelection); + const searchLocation = searchNext(ctx, rev, query, isNewQuery, modifiers); + return searchLocation ? searchLocation.from : defaultIndex; + }); +} + +function searchSourceForHighlight(ctx, rev, query, keepSelection, modifiers, line, ch) { + const { + cm + } = ctx; + + if (!cm) { + return; + } + + return cm.operation(function () { + const state = getSearchState(cm, query); + const isNewQuery = state.query !== query; + state.query = query; + updateOverlay(cm, state, query, modifiers); + updateCursor(cm, state, keepSelection); + findNextOnLine(ctx, rev, query, isNewQuery, modifiers, line, ch); + }); +} + +function getCursorPos(newQuery, rev, state) { + if (newQuery) { + return rev ? state.posFrom : state.posTo; + } + + return rev ? state.posTo : state.posFrom; +} +/** + * Selects the next result of a saved search. + * + * @memberof utils/source-search + * @static + */ + + +function searchNext(ctx, rev, query, newQuery, modifiers) { + const { + cm, + ed + } = ctx; + let nextMatch; + cm.operation(function () { + const state = getSearchState(cm, query); + const pos = getCursorPos(newQuery, rev, state); + + if (!state.query) { + return; + } + + let cursor = getSearchCursor(cm, state.query, pos, modifiers); + const location = rev ? { + line: cm.lastLine(), + ch: null + } : { + line: cm.firstLine(), + ch: 0 + }; + + if (!cursor.find(rev) && state.query) { + cursor = getSearchCursor(cm, state.query, location, modifiers); + + if (!cursor.find(rev)) { + return; + } + } // We don't want to jump the editor + // when we're selecting text + + + if (!cm.state.selectingText) { + ed.alignLine(cursor.from().line, "center"); + cm.setSelection(cursor.from(), cursor.to()); + } + + nextMatch = { + from: cursor.from(), + to: cursor.to() + }; + }); + return nextMatch; +} + +function findNextOnLine(ctx, rev, query, newQuery, modifiers, line, ch) { + const { + cm, + ed + } = ctx; + cm.operation(function () { + const pos = { + line: line - 1, + ch + }; + let cursor = getSearchCursor(cm, query, pos, modifiers); + + if (!cursor.find(rev) && query) { + cursor = getSearchCursor(cm, query, pos, modifiers); + + if (!cursor.find(rev)) { + return; + } + } // We don't want to jump the editor + // when we're selecting text + + + if (!cm.state.selectingText) { + ed.alignLine(cursor.from().line, "center"); + cm.setSelection(cursor.from(), cursor.to()); + } + }); +} +/** + * Remove overlay. + * + * @memberof utils/source-search + * @static + */ + + +function removeOverlay(ctx, query) { + const state = getSearchState(ctx.cm, query); + ctx.cm.removeOverlay(state.overlay); + const { + line, + ch + } = ctx.cm.getCursor(); + ctx.cm.doc.setSelection({ + line, + ch + }, { + line, + ch + }, { + scroll: false + }); +} +/** + * Clears the currently saved search. + * + * @memberof utils/source-search + * @static + */ + + +function clearSearch(cm, query) { + const state = getSearchState(cm, query); + state.results = []; + + if (!state.query) { + return; + } + + cm.removeOverlay(state.overlay); + state.query = null; +} +/** + * Starts a new search. + * + * @memberof utils/source-search + * @static + */ + + +function find(ctx, query, keepSelection, modifiers) { + clearSearch(ctx.cm, query); + return doSearch(ctx, false, query, keepSelection, modifiers); +} +/** + * Finds the next item based on the currently saved search. + * + * @memberof utils/source-search + * @static + */ + + +function findNext(ctx, query, keepSelection, modifiers) { + return doSearch(ctx, false, query, keepSelection, modifiers); +} +/** + * Finds the previous item based on the currently saved search. + * + * @memberof utils/source-search + * @static + */ + + +function findPrev(ctx, query, keepSelection, modifiers) { + return doSearch(ctx, true, query, keepSelection, modifiers); +} + +exports.buildQuery = _buildQuery2.default; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/expressions.js b/devtools/client/debugger/new/src/utils/expressions.js new file mode 100644 index 000000000000..45007b47823d --- /dev/null +++ b/devtools/client/debugger/new/src/utils/expressions.js @@ -0,0 +1,111 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sanitizeInput = sanitizeInput; +exports.wrapExpression = wrapExpression; +exports.getValue = getValue; + +var _indentation = require("./indentation"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// replace quotes that could interfere with the evaluation. +function sanitizeInput(input) { + return input.replace(/"/g, '"'); +} +/* + * wrap the expression input in a try/catch so that it can be safely + * evaluated. + * + * NOTE: we add line after the expression to protect against comments. +*/ + + +function wrapExpression(input) { + return (0, _indentation.correctIndentation)(` + try { + ${sanitizeInput(input)} + } catch (e) { + e + } + `); +} + +function isUnavailable(value) { + if (!value.preview || !value.preview.name) { + return false; + } + + return ["ReferenceError", "TypeError"].includes(value.preview.name); +} + +function getValue(expression) { + const value = expression.value; + + if (!value) { + return { + path: expression.from, + value: { + unavailable: true + } + }; + } + + if (value.exception) { + if (isUnavailable(value.exception)) { + return { + value: { + unavailable: true + } + }; + } + + return { + path: value.from, + value: value.exception + }; + } + + if (value.error) { + return { + path: value.from, + value: value.error + }; + } + + if (value.result && value.result.class == "Error") { + const { + name, + message + } = value.result.preview; + + if (isUnavailable(value.result)) { + return { + value: { + unavailable: true + } + }; + } + + const newValue = `${name}: ${message}`; + return { + path: value.input, + value: newValue + }; + } + + if (typeof value.result == "object") { + return { + path: value.result.actor, + value: value.result + }; + } + + return { + path: value.input, + value: value.result + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/fromJS.js b/devtools/client/debugger/new/src/utils/fromJS.js new file mode 100644 index 000000000000..07bd1f45f20a --- /dev/null +++ b/devtools/client/debugger/new/src/utils/fromJS.js @@ -0,0 +1,106 @@ +"use strict"; + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Immutable JS conversion utils + * @deprecated + * @module utils/fromJS + */ +// hasOwnProperty is defensive because it is possible that the +// object that we're creating a map for has a `hasOwnProperty` field +function hasOwnProperty(value, key) { + if (value.hasOwnProperty && (0, _lodash.isFunction)(value.hasOwnProperty)) { + return value.hasOwnProperty(key); + } + + if (value.prototype && value.prototype.hasOwnProperty) { + return value.prototype.hasOwnProperty(key); + } + + return false; +} +/* + creates an immutable map, where each of the value's + items are transformed into their own map. + + NOTE: we guard against `length` being a property because + length confuses Immutable's internal algorithm. +*/ + + +function createMap(value) { + const hasLength = hasOwnProperty(value, "length"); + const length = value.length; + + if (hasLength) { + value.length = `${value.length}`; + } + + let map = I.Seq(value).map(fromJS).toMap(); + + if (hasLength) { + map = map.set("length", length); + value.length = length; + } + + return map; +} + +function createList(value) { + return I.Seq(value).map(fromJS).toList(); +} +/** + * When our app state is fully typed, we should be able to get rid of + * this function. This is only temporarily necessary to support + * converting typed objects to immutable.js, which usually happens in + * reducers. + * + * @memberof utils/fromJS + * @static + */ + + +function fromJS(value) { + if (Array.isArray(value)) { + return createList(value); + } + + if (value && value.constructor && value.constructor.meta) { + // This adds support for tcomb objects which are native JS objects + // but are not "plain", so the above checks fail. Since they + // behave the same we can use the same constructors, but we need + // special checks for them. + const kind = value.constructor.meta.kind; + + if (kind === "struct") { + return createMap(value); + } else if (kind === "list") { + return createList(value); + } + } // If it's a primitive type, just return the value. Note `==` check + // for null, which is intentionally used to match either `null` or + // `undefined`. + + + if (value == null || typeof value !== "object") { + return value; + } // Otherwise, treat it like an object. We can't reliably detect if + // it's a plain object because we might be objects from other JS + // contexts so `Object !== Object`. + + + return createMap(value); +} + +module.exports = fromJS; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/function.js b/devtools/client/debugger/new/src/utils/function.js new file mode 100644 index 000000000000..a27ecd5a402f --- /dev/null +++ b/devtools/client/debugger/new/src/utils/function.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findFunctionText = findFunctionText; + +var _ast = require("./ast"); + +var _indentation = require("./indentation"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function findFunctionText(line, source, symbols) { + const func = (0, _ast.findClosestFunction)(symbols, { + sourceId: source.id, + line, + column: Infinity + }); + + if (!func || !source.text) { + return null; + } + + const { + location: { + start, + end + } + } = func; + const lines = source.text.split("\n"); + const firstLine = lines[start.line - 1].slice(start.column); + const lastLine = lines[end.line - 1].slice(0, end.column); + const middle = lines.slice(start.line, end.line - 1); + const functionText = [firstLine, ...middle, lastLine].join("\n"); + const indentedFunctionText = (0, _indentation.correctIndentation)(functionText); + return indentedFunctionText; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/indentation.js b/devtools/client/debugger/new/src/utils/indentation.js new file mode 100644 index 000000000000..72a43fe9ebe3 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/indentation.js @@ -0,0 +1,33 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getIndentation = getIndentation; +exports.correctIndentation = correctIndentation; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getIndentation(line) { + if (!line) { + return 0; + } + + return line.match(/^\s*/)[0].length; +} + +function getMaxIndentation(lines) { + const firstLine = lines[0]; + const secondLine = lines[1]; + const lastLine = lines[lines.length - 1]; + const indentations = [getIndentation(firstLine), getIndentation(secondLine), getIndentation(lastLine)]; + return Math.max(...indentations); +} + +function correctIndentation(text) { + const lines = text.trim().split("\n"); + const indentation = getMaxIndentation(lines); + const formattedLines = lines.map(_line => _line.replace(new RegExp(`^\\s{0,${indentation - 1}}`), "")); + return formattedLines.join("\n"); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/isMinified.js b/devtools/client/debugger/new/src/utils/isMinified.js new file mode 100644 index 000000000000..c3bf13c3536d --- /dev/null +++ b/devtools/client/debugger/new/src/utils/isMinified.js @@ -0,0 +1,62 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isMinified = isMinified; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Used to detect minification for automatic pretty printing +const SAMPLE_SIZE = 50; +const INDENT_COUNT_THRESHOLD = 5; +const CHARACTER_LIMIT = 250; + +const _minifiedCache = new Map(); + +function isMinified(source) { + if (_minifiedCache.has(source.id)) { + return _minifiedCache.get(source.id); + } + + let text = source.get("text"); + + if (!text) { + return false; + } + + let lineEndIndex = 0; + let lineStartIndex = 0; + let lines = 0; + let indentCount = 0; + let overCharLimit = false; // Strip comments. + + text = text.replace(/\/\*[\S\s]*?\*\/|\/\/(.+|\n)/g, ""); + + while (lines++ < SAMPLE_SIZE) { + lineEndIndex = text.indexOf("\n", lineStartIndex); + + if (lineEndIndex == -1) { + break; + } + + if (/^\s+/.test(text.slice(lineStartIndex, lineEndIndex))) { + indentCount++; + } // For files with no indents but are not minified. + + + if (lineEndIndex - lineStartIndex > CHARACTER_LIMIT) { + overCharLimit = true; + break; + } + + lineStartIndex = lineEndIndex + 1; + } + + const minified = indentCount / lines * 100 < INDENT_COUNT_THRESHOLD || overCharLimit; + + _minifiedCache.set(source.id, minified); + + return minified; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/location.js b/devtools/client/debugger/new/src/utils/location.js new file mode 100644 index 000000000000..c372722a9967 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/location.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createLocation = createLocation; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function createLocation({ + sourceId, + line, + column, + sourceUrl +}) { + return { + sourceId, + line, + column, + sourceUrl: sourceUrl || null + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/log.js b/devtools/client/debugger/new/src/utils/log.js new file mode 100644 index 000000000000..e3493ed018d7 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/log.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.log = log; + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * + * Utils for logging to the console + * Suppresses logging in non-development environment + * + * @module utils/log + */ + +/** + * Produces a formatted console log line by imploding args, prefixed by [log] + * + * function input: log(["hello", "world"]) + * console output: [log] hello world + * + * @memberof utils/log + * @static + */ +function log(...args) { + if (!(0, _devtoolsEnvironment.isDevelopment)()) { + return; + } + + console.log.apply(console, ["[log]", ...args]); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/makeRecord.js b/devtools/client/debugger/new/src/utils/makeRecord.js new file mode 100644 index 000000000000..4a8f5bead931 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/makeRecord.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * When Flow 0.29 is released (very soon), we can use this Record type + * instead of the builtin immutable.js Record type. This is better + * because all the fields are actually typed, unlike the builtin one. + * This depends on a performance fix that will go out in 0.29 though; + * @module utils/makeRecord + */ + +/** + * Make an immutable record type + * + * @param spec - the keys and their default values + * @return a state record factory function + * @memberof utils/makeRecord + * @static + */ +function makeRecord(spec) { + return I.Record(spec); +} + +exports.default = makeRecord; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/moz.build b/devtools/client/debugger/new/src/utils/moz.build new file mode 100644 index 000000000000..ee14d01710e0 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/moz.build @@ -0,0 +1,47 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'breakpoint', + 'editor', + 'pause', + 'sources-tree', +] + +DevToolsModules( + 'assert.js', + 'ast.js', + 'bootstrap.js', + 'clipboard.js', + 'dbg.js', + 'defer.js', + 'DevToolsUtils.js', + 'expressions.js', + 'fromJS.js', + 'function.js', + 'indentation.js', + 'isMinified.js', + 'location.js', + 'log.js', + 'makeRecord.js', + 'path.js', + 'prefs.js', + 'preview.js', + 'project-search.js', + 'quick-open.js', + 'result-list.js', + 'source-maps.js', + 'source-queue.js', + 'source.js', + 'tabs.js', + 'task.js', + 'test-head.js', + 'text.js', + 'timings.js', + 'ui.js', + 'utils.js', + 'wasm.js', + 'worker.js', +) diff --git a/devtools/client/debugger/new/src/utils/path.js b/devtools/client/debugger/new/src/utils/path.js new file mode 100644 index 000000000000..2afa614079a8 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/path.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function basename(path) { + return path.split("/").pop(); +} + +function dirname(path) { + const idx = path.lastIndexOf("/"); + return path.slice(0, idx); +} + +function isURL(str) { + return str.indexOf("://") !== -1; +} + +function isAbsolute(str) { + return str[0] === "/"; +} + +function join(base, dir) { + return `${base}/${dir}`; +} + +exports.basename = basename; +exports.dirname = dirname; +exports.isURL = isURL; +exports.isAbsolute = isAbsolute; +exports.join = join; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/annotateFrames.js b/devtools/client/debugger/new/src/utils/pause/frames/annotateFrames.js new file mode 100644 index 000000000000..48ecd137bc63 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/annotateFrames.js @@ -0,0 +1,75 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.annotateFrames = annotateFrames; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _getFrameUrl = require("./getFrameUrl"); + +var _getLibraryFromUrl = require("./getLibraryFromUrl"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function annotateFrames(frames) { + const annotatedFrames = frames.map(annotateFrame); + return annotateBabelAsyncFrames(annotatedFrames); +} + +function annotateFrame(frame) { + const library = (0, _getLibraryFromUrl.getLibraryFromUrl)(frame); + + if (library) { + return _objectSpread({}, frame, { + library + }); + } + + return frame; +} + +function annotateBabelAsyncFrames(frames) { + const babelFrameIndexes = getBabelFrameIndexes(frames); + + const isBabelFrame = frameIndex => babelFrameIndexes.includes(frameIndex); + + return frames.map((frame, frameIndex) => isBabelFrame(frameIndex) ? _objectSpread({}, frame, { + library: "Babel" + }) : frame); +} // Receives an array of frames and looks for babel async +// call stack groups. + + +function getBabelFrameIndexes(frames) { + const startIndexes = frames.reduce((accumulator, frame, index) => { + if ((0, _getFrameUrl.getFrameUrl)(frame).match(/regenerator-runtime/i) && frame.displayName === "tryCatch") { + return [...accumulator, index]; + } + + return accumulator; + }, []); + const endIndexes = frames.reduce((accumulator, frame, index) => { + if ((0, _getFrameUrl.getFrameUrl)(frame).match(/_microtask/i) && frame.displayName === "flush") { + return [...accumulator, index]; + } + + if (frame.displayName === "_asyncToGenerator/<") { + return [...accumulator, index + 1]; + } + + return accumulator; + }, []); + + if (startIndexes.length != endIndexes.length || startIndexes.length === 0) { + return frames; + } // Receives an array of start and end index tuples and returns + // an array of async call stack index ranges. + // e.g. [[1,3], [5,7]] => [[1,2,3], [5,6,7]] + + + return (0, _lodash.flatMap)((0, _lodash.zip)(startIndexes, endIndexes), ([startIndex, endIndex]) => (0, _lodash.range)(startIndex, endIndex + 1)); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js b/devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js new file mode 100644 index 000000000000..0128967aab35 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js @@ -0,0 +1,77 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.collapseFrames = collapseFrames; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _getFrameUrl = require("./getFrameUrl"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function collapseLastFrames(frames) { + const index = (0, _lodash.findIndex)(frames, frame => (0, _getFrameUrl.getFrameUrl)(frame).match(/webpack\/bootstrap/i)); + + if (index == -1) { + return { + newFrames: frames, + lastGroup: [] + }; + } + + const newFrames = frames.slice(0, index); + const lastGroup = frames.slice(index); + return { + newFrames, + lastGroup + }; +} + +function collapseFrames(frames) { + // We collapse groups of one so that user frames + // are not in a group of one + function addGroupToList(group, list) { + if (!group) { + return list; + } + + if (group.length > 1) { + list.push(group); + } else { + list = list.concat(group); + } + + return list; + } + + const { + newFrames, + lastGroup + } = collapseLastFrames(frames); + frames = newFrames; + let items = []; + let currentGroup = null; + let prevItem = null; + + for (const frame of frames) { + const prevLibrary = (0, _lodash.get)(prevItem, "library"); + + if (!currentGroup) { + currentGroup = [frame]; + } else if (prevLibrary && prevLibrary == frame.library) { + currentGroup.push(frame); + } else { + items = addGroupToList(currentGroup, items); + currentGroup = [frame]; + } + + prevItem = frame; + } + + items = addGroupToList(currentGroup, items); + items = addGroupToList(lastGroup, items); + return items; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/displayName.js b/devtools/client/debugger/new/src/utils/pause/frames/displayName.js new file mode 100644 index 000000000000..06821e760155 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/displayName.js @@ -0,0 +1,100 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.simplifyDisplayName = simplifyDisplayName; +exports.formatDisplayName = formatDisplayName; +exports.formatCopyName = formatCopyName; + +var _source = require("../../source"); + +var _utils = require("../../../utils/utils"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// eslint-disable-next-line max-len +// Decodes an anonymous naming scheme that +// spider monkey implements based on "Naming Anonymous JavaScript Functions" +// http://johnjbarton.github.io/nonymous/index.html +const objectProperty = /([\w\d]+)$/; +const arrayProperty = /\[(.*?)\]$/; +const functionProperty = /([\w\d]+)[\/\.<]*?$/; +const annonymousProperty = /([\w\d]+)\(\^\)$/; + +function simplifyDisplayName(displayName) { + // if the display name has a space it has already been mapped + if (/\s/.exec(displayName)) { + return displayName; + } + + const scenarios = [objectProperty, arrayProperty, functionProperty, annonymousProperty]; + + for (const reg of scenarios) { + const match = reg.exec(displayName); + + if (match) { + return match[1]; + } + } + + return displayName; +} + +const displayNameMap = { + Babel: { + tryCatch: "Async" + }, + Backbone: { + "extend/child": "Create Class", + ".create": "Create Model" + }, + jQuery: { + "jQuery.event.dispatch": "Dispatch Event" + }, + React: { + // eslint-disable-next-line max-len + "ReactCompositeComponent._renderValidatedComponentWithoutOwnerOrContext/renderedElement<": "Render", + _renderValidatedComponentWithoutOwnerOrContext: "Render" + }, + VueJS: { + "renderMixin/Vue.prototype._render": "Render" + }, + Webpack: { + // eslint-disable-next-line camelcase + __webpack_require__: "Bootstrap" + } +}; + +function mapDisplayNames(frame, library) { + const { + displayName + } = frame; + return displayNameMap[library] && displayNameMap[library][displayName] || displayName; +} + +function formatDisplayName(frame, { + shouldMapDisplayName = true +} = {}) { + let { + displayName, + originalDisplayName, + library + } = frame; + displayName = originalDisplayName || displayName; + + if (library && shouldMapDisplayName) { + displayName = mapDisplayNames(frame, library); + } + + displayName = simplifyDisplayName(displayName); + return (0, _utils.endTruncateStr)(displayName, 25); +} + +function formatCopyName(frame) { + const displayName = formatDisplayName(frame); + const fileName = (0, _source.getFilename)(frame.source); + const frameLocation = frame.location.line; + return `${displayName} (${fileName}#${frameLocation})`; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/getFrameUrl.js b/devtools/client/debugger/new/src/utils/pause/frames/getFrameUrl.js new file mode 100644 index 000000000000..7de2c086d50f --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/getFrameUrl.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFrameUrl = getFrameUrl; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getFrameUrl(frame) { + return (0, _lodash.get)(frame, "source.url", "") || ""; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/getLibraryFromUrl.js b/devtools/client/debugger/new/src/utils/pause/frames/getLibraryFromUrl.js new file mode 100644 index 000000000000..7a086ec1750a --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/getLibraryFromUrl.js @@ -0,0 +1,95 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getLibraryFromUrl = getLibraryFromUrl; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _getFrameUrl = require("./getFrameUrl"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const libraryMap = [{ + label: "Backbone", + pattern: /backbone/i +}, { + label: "jQuery", + pattern: /jquery/i +}, { + label: "Preact", + pattern: /preact/i +}, { + label: "React", + pattern: /react/i +}, { + label: "Immutable", + pattern: /immutable/i +}, { + label: "Webpack", + pattern: /webpack\/bootstrap/i +}, { + label: "Node", + pattern: /(^internal\/|^[^.\/]+\.js)/ +}, { + label: "Express", + pattern: /node_modules\/express/ +}, { + label: "Pug", + pattern: /node_modules\/pug/ +}, { + label: "ExtJS", + pattern: /\/ext-all[\.\-]/ +}, { + label: "MobX", + pattern: /mobx/i +}, { + label: "Underscore", + pattern: /underscore/i +}, { + label: "Lodash", + pattern: /lodash/i +}, { + label: "Ember", + pattern: /ember/i +}, { + label: "Choo", + pattern: /choo/i +}, { + label: "VueJS", + pattern: /vue\.js/i +}, { + label: "RxJS", + pattern: /rxjs/i +}, { + label: "Angular", + pattern: /angular/i +}, { + label: "Redux", + pattern: /redux/i +}, { + label: "Dojo", + pattern: /dojo/i +}, { + label: "Marko", + pattern: /marko/i +}, { + label: "NuxtJS", + pattern: /[\._]nuxt/i +}, { + label: "Aframe", + pattern: /aframe/i +}, { + label: "NextJS", + pattern: /[\._]next/i +}]; + +function getLibraryFromUrl(frame) { + // @TODO each of these fns calls getFrameUrl, just call it once + // (assuming there's not more complex logic to identify a lib) + const frameUrl = (0, _getFrameUrl.getFrameUrl)(frame); + const match = (0, _lodash.find)(libraryMap, o => frameUrl.match(o.pattern)); + return match && match.label; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/index.js b/devtools/client/debugger/new/src/utils/pause/frames/index.js new file mode 100644 index 000000000000..f60517b17d02 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/index.js @@ -0,0 +1,65 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _annotateFrames = require("./annotateFrames"); + +Object.keys(_annotateFrames).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _annotateFrames[key]; + } + }); +}); + +var _collapseFrames = require("./collapseFrames"); + +Object.keys(_collapseFrames).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _collapseFrames[key]; + } + }); +}); + +var _displayName = require("./displayName"); + +Object.keys(_displayName).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _displayName[key]; + } + }); +}); + +var _getFrameUrl = require("./getFrameUrl"); + +Object.keys(_getFrameUrl).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _getFrameUrl[key]; + } + }); +}); + +var _getLibraryFromUrl = require("./getLibraryFromUrl"); + +Object.keys(_getLibraryFromUrl).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _getLibraryFromUrl[key]; + } + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/frames/moz.build b/devtools/client/debugger/new/src/utils/pause/frames/moz.build new file mode 100644 index 000000000000..d398eb1675bf --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/frames/moz.build @@ -0,0 +1,17 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'annotateFrames.js', + 'collapseFrames.js', + 'displayName.js', + 'getFrameUrl.js', + 'getLibraryFromUrl.js', + 'index.js', +) diff --git a/devtools/client/debugger/new/src/utils/pause/index.js b/devtools/client/debugger/new/src/utils/pause/index.js new file mode 100644 index 000000000000..2d9651747b2b --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/index.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _why = require("./why"); + +Object.keys(_why).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _why[key]; + } + }); +}); + +var _stepping = require("./stepping"); + +Object.keys(_stepping).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _stepping[key]; + } + }); +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/buildGeneratedBindingList.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/buildGeneratedBindingList.js new file mode 100644 index 000000000000..c48ffdea5b6b --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/buildGeneratedBindingList.js @@ -0,0 +1,117 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.buildGeneratedBindingList = buildGeneratedBindingList; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _firefox = require("../../../client/firefox"); + +var _locColumn = require("./locColumn"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function buildGeneratedBindingList(scopes, generatedAstScopes, thisBinding) { + // The server's binding data doesn't include general 'this' binding + // information, so we manually inject the one 'this' binding we have into + // the normal binding data we are working with. + const frameThisOwner = generatedAstScopes.find(generated => "this" in generated.bindings); + let globalScope = null; + const clientScopes = []; + + for (let s = scopes; s; s = s.parent) { + const bindings = s.bindings ? Object.assign({}, ...s.bindings.arguments, s.bindings.variables) : {}; + clientScopes.push(bindings); + globalScope = s; + } + + const generatedMainScopes = generatedAstScopes.slice(0, -2); + const generatedGlobalScopes = generatedAstScopes.slice(-2); + const clientMainScopes = clientScopes.slice(0, generatedMainScopes.length); + const clientGlobalScopes = clientScopes.slice(generatedMainScopes.length); // Map the main parsed script body using the nesting hierarchy of the + // generated and client scopes. + + const generatedBindings = generatedMainScopes.reduce((acc, generated, i) => { + const bindings = clientMainScopes[i]; + + if (generated === frameThisOwner && thisBinding) { + bindings.this = { + value: thisBinding + }; + } + + for (const name of Object.keys(generated.bindings)) { + // If there is no 'this' value, we exclude the binding entirely. + // Otherwise it would pass through as found, but "(unscoped)", causing + // the search logic to stop with a match. + if (name === "this" && !bindings[name]) { + continue; + } + + const { + refs + } = generated.bindings[name]; + + for (const loc of refs) { + acc.push({ + name, + loc, + desc: () => Promise.resolve(bindings[name] || null) + }); + } + } + + return acc; + }, []); // Bindings in the global/lexical global of the generated code may or + // may not be the real global if the generated code is running inside + // of an evaled context. To handle this, we just look up the client scope + // hierarchy to find the closest binding with that name. + + for (const generated of generatedGlobalScopes) { + for (const name of Object.keys(generated.bindings)) { + const { + refs + } = generated.bindings[name]; + const bindings = clientGlobalScopes.find(b => (0, _lodash.has)(b, name)); + + for (const loc of refs) { + if (bindings) { + generatedBindings.push({ + name, + loc, + desc: () => Promise.resolve(bindings[name]) + }); + } else { + const globalGrip = globalScope && globalScope.object; + + if (globalGrip) { + // Should always exist, just checking to keep Flow happy. + generatedBindings.push({ + name, + loc, + desc: async () => { + const objectClient = (0, _firefox.createObjectClient)(globalGrip); + return (await objectClient.getProperty(name)).descriptor; + } + }); + } + } + } + } + } // Sort so we can binary-search. + + + return generatedBindings.sort((a, b) => { + const aStart = a.loc.start; + const bStart = b.loc.start; + + if (aStart.line === bStart.line) { + return (0, _locColumn.locColumn)(aStart) - (0, _locColumn.locColumn)(bStart); + } + + return aStart.line - bStart.line; + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/filtering.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/filtering.js new file mode 100644 index 000000000000..1f97b0ae9e1a --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/filtering.js @@ -0,0 +1,55 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.filterSortedArray = filterSortedArray; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function findInsertionLocation(array, callback) { + let left = 0; + let right = array.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + const item = array[mid]; + const result = callback(item); + + if (result === 0) { + left = mid; + break; + } + + if (result >= 0) { + right = mid; + } else { + left = mid + 1; + } + } // Ensure the value is the start of any set of matches. + + + let i = left; + + if (i < array.length) { + while (i >= 0 && callback(array[i]) >= 0) { + i--; + } + + return i + 1; + } + + return i; +} + +function filterSortedArray(array, callback) { + const start = findInsertionLocation(array, callback); + const results = []; + + for (let i = start; i < array.length && callback(array[i]) === 0; i++) { + results.push(array[i]); + } + + return results; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/findGeneratedBindingFromPosition.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/findGeneratedBindingFromPosition.js new file mode 100644 index 000000000000..fc839543b450 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/findGeneratedBindingFromPosition.js @@ -0,0 +1,331 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findGeneratedBindingForStandardBinding = findGeneratedBindingForStandardBinding; +exports.findGeneratedBindingForImportBinding = findGeneratedBindingForImportBinding; +exports.findGeneratedBindingForNormalDeclaration = findGeneratedBindingForNormalDeclaration; +exports.findGeneratedBindingForImportDeclaration = findGeneratedBindingForImportDeclaration; + +var _locColumn = require("./locColumn"); + +var _mappingContains = require("./mappingContains"); + +var _getGeneratedLocationRanges = require("./getGeneratedLocationRanges"); + +var _firefox = require("../../../client/firefox"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Find a simple 1-1 match of a binding in the original code to a binding + * in the generated code. + */ +async function findGeneratedBindingForStandardBinding(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { + return await findGeneratedReference((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos, bindingType, pos.type, sourceMaps))); +} +/** + * Find a simple 1-1 match of a binding in the original code to an + * expression in the generated code. + */ + + +async function findGeneratedBindingForImportBinding(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { + return await findGeneratedImportReference((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos, bindingType, pos.type, sourceMaps))); +} +/** + * Find a simple 1-1 match of a binding's declaration in the original code to a + * binding in the generated code. + */ + + +async function findGeneratedBindingForNormalDeclaration(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { + return await findGeneratedReference((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos.declaration, bindingType, pos.type, sourceMaps))); +} +/** + * Find a simple 1-1 match of an import binding's declaration in the original + * code to an expression in the generated code. + */ + + +async function findGeneratedBindingForImportDeclaration(sourceMaps, client, source, pos, name, bindingType, generatedAstBindings) { + const importName = pos.importName; + + if (typeof importName !== "string") { + // Should never happen, just keeping Flow happy. + return null; + } + + return await findGeneratedImportDeclaration((await (0, _getGeneratedLocationRanges.getGeneratedLocationRanges)(generatedAstBindings, source, pos.declaration, bindingType, pos.type, sourceMaps)), importName); +} +/** + * Given a mapped range over the generated source, attempt to resolve a real + * binding descriptor that can be used to access the value. + */ + + +async function findGeneratedReference(applicableBindings) { + // We can adjust this number as we go, but these are a decent start as a + // general heuristic to assume the bindings were bad or just map a chunk of + // whole line or something. + if (applicableBindings.length > 4) { + // Babel's for..of generates at least 3 bindings inside one range for + // block-scoped loop variables, so we shouldn't go below that. + applicableBindings = []; + } + + for (const applicable of applicableBindings) { + const result = await mapBindingReferenceToDescriptor(applicable); + + if (result) { + return result; + } + } + + return null; +} + +async function findGeneratedImportReference(applicableBindings) { + // When wrapped, for instance as `Object(ns.default)`, the `Object` binding + // will be the first in the list. To avoid resolving `Object` as the + // value of the import itself, we potentially skip the first binding. + applicableBindings = applicableBindings.filter((applicable, i) => { + if (!applicable.firstInRange || applicable.binding.loc.type !== "ref" || applicable.binding.loc.meta) { + return true; + } + + const next = i + 1 < applicableBindings.length ? applicableBindings[i + 1] : null; + return !next || next.binding.loc.type !== "ref" || !next.binding.loc.meta; + }); // We can adjust this number as we go, but these are a decent start as a + // general heuristic to assume the bindings were bad or just map a chunk of + // whole line or something. + + if (applicableBindings.length > 2) { + // Babel's for..of generates at least 3 bindings inside one range for + // block-scoped loop variables, so we shouldn't go below that. + applicableBindings = []; + } + + for (const applicable of applicableBindings) { + const result = await mapImportReferenceToDescriptor(applicable); + + if (result) { + return result; + } + } + + return null; +} +/** + * Given a mapped range over the generated source and the name of the imported + * value that is referenced, attempt to resolve a binding descriptor for + * the import's value. + */ + + +async function findGeneratedImportDeclaration(applicableBindings, importName) { + // We can adjust this number as we go, but these are a decent start as a + // general heuristic to assume the bindings were bad or just map a chunk of + // whole line or something. + if (applicableBindings.length > 10) { + // Import declarations tend to have a large number of bindings for + // for things like 'require' and 'interop', so this number is larger + // than other binding count checks. + applicableBindings = []; + } + + let result = null; + + for (const _ref of applicableBindings) { + const { + binding + } = _ref; + + if (binding.loc.type === "ref") { + continue; + } + + const namespaceDesc = await binding.desc(); + + if (isPrimitiveValue(namespaceDesc)) { + continue; + } + + if (!isObjectValue(namespaceDesc)) { + // We want to handle cases like + // + // var _mod = require(...); + // var _mod2 = _interopRequire(_mod); + // + // where "_mod" is optimized out because it is only referenced once. To + // allow that, we track the optimized-out value as a possible result, + // but allow later binding values to overwrite the result. + result = { + name: binding.name, + desc: namespaceDesc, + expression: binding.name + }; + continue; + } + + const desc = await readDescriptorProperty(namespaceDesc, importName); + const expression = `${binding.name}.${importName}`; + + if (desc) { + result = { + name: binding.name, + desc, + expression + }; + break; + } + } + + return result; +} +/** + * Given a generated binding, and a range over the generated code, statically + * check if the given binding matches the range. + */ + + +async function mapBindingReferenceToDescriptor({ + binding, + range, + firstInRange, + firstOnLine +}) { + // Allow the mapping to point anywhere within the generated binding + // location to allow for less than perfect sourcemaps. Since you also + // need at least one character between identifiers, we also give one + // characters of space at the front the generated binding in order + // to increase the probability of finding the right mapping. + if (range.start.line === binding.loc.start.line && ( // If a binding is the first on a line, Babel will extend the mapping to + // include the whitespace between the newline and the binding. To handle + // that, we skip the range requirement for starting location. + firstInRange || firstOnLine || (0, _locColumn.locColumn)(range.start) >= (0, _locColumn.locColumn)(binding.loc.start)) && (0, _locColumn.locColumn)(range.start) <= (0, _locColumn.locColumn)(binding.loc.end)) { + return { + name: binding.name, + desc: await binding.desc(), + expression: binding.name + }; + } + + return null; +} +/** + * Given an generated binding, and a range over the generated code, statically + * evaluate accessed properties within the mapped range to resolve the actual + * imported value. + */ + + +async function mapImportReferenceToDescriptor({ + binding, + range +}) { + if (binding.loc.type !== "ref") { + return null; + } // Expression matches require broader searching because sourcemaps usage + // varies in how they map certain things. For instance given + // + // import { bar } from "mod"; + // bar(); + // + // The "bar()" expression is generally expanded into one of two possibly + // forms, both of which map the "bar" identifier in different ways. See + // the "^^" markers below for the ranges. + // + // (0, foo.bar)() // Babel + // ^^^^^^^ // mapping + // ^^^ // binding + // vs + // + // Object(foo.bar)() // Webpack + // ^^^^^^^^^^^^^^^ // mapping + // ^^^ // binding + // + // Unfortunately, Webpack also has a tendancy to over-map past the call + // expression to the start of the next line, at least when there isn't + // anything else on that line that is mapped, e.g. + // + // Object(foo.bar)() + // ^^^^^^^^^^^^^^^^^ + // ^ // wrapped to column 0 of next line + + + if (!(0, _mappingContains.mappingContains)(range, binding.loc)) { + return null; + } + + let expression = binding.name; + let desc = await binding.desc(); + + if (binding.loc.type === "ref") { + const { + meta + } = binding.loc; // Limit to 2 simple property or inherits operartions, since it would + // just be more work to search more and it is very unlikely that + // bindings would be mapped to more than a single member + inherits + // wrapper. + + for (let op = meta, index = 0; op && (0, _mappingContains.mappingContains)(range, op) && desc && index < 2; index++, op = op && op.parent) { + // Calling could potentially trigger side-effects, which would not + // be ideal for this case. + if (op.type === "call") { + return null; + } + + if (op.type === "inherit") { + continue; + } + + desc = await readDescriptorProperty(desc, op.property); + expression += `.${op.property}`; + } + } + + return desc ? { + name: binding.name, + desc, + expression + } : null; +} + +function isPrimitiveValue(desc) { + return desc && (!desc.value || typeof desc.value !== "object"); +} + +function isObjectValue(desc) { + return desc && !isPrimitiveValue(desc) && desc.value.type === "object" && // Note: The check for `.type` might already cover the optimizedOut case + // but not 100% sure, so just being cautious. + !desc.value.optimizedOut; +} + +async function readDescriptorProperty(desc, property) { + if (!desc) { + return null; + } + + if (typeof desc.value !== "object" || !desc.value) { + // If accessing a property on a primitive type, just return 'undefined' + // as the value. + return { + value: { + type: "undefined" + } + }; + } + + if (!isObjectValue(desc)) { + // If we got a non-primitive descriptor but it isn't an object, then + // it's definitely not the namespace and it is probably an error. + return desc; + } + + const objectClient = (0, _firefox.createObjectClient)(desc.value); + return (await objectClient.getProperty(property)).descriptor; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/getGeneratedLocationRanges.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/getGeneratedLocationRanges.js new file mode 100644 index 000000000000..bd5482f82a81 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/getGeneratedLocationRanges.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getGeneratedLocationRanges = getGeneratedLocationRanges; + +var _positionCmp = require("./positionCmp"); + +var _filtering = require("./filtering"); + +var _mappingContains = require("./mappingContains"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +async function getGeneratedLocationRanges(generatedAstBindings, source, { + start, + end +}, bindingType, locationType, sourceMaps) { + const endPosition = await sourceMaps.getGeneratedLocation(end, source); + const startPosition = await sourceMaps.getGeneratedLocation(start, source); // If the start and end positions collapse into eachother, it means that + // the range in the original content didn't _start_ at the start position. + // Since this likely means that the range doesn't logically apply to this + // binding location, we skip it. + + if ((0, _positionCmp.positionCmp)(startPosition, endPosition) === 0) { + return []; + } + + const ranges = await sourceMaps.getGeneratedRanges(start, source); + const resultRanges = ranges.reduce((acc, mapRange) => { + // Some tooling creates ranges that map a line as a whole, which is useful + // for step-debugging, but can easily lead to finding the wrong binding. + // To avoid these false-positives, we entirely ignore ranges that cover + // full lines. + if (locationType === "ref" && mapRange.columnStart === 0 && mapRange.columnEnd === Infinity) { + return acc; + } + + const range = { + start: { + line: mapRange.line, + column: mapRange.columnStart + }, + end: { + line: mapRange.line, + // SourceMapConsumer's 'lastColumn' is inclusive, so we add 1 to make + // it exclusive like all other locations. + column: mapRange.columnEnd + 1 + } + }; + const previous = acc[acc.length - 1]; + + if (previous && (previous.end.line === range.start.line && previous.end.column === range.start.column || previous.end.line + 1 === range.start.line && previous.end.column === Infinity && range.start.column === 0)) { + previous.end.line = range.end.line; + previous.end.column = range.end.column; + } else { + acc.push(range); + } + + return acc; + }, []); // When searching for imports, we expand the range to up to the next available + // mapping to allow for import declarations that are composed of multiple + // variable statements, where the later ones are entirely unmapped. + // Babel 6 produces imports in this style, e.g. + // + // var _mod = require("mod"); // mapped from import statement + // var _mod2 = interop(_mod); // entirely unmapped + + if (bindingType === "import" && locationType !== "ref") { + for (const range of resultRanges) { + if ((0, _mappingContains.mappingContains)(range, { + start: startPosition, + end: startPosition + }) && (0, _positionCmp.positionCmp)(range.end, endPosition) < 0) { + range.end.line = endPosition.line; + range.end.column = endPosition.column; + break; + } + } + } + + return filterApplicableBindings(generatedAstBindings, resultRanges); +} + +function filterApplicableBindings(bindings, ranges) { + const result = []; + + for (const range of ranges) { + // Any binding overlapping a part of the mapping range. + const filteredBindings = (0, _filtering.filterSortedArray)(bindings, binding => { + if ((0, _positionCmp.positionCmp)(binding.loc.end, range.start) <= 0) { + return -1; + } + + if ((0, _positionCmp.positionCmp)(binding.loc.start, range.end) >= 0) { + return 1; + } + + return 0; + }); + let firstInRange = true; + let firstOnLine = true; + let line = -1; + + for (const binding of filteredBindings) { + if (binding.loc.start.line === line) { + firstOnLine = false; + } else { + line = binding.loc.start.line; + firstOnLine = true; + } + + result.push({ + binding, + range, + firstOnLine, + firstInRange + }); + firstInRange = false; + } + } + + return result; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js new file mode 100644 index 000000000000..596756ca7d51 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js @@ -0,0 +1,309 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.buildMappedScopes = buildMappedScopes; + +var _parser = require("../../../workers/parser/index"); + +var _locColumn = require("./locColumn"); + +var _findGeneratedBindingFromPosition = require("./findGeneratedBindingFromPosition"); + +var _buildGeneratedBindingList = require("./buildGeneratedBindingList"); + +var _log = require("../../log"); + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +async function buildMappedScopes(source, frame, scopes, sourceMaps, client) { + const originalAstScopes = await (0, _parser.getScopes)(frame.location); + const generatedAstScopes = await (0, _parser.getScopes)(frame.generatedLocation); + + if (!originalAstScopes || !generatedAstScopes) { + return null; + } + + const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this); + const { + mappedOriginalScopes, + expressionLookup + } = await mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps); + const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes); + return isReliableScope(mappedGeneratedScopes) ? { + mappings: expressionLookup, + scope: mappedGeneratedScopes + } : null; +} + +async function mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps) { + const expressionLookup = {}; + const mappedOriginalScopes = []; + const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps); + + for (const item of originalAstScopes) { + const generatedBindings = {}; + + for (const name of Object.keys(item.bindings)) { + const binding = item.bindings[name]; + const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, generatedAstBindings); + + if (result) { + generatedBindings[name] = result.grip; + + if (binding.refs.length !== 0 && // These are assigned depth-first, so we don't want shadowed + // bindings in parent scopes overwriting the expression. + !Object.prototype.hasOwnProperty.call(expressionLookup, name)) { + expressionLookup[name] = result.expression; + } + } + } + + mappedOriginalScopes.push(_objectSpread({}, item, { + generatedBindings + })); + } + + return { + mappedOriginalScopes, + expressionLookup + }; +} +/** + * Consider a scope and its parents reliable if the vast majority of its + * bindings were successfully mapped to generated scope bindings. + */ + + +function isReliableScope(scope) { + let totalBindings = 0; + let unknownBindings = 0; + + for (let s = scope; s; s = s.parent) { + const vars = s.bindings && s.bindings.variables || {}; + + for (const key of Object.keys(vars)) { + const binding = vars[key]; + totalBindings += 1; + + if (binding.value && typeof binding.value === "object" && (binding.value.type === "unscoped" || binding.value.type === "unmapped")) { + unknownBindings += 1; + } + } + } // As determined by fair dice roll. + + + return totalBindings === 0 || unknownBindings / totalBindings < 0.1; +} + +function batchScopeMappings(originalAstScopes, source, sourceMaps) { + const precalculatedRanges = new Map(); + const precalculatedLocations = new Map(); // Explicitly dispatch all of the sourcemap requests synchronously up front so + // that they will be batched into a single request for the worker to process. + + for (const item of originalAstScopes) { + for (const name of Object.keys(item.bindings)) { + for (const ref of item.bindings[name].refs) { + const locs = [ref]; + + if (ref.type !== "ref") { + locs.push(ref.declaration); + } + + for (const loc of locs) { + precalculatedRanges.set(buildLocationKey(loc.start), sourceMaps.getGeneratedRanges(loc.start, source)); + precalculatedLocations.set(buildLocationKey(loc.start), sourceMaps.getGeneratedLocation(loc.start, source)); + precalculatedLocations.set(buildLocationKey(loc.end), sourceMaps.getGeneratedLocation(loc.end, source)); + } + } + } + } + + return { + async getGeneratedRanges(pos, s) { + const key = buildLocationKey(pos); + + if (s !== source || !precalculatedRanges.has(key)) { + (0, _log.log)("Bad precalculated mapping"); + return sourceMaps.getGeneratedRanges(pos, s); + } + + return precalculatedRanges.get(key); + }, + + async getGeneratedLocation(pos, s) { + const key = buildLocationKey(pos); + + if (s !== source || !precalculatedLocations.has(key)) { + (0, _log.log)("Bad precalculated mapping"); + return sourceMaps.getGeneratedLocation(pos, s); + } + + return precalculatedLocations.get(key); + } + + }; +} + +function buildLocationKey(loc) { + return `${loc.line}:${(0, _locColumn.locColumn)(loc)}`; +} + +function generateClientScope(scopes, originalScopes) { + // Pull the root object scope and root lexical scope to reuse them in + // our mapped scopes. This assumes that file file being processed is + // a CommonJS or ES6 module, which might not be ideal. Potentially + let globalLexicalScope = null; + + for (let s = scopes; s.parent; s = s.parent) { + // $FlowIgnore - Flow doesn't like casting 'parent'. + globalLexicalScope = s; + } + + if (!globalLexicalScope) { + throw new Error("Assertion failure - there should always be a scope"); + } // Build a structure similar to the client's linked scope object using + // the original AST scopes, but pulling in the generated bindings + // linked to each scope. + + + const result = originalScopes.slice(0, -2).reverse().reduce((acc, orig, i) => { + const _orig$generatedBindin = orig.generatedBindings, + { + // The 'this' binding data we have is handled independently, so + // the binding data is not included here. + // eslint-disable-next-line no-unused-vars + this: _this + } = _orig$generatedBindin, + variables = _objectWithoutProperties(_orig$generatedBindin, ["this"]); + + return _objectSpread({ + // Flow doesn't like casting 'parent'. + parent: acc, + actor: `originalActor${i}`, + type: orig.type, + bindings: { + arguments: [], + variables + } + }, orig.type === "function" ? { + function: { + displayName: orig.displayName + } + } : null, orig.type === "block" ? { + block: { + displayName: orig.displayName + } + } : null); + }, globalLexicalScope); // The rendering logic in getScope 'this' bindings only runs on the current + // selected frame scope, so we pluck out the 'this' binding that was mapped, + // and put it in a special location + + const thisScope = originalScopes.find(scope => scope.bindings.this); + + if (thisScope) { + result.bindings.this = thisScope.generatedBindings.this || null; + } + + return result; +} + +async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, generatedAstBindings) { + // If there are no references to the implicits, then we have no way to + // even attempt to map it back to the original since there is no location + // data to use. Bail out instead of just showing it as unmapped. + if (originalBinding.type === "implicit" && !originalBinding.refs.some(item => item.type === "ref")) { + return null; + } + + const { + refs + } = originalBinding; + let genContent = null; + + for (const pos of refs) { + if (originalBinding.type === "import") { + genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + } else { + genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + } + + if ((pos.type === "class-decl" || pos.type === "class-inner") && source.contentType && source.contentType.match(/\/typescript/)) { + // Resolve to first binding in the range + const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + + if (declContent) { + // Prefer the declaration mapping in this case because TS sometimes + // maps class declaration names to "export.Foo = Foo;" or to + // the decorator logic itself + genContent = declContent; + } + } + + if (!genContent && (pos.type === "import-decl" || pos.type === "import-ns-decl")) { + // match the import declaration location + genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + } + + if (genContent) { + break; + } + } + + if (genContent && genContent.desc) { + return { + grip: genContent.desc, + expression: genContent.expression + }; + } else if (genContent) { + // If there is no descriptor for 'this', then this is not the top-level + // 'this' that the server gave us a binding for, and we can just ignore it. + if (name === "this") { + return null; + } // If the location is found but the descriptor is not, then it + // means that the server scope information didn't match the scope + // information from the DevTools parsed scopes. + + + return { + grip: { + configurable: false, + enumerable: true, + writable: false, + value: { + type: "unscoped", + unscoped: true, + // HACK: Until support for "unscoped" lands in devtools-reps, + // this will make these show as (unavailable). + missingArguments: true + } + }, + expression: null + }; + } // If no location mapping is found, then the map is bad, or + // the map is okay but it original location is inside + // of some scope, but the generated location is outside, leading + // us to search for bindings that don't technically exist. + + + return { + grip: { + configurable: false, + enumerable: true, + writable: false, + value: { + type: "unmapped", + unmapped: true, + // HACK: Until support for "unmapped" lands in devtools-reps, + // this will make these show as (unavailable). + missingArguments: true + } + }, + expression: null + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/locColumn.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/locColumn.js new file mode 100644 index 000000000000..3b434fa4bdcb --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/locColumn.js @@ -0,0 +1,19 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.locColumn = locColumn; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function locColumn(loc) { + if (typeof loc.column !== "number") { + // This shouldn't really happen with locations from the AST, but + // the datatype we are using allows null/undefined column. + return 0; + } + + return loc.column; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/mappingContains.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/mappingContains.js new file mode 100644 index 000000000000..d668d2df537f --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/mappingContains.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.mappingContains = mappingContains; + +var _positionCmp = require("./positionCmp"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function mappingContains(mapped, item) { + return (0, _positionCmp.positionCmp)(item.start, mapped.start) >= 0 && (0, _positionCmp.positionCmp)(item.end, mapped.end) <= 0; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build b/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build new file mode 100644 index 000000000000..b8c2b558d199 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build @@ -0,0 +1,19 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'buildGeneratedBindingList.js', + 'filtering.js', + 'findGeneratedBindingFromPosition.js', + 'getGeneratedLocationRanges.js', + 'index.js', + 'locColumn.js', + 'mappingContains.js', + 'positionCmp.js', +) diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/positionCmp.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/positionCmp.js new file mode 100644 index 000000000000..d00c551701c0 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/positionCmp.js @@ -0,0 +1,32 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.positionCmp = positionCmp; + +var _locColumn = require("./locColumn"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * * === 0 - Positions are equal. + * * < 0 - first position before second position + * * > 0 - first position after second position + */ +function positionCmp(p1, p2) { + if (p1.line === p2.line) { + const l1 = (0, _locColumn.locColumn)(p1); + const l2 = (0, _locColumn.locColumn)(p2); + + if (l1 === l2) { + return 0; + } + + return l1 < l2 ? -1 : 1; + } + + return p1.line < p2.line ? -1 : 1; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/moz.build b/devtools/client/debugger/new/src/utils/pause/moz.build new file mode 100644 index 000000000000..45e284d09db0 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/moz.build @@ -0,0 +1,17 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'frames', + 'mapScopes', + 'scopes', +] + +DevToolsModules( + 'index.js', + 'pausePoints.js', + 'stepping.js', + 'why.js', +) diff --git a/devtools/client/debugger/new/src/utils/pause/pausePoints.js b/devtools/client/debugger/new/src/utils/pause/pausePoints.js new file mode 100644 index 000000000000..80b1c8359650 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/pausePoints.js @@ -0,0 +1,57 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.convertToList = convertToList; +exports.formatPausePoints = formatPausePoints; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function insertStrtAt(string, index, newString) { + const start = string.slice(0, index); + const end = string.slice(index); + return `${start}${newString}${end}`; +} + +function convertToList(pausePoints) { + const list = []; + + for (const line in pausePoints) { + for (const column in pausePoints[line]) { + const point = pausePoints[line][column]; + list.push({ + location: { + line: parseInt(line, 10), + column: parseInt(column, 10) + }, + types: point + }); + } + } + + return list; +} + +function formatPausePoints(text, pausePoints) { + const nodes = (0, _lodash.reverse)(convertToList(pausePoints)); + const lines = text.split("\n"); + nodes.forEach((node, index) => { + const { + line, + column + } = node.location; + const { + break: breakPoint, + step + } = node.types; + const num = nodes.length - index; + const types = `${breakPoint ? "b" : ""}${step ? "s" : ""}`; + const spacer = breakPoint || step ? " " : ""; + lines[line - 1] = insertStrtAt(lines[line - 1], column, `/*${types}${spacer}${num}*/`); + }); + return lines.join("\n"); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/scopes/getScope.js b/devtools/client/debugger/new/src/utils/pause/scopes/getScope.js new file mode 100644 index 000000000000..2a7886b84d6c --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/scopes/getScope.js @@ -0,0 +1,92 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getScope = getScope; + +var _devtoolsReps = require("devtools/client/shared/components/reps/reps.js"); + +var _getVariables = require("./getVariables"); + +var _utils = require("./utils"); + +var _frames = require("../../pause/frames/index"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getScopeTitle(type, scope) { + if (type === "block" && scope.block && scope.block.displayName) { + return scope.block.displayName; + } + + if (type === "function" && scope.function) { + return scope.function.displayName ? (0, _frames.simplifyDisplayName)(scope.function.displayName) : L10N.getStr("anonymous"); + } + + return L10N.getStr("scopes.block"); +} + +function getScope(scope, selectedFrame, frameScopes, why, scopeIndex) { + const { + type, + actor + } = scope; + const isLocalScope = scope.actor === frameScopes.actor; + const key = `${actor}-${scopeIndex}`; + + if (type === "function" || type === "block") { + const bindings = scope.bindings; + let vars = (0, _getVariables.getBindingVariables)(bindings, key); // show exception, return, and this variables in innermost scope + + if (isLocalScope) { + vars = vars.concat((0, _utils.getFramePopVariables)(why, key)); + let thisDesc_ = selectedFrame.this; + + if ("this" in bindings) { + // The presence of "this" means we're rendering a "this" binding + // generated from mapScopes and this can override the binding + // provided by the current frame. + thisDesc_ = bindings.this ? bindings.this.value : null; + } + + const this_ = (0, _utils.getThisVariable)(thisDesc_, key); + + if (this_) { + vars.push(this_); + } + } + + if (vars && vars.length) { + const title = getScopeTitle(type, scope); + vars.sort((a, b) => a.name.localeCompare(b.name)); + return { + name: title, + path: key, + contents: vars, + type: _devtoolsReps.ObjectInspectorUtils.node.NODE_TYPES.BLOCK + }; + } + } else if (type === "object" && scope.object) { + let value = scope.object; // If this is the global window scope, mark it as such so that it will + // preview Window: Global instead of Window: Window + + if (value.class === "Window") { + value = _objectSpread({}, scope.object, { + displayClass: "Global" + }); + } + + return { + name: scope.object.class, + path: key, + contents: { + value + } + }; + } + + return null; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/scopes/getVariables.js b/devtools/client/debugger/new/src/utils/pause/scopes/getVariables.js new file mode 100644 index 000000000000..9ac9f53967fb --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/scopes/getVariables.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getBindingVariables = getBindingVariables; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* eslint max-nested-callbacks: ["error", 4] */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Create the tree nodes representing all the variables and arguments +// for the bindings from a scope. +function getBindingVariables(bindings, parentName) { + const args = bindings.arguments.map(arg => (0, _lodash.toPairs)(arg)[0]); + const variables = (0, _lodash.toPairs)(bindings.variables); + return args.concat(variables).map(binding => { + const name = binding[0]; + const contents = binding[1]; + return { + name, + path: `${parentName}/${name}`, + contents + }; + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/scopes/index.js b/devtools/client/debugger/new/src/utils/pause/scopes/index.js new file mode 100644 index 000000000000..7fac1a602df8 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/scopes/index.js @@ -0,0 +1,38 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getScopes = getScopes; + +var _getScope = require("./getScope"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getScopes(why, selectedFrame, frameScopes) { + if (!why || !selectedFrame) { + return null; + } + + if (!frameScopes) { + return null; + } + + const scopes = []; + let scope = frameScopes; + let scopeIndex = 1; + + while (scope) { + const scopeItem = (0, _getScope.getScope)(scope, selectedFrame, frameScopes, why, scopeIndex); + + if (scopeItem) { + scopes.push(scopeItem); + } + + scopeIndex++; + scope = scope.parent; + } + + return scopes; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/scopes/moz.build b/devtools/client/debugger/new/src/utils/pause/scopes/moz.build new file mode 100644 index 000000000000..a82529fadab5 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/scopes/moz.build @@ -0,0 +1,15 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'getScope.js', + 'getVariables.js', + 'index.js', + 'utils.js', +) diff --git a/devtools/client/debugger/new/src/utils/pause/scopes/utils.js b/devtools/client/debugger/new/src/utils/pause/scopes/utils.js new file mode 100644 index 000000000000..07a86deb1d2c --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/scopes/utils.js @@ -0,0 +1,59 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFramePopVariables = getFramePopVariables; +exports.getThisVariable = getThisVariable; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getFramePopVariables(why, path) { + const vars = []; + + if (why && why.frameFinished) { + const frameFinished = why.frameFinished; // Always display a `throw` property if present, even if it is falsy. + + if (Object.prototype.hasOwnProperty.call(frameFinished, "throw")) { + vars.push({ + name: "", + path: `${path}/`, + contents: { + value: frameFinished.throw + } + }); + } + + if (Object.prototype.hasOwnProperty.call(frameFinished, "return")) { + const returned = frameFinished.return; // Do not display undefined. Do display falsy values like 0 and false. The + // protocol grip for undefined is a JSON object: { type: "undefined" }. + + if (typeof returned !== "object" || returned.type !== "undefined") { + vars.push({ + name: "", + path: `${path}/`, + contents: { + value: returned + } + }); + } + } + } + + return vars; +} + +function getThisVariable(this_, path) { + if (!this_) { + return null; + } + + return { + name: "", + path: `${path}/`, + contents: { + value: this_ + } + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/stepping.js b/devtools/client/debugger/new/src/utils/pause/stepping.js new file mode 100644 index 000000000000..6ea8726e3943 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/stepping.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.shouldStep = shouldStep; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _selectors = require("../../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getFrameLocation(source, frame) { + if (!frame) { + return null; + } + + return (0, _devtoolsSourceMap.isOriginalId)(source.id) ? frame.location : frame.generatedLocation; +} + +function shouldStep(rootFrame, state, sourceMaps) { + const selectedSource = (0, _selectors.getSelectedSource)(state); + const previousFrameInfo = (0, _selectors.getPreviousPauseFrameLocation)(state); + + if (!rootFrame || !selectedSource) { + return false; + } + + const previousFrameLoc = getFrameLocation(selectedSource, previousFrameInfo); + const frameLoc = getFrameLocation(selectedSource, rootFrame); + const sameLocation = previousFrameLoc && (0, _lodash.isEqual)(previousFrameLoc, frameLoc); + const pausePoint = (0, _selectors.getPausePoint)(state, frameLoc); + const invalidPauseLocation = pausePoint && !pausePoint.step; // We always want to pause in generated locations + + if (!frameLoc || (0, _devtoolsSourceMap.isGeneratedId)(frameLoc.sourceId)) { + return false; + } + + return sameLocation || invalidPauseLocation; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/pause/why.js b/devtools/client/debugger/new/src/utils/pause/why.js new file mode 100644 index 000000000000..dd9700d40e03 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/why.js @@ -0,0 +1,63 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getPauseReason = getPauseReason; +exports.isException = isException; +exports.isInterrupted = isInterrupted; +exports.inDebuggerEval = inDebuggerEval; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Map protocol pause "why" reason to a valid L10N key +// These are the known unhandled reasons: +// "breakpointConditionThrown", "clientEvaluated" +// "interrupted", "attached" +const reasons = { + debuggerStatement: "whyPaused.debuggerStatement", + breakpoint: "whyPaused.breakpoint", + exception: "whyPaused.exception", + resumeLimit: "whyPaused.resumeLimit", + pauseOnDOMEvents: "whyPaused.pauseOnDOMEvents", + breakpointConditionThrown: "whyPaused.breakpointConditionThrown", + // V8 + DOM: "whyPaused.breakpoint", + EventListener: "whyPaused.pauseOnDOMEvents", + XHR: "whyPaused.xhr", + promiseRejection: "whyPaused.promiseRejection", + assert: "whyPaused.assert", + debugCommand: "whyPaused.debugCommand", + other: "whyPaused.other" +}; + +function getPauseReason(why) { + if (!why) { + return null; + } + + const reasonType = why.type; + + if (!reasons[reasonType]) { + console.log("Please file an issue: reasonType=", reasonType); + } + + return reasons[reasonType]; +} + +function isException(why) { + return why && why.type && why.type === "exception"; +} + +function isInterrupted(why) { + return why && why.type && why.type === "interrupted"; +} + +function inDebuggerEval(why) { + if (why && why.type === "exception" && why.exception && why.exception.preview && why.exception.preview.fileName) { + return why.exception.preview.fileName === "debugger eval code"; + } + + return false; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/prefs.js b/devtools/client/debugger/new/src/utils/prefs.js new file mode 100644 index 000000000000..14caf5657fc4 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/prefs.js @@ -0,0 +1,121 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + isDevelopment +} = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +const { + Services, + PrefsHelper +} = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; + +const prefsSchemaVersion = "1.0.3"; +const pref = Services.pref; + +if (isDevelopment()) { + pref("devtools.debugger.alphabetize-outline", false); + pref("devtools.debugger.auto-pretty-print", false); + pref("devtools.source-map.client-service.enabled", true); + pref("devtools.debugger.pause-on-exceptions", false); + pref("devtools.debugger.pause-on-caught-exceptions", false); + pref("devtools.debugger.ignore-caught-exceptions", true); + pref("devtools.debugger.call-stack-visible", true); + pref("devtools.debugger.scopes-visible", true); + pref("devtools.debugger.component-visible", true); + pref("devtools.debugger.component-stack-visible", false); + pref("devtools.debugger.workers-visible", true); + pref("devtools.debugger.expressions-visible", true); + pref("devtools.debugger.breakpoints-visible", true); + pref("devtools.debugger.start-panel-collapsed", false); + pref("devtools.debugger.end-panel-collapsed", false); + pref("devtools.debugger.tabs", "[]"); + pref("devtools.debugger.tabsBlackBoxed", "[]"); + pref("devtools.debugger.ui.framework-grouping-on", true); + pref("devtools.debugger.pending-selected-location", "{}"); + pref("devtools.debugger.pending-breakpoints", "{}"); + pref("devtools.debugger.expressions", "[]"); + pref("devtools.debugger.file-search-case-sensitive", false); + pref("devtools.debugger.file-search-whole-word", false); + pref("devtools.debugger.file-search-regex-match", false); + pref("devtools.debugger.project-directory-root", ""); + pref("devtools.debugger.prefs-schema-version", "1.0.1"); + pref("devtools.debugger.skip-pausing", false); + pref("devtools.debugger.features.workers", true); + pref("devtools.debugger.features.async-stepping", true); + pref("devtools.debugger.features.wasm", true); + pref("devtools.debugger.features.shortcuts", true); + pref("devtools.debugger.features.root", true); + pref("devtools.debugger.features.column-breakpoints", false); + pref("devtools.debugger.features.map-scopes", true); + pref("devtools.debugger.features.remove-command-bar-options", true); + pref("devtools.debugger.features.code-coverage", false); + pref("devtools.debugger.features.event-listeners", false); + pref("devtools.debugger.features.code-folding", false); + pref("devtools.debugger.features.outline", true); + pref("devtools.debugger.features.column-breakpoints", true); + pref("devtools.debugger.features.replay", true); + pref("devtools.debugger.features.pause-points", true); + pref("devtools.debugger.features.component-stack", true); + pref("devtools.debugger.features.skip-pausing", false); +} + +const prefs = exports.prefs = new PrefsHelper("devtools", { + alphabetizeOutline: ["Bool", "debugger.alphabetize-outline"], + autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"], + clientSourceMapsEnabled: ["Bool", "source-map.client-service.enabled"], + pauseOnExceptions: ["Bool", "debugger.pause-on-exceptions"], + pauseOnCaughtExceptions: ["Bool", "debugger.pause-on-caught-exceptions"], + ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"], + callStackVisible: ["Bool", "debugger.call-stack-visible"], + scopesVisible: ["Bool", "debugger.scopes-visible"], + componentVisible: ["Bool", "debugger.component-visible"], + componentStackVisible: ["Bool", "debugger.component-stack-visible"], + workersVisible: ["Bool", "debugger.workers-visible"], + breakpointsVisible: ["Bool", "debugger.breakpoints-visible"], + expressionsVisible: ["Bool", "debugger.expressions-visible"], + startPanelCollapsed: ["Bool", "debugger.start-panel-collapsed"], + endPanelCollapsed: ["Bool", "debugger.end-panel-collapsed"], + frameworkGroupingOn: ["Bool", "debugger.ui.framework-grouping-on"], + tabs: ["Json", "debugger.tabs", []], + tabsBlackBoxed: ["Json", "debugger.tabsBlackBoxed", []], + pendingSelectedLocation: ["Json", "debugger.pending-selected-location", {}], + pendingBreakpoints: ["Json", "debugger.pending-breakpoints", {}], + expressions: ["Json", "debugger.expressions", []], + fileSearchCaseSensitive: ["Bool", "debugger.file-search-case-sensitive"], + fileSearchWholeWord: ["Bool", "debugger.file-search-whole-word"], + fileSearchRegexMatch: ["Bool", "debugger.file-search-regex-match"], + debuggerPrefsSchemaVersion: ["Char", "debugger.prefs-schema-version"], + projectDirectoryRoot: ["Char", "debugger.project-directory-root", ""], + skipPausing: ["Bool", "debugger.skip-pausing"] +}); +const features = exports.features = new PrefsHelper("devtools.debugger.features", { + asyncStepping: ["Bool", "async-stepping"], + wasm: ["Bool", "wasm"], + shortcuts: ["Bool", "shortcuts"], + root: ["Bool", "root"], + columnBreakpoints: ["Bool", "column-breakpoints"], + mapScopes: ["Bool", "map-scopes"], + removeCommandBarOptions: ["Bool", "remove-command-bar-options"], + workers: ["Bool", "workers"], + codeCoverage: ["Bool", "code-coverage"], + eventListeners: ["Bool", "event-listeners"], + outline: ["Bool", "outline"], + codeFolding: ["Bool", "code-folding"], + replay: ["Bool", "replay"], + pausePoints: ["Bool", "pause-points"], + componentStack: ["Bool", "component-stack"], + skipPausing: ["Bool", "skip-pausing"] +}); + +if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) { + // clear pending Breakpoints + prefs.pendingBreakpoints = {}; + prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/preview.js b/devtools/client/debugger/new/src/utils/preview.js new file mode 100644 index 000000000000..9e2583d927b6 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/preview.js @@ -0,0 +1,45 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isImmutable = isImmutable; +exports.isReactComponent = isReactComponent; +exports.isConsole = isConsole; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const IMMUTABLE_FIELDS = ["_root", "__ownerID", "__altered", "__hash"]; + +function isImmutable(result) { + if (!result || !result.preview) { + return; + } + + const ownProperties = result.preview.ownProperties; + + if (!ownProperties) { + return; + } + + return IMMUTABLE_FIELDS.every(field => Object.keys(ownProperties).includes(field)); +} + +function isReactComponent(result) { + if (!result || !result.preview) { + return; + } + + const ownProperties = result.preview.ownProperties; + + if (!ownProperties) { + return; + } + + return Object.keys(ownProperties).includes("_reactInternalInstance") || Object.keys(ownProperties).includes("_reactInternalFiber"); +} + +function isConsole(expression) { + return /^console/.test(expression); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/project-search.js b/devtools/client/debugger/new/src/utils/project-search.js new file mode 100644 index 000000000000..445e119e9a56 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/project-search.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.highlightMatches = highlightMatches; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Maybe reuse file search's functions? +function highlightMatches(lineMatch) { + const { + value, + column, + match + } = lineMatch; + const len = match.length; + return _react2.default.createElement("span", { + className: "line-value" + }, _react2.default.createElement("span", { + className: "line-match", + key: 0 + }, value.slice(0, column)), _react2.default.createElement("span", { + className: "query-match", + key: 1 + }, value.substr(column, len)), _react2.default.createElement("span", { + className: "line-match", + key: 2 + }, value.slice(column + len, value.length))); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/quick-open.js b/devtools/client/debugger/new/src/utils/quick-open.js new file mode 100644 index 000000000000..86f1ed745079 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/quick-open.js @@ -0,0 +1,129 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MODIFIERS = undefined; +exports.parseQuickOpenQuery = parseQuickOpenQuery; +exports.parseLineColumn = parseLineColumn; +exports.formatSourcesForList = formatSourcesForList; +exports.formatSymbol = formatSymbol; +exports.formatSymbols = formatSymbols; +exports.formatShortcutResults = formatShortcutResults; +exports.formatSources = formatSources; + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _utils = require("./utils"); + +var _source = require("./source"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const MODIFIERS = exports.MODIFIERS = { + "@": "functions", + "#": "variables", + ":": "goto", + "?": "shortcuts" +}; + +function parseQuickOpenQuery(query) { + const modifierPattern = /^@|#|:|\?$/; + const gotoSourcePattern = /^(\w+)\:/; + const startsWithModifier = modifierPattern.test(query[0]); + const isGotoSource = gotoSourcePattern.test(query); + + if (startsWithModifier) { + const modifier = query[0]; + return MODIFIERS[modifier]; + } + + if (isGotoSource) { + return "gotoSource"; + } + + return "sources"; +} + +function parseLineColumn(query) { + const [, line, column] = query.split(":"); + const lineNumber = parseInt(line, 10); + const columnNumber = parseInt(column, 10); + + if (!isNaN(lineNumber)) { + return _objectSpread({ + line: lineNumber + }, !isNaN(columnNumber) ? { + column: columnNumber + } : null); + } +} + +function formatSourcesForList(source, tabs) { + const title = (0, _source.getFilename)(source); + const subtitle = (0, _utils.endTruncateStr)(source.relativeUrl, 100); + return { + value: source.relativeUrl, + title, + subtitle, + icon: tabs.includes(source.url) ? "tab result-item-icon" : (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "result-item-icon"), + id: source.id, + url: source.url + }; +} + +function formatSymbol(symbol) { + return { + id: `${symbol.name}:${symbol.location.start.line}`, + title: symbol.name, + subtitle: `${symbol.location.start.line}`, + value: symbol.name, + location: symbol.location + }; +} + +function formatSymbols(symbols) { + if (!symbols || symbols.loading) { + return { + variables: [], + functions: [] + }; + } + + const { + variables, + functions + } = symbols; + return { + variables: variables.map(formatSymbol), + functions: functions.map(formatSymbol) + }; +} + +function formatShortcutResults() { + return [{ + value: L10N.getStr("symbolSearch.search.functionsPlaceholder.title"), + title: `@ ${L10N.getStr("symbolSearch.search.functionsPlaceholder")}`, + id: "@" + }, { + value: L10N.getStr("symbolSearch.search.variablesPlaceholder.title"), + title: `# ${L10N.getStr("symbolSearch.search.variablesPlaceholder")}`, + id: "#" + }, { + value: L10N.getStr("gotoLineModal.title"), + title: `: ${L10N.getStr("gotoLineModal.placeholder")}`, + id: ":" + }]; +} + +function formatSources(sources, tabs) { + return sources.filter(source => !(0, _source.isPretty)(source)).map(source => formatSourcesForList(source, tabs)).filter(({ + value + }) => value != ""); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/result-list.js b/devtools/client/debugger/new/src/utils/result-list.js new file mode 100644 index 000000000000..05b37de0da06 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/result-list.js @@ -0,0 +1,58 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.scrollList = undefined; + +var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"]; + +var _Modal = require("../components/shared/Modal"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function scrollList(resultList, index, delayed = false) { + if (!resultList.hasOwnProperty(index)) { + return; + } + + const resultEl = resultList[index]; + + const scroll = () => { + if ((0, _devtoolsEnvironment.isFirefox)()) { + resultEl.scrollIntoView({ + block: "center", + behavior: "smooth" + }); + } else { + chromeScrollList(resultEl, index); + } + }; + + if (delayed) { + // Wait for Modal Transition timeout before scrolling to resultEl. + setTimeout(scroll, _Modal.transitionTimeout + 10); + return; + } + + scroll(); +} + +function chromeScrollList(elem, index) { + const resultsEl = elem.parentNode; + + if (!resultsEl || resultsEl.children.length === 0) { + return; + } + + const resultsHeight = resultsEl.clientHeight; + const itemHeight = resultsEl.children[0].clientHeight; + const numVisible = resultsHeight / itemHeight; + const positionsToScroll = index - numVisible + 1; + const itemOffset = resultsHeight % itemHeight; + const scroll = positionsToScroll * (itemHeight + 2) + itemOffset; + resultsEl.scrollTop = Math.max(0, scroll); +} + +exports.scrollList = scrollList; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/source-maps.js b/devtools/client/debugger/new/src/utils/source-maps.js new file mode 100644 index 000000000000..9193fe57aec4 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/source-maps.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getGeneratedLocation = getGeneratedLocation; + +var _selectors = require("../selectors/index"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +async function getGeneratedLocation(state, source, location, sourceMaps) { + if (!sourceMaps.isOriginalId(location.sourceId)) { + return location; + } + + const { + line, + sourceId, + column + } = await sourceMaps.getGeneratedLocation(location, source.toJS()); + const generatedSource = (0, _selectors.getSource)(state, sourceId); + + if (!generatedSource) { + return location; + } + + return { + line, + sourceId, + column: column === 0 ? undefined : column, + sourceUrl: generatedSource.url + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/source-queue.js b/devtools/client/debugger/new/src/utils/source-queue.js new file mode 100644 index 000000000000..142a910ac380 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/source-queue.js @@ -0,0 +1,40 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let newSources; +let createSource; +let supportsWasm = false; +let queuedSources; +let currentWork; + +async function dispatchNewSources() { + const sources = queuedSources; + queuedSources = []; + currentWork = await newSources(sources.map(source => createSource(source, { + supportsWasm + }))); +} + +const queue = (0, _lodash.throttle)(dispatchNewSources, 100); +exports.default = { + initialize: options => { + newSources = options.actions.newSources; + createSource = options.createSource; + supportsWasm = options.supportsWasm; + queuedSources = []; + }, + queue: source => { + queuedSources.push(source); + queue(); + }, + flush: () => Promise.all([queue.flush(), currentWork]), + clear: () => queue.cancel() +}; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/source.js b/devtools/client/debugger/new/src/utils/source.js new file mode 100644 index 000000000000..5ce81ac0d956 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/source.js @@ -0,0 +1,441 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sourceTypes = exports.isMinified = undefined; + +var _isMinified = require("./isMinified"); + +Object.defineProperty(exports, "isMinified", { + enumerable: true, + get: function () { + return _isMinified.isMinified; + } +}); +exports.shouldPrettyPrint = shouldPrettyPrint; +exports.isJavaScript = isJavaScript; +exports.isPretty = isPretty; +exports.isPrettyURL = isPrettyURL; +exports.isThirdParty = isThirdParty; +exports.getPrettySourceURL = getPrettySourceURL; +exports.getRawSourceURL = getRawSourceURL; +exports.getFilenameFromURL = getFilenameFromURL; +exports.getFormattedSourceId = getFormattedSourceId; +exports.getFilename = getFilename; +exports.getFileURL = getFileURL; +exports.getSourcePath = getSourcePath; +exports.getSourceLineCount = getSourceLineCount; +exports.getMode = getMode; +exports.isLoaded = isLoaded; +exports.isLoading = isLoading; +exports.getTextAtPosition = getTextAtPosition; +exports.getSourceClassnames = getSourceClassnames; + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _utils = require("./utils"); + +var _path = require("./path"); + +var _url = require("devtools/client/debugger/new/dist/vendors").vendored["url"]; + +var _sourcesTree = require("./sources-tree/index"); + +const sourceTypes = exports.sourceTypes = { + coffee: "coffeescript", + js: "javascript", + jsx: "react", + ts: "typescript" +}; +/** + * Trims the query part or reference identifier of a url string, if necessary. + * + * @memberof utils/source + * @static + */ + +function trimUrlQuery(url) { + const length = url.length; + const q1 = url.indexOf("?"); + const q2 = url.indexOf("&"); + const q3 = url.indexOf("#"); + const q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length); + return url.slice(0, q); +} + +function shouldPrettyPrint(source) { + if (!source) { + return false; + } + + const _isPretty = isPretty(source); + + const _isJavaScript = isJavaScript(source); + + const isOriginal = (0, _devtoolsSourceMap.isOriginalId)(source.id); + const hasSourceMap = source.get("sourceMapURL"); + + if (_isPretty || isOriginal || hasSourceMap || !_isJavaScript) { + return false; + } + + return true; +} +/** + * Returns true if the specified url and/or content type are specific to + * javascript files. + * + * @return boolean + * True if the source is likely javascript. + * + * @memberof utils/source + * @static + */ + + +function isJavaScript(source) { + const url = source.url; + const contentType = source.contentType; + return url && /\.(jsm|js)?$/.test(trimUrlQuery(url)) || !!(contentType && contentType.includes("javascript")); +} +/** + * @memberof utils/source + * @static + */ + + +function isPretty(source) { + const url = source.url; + return isPrettyURL(url); +} + +function isPrettyURL(url) { + return url ? /formatted$/.test(url) : false; +} + +function isThirdParty(source) { + const url = source.url; + + if (!source || !url) { + return false; + } + + return !!url.match(/(node_modules|bower_components)/); +} +/** + * @memberof utils/source + * @static + */ + + +function getPrettySourceURL(url) { + if (!url) { + url = ""; + } + + return `${url}:formatted`; +} +/** + * @memberof utils/source + * @static + */ + + +function getRawSourceURL(url) { + return url ? url.replace(/:formatted$/, "") : url; +} + +function resolveFileURL(url, transformUrl = initialUrl => initialUrl) { + url = getRawSourceURL(url || ""); + const name = transformUrl(url); + return (0, _utils.endTruncateStr)(name, 50); +} + +function getFilenameFromURL(url) { + return resolveFileURL(url, initialUrl => (0, _path.basename)(initialUrl) || "(index)"); +} + +function getFormattedSourceId(id) { + const sourceId = id.split("/")[1]; + return `SOURCE${sourceId}`; +} +/** + * Show a source url's filename. + * If the source does not have a url, use the source id. + * + * @memberof utils/source + * @static + */ + + +function getFilename(source) { + const { + url, + id + } = source; + + if (!url) { + return getFormattedSourceId(id); + } + + let filename = getFilenameFromURL(url); + const qMarkIdx = filename.indexOf("?"); + + if (qMarkIdx > 0) { + filename = filename.slice(0, qMarkIdx); + } + + return filename; +} +/** + * Show a source url. + * If the source does not have a url, use the source id. + * + * @memberof utils/source + * @static + */ + + +function getFileURL(source) { + const { + url, + id + } = source; + + if (!url) { + return getFormattedSourceId(id); + } + + return resolveFileURL(url); +} + +const contentTypeModeMap = { + "text/javascript": { + name: "javascript" + }, + "text/typescript": { + name: "javascript", + typescript: true + }, + "text/coffeescript": { + name: "coffeescript" + }, + "text/typescript-jsx": { + name: "jsx", + base: { + name: "javascript", + typescript: true + } + }, + "text/jsx": { + name: "jsx" + }, + "text/x-elm": { + name: "elm" + }, + "text/x-clojure": { + name: "clojure" + }, + "text/wasm": { + name: "text" + }, + "text/html": { + name: "htmlmixed" + } +}; + +function getSourcePath(url) { + if (!url) { + return ""; + } + + const { + path, + href + } = (0, _url.parse)(url); // for URLs like "about:home" the path is null so we pass the full href + + return path || href; +} +/** + * Returns amount of lines in the source. If source is a WebAssembly binary, + * the function returns amount of bytes. + */ + + +function getSourceLineCount(source) { + if (source.isWasm && !source.error) { + const { + binary + } = source.text; + return binary.length; + } + + return source.text != undefined ? source.text.split("\n").length : 0; +} +/** + * + * Checks if a source is minified based on some heuristics + * @param key + * @param text + * @return boolean + * @memberof utils/source + * @static + */ + +/** + * + * Returns Code Mirror mode for source content type + * @param contentType + * @return String + * @memberof utils/source + * @static + */ + + +function getMode(source, symbols) { + const { + contentType, + text, + isWasm, + url + } = source; + + if (!text || isWasm) { + return { + name: "text" + }; + } + + if (url && url.match(/\.jsx$/i) || symbols && symbols.hasJsx) { + if (symbols && symbols.hasTypes) { + return { + name: "text/typescript-jsx" + }; + } + + return { + name: "jsx" + }; + } + + if (symbols && symbols.hasTypes) { + if (symbols.hasJsx) { + return { + name: "text/typescript-jsx" + }; + } + + return { + name: "text/typescript" + }; + } + + const languageMimeMap = [{ + ext: ".c", + mode: "text/x-csrc" + }, { + ext: ".kt", + mode: "text/x-kotlin" + }, { + ext: ".cpp", + mode: "text/x-c++src" + }, { + ext: ".m", + mode: "text/x-objectivec" + }, { + ext: ".rs", + mode: "text/x-rustsrc" + }]; // check for C and other non JS languages + + if (url) { + const result = languageMimeMap.find(({ + ext + }) => url.endsWith(ext)); + + if (result !== undefined) { + return { + name: result.mode + }; + } + } // if the url ends with .marko we set the name to Javascript so + // syntax highlighting works for marko too + + + if (url && url.match(/\.marko$/i)) { + return { + name: "javascript" + }; + } // Use HTML mode for files in which the first non whitespace + // character is `<` regardless of extension. + + + const isHTMLLike = text.match(/^\s*. */ +function isUnderRoot(url, projectRoot) { + if (!projectRoot) { + return true; + } + + return `${url.group}${url.path}`.startsWith(projectRoot); +} + +function removeProjectRoot(parts, projectRoot) { + const rootParts = projectRoot.replace("://", "").split("/"); + return parts.splice(0, rootParts.length - 2); +} + +function createNodeInTree(part, path, tree, index) { + const node = (0, _utils.createNode)(part, path, []); // we are modifying the tree + + const contents = tree.contents.slice(0); + contents.splice(index, 0, node); + tree.contents = contents; + return node; +} +/* + * Look for the child directory + * 1. if it exists return it + * 2. if it does not exist create it + * 3. if it is a file, replace it with a directory + */ + + +function findOrCreateNode(parts, subTree, path, part, index, url, debuggeeHost) { + const addedPartIsFile = (0, _utils.partIsFile)(index, parts, url); + const { + found: childFound, + index: childIndex + } = (0, _treeOrder.findNodeInContents)(subTree, (0, _treeOrder.createTreeNodeMatcher)(part, !addedPartIsFile, debuggeeHost)); // we create and enter the new node + + if (!childFound) { + return createNodeInTree(part, path, subTree, childIndex); + } // we found a path with the same name as the part. We need to determine + // if this is the correct child, or if we have a naming conflict + + + const child = subTree.contents[childIndex]; + const childIsFile = !(0, _utils.nodeHasChildren)(child); // if we have a naming conflict, we'll create a new node + + if (childIsFile && !addedPartIsFile || !childIsFile && addedPartIsFile) { + return createNodeInTree(part, path, subTree, childIndex); + } // if there is no naming conflict, we can traverse into the child + + + return child; +} +/* + * walk the source tree to the final node for a given url, + * adding new nodes along the way + */ + + +function traverseTree(url, tree, debuggeeHost, projectRoot) { + url.path = decodeURIComponent(url.path); + const parts = url.path.split("/").filter(p => p !== ""); + parts.unshift(url.group); + + if (projectRoot) { + removeProjectRoot(parts, projectRoot); + } + + let path = ""; + return parts.reduce((subTree, part, index) => { + path = path ? `${path}/${part}` : part; + const debuggeeHostIfRoot = index === 0 ? debuggeeHost : null; + return findOrCreateNode(parts, subTree, path, part, index, url, debuggeeHostIfRoot); + }, tree); +} +/* + * Add a source file to a directory node in the tree + */ + + +function addSourceToNode(node, url, source) { + const isFile = !(0, _utils.isDirectory)(url); // if we have a file, and the subtree has no elements, overwrite the + // subtree contents with the source + + if (isFile) { + return source; + } + + const { + filename + } = url; + const { + found: childFound, + index: childIndex + } = (0, _treeOrder.findNodeInContents)(node, (0, _treeOrder.createTreeNodeMatcher)(filename, false, null)); // if we are readding an existing file in the node, overwrite the existing + // file and return the node's contents + + if (childFound) { + const existingNode = node.contents[childIndex]; + existingNode.contents = source; + return node.contents; + } // if this is a new file, add the new file; + + + const newNode = (0, _utils.createNode)(filename, source.get("url"), source); + const contents = node.contents.slice(0); + contents.splice(childIndex, 0, newNode); + return contents; +} +/** + * @memberof utils/sources-tree + * @static + */ + + +function addToTree(tree, source, debuggeeUrl, projectRoot) { + const url = (0, _getURL.getURL)(source.get("url"), debuggeeUrl); + const debuggeeHost = (0, _treeOrder.getDomain)(debuggeeUrl); + + if ((0, _utils.isInvalidUrl)(url, source) || !isUnderRoot(url, projectRoot)) { + return; + } + + const finalNode = traverseTree(url, tree, debuggeeHost, projectRoot); + finalNode.contents = addSourceToNode(finalNode, url, source); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/collapseTree.js b/devtools/client/debugger/new/src/utils/sources-tree/collapseTree.js new file mode 100644 index 000000000000..2b6224df5035 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/collapseTree.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.collapseTree = collapseTree; + +var _utils = require("./utils"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Take an existing source tree, and return a new one with collapsed nodes. + */ +function collapseTree(node, depth = 0) { + // Node is a folder. + if (Array.isArray(node.contents)) { + // Node is not a root/domain node, and only contains 1 item. + if (depth > 1 && node.contents.length === 1) { + const next = node.contents[0]; // Do not collapse if the next node is a leaf node. + + if ((0, _utils.nodeHasChildren)(next)) { + return collapseTree((0, _utils.createNode)(`${node.name}/${next.name}`, next.path, next.contents), depth + 1); + } + } // Map the contents. + + + return (0, _utils.createNode)(node.name, node.path, node.contents.map(next => collapseTree(next, depth + 1))); + } // Node is a leaf, not a folder, do not modify it. + + + return node; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/createTree.js b/devtools/client/debugger/new/src/utils/sources-tree/createTree.js new file mode 100644 index 000000000000..ce9e01c2fbd2 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/createTree.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createTree = createTree; + +var _addToTree = require("./addToTree"); + +var _collapseTree = require("./collapseTree"); + +var _utils = require("./utils"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function createTree({ + sources, + debuggeeUrl, + projectRoot +}) { + const uncollapsedTree = (0, _utils.createNode)("root", "", []); + + for (const source of sources.valueSeq()) { + (0, _addToTree.addToTree)(uncollapsedTree, source, debuggeeUrl, projectRoot); + } + + const sourceTree = (0, _collapseTree.collapseTree)(uncollapsedTree); + return { + uncollapsedTree, + sourceTree, + parentMap: (0, _utils.createParentMap)(sourceTree), + focusedItem: null + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/formatTree.js b/devtools/client/debugger/new/src/utils/sources-tree/formatTree.js new file mode 100644 index 000000000000..6d2fe8dd9834 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/formatTree.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.formatTree = formatTree; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function formatTree(tree, depth = 0, str = "") { + const whitespace = new Array(depth * 2).join(" "); + + if (Array.isArray(tree.contents)) { + str += `${whitespace} - ${tree.name} path=${tree.path} \n`; + tree.contents.forEach(t => { + str = formatTree(t, depth + 1, str); + }); + } else { + const id = tree.contents.get("id"); + str += `${whitespace} - ${tree.name} path=${tree.path} source_id=${id} \n`; + } + + return str; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/getDirectories.js b/devtools/client/debugger/new/src/utils/sources-tree/getDirectories.js new file mode 100644 index 000000000000..7355158636e0 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/getDirectories.js @@ -0,0 +1,63 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getDirectories = getDirectories; + +var _utils = require("./utils"); + +var _getURL = require("./getURL"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function findSource(sourceTree, sourceUrl) { + let returnTarget = null; + + function _traverse(subtree) { + if ((0, _utils.nodeHasChildren)(subtree)) { + for (const child of subtree.contents) { + _traverse(child); + } + } else if (!returnTarget) { + if (subtree.path.replace(/http(s)?:\//, "") == sourceUrl) { + returnTarget = subtree; + return; + } + } + } + + sourceTree.contents.forEach(_traverse); + + if (!returnTarget) { + return sourceTree; + } + + return returnTarget; +} + +function getDirectories(sourceUrl, sourceTree) { + const url = (0, _getURL.getURL)(sourceUrl); + const fullUrl = `${url.group}${url.path}`; + const parentMap = (0, _utils.createParentMap)(sourceTree); + const source = findSource(sourceTree, fullUrl); + + if (!source) { + return []; + } + + let node = source; + const directories = []; + directories.push(source); + + while (true) { + node = parentMap.get(node); + + if (!node) { + return directories; + } + + directories.push(node); + } +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/getURL.js b/devtools/client/debugger/new/src/utils/sources-tree/getURL.js new file mode 100644 index 000000000000..04d45ab83eef --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/getURL.js @@ -0,0 +1,124 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFilenameFromPath = getFilenameFromPath; +exports.getURL = getURL; + +var _url = require("devtools/client/debugger/new/dist/vendors").vendored["url"]; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getFilenameFromPath(pathname) { + let filename = ""; + + if (pathname) { + filename = pathname.substring(pathname.lastIndexOf("/") + 1); // This file does not have a name. Default should be (index). + + if (filename == "" || !filename.includes(".")) { + filename = "(index)"; + } + } + + return filename; +} + +const NoDomain = "(no domain)"; + +function getURL(sourceUrl, debuggeeUrl = "") { + const url = sourceUrl; + const def = { + path: "", + group: "", + filename: "" + }; + + if (!url) { + return def; + } + + const { + pathname, + protocol, + host, + path + } = (0, _url.parse)(url); + const defaultDomain = (0, _url.parse)(debuggeeUrl).host; + const filename = getFilenameFromPath(pathname); + + switch (protocol) { + case "javascript:": + // Ignore `javascript:` URLs for now + return def; + + case "webpack:": + // A Webpack source is a special case + return (0, _lodash.merge)(def, { + path: path, + group: "webpack://", + filename: filename + }); + + case "ng:": + // An Angular source is a special case + return (0, _lodash.merge)(def, { + path: path, + group: "ng://", + filename: filename + }); + + case "about:": + // An about page is a special case + return (0, _lodash.merge)(def, { + path: "/", + group: url, + filename: filename + }); + + case "data:": + return (0, _lodash.merge)(def, { + path: "/", + group: NoDomain, + filename: url + }); + + case null: + if (pathname && pathname.startsWith("/")) { + // If it's just a URL like "/foo/bar.js", resolve it to the file + // protocol + return (0, _lodash.merge)(def, { + path: path, + group: "file://", + filename: filename + }); + } else if (host === null) { + // We don't know what group to put this under, and it's a script + // with a weird URL. Just group them all under an anonymous group. + return (0, _lodash.merge)(def, { + path: url, + group: defaultDomain, + filename: filename + }); + } + + break; + + case "http:": + case "https:": + return (0, _lodash.merge)(def, { + path: pathname, + group: host, + filename: filename + }); + } + + return (0, _lodash.merge)(def, { + path: path, + group: protocol ? `${protocol}//` : "", + filename: filename + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/index.js b/devtools/client/debugger/new/src/utils/sources-tree/index.js new file mode 100644 index 000000000000..5ef6d45d1553 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/index.js @@ -0,0 +1,140 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _addToTree = require("./addToTree"); + +Object.defineProperty(exports, "addToTree", { + enumerable: true, + get: function () { + return _addToTree.addToTree; + } +}); + +var _collapseTree = require("./collapseTree"); + +Object.defineProperty(exports, "collapseTree", { + enumerable: true, + get: function () { + return _collapseTree.collapseTree; + } +}); + +var _createTree = require("./createTree"); + +Object.defineProperty(exports, "createTree", { + enumerable: true, + get: function () { + return _createTree.createTree; + } +}); + +var _formatTree = require("./formatTree"); + +Object.defineProperty(exports, "formatTree", { + enumerable: true, + get: function () { + return _formatTree.formatTree; + } +}); + +var _getDirectories = require("./getDirectories"); + +Object.defineProperty(exports, "getDirectories", { + enumerable: true, + get: function () { + return _getDirectories.getDirectories; + } +}); + +var _getURL = require("./getURL"); + +Object.defineProperty(exports, "getFilenameFromPath", { + enumerable: true, + get: function () { + return _getURL.getFilenameFromPath; + } +}); +Object.defineProperty(exports, "getURL", { + enumerable: true, + get: function () { + return _getURL.getURL; + } +}); + +var _sortTree = require("./sortTree"); + +Object.defineProperty(exports, "sortEntireTree", { + enumerable: true, + get: function () { + return _sortTree.sortEntireTree; + } +}); +Object.defineProperty(exports, "sortTree", { + enumerable: true, + get: function () { + return _sortTree.sortTree; + } +}); + +var _updateTree = require("./updateTree"); + +Object.defineProperty(exports, "updateTree", { + enumerable: true, + get: function () { + return _updateTree.updateTree; + } +}); + +var _utils = require("./utils"); + +Object.defineProperty(exports, "createNode", { + enumerable: true, + get: function () { + return _utils.createNode; + } +}); +Object.defineProperty(exports, "createParentMap", { + enumerable: true, + get: function () { + return _utils.createParentMap; + } +}); +Object.defineProperty(exports, "getRelativePath", { + enumerable: true, + get: function () { + return _utils.getRelativePath; + } +}); +Object.defineProperty(exports, "isDirectory", { + enumerable: true, + get: function () { + return _utils.isDirectory; + } +}); +Object.defineProperty(exports, "isExactUrlMatch", { + enumerable: true, + get: function () { + return _utils.isExactUrlMatch; + } +}); +Object.defineProperty(exports, "isNotJavaScript", { + enumerable: true, + get: function () { + return _utils.isNotJavaScript; + } +}); +Object.defineProperty(exports, "nodeHasChildren", { + enumerable: true, + get: function () { + return _utils.nodeHasChildren; + } +}); +Object.defineProperty(exports, "getExtension", { + enumerable: true, + get: function () { + return _utils.getExtension; + } +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/moz.build b/devtools/client/debugger/new/src/utils/sources-tree/moz.build new file mode 100644 index 000000000000..04391810879d --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/moz.build @@ -0,0 +1,22 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'addToTree.js', + 'collapseTree.js', + 'createTree.js', + 'formatTree.js', + 'getDirectories.js', + 'getURL.js', + 'index.js', + 'sortTree.js', + 'treeOrder.js', + 'updateTree.js', + 'utils.js', +) diff --git a/devtools/client/debugger/new/src/utils/sources-tree/sortTree.js b/devtools/client/debugger/new/src/utils/sources-tree/sortTree.js new file mode 100644 index 000000000000..97909a2b5110 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/sortTree.js @@ -0,0 +1,60 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sortEntireTree = sortEntireTree; +exports.sortTree = sortTree; + +var _utils = require("./utils"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Look at the nodes in the source tree, and determine the index of where to + * insert a new node. The ordering is index -> folder -> file. + * @memberof utils/sources-tree + * @static + */ +function sortEntireTree(tree, debuggeeUrl = "") { + if ((0, _utils.nodeHasChildren)(tree)) { + const contents = sortTree(tree, debuggeeUrl).map(subtree => sortEntireTree(subtree)); + return _objectSpread({}, tree, { + contents + }); + } + + return tree; +} +/** + * Look at the nodes in the source tree, and determine the index of where to + * insert a new node. The ordering is index -> folder -> file. + * @memberof utils/sources-tree + * @static + */ + + +function sortTree(tree, debuggeeUrl = "") { + return tree.contents.sort((previousNode, currentNode) => { + const currentNodeIsDir = (0, _utils.nodeHasChildren)(currentNode); + const previousNodeIsDir = (0, _utils.nodeHasChildren)(previousNode); + + if (currentNode.name === "(index)") { + return 1; + } else if (previousNode.name === "(index)") { + return -1; + } else if ((0, _utils.isExactUrlMatch)(currentNode.name, debuggeeUrl)) { + return 1; + } else if ((0, _utils.isExactUrlMatch)(previousNode.name, debuggeeUrl)) { + return -1; // If neither is the case, continue to compare alphabetically + } else if (previousNodeIsDir && !currentNodeIsDir) { + return -1; + } else if (!previousNodeIsDir && currentNodeIsDir) { + return 1; + } + + return previousNode.name.localeCompare(currentNode.name); + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/treeOrder.js b/devtools/client/debugger/new/src/utils/sources-tree/treeOrder.js new file mode 100644 index 000000000000..8a9b912f9f76 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/treeOrder.js @@ -0,0 +1,160 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getDomain = getDomain; +exports.findNodeInContents = findNodeInContents; +exports.createTreeNodeMatcher = createTreeNodeMatcher; + +var _url = require("devtools/client/debugger/new/dist/vendors").vendored["url"]; + +var _utils = require("./utils"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* + * Gets domain from url (without www prefix) + */ +function getDomain(url) { + // TODO: define how files should be ordered on the browser debugger + if (!url) { + return null; + } + + const { + host + } = (0, _url.parse)(url); + + if (!host) { + return null; + } + + return host.startsWith("www.") ? host.substr("www.".length) : host; +} +/* + * Checks if node name matches debugger host/domain. + */ + + +function isExactDomainMatch(part, debuggeeHost) { + return part.startsWith("www.") ? part.substr("www.".length) === debuggeeHost : part === debuggeeHost; +} +/* + * Function to assist with node search for a defined sorted order, see e.g. + * `createTreeNodeMatcher`. Returns negative number if the node + * stands earlier in sorting order, positive number if the node stands later + * in sorting order, or zero if the node is found. + */ + + +/* + * Performs a binary search to insert a node into contents. Returns positive + * number, index of the found child, or negative number, which can be used + * to calculate a position where a new node can be inserted (`-index - 1`). + * The matcher is a function that returns result of comparision of a node with + * lookup value. + */ +function findNodeInContents(tree, matcher) { + const { + contents + } = tree; + + if (contents.length === 0) { + return { + found: false, + index: 0 + }; + } + + let left = 0; + let right = contents.length - 1; + + while (left < right) { + const middle = Math.floor((left + right) / 2); + + if (matcher(contents[middle]) < 0) { + left = middle + 1; + } else { + right = middle; + } + } + + const result = matcher(contents[left]); + + if (result === 0) { + return { + found: true, + index: left + }; + } + + return { + found: false, + index: result > 0 ? left : left + 1 + }; +} + +const IndexName = "(index)"; + +function createTreeNodeMatcherWithIndex() { + return node => node.name === IndexName ? 0 : 1; +} + +function createTreeNodeMatcherWithDebuggeeHost(debuggeeHost) { + return node => { + if (node.name === IndexName) { + return -1; + } + + return isExactDomainMatch(node.name, debuggeeHost) ? 0 : 1; + }; +} + +function createTreeNodeMatcherWithNameAndOther(part, isDir, debuggeeHost) { + return node => { + if (node.name === IndexName) { + return -1; + } + + if (debuggeeHost && isExactDomainMatch(node.name, debuggeeHost)) { + return -1; + } + + const nodeIsDir = (0, _utils.nodeHasChildren)(node); + + if (nodeIsDir && !isDir) { + return -1; + } else if (!nodeIsDir && isDir) { + return 1; + } + + return node.name.localeCompare(part); + }; +} +/* + * Creates a matcher for findNodeInContents. + * The sorting order of nodes during comparison is: + * - "(index)" node + * - root node with the debuggee host/domain + * - hosts/directories (not files) sorted by name + * - files sorted by name + */ + + +function createTreeNodeMatcher(part, isDir, debuggeeHost) { + if (part === IndexName) { + // Specialied matcher, when we are looking for "(index)" position. + return createTreeNodeMatcherWithIndex(); + } + + if (debuggeeHost && isExactDomainMatch(part, debuggeeHost)) { + // Specialied matcher, when we are looking for domain position. + return createTreeNodeMatcherWithDebuggeeHost(debuggeeHost); + } // Rest of the cases, without mentioned above. + + + return createTreeNodeMatcherWithNameAndOther(part, isDir, debuggeeHost); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/updateTree.js b/devtools/client/debugger/new/src/utils/sources-tree/updateTree.js new file mode 100644 index 000000000000..254b84e17880 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/updateTree.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.updateTree = updateTree; + +var _addToTree = require("./addToTree"); + +var _collapseTree = require("./collapseTree"); + +var _utils = require("./utils"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function newSourcesSet(newSources, prevSources) { + const next = newSources.toSet(); + const prev = prevSources.toSet(); + return next.subtract(prev); +} + +function updateTree({ + newSources, + prevSources, + debuggeeUrl, + projectRoot, + uncollapsedTree, + sourceTree +}) { + const newSet = newSourcesSet(newSources, prevSources); + + for (const source of newSet) { + (0, _addToTree.addToTree)(uncollapsedTree, source, debuggeeUrl, projectRoot); + } + + const newSourceTree = (0, _collapseTree.collapseTree)(uncollapsedTree); + return { + uncollapsedTree, + sourceTree: newSourceTree, + parentMap: (0, _utils.createParentMap)(sourceTree), + focusedItem: null + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/utils.js b/devtools/client/debugger/new/src/utils/sources-tree/utils.js new file mode 100644 index 000000000000..aee48530cf75 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/sources-tree/utils.js @@ -0,0 +1,113 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.nodeHasChildren = nodeHasChildren; +exports.isExactUrlMatch = isExactUrlMatch; +exports.isDirectory = isDirectory; +exports.getExtension = getExtension; +exports.isNotJavaScript = isNotJavaScript; +exports.isInvalidUrl = isInvalidUrl; +exports.partIsFile = partIsFile; +exports.createNode = createNode; +exports.createParentMap = createParentMap; +exports.getRelativePath = getRelativePath; + +var _url = require("devtools/client/debugger/new/dist/vendors").vendored["url"]; + +var _source = require("../source"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const IGNORED_URLS = ["debugger eval code", "XStringBundle"]; + +function nodeHasChildren(item) { + return Array.isArray(item.contents); +} + +function isExactUrlMatch(pathPart, debuggeeUrl) { + // compare to hostname with an optional 'www.' prefix + const { + host + } = (0, _url.parse)(debuggeeUrl); + + if (!host) { + return false; + } + + return host.replace(/^www\./, "") === pathPart.replace(/^www\./, ""); +} + +function isDirectory(url) { + const parts = url.path.split("/").filter(p => p !== ""); // Assume that all urls point to files except when they end with '/' + // Or directory node has children + + return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)"; +} + +function getExtension(source) { + const url = source.get ? source.get("url") : source.url; + const parsedUrl = (0, _url.parse)(url).pathname; + + if (!parsedUrl) { + return ""; + } + + return parsedUrl.split(".").pop(); +} + +function isNotJavaScript(source) { + return ["css", "svg", "png"].includes(getExtension(source)); +} + +function isInvalidUrl(url, source) { + return IGNORED_URLS.indexOf(url) != -1 || !source.get("url") || !url.group || (0, _source.isPretty)(source) || isNotJavaScript(source); +} + +function partIsFile(index, parts, url) { + const isLastPart = index === parts.length - 1; + return !isDirectory(url) && isLastPart; +} + +function createNode(name, path, contents) { + return { + name, + path, + contents + }; +} + +function createParentMap(tree) { + const map = new WeakMap(); + + function _traverse(subtree) { + if (nodeHasChildren(subtree)) { + for (const child of subtree.contents) { + map.set(child, subtree); + + _traverse(child); + } + } + } // Don't link each top-level path to the "root" node because the + // user never sees the root + + + tree.contents.forEach(_traverse); + return map; +} + +function getRelativePath(url) { + const { + pathname + } = (0, _url.parse)(url); + + if (!pathname) { + return url; + } + + const path = pathname.split("/"); + path.shift(); + return path.join("/"); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/tabs.js b/devtools/client/debugger/new/src/utils/tabs.js new file mode 100644 index 000000000000..897d96211959 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/tabs.js @@ -0,0 +1,125 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getHiddenTabs = getHiddenTabs; +exports.getSourceAnnotation = getSourceAnnotation; +exports.getTabMenuItems = getTabMenuItems; + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _source = require("./source"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* + * Finds the hidden tabs by comparing the tabs' top offset. + * hidden tabs will have a great top offset. + * + * @param sourceTabs Immutable.list + * @param sourceTabEls HTMLCollection + * + * @returns Immutable.list + */ +function getHiddenTabs(sourceTabs, sourceTabEls) { + sourceTabEls = [].slice.call(sourceTabEls); + + function getTopOffset() { + const topOffsets = sourceTabEls.map(t => t.getBoundingClientRect().top); + return Math.min(...topOffsets); + } + + function hasTopOffset(el) { + // adding 10px helps account for cases where the tab might be offset by + // styling such as selected tabs which don't have a border. + const tabTopOffset = getTopOffset(); + return el.getBoundingClientRect().top > tabTopOffset + 10; + } + + return sourceTabs.filter((tab, index) => { + const element = sourceTabEls[index]; + return element && hasTopOffset(element); + }); +} + +function getSourceAnnotation(source, sourceMetaData) { + const framework = sourceMetaData && sourceMetaData.framework ? sourceMetaData.framework : false; + + if (framework) { + return _react2.default.createElement("img", { + className: framework.toLowerCase() + }); + } + + if ((0, _source.isPretty)(source)) { + return _react2.default.createElement("img", { + className: "prettyPrint" + }); + } + + if (source.isBlackBoxed) { + return _react2.default.createElement("img", { + className: "blackBox" + }); + } +} + +function getTabMenuItems() { + return { + closeTab: { + id: "node-menu-close-tab", + label: L10N.getStr("sourceTabs.closeTab"), + accesskey: L10N.getStr("sourceTabs.closeTab.accesskey"), + disabled: false + }, + closeOtherTabs: { + id: "node-menu-close-other-tabs", + label: L10N.getStr("sourceTabs.closeOtherTabs"), + accesskey: L10N.getStr("sourceTabs.closeOtherTabs.accesskey"), + disabled: false + }, + closeTabsToEnd: { + id: "node-menu-close-tabs-to-end", + label: L10N.getStr("sourceTabs.closeTabsToEnd"), + accesskey: L10N.getStr("sourceTabs.closeTabsToEnd.accesskey"), + disabled: false + }, + closeAllTabs: { + id: "node-menu-close-all-tabs", + label: L10N.getStr("sourceTabs.closeAllTabs"), + accesskey: L10N.getStr("sourceTabs.closeAllTabs.accesskey"), + disabled: false + }, + showSource: { + id: "node-menu-show-source", + label: L10N.getStr("sourceTabs.revealInTree"), + accesskey: L10N.getStr("sourceTabs.revealInTree.accesskey"), + disabled: false + }, + copyToClipboard: { + id: "node-menu-copy-to-clipboard", + label: L10N.getStr("copyToClipboard.label"), + accesskey: L10N.getStr("copyToClipboard.accesskey"), + disabled: false + }, + copySourceUri2: { + id: "node-menu-copy-source-url", + label: L10N.getStr("copySourceUri2"), + accesskey: L10N.getStr("copySourceUri2.accesskey"), + disabled: false + }, + prettyPrint: { + id: "node-menu-pretty-print", + label: L10N.getStr("sourceTabs.prettyPrint"), + accesskey: L10N.getStr("sourceTabs.prettyPrint.accesskey"), + disabled: false + } + }; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/task.js b/devtools/client/debugger/new/src/utils/task.js new file mode 100644 index 000000000000..c12aef564955 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/task.js @@ -0,0 +1,53 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * This object provides the public module functions. + */ +const Task = { + // XXX: Not sure if this works in all cases... + async: function (task) { + return function () { + return Task.spawn(task, this, arguments); + }; + }, + + /** + * Creates and starts a new task. + * @param task A generator function + * @return A promise, resolved when the task terminates + */ + spawn: function (task, scope, args) { + return new Promise(function (resolve, reject) { + const iterator = task.apply(scope, args); + + const callNext = lastValue => { + const iteration = iterator.next(lastValue); + Promise.resolve(iteration.value).then(value => { + if (iteration.done) { + resolve(value); + } else { + callNext(value); + } + }).catch(error => { + reject(error); + iterator.throw(error); + }); + }; + + callNext(undefined); + }); + } +}; +exports.Task = Task; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/test-head.js b/devtools/client/debugger/new/src/utils/test-head.js new file mode 100644 index 000000000000..ae492308299b --- /dev/null +++ b/devtools/client/debugger/new/src/utils/test-head.js @@ -0,0 +1,167 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getHistory = exports.waitForState = exports.makeSymbolDeclaration = exports.makeSourceRecord = exports.makeOriginalSource = exports.makeSource = exports.makeFrame = exports.commonLog = exports.createStore = exports.reducers = exports.selectors = exports.actions = undefined; + +var _redux = require("devtools/client/shared/vendor/redux"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _devtoolsSourceMap2 = _interopRequireDefault(_devtoolsSourceMap); + +var _reducers = require("../reducers/index"); + +var _reducers2 = _interopRequireDefault(_reducers); + +var _actions = require("../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _selectors = require("../selectors/index"); + +var selectors = _interopRequireWildcard(_selectors); + +var _history = require("../test/utils/history"); + +var _createStore = require("../actions/utils/create-store"); + +var _createStore2 = _interopRequireDefault(_createStore); + +var _immutable = require("devtools/client/shared/vendor/immutable"); + +var I = _interopRequireWildcard(_immutable); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @memberof utils/test-head + * @static + */ +function createStore(client, initialState = {}, sourceMapsMock) { + return (0, _createStore2.default)({ + log: false, + history: (0, _history.getHistory)(), + makeThunkArgs: args => { + return _objectSpread({}, args, { + client, + sourceMaps: sourceMapsMock !== undefined ? sourceMapsMock : _devtoolsSourceMap2.default + }); + } + })((0, _redux.combineReducers)(_reducers2.default), initialState); +} +/** + * @memberof utils/test-head + * @static + */ + + +function commonLog(msg, data = {}) { + console.log(`[INFO] ${msg} ${JSON.stringify(data)}`); +} + +function makeFrame({ + id, + sourceId +}, opts = {}) { + return _objectSpread({ + id, + scope: [], + location: { + sourceId, + line: 4 + } + }, opts); +} +/** + * @memberof utils/test-head + * @static + */ + + +function makeSource(name, props = {}) { + return _objectSpread({ + id: name, + loadedState: "unloaded", + url: `http://localhost:8000/examples/${name}` + }, props); +} + +function makeOriginalSource(name, props) { + const source = makeSource(name, props); + return _objectSpread({}, source, { + id: `${name}-original` + }); +} + +function makeSourceRecord(name, props = {}) { + return I.Map(makeSource(name, props)); +} + +function makeFuncLocation(startLine, endLine) { + if (!endLine) { + endLine = startLine + 1; + } + + return { + start: { + line: startLine + }, + end: { + line: endLine + } + }; +} + +function makeSymbolDeclaration(name, start, end, klass) { + return { + id: `${name}:${start}`, + name, + location: makeFuncLocation(start, end), + klass + }; +} +/** + * @memberof utils/test-head + * @static + */ + + +function waitForState(store, predicate) { + return new Promise(resolve => { + let ret = predicate(store.getState()); + + if (ret) { + resolve(ret); + } + + const unsubscribe = store.subscribe(() => { + ret = predicate(store.getState()); + + if (ret) { + unsubscribe(); + resolve(ret); + } + }); + }); +} + +exports.actions = _actions2.default; +exports.selectors = selectors; +exports.reducers = _reducers2.default; +exports.createStore = createStore; +exports.commonLog = commonLog; +exports.makeFrame = makeFrame; +exports.makeSource = makeSource; +exports.makeOriginalSource = makeOriginalSource; +exports.makeSourceRecord = makeSourceRecord; +exports.makeSymbolDeclaration = makeSymbolDeclaration; +exports.waitForState = waitForState; +exports.getHistory = _history.getHistory; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/text.js b/devtools/client/debugger/new/src/utils/text.js new file mode 100644 index 000000000000..aa5f7afe824c --- /dev/null +++ b/devtools/client/debugger/new/src/utils/text.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.formatKeyShortcut = undefined; + +var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Utils for keyboard command strings + * @module utils/text + */ +const { + appinfo +} = _devtoolsModules.Services; +const isMacOS = appinfo.OS === "Darwin"; +/** + * Formats key for use in tooltips + * For macOS we use the following unicode + * + * cmd ⌘ = \u2318 + * shift ⇧ – \u21E7 + * option (alt) ⌥ \u2325 + * + * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl + * + * @memberof utils/text + * @static + */ + +function formatKeyShortcut(shortcut) { + if (isMacOS) { + return shortcut.replace(/Shift\+/g, "\u21E7 ").replace(/Command\+|Cmd\+/g, "\u2318 ").replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318 ").replace(/Alt\+/g, "\u2325 "); + } + + return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")} `).replace(/Shift\+/g, "Shift "); +} + +exports.formatKeyShortcut = formatKeyShortcut; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/timings.js b/devtools/client/debugger/new/src/utils/timings.js new file mode 100644 index 000000000000..5b83e9e1aaf3 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/timings.js @@ -0,0 +1,48 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getAsyncTimes = getAsyncTimes; +exports.steppingTimings = steppingTimings; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getAsyncTimes(name) { + return (0, _lodash.zip)(window.performance.getEntriesByName(`${name}_start`), window.performance.getEntriesByName(`${name}_end`)).map(([start, end]) => +(end.startTime - start.startTime).toPrecision(2)); +} + +function getTimes(name) { + return window.performance.getEntriesByName(name).map(time => +time.duration.toPrecision(2)); +} + +function getStats(times) { + if (times.length == 0) { + return { + times: [], + avg: null, + median: null + }; + } + + const avg = times.reduce((sum, time) => time + sum, 0) / times.length; + const sortedtimings = [...times].sort((a, b) => a - b); + const median = sortedtimings[times.length / 2]; + return { + times, + avg: +avg.toPrecision(2), + median: +median.toPrecision(2) + }; +} + +function steppingTimings() { + const commandTimings = getAsyncTimes("COMMAND"); + const pausedTimings = getTimes("PAUSED"); + return { + commands: getStats(commandTimings), + paused: getStats(pausedTimings) + }; +} // console.log("..", asyncTimes("COMMAND")); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/ui.js b/devtools/client/debugger/new/src/utils/ui.js new file mode 100644 index 000000000000..29783acdfa37 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/ui.js @@ -0,0 +1,61 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isVisible = isVisible; +exports.getLineNumberWidth = getLineNumberWidth; +exports.resizeBreakpointGutter = resizeBreakpointGutter; +exports.resizeToggleButton = resizeToggleButton; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/* Checks to see if the root element is available and + * if the element is visible. We check the width of the element + * because it is more reliable than either checking a focus state or + * the visibleState or hidden property. + */ +function isVisible() { + const el = document.querySelector("#mount"); + return el && el.getBoundingClientRect().width; +} +/* Gets the line numbers width in the code editor + */ + + +function getLineNumberWidth(editor) { + const gutters = editor.display.gutters; + const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers"); + return lineNumbers && lineNumbers.clientWidth; +} +/** + * Forces the breakpoint gutter to be the same size as the line + * numbers gutter. Editor CSS will absolutely position the gutter + * beneath the line numbers. This makes it easy to be flexible with + * how we overlay breakpoints. + */ + + +function resizeBreakpointGutter(editor) { + const gutters = editor.display.gutters; + const breakpoints = gutters.querySelector(".breakpoints"); + + if (breakpoints) { + breakpoints.style.width = `${getLineNumberWidth(editor)}px`; + } +} +/** + * Forces the left toggle button in source header to be the same size + * as the line numbers gutter. + */ + + +function resizeToggleButton(editor) { + const toggleButton = document.querySelector(".source-header .toggle-button-start"); + + if (toggleButton) { + toggleButton.style.width = `${getLineNumberWidth(editor)}px`; + } +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/utils.js b/devtools/client/debugger/new/src/utils/utils.js new file mode 100644 index 000000000000..1bb761c4da02 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/utils.js @@ -0,0 +1,62 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Utils for utils, by utils + * @module utils/utils + */ + +/** + * @memberof utils/utils + * @static + */ +function handleError(err) { + console.log("ERROR: ", err); +} +/** + * @memberof utils/utils + * @static + */ + + +function promisify(context, method, ...args) { + return new Promise((resolve, reject) => { + args.push(response => { + if (response.error) { + reject(response); + } else { + resolve(response); + } + }); + method.apply(context, args); + }); +} +/** + * @memberof utils/utils + * @static + */ + + +function endTruncateStr(str, size) { + if (str.length > size) { + return `...${str.slice(str.length - size)}`; + } + + return str; +} + +function waitForMs(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +exports.handleError = handleError; +exports.promisify = promisify; +exports.endTruncateStr = endTruncateStr; +exports.waitForMs = waitForMs; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/wasm.js b/devtools/client/debugger/new/src/utils/wasm.js new file mode 100644 index 000000000000..274ed5939ecd --- /dev/null +++ b/devtools/client/debugger/new/src/utils/wasm.js @@ -0,0 +1,190 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.renderWasmText = exports.clearWasmStates = exports.wasmOffsetToLine = exports.lineToWasmOffset = exports.isWasm = exports.getWasmLineNumberFormatter = exports.getWasmText = undefined; + +var _WasmParser = require("devtools/client/shared/vendor/WasmParser"); + +var _WasmDis = require("devtools/client/shared/vendor/WasmDis"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +var wasmStates = Object.create(null); + +function maybeWasmSectionNameResolver(data) { + try { + const parser = new _WasmParser.BinaryReader(); + parser.setData(data.buffer, 0, data.length); + const reader = new _WasmDis.NameSectionReader(); + reader.read(parser); + return reader.hasValidNames() ? reader.getNameResolver() : null; + } catch (ex) { + // Ignoring any errors during names section retrival. + return null; + } +} +/** + * @memberof utils/wasm + * @static + */ + + +function getWasmText(sourceId, data) { + const nameResolver = maybeWasmSectionNameResolver(data); + const parser = new _WasmParser.BinaryReader(); + parser.setData(data.buffer, 0, data.length); + const dis = new _WasmDis.WasmDisassembler(); + + if (nameResolver) { + dis.nameResolver = nameResolver; + } + + dis.addOffsets = true; + const done = dis.disassembleChunk(parser); + let result = dis.getResult(); + + if (result.lines.length === 0) { + result = { + lines: ["No luck with wast conversion"], + offsets: [0], + done + }; + } + + const offsets = result.offsets; + const lines = []; + + for (let i = 0; i < offsets.length; i++) { + lines[offsets[i]] = i; + } + + wasmStates[sourceId] = { + offsets, + lines + }; + return { + lines: result.lines, + done: result.done + }; +} +/** + * @memberof utils/wasm + * @static + */ + + +function getWasmLineNumberFormatter(sourceId) { + const codeOf0 = 48, + codeOfA = 65; + const buffer = [codeOf0, codeOf0, codeOf0, codeOf0, codeOf0, codeOf0, codeOf0, codeOf0]; + let last0 = 7; + return function (number) { + const offset = lineToWasmOffset(sourceId, number - 1); + + if (offset == undefined) { + return ""; + } + + let i = 7; + + for (let n = offset; n !== 0 && i >= 0; n >>= 4, i--) { + const nibble = n & 15; + buffer[i] = nibble < 10 ? codeOf0 + nibble : codeOfA - 10 + nibble; + } + + for (let j = i; j > last0; j--) { + buffer[j] = codeOf0; + } + + last0 = i; + return String.fromCharCode.apply(null, buffer); + }; +} +/** + * @memberof utils/wasm + * @static + */ + + +function isWasm(sourceId) { + return sourceId in wasmStates; +} +/** + * @memberof utils/wasm + * @static + */ + + +function lineToWasmOffset(sourceId, number) { + const wasmState = wasmStates[sourceId]; + + if (!wasmState) { + return undefined; + } + + let offset = wasmState.offsets[number]; + + while (offset === undefined && number > 0) { + offset = wasmState.offsets[--number]; + } + + return offset; +} +/** + * @memberof utils/wasm + * @static + */ + + +function wasmOffsetToLine(sourceId, offset) { + const wasmState = wasmStates[sourceId]; + + if (!wasmState) { + return undefined; + } + + return wasmState.lines[offset]; +} +/** + * @memberof utils/wasm + * @static + */ + + +function clearWasmStates() { + wasmStates = Object.create(null); +} + +function renderWasmText(sourceId, { + binary +}) { + // binary does not survive as Uint8Array, converting from string + const data = new Uint8Array(binary.length); + + for (let i = 0; i < data.length; i++) { + data[i] = binary.charCodeAt(i); + } + + const { + lines + } = getWasmText(sourceId, data); + const MAX_LINES = 1000000; + + if (lines.length > MAX_LINES) { + lines.splice(MAX_LINES, lines.length - MAX_LINES); + lines.push(";; .... text is truncated due to the size"); + } + + return lines; +} + +exports.getWasmText = getWasmText; +exports.getWasmLineNumberFormatter = getWasmLineNumberFormatter; +exports.isWasm = isWasm; +exports.lineToWasmOffset = lineToWasmOffset; +exports.wasmOffsetToLine = wasmOffsetToLine; +exports.clearWasmStates = clearWasmStates; +exports.renderWasmText = renderWasmText; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/worker.js b/devtools/client/debugger/new/src/utils/worker.js new file mode 100644 index 000000000000..a1e7e1f85445 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/worker.js @@ -0,0 +1,74 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let msgId = 1; +/** + * @memberof utils/utils + * @static + */ + +function workerTask(worker, method) { + return function (...args) { + return new Promise((resolve, reject) => { + const id = msgId++; + worker.postMessage({ + id, + method, + args + }); + + const listener = ({ + data: result + }) => { + if (result.id !== id) { + return; + } + + worker.removeEventListener("message", listener); + + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + worker.addEventListener("message", listener); + }); + }; +} + +function workerHandler(publicInterface) { + return function onTask(msg) { + const { + id, + method, + args + } = msg.data; + const response = publicInterface[method].apply(null, args); + + if (response instanceof Promise) { + response.then(val => self.postMessage({ + id, + response: val + })).catch(error => self.postMessage({ + id, + error + })); + } else { + self.postMessage({ + id, + response + }); + } + }; +} + +exports.workerTask = workerTask; +exports.workerHandler = workerHandler; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/moz.build b/devtools/client/debugger/new/src/workers/moz.build new file mode 100644 index 000000000000..5740bc7ea248 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/moz.build @@ -0,0 +1,14 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'parser', + 'pretty-print', + 'search', +] + +DevToolsModules( + +) diff --git a/devtools/client/debugger/new/src/workers/parser/findOutOfScopeLocations.js b/devtools/client/debugger/new/src/workers/parser/findOutOfScopeLocations.js new file mode 100644 index 000000000000..f5e89bbcb327 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/findOutOfScopeLocations.js @@ -0,0 +1,149 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _get = require("devtools/client/shared/vendor/lodash").get; + +var _get2 = _interopRequireDefault(_get); + +var _findIndex = require("devtools/client/shared/vendor/lodash").findIndex; + +var _findIndex2 = _interopRequireDefault(_findIndex); + +var _findLastIndex = require("devtools/client/shared/vendor/lodash").findLastIndex; + +var _findLastIndex2 = _interopRequireDefault(_findLastIndex); + +var _contains = require("./utils/contains"); + +var _getSymbols = require("./getSymbols"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function findSymbols(source) { + const { + functions, + comments + } = (0, _getSymbols.getSymbols)(source); + return { + functions, + comments + }; +} +/** + * Returns the location for a given function path. If the path represents a + * function declaration, the location will begin after the function identifier + * but before the function parameters. + */ + + +function getLocation(func) { + const location = _objectSpread({}, func.location); // if the function has an identifier, start the block after it so the + // identifier is included in the "scope" of its parent + + + const identifierEnd = (0, _get2.default)(func, "identifier.loc.end"); + + if (identifierEnd) { + location.start = identifierEnd; + } + + return location; +} +/** + * Find the nearest location containing the input position and + * return new locations without inner locations under that nearest location + * + * @param locations Notice! The locations MUST be sorted by `sortByStart` + * so that we can do linear time complexity operation. + */ + + +function removeInnerLocations(locations, position) { + // First, let's find the nearest position-enclosing function location, + // which is to find the last location enclosing the position. + const newLocs = locations.slice(); + const parentIndex = (0, _findLastIndex2.default)(newLocs, loc => (0, _contains.containsPosition)(loc, position)); + + if (parentIndex < 0) { + return newLocs; + } // Second, from the nearest location, loop locations again, stop looping + // once seeing the 1st location not enclosed by the nearest location + // to find the last inner locations inside the nearest location. + + + const innerStartIndex = parentIndex + 1; + const parentLoc = newLocs[parentIndex]; + const outerBoundaryIndex = (0, _findIndex2.default)(newLocs, loc => !(0, _contains.containsLocation)(parentLoc, loc), innerStartIndex); + const innerBoundaryIndex = outerBoundaryIndex < 0 ? newLocs.length - 1 : outerBoundaryIndex - 1; // Third, remove those inner functions + + newLocs.splice(innerStartIndex, innerBoundaryIndex - parentIndex); + return newLocs; +} +/** + * Return an new locations array which excludes + * items that are completely enclosed by another location in the input locations + * + * @param locations Notice! The locations MUST be sorted by `sortByStart` + * so that we can do linear time complexity operation. + */ + + +function removeOverlaps(locations) { + if (locations.length == 0) { + return []; + } + + const firstParent = locations[0]; + return locations.reduce(deduplicateNode, [firstParent]); +} + +function deduplicateNode(nodes, location) { + const parent = nodes[nodes.length - 1]; + + if (!(0, _contains.containsLocation)(parent, location)) { + nodes.push(location); + } + + return nodes; +} +/** + * Sorts an array of locations by start position + */ + + +function sortByStart(a, b) { + if (a.start.line < b.start.line) { + return -1; + } else if (a.start.line === b.start.line) { + return a.start.column - b.start.column; + } + + return 1; +} +/** + * Returns an array of locations that are considered out of scope for the given + * location. + */ + + +function findOutOfScopeLocations(sourceId, position) { + const { + functions, + comments + } = findSymbols(sourceId); + const commentLocations = comments.map(c => c.location); + let locations = functions.map(getLocation).concat(commentLocations).sort(sortByStart); // Must remove inner locations then filter, otherwise, + // we will mis-judge in-scope inner locations as out of scope. + + locations = removeInnerLocations(locations, position).filter(loc => !(0, _contains.containsPosition)(loc, position)); + return removeOverlaps(locations); +} + +exports.default = findOutOfScopeLocations; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/frameworks.js b/devtools/client/debugger/new/src/workers/parser/frameworks.js new file mode 100644 index 000000000000..88e167c340ac --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/frameworks.js @@ -0,0 +1,88 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFramework = getFramework; + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _getSymbols = require("./getSymbols"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getFramework(sourceId) { + const sourceSymbols = (0, _getSymbols.getSymbols)(sourceId); + + if (isReactComponent(sourceSymbols)) { + return "React"; + } + + if (isAngularComponent(sourceSymbols)) { + return "Angular"; + } + + if (isVueComponent(sourceSymbols)) { + return "Vue"; + } +} // React + + +function isReactComponent(sourceSymbols) { + const { + imports, + classes, + callExpressions + } = sourceSymbols; + return importsReact(imports) || requiresReact(callExpressions) || extendsReactComponent(classes); +} + +function importsReact(imports) { + return imports.some(importObj => importObj.source === "react" && importObj.specifiers.some(specifier => specifier === "React")); +} + +function requiresReact(callExpressions) { + return callExpressions.some(callExpression => callExpression.name === "require" && callExpression.values.some(value => value === "react")); +} + +function extendsReactComponent(classes) { + return classes.some(classObj => t.isIdentifier(classObj.parent, { + name: "Component" + }) || t.isIdentifier(classObj.parent, { + name: "PureComponent" + }) || t.isMemberExpression(classObj.parent, { + computed: false + }) && t.isIdentifier(classObj.parent, { + name: "Component" + })); +} // Angular + + +const isAngularComponent = sourceSymbols => { + const { + memberExpressions, + identifiers + } = sourceSymbols; + return identifiesAngular(identifiers) && hasAngularExpressions(memberExpressions); +}; + +const identifiesAngular = identifiers => { + return identifiers.some(item => item.name == "angular"); +}; + +const hasAngularExpressions = memberExpressions => { + return memberExpressions.some(item => item.name == "controller" || item.name == "module"); +}; // Vue + + +const isVueComponent = sourceSymbols => { + const { + identifiers + } = sourceSymbols; + return identifiers.some(identifier => identifier.name == "Vue"); +}; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/getScopes/index.js b/devtools/client/debugger/new/src/workers/parser/getScopes/index.js new file mode 100644 index 000000000000..11b54cd4c0fa --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/getScopes/index.js @@ -0,0 +1,78 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.buildScopeList = undefined; +exports.default = getScopes; +exports.clearScopes = clearScopes; + +var _visitor = require("./visitor"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let parsedScopesCache = new Map(); + +function getScopes(location) { + const { + sourceId + } = location; + let parsedScopes = parsedScopesCache.get(sourceId); + + if (!parsedScopes) { + parsedScopes = (0, _visitor.parseSourceScopes)(sourceId); + parsedScopesCache.set(sourceId, parsedScopes); + } + + return parsedScopes ? findScopes(parsedScopes, location) : []; +} + +function clearScopes() { + parsedScopesCache = new Map(); +} + +exports.buildScopeList = _visitor.buildScopeList; +/** + * Searches all scopes and their bindings at the specific location. + */ + +function findScopes(scopes, location) { + // Find inner most in the tree structure. + let searchInScopes = scopes; + const found = []; + + while (searchInScopes) { + const foundOne = searchInScopes.some(s => { + if (compareLocations(s.start, location) <= 0 && compareLocations(location, s.end) < 0) { + // Found the next scope, trying to search recusevly in its children. + found.unshift(s); + searchInScopes = s.children; + return true; + } + + return false; + }); + + if (!foundOne) { + break; + } + } + + return found.map(i => { + return { + type: i.type, + displayName: i.displayName, + start: i.start, + end: i.end, + bindings: i.bindings + }; + }); +} + +function compareLocations(a, b) { + // According to type of Location.column can be undefined, if will not be the + // case here, ignoring flow error. + // $FlowIgnore + return a.line == b.line ? a.column - b.column : a.line - b.line; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/getScopes/moz.build b/devtools/client/debugger/new/src/workers/parser/getScopes/moz.build new file mode 100644 index 000000000000..981c1233b712 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/getScopes/moz.build @@ -0,0 +1,13 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'index.js', + 'visitor.js', +) diff --git a/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js b/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js new file mode 100644 index 000000000000..92b0fa50296c --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js @@ -0,0 +1,673 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.parseSourceScopes = parseSourceScopes; +exports.buildScopeList = buildScopeList; + +var _isEmpty = require("devtools/client/shared/vendor/lodash").isEmpty; + +var _isEmpty2 = _interopRequireDefault(_isEmpty); + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _getFunctionName = require("../utils/getFunctionName"); + +var _getFunctionName2 = _interopRequireDefault(_getFunctionName); + +var _ast = require("../utils/ast"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function parseSourceScopes(sourceId) { + const ast = (0, _ast.getAst)(sourceId); + + if ((0, _isEmpty2.default)(ast)) { + return null; + } + + return buildScopeList(ast, sourceId); +} + +function buildScopeList(ast, sourceId) { + const { + global, + lexical + } = createGlobalScope(ast, sourceId); + const state = { + sourceId, + freeVariables: new Map(), + freeVariableStack: [], + scope: lexical, + scopeStack: [], + declarationBindingIds: new Set() + }; + t.traverse(ast, scopeCollectionVisitor, state); + + for (const [key, freeVariables] of state.freeVariables) { + let binding = global.bindings[key]; + + if (!binding) { + binding = { + type: "global", + refs: [] + }; + global.bindings[key] = binding; + } + + binding.refs = freeVariables.concat(binding.refs); + } // TODO: This should probably check for ".mjs" extension on the + // original file, and should also be skipped if the the generated + // code is an ES6 module rather than a script. + + + if ((0, _devtoolsSourceMap.isGeneratedId)(sourceId) || ast.program.sourceType === "script" && !looksLikeCommonJS(global)) { + stripModuleScope(global); + } + + return toParsedScopes([global], sourceId) || []; +} + +function toParsedScopes(children, sourceId) { + if (!children || children.length === 0) { + return undefined; + } + + return children.map(scope => { + // Removing unneed information from TempScope such as parent reference. + // We also need to convert BabelLocation to the Location type. + return { + start: scope.loc.start, + end: scope.loc.end, + type: scope.type === "module" ? "block" : scope.type, + displayName: scope.displayName, + bindings: scope.bindings, + children: toParsedScopes(scope.children, sourceId) + }; + }); +} + +function createTempScope(type, displayName, parent, loc) { + const result = { + type, + displayName, + parent, + children: [], + loc, + bindings: Object.create(null) + }; + + if (parent) { + parent.children.push(result); + } + + return result; +} + +function pushTempScope(state, type, displayName, loc) { + const scope = createTempScope(type, displayName, state.scope, loc); + state.scope = scope; + state.freeVariableStack.push(state.freeVariables); + state.freeVariables = new Map(); + return scope; +} + +function isNode(node, type) { + return node ? node.type === type : false; +} + +function getVarScope(scope) { + let s = scope; + + while (s.type !== "function" && s.type !== "module") { + if (!s.parent) { + return s; + } + + s = s.parent; + } + + return s; +} + +function fromBabelLocation(location, sourceId) { + return { + sourceId, + line: location.line, + column: location.column + }; +} + +function parseDeclarator(declaratorId, targetScope, type, locationType, declaration, state) { + if (isNode(declaratorId, "Identifier")) { + let existing = targetScope.bindings[declaratorId.name]; + + if (!existing) { + existing = { + type, + refs: [] + }; + targetScope.bindings[declaratorId.name] = existing; + } + + state.declarationBindingIds.add(declaratorId); + existing.refs.push({ + type: locationType, + start: fromBabelLocation(declaratorId.loc.start, state.sourceId), + end: fromBabelLocation(declaratorId.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(declaration.loc.start, state.sourceId), + end: fromBabelLocation(declaration.loc.end, state.sourceId) + } + }); + } else if (isNode(declaratorId, "ObjectPattern")) { + declaratorId.properties.forEach(prop => { + parseDeclarator(prop.value, targetScope, type, locationType, declaration, state); + }); + } else if (isNode(declaratorId, "ArrayPattern")) { + declaratorId.elements.forEach(item => { + parseDeclarator(item, targetScope, type, locationType, declaration, state); + }); + } else if (isNode(declaratorId, "AssignmentPattern")) { + parseDeclarator(declaratorId.left, targetScope, type, locationType, declaration, state); + } else if (isNode(declaratorId, "RestElement")) { + parseDeclarator(declaratorId.argument, targetScope, type, locationType, declaration, state); + } +} + +function isLetOrConst(node) { + return node.kind === "let" || node.kind === "const"; +} + +function hasLexicalDeclaration(node, parent) { + const isFunctionBody = t.isFunction(parent, { + body: node + }); + return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration"); +} + +function isLexicalVariable(node) { + return isNode(node, "VariableDeclaration") && isLetOrConst(node); +} + +function createGlobalScope(ast, sourceId) { + const global = createTempScope("object", "Global", null, { + start: fromBabelLocation(ast.loc.start, sourceId), + end: fromBabelLocation(ast.loc.end, sourceId) + }); + const lexical = createTempScope("block", "Lexical Global", global, { + start: fromBabelLocation(ast.loc.start, sourceId), + end: fromBabelLocation(ast.loc.end, sourceId) + }); + return { + global, + lexical + }; +} + +const scopeCollectionVisitor = { + // eslint-disable-next-line complexity + enter(node, ancestors, state) { + state.scopeStack.push(state.scope); + const parentNode = ancestors.length === 0 ? null : ancestors[ancestors.length - 1].node; + + if (t.isProgram(node)) { + const scope = pushTempScope(state, "module", "Module", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + scope.bindings.this = { + type: "implicit", + refs: [] + }; + } else if (t.isFunction(node)) { + let scope = state.scope; + + if (t.isFunctionExpression(node) && isNode(node.id, "Identifier")) { + scope = pushTempScope(state, "block", "Function Expression", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + state.declarationBindingIds.add(node.id); + scope.bindings[node.id.name] = { + type: "const", + refs: [{ + type: "fn-expr", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }] + }; + } + + if (t.isFunctionDeclaration(node) && isNode(node.id, "Identifier")) { + // This ignores Annex B function declaration hoisting, which + // is probably a fine assumption. + state.declarationBindingIds.add(node.id); + const fnScope = getVarScope(scope); + scope.bindings[node.id.name] = { + type: fnScope === scope ? "var" : "let", + refs: [{ + type: "fn-decl", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }] + }; + } + + scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), { + // Being at the start of a function doesn't count as + // being inside of it. + start: fromBabelLocation(node.params[0] ? node.params[0].loc.start : node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + node.params.forEach(param => parseDeclarator(param, scope, "var", "fn-param", node, state)); + + if (!t.isArrowFunctionExpression(node)) { + scope.bindings.this = { + type: "implicit", + refs: [] + }; + scope.bindings.arguments = { + type: "implicit", + refs: [] + }; + } + } else if (t.isClass(node)) { + if (t.isIdentifier(node.id)) { + // For decorated classes, the AST considers the first the decorator + // to be the start of the class. For the purposes of mapping class + // declarations however, we really want to look for the "class Foo" + // piece. To achieve that, we estimate the location of the declaration + // instead. + let declStart = node.loc.start; + + if (node.decorators && node.decorators.length > 0) { + // Estimate the location of the "class" keyword since it + // is unlikely to be a different line than the class name. + declStart = { + line: node.id.loc.start.line, + column: node.id.loc.start.column - "class ".length + }; + } + + const declaration = { + start: fromBabelLocation(declStart, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }; + + if (t.isClassDeclaration(node)) { + state.declarationBindingIds.add(node.id); + state.scope.bindings[node.id.name] = { + type: "let", + refs: [{ + type: "class-decl", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration + }] + }; + } + + const scope = pushTempScope(state, "block", "Class", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + state.declarationBindingIds.add(node.id); + scope.bindings[node.id.name] = { + type: "const", + refs: [{ + type: "class-inner", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration + }] + }; + } + } else if (t.isForXStatement(node) || t.isForStatement(node)) { + const init = node.init || node.left; + + if (isNode(init, "VariableDeclaration") && isLetOrConst(init)) { + // Debugger will create new lexical environment for the for. + pushTempScope(state, "block", "For", { + // Being at the start of a for loop doesn't count as + // being inside it. + start: fromBabelLocation(init.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + } + } else if (t.isCatchClause(node)) { + const scope = pushTempScope(state, "block", "Catch", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + parseDeclarator(node.param, scope, "var", "catch", node, state); + } else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) { + // Debugger will create new lexical environment for the block. + pushTempScope(state, "block", "Block", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + } else if (t.isVariableDeclaration(node) && (node.kind === "var" || // Lexical declarations in for statements are handled above. + !t.isForStatement(parentNode, { + init: node + }) || !t.isForXStatement(parentNode, { + left: node + }))) { + // Finds right lexical environment + const hoistAt = !isLetOrConst(node) ? getVarScope(state.scope) : state.scope; + node.declarations.forEach(declarator => { + parseDeclarator(declarator.id, hoistAt, node.kind, node.kind, node, state); + }); + } else if (t.isImportDeclaration(node) && (!node.importKind || node.importKind === "value")) { + node.specifiers.forEach(spec => { + if (t.isImportNamespaceSpecifier(spec)) { + state.declarationBindingIds.add(spec.local); + state.scope.bindings[spec.local.name] = { + // Imported namespaces aren't live import bindings, they are + // just normal const bindings. + type: "const", + refs: [{ + type: "import-ns-decl", + start: fromBabelLocation(spec.local.loc.start, state.sourceId), + end: fromBabelLocation(spec.local.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }] + }; + } else { + state.declarationBindingIds.add(spec.local); + state.scope.bindings[spec.local.name] = { + type: "import", + refs: [{ + type: "import-decl", + start: fromBabelLocation(spec.local.loc.start, state.sourceId), + end: fromBabelLocation(spec.local.loc.end, state.sourceId), + importName: t.isImportDefaultSpecifier(spec) ? "default" : spec.imported.name, + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }] + }; + } + }); + } else if (t.isTSEnumDeclaration(node)) { + state.declarationBindingIds.add(node.id); + state.scope.bindings[node.id.name] = { + type: "const", + refs: [{ + type: "ts-enum-decl", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }] + }; + } else if (t.isIdentifier(node) && t.isReferenced(node, parentNode) && // Babel doesn't cover this in 'isReferenced' yet, but it should + // eventually. + !t.isTSEnumMember(parentNode, { + id: node + }) && // isReferenced above fails to see `var { foo } = ...` as a non-reference + // because the direct parent is not enough to know that the pattern is + // used within a variable declaration. + !state.declarationBindingIds.has(node)) { + let freeVariables = state.freeVariables.get(node.name); + + if (!freeVariables) { + freeVariables = []; + state.freeVariables.set(node.name, freeVariables); + } + + freeVariables.push({ + type: "ref", + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId), + meta: buildMetaBindings(state.sourceId, node, ancestors) + }); + } else if (isOpeningJSXIdentifier(node, ancestors)) { + let freeVariables = state.freeVariables.get(node.name); + + if (!freeVariables) { + freeVariables = []; + state.freeVariables.set(node.name, freeVariables); + } + + freeVariables.push({ + type: "ref", + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId), + meta: buildMetaBindings(state.sourceId, node, ancestors) + }); + } else if (t.isThisExpression(node)) { + let freeVariables = state.freeVariables.get("this"); + + if (!freeVariables) { + freeVariables = []; + state.freeVariables.set("this", freeVariables); + } + + freeVariables.push({ + type: "ref", + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId), + meta: buildMetaBindings(state.sourceId, node, ancestors) + }); + } else if (t.isClassProperty(parentNode, { + value: node + })) { + const scope = pushTempScope(state, "function", "Class Field", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + scope.bindings.this = { + type: "implicit", + refs: [] + }; + scope.bindings.arguments = { + type: "implicit", + refs: [] + }; + } else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) { + pushTempScope(state, "block", "Switch", { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + }); + } + }, + + exit(node, ancestors, state) { + const currentScope = state.scope; + const parentScope = state.scopeStack.pop(); + + if (!parentScope) { + throw new Error("Assertion failure - unsynchronized pop"); + } + + state.scope = parentScope; // It is possible, as in the case of function expressions, that a single + // node has added multiple scopes, so we need to traverse upward here + // rather than jumping stright to 'parentScope'. + + for (let scope = currentScope; scope && scope !== parentScope; scope = scope.parent) { + const freeVariables = state.freeVariables; + state.freeVariables = state.freeVariableStack.pop(); + const parentFreeVariables = state.freeVariables; // Match up any free variables that match this scope's bindings and + // merge then into the refs. + + for (const key of Object.keys(scope.bindings)) { + const binding = scope.bindings[key]; + const freeVars = freeVariables.get(key); + + if (freeVars) { + binding.refs.push(...freeVars); + freeVariables.delete(key); + } + } // Move any undeclared references in this scope into the parent for + // processing in higher scopes. + + + for (const [key, value] of freeVariables) { + let refs = parentFreeVariables.get(key); + + if (!refs) { + refs = []; + parentFreeVariables.set(key, refs); + } + + refs.push(...value); + } + } + } + +}; + +function isOpeningJSXIdentifier(node, ancestors) { + if (!t.isJSXIdentifier(node)) { + return false; + } + + for (let i = ancestors.length - 1; i >= 0; i--) { + const { + node: parent, + key + } = ancestors[i]; + + if (t.isJSXOpeningElement(parent) && key === "name") { + return true; + } else if (!t.isJSXMemberExpression(parent) || key !== "object") { + break; + } + } + + return false; +} + +function buildMetaBindings(sourceId, node, ancestors, parentIndex = ancestors.length - 1) { + if (parentIndex <= 1) { + return null; + } + + const parent = ancestors[parentIndex].node; + const grandparent = ancestors[parentIndex - 1].node; // Consider "0, foo" to be equivalent to "foo". + + if (t.isSequenceExpression(parent) && parent.expressions.length === 2 && t.isNumericLiteral(parent.expressions[0]) && parent.expressions[1] === node) { + let start = parent.loc.start; + let end = parent.loc.end; + + if (t.isCallExpression(grandparent, { + callee: parent + })) { + // Attempt to expand the range around parentheses, e.g. + // (0, foo.bar)() + start = grandparent.loc.start; + end = Object.assign({}, end); + end.column += 1; + } + + return { + type: "inherit", + start: fromBabelLocation(start, sourceId), + end: fromBabelLocation(end, sourceId), + parent: buildMetaBindings(sourceId, parent, ancestors, parentIndex - 1) + }; + } // Consider "Object(foo)" to be equivalent to "foo" + + + if (t.isCallExpression(parent) && t.isIdentifier(parent.callee, { + name: "Object" + }) && parent.arguments.length === 1 && parent.arguments[0] === node) { + return { + type: "inherit", + start: fromBabelLocation(parent.loc.start, sourceId), + end: fromBabelLocation(parent.loc.end, sourceId), + parent: buildMetaBindings(sourceId, parent, ancestors, parentIndex - 1) + }; + } + + if (t.isMemberExpression(parent, { + object: node + })) { + if (parent.computed) { + if (t.isStringLiteral(parent.property)) { + return { + type: "member", + start: fromBabelLocation(parent.loc.start, sourceId), + end: fromBabelLocation(parent.loc.end, sourceId), + property: parent.property.value, + parent: buildMetaBindings(sourceId, parent, ancestors, parentIndex - 1) + }; + } + } else { + return { + type: "member", + start: fromBabelLocation(parent.loc.start, sourceId), + end: fromBabelLocation(parent.loc.end, sourceId), + property: parent.property.name, + parent: buildMetaBindings(sourceId, parent, ancestors, parentIndex - 1) + }; + } + } + + if (t.isCallExpression(parent, { + callee: node + }) && parent.arguments.length == 0) { + return { + type: "call", + start: fromBabelLocation(parent.loc.start, sourceId), + end: fromBabelLocation(parent.loc.end, sourceId), + parent: buildMetaBindings(sourceId, parent, ancestors, parentIndex - 1) + }; + } + + return null; +} + +function looksLikeCommonJS(rootScope) { + const hasRefs = name => rootScope.bindings[name] && rootScope.bindings[name].refs.length > 0; + + return hasRefs("__dirname") || hasRefs("__filename") || hasRefs("require") || hasRefs("exports") || hasRefs("module"); +} + +function stripModuleScope(rootScope) { + const rootLexicalScope = rootScope.children[0]; + const moduleScope = rootLexicalScope.children[0]; + + if (moduleScope.type !== "module") { + throw new Error("Assertion failure - should be module"); + } + + Object.keys(moduleScope.bindings).forEach(name => { + const binding = moduleScope.bindings[name]; + + if (binding.type === "let" || binding.type === "const") { + rootLexicalScope.bindings[name] = binding; + } else { + rootScope.bindings[name] = binding; + } + }); + rootLexicalScope.children = moduleScope.children; + rootLexicalScope.children.forEach(child => { + child.parent = rootLexicalScope; + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/getSymbols.js b/devtools/client/debugger/new/src/workers/parser/getSymbols.js new file mode 100644 index 000000000000..17f82e4ede82 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/getSymbols.js @@ -0,0 +1,471 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.clearSymbols = clearSymbols; +exports.getSymbols = getSymbols; + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _simplePath = require("./utils/simple-path"); + +var _simplePath2 = _interopRequireDefault(_simplePath); + +var _ast = require("./utils/ast"); + +var _helpers = require("./utils/helpers"); + +var _inferClassName = require("./utils/inferClassName"); + +var _getFunctionName = require("./utils/getFunctionName"); + +var _getFunctionName2 = _interopRequireDefault(_getFunctionName); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +let symbolDeclarations = new Map(); + +function getFunctionParameterNames(path) { + if (path.node.params != null) { + return path.node.params.map(param => { + if (param.type !== "AssignmentPattern") { + return param.name; + } // Parameter with default value + + + if (param.left.type === "Identifier" && param.right.type === "Identifier") { + return `${param.left.name} = ${param.right.name}`; + } else if (param.left.type === "Identifier" && param.right.type === "StringLiteral") { + return `${param.left.name} = ${param.right.value}`; + } else if (param.left.type === "Identifier" && param.right.type === "ObjectExpression") { + return `${param.left.name} = {}`; + } else if (param.left.type === "Identifier" && param.right.type === "ArrayExpression") { + return `${param.left.name} = []`; + } else if (param.left.type === "Identifier" && param.right.type === "NullLiteral") { + return `${param.left.name} = null`; + } + }); + } + + return []; +} +/* eslint-disable complexity */ + + +function extractSymbol(path, symbols) { + if ((0, _helpers.isVariable)(path)) { + symbols.variables.push(...(0, _helpers.getVariableNames)(path)); + } + + if ((0, _helpers.isFunction)(path)) { + symbols.functions.push({ + name: (0, _getFunctionName2.default)(path.node, path.parent), + klass: (0, _inferClassName.inferClassName)(path), + location: path.node.loc, + parameterNames: getFunctionParameterNames(path), + identifier: path.node.id + }); + } + + if (t.isJSXElement(path)) { + symbols.hasJsx = true; + } + + if (t.isGenericTypeAnnotation(path)) { + symbols.hasTypes = true; + } + + if (t.isClassDeclaration(path)) { + symbols.classes.push({ + name: path.node.id.name, + parent: path.node.superClass, + location: path.node.loc + }); + } + + if (t.isImportDeclaration(path)) { + symbols.imports.push({ + source: path.node.source.value, + location: path.node.loc, + specifiers: (0, _helpers.getSpecifiers)(path.node.specifiers) + }); + } + + if (t.isObjectProperty(path)) { + const { + start, + end, + identifierName + } = path.node.key.loc; + symbols.objectProperties.push({ + name: identifierName, + location: { + start, + end + }, + expression: getSnippet(path) + }); + } + + if (t.isMemberExpression(path)) { + const { + start, + end + } = path.node.property.loc; + symbols.memberExpressions.push({ + name: path.node.property.name, + location: { + start, + end + }, + expression: getSnippet(path), + computed: path.node.computed + }); + } + + if ((t.isStringLiteral(path) || t.isNumericLiteral(path)) && t.isMemberExpression(path.parentPath)) { + // We only need literals that are part of computed memeber expressions + const { + start, + end + } = path.node.loc; + symbols.literals.push({ + name: path.node.value, + location: { + start, + end + }, + expression: getSnippet(path.parentPath) + }); + } + + if (t.isCallExpression(path)) { + const callee = path.node.callee; + const args = path.node.arguments; + + if (!t.isMemberExpression(callee)) { + const { + start, + end, + identifierName + } = callee.loc; + symbols.callExpressions.push({ + name: identifierName, + values: args.filter(arg => arg.value).map(arg => arg.value), + location: { + start, + end + } + }); + } + } + + if (t.isStringLiteral(path) && t.isProperty(path.parentPath)) { + const { + start, + end + } = path.node.loc; + return symbols.identifiers.push({ + name: path.node.value, + expression: (0, _helpers.getObjectExpressionValue)(path.parent), + location: { + start, + end + } + }); + } + + if (t.isIdentifier(path) && !t.isGenericTypeAnnotation(path.parent)) { + let { + start, + end + } = path.node.loc; // We want to include function params, but exclude the function name + + if (t.isClassMethod(path.parent) && !path.inList) { + return; + } + + if (t.isProperty(path.parentPath) && !(0, _helpers.isObjectShorthand)(path.parent)) { + return symbols.identifiers.push({ + name: path.node.name, + expression: (0, _helpers.getObjectExpressionValue)(path.parent), + location: { + start, + end + } + }); + } + + if (path.node.typeAnnotation) { + const column = path.node.typeAnnotation.loc.start.column; + end = _objectSpread({}, end, { + column + }); + } + + symbols.identifiers.push({ + name: path.node.name, + expression: path.node.name, + location: { + start, + end + } + }); + } + + if (t.isThisExpression(path.node)) { + const { + start, + end + } = path.node.loc; + symbols.identifiers.push({ + name: "this", + location: { + start, + end + }, + expression: "this" + }); + } + + if (t.isVariableDeclarator(path)) { + const nodeId = path.node.id; + + if (t.isArrayPattern(nodeId)) { + return; + } + + const properties = nodeId.properties && t.objectPattern(nodeId.properties) ? nodeId.properties : [{ + value: { + name: nodeId.name + }, + loc: path.node.loc + }]; + properties.forEach(function (property) { + const { + start, + end + } = property.loc; + symbols.identifiers.push({ + name: property.value.name, + expression: property.value.name, + location: { + start, + end + } + }); + }); + } +} +/* eslint-enable complexity */ + + +function extractSymbols(sourceId) { + const symbols = { + functions: [], + variables: [], + callExpressions: [], + memberExpressions: [], + objectProperties: [], + comments: [], + identifiers: [], + classes: [], + imports: [], + literals: [], + hasJsx: false, + hasTypes: false + }; + const ast = (0, _ast.traverseAst)(sourceId, { + enter(node, ancestors) { + try { + const path = (0, _simplePath2.default)(ancestors); + + if (path) { + extractSymbol(path, symbols); + } + } catch (e) { + console.error(e); + } + } + + }); // comments are extracted separately from the AST + + symbols.comments = (0, _helpers.getComments)(ast); + return symbols; +} + +function extendSnippet(name, expression, path, prevPath) { + const computed = path && path.node.computed; + const prevComputed = prevPath && prevPath.node.computed; + const prevArray = t.isArrayExpression(prevPath); + const array = t.isArrayExpression(path); + const value = path && path.node.property && path.node.property.extra && path.node.property.extra.raw || ""; + + if (expression === "") { + if (computed) { + return name === undefined ? `[${value}]` : `[${name}]`; + } + + return name; + } + + if (computed || array) { + if (prevComputed || prevArray) { + return `[${name}]${expression}`; + } + + return `[${name === undefined ? value : name}].${expression}`; + } + + if (prevComputed || prevArray) { + return `${name}${expression}`; + } + + if ((0, _helpers.isComputedExpression)(expression) && name !== undefined) { + return `${name}${expression}`; + } + + return `${name}.${expression}`; +} + +function getMemberSnippet(node, expression = "") { + if (t.isMemberExpression(node)) { + const name = node.property.name; + const snippet = getMemberSnippet(node.object, extendSnippet(name, expression, { + node + })); + return snippet; + } + + if (t.isCallExpression(node)) { + return ""; + } + + if (t.isThisExpression(node)) { + return `this.${expression}`; + } + + if (t.isIdentifier(node)) { + if ((0, _helpers.isComputedExpression)(expression)) { + return `${node.name}${expression}`; + } + + return `${node.name}.${expression}`; + } + + return expression; +} + +function getObjectSnippet(path, prevPath, expression = "") { + if (!path) { + return expression; + } + + const name = path.node.key.name; + const extendedExpression = extendSnippet(name, expression, path, prevPath); + const nextPrevPath = path; + const nextPath = path.parentPath && path.parentPath.parentPath; + return getSnippet(nextPath, nextPrevPath, extendedExpression); +} + +function getArraySnippet(path, prevPath, expression) { + if (!prevPath.parentPath) { + throw new Error("Assertion failure - path should exist"); + } + + const index = `${prevPath.parentPath.containerIndex}`; + const extendedExpression = extendSnippet(index, expression, path, prevPath); + const nextPrevPath = path; + const nextPath = path.parentPath && path.parentPath.parentPath; + return getSnippet(nextPath, nextPrevPath, extendedExpression); +} + +function getSnippet(path, prevPath, expression = "") { + if (!path) { + return expression; + } + + if (t.isVariableDeclaration(path)) { + const node = path.node.declarations[0]; + const name = node.id.name; + return extendSnippet(name, expression, path, prevPath); + } + + if (t.isVariableDeclarator(path)) { + const node = path.node.id; + + if (t.isObjectPattern(node)) { + return expression; + } + + const name = node.name; + const prop = extendSnippet(name, expression, path, prevPath); + return prop; + } + + if (t.isAssignmentExpression(path)) { + const node = path.node.left; + const name = t.isMemberExpression(node) ? getMemberSnippet(node) : node.name; + const prop = extendSnippet(name, expression, path, prevPath); + return prop; + } + + if ((0, _helpers.isFunction)(path)) { + return expression; + } + + if (t.isIdentifier(path)) { + const node = path.node; + return `${node.name}.${expression}`; + } + + if (t.isObjectProperty(path)) { + return getObjectSnippet(path, prevPath, expression); + } + + if (t.isObjectExpression(path)) { + const parentPath = prevPath && prevPath.parentPath; + return getObjectSnippet(parentPath, prevPath, expression); + } + + if (t.isMemberExpression(path)) { + return getMemberSnippet(path.node, expression); + } + + if (t.isArrayExpression(path)) { + if (!prevPath) { + throw new Error("Assertion failure - path should exist"); + } + + return getArraySnippet(path, prevPath, expression); + } + + return ""; +} + +function clearSymbols() { + symbolDeclarations = new Map(); +} + +function getSymbols(sourceId) { + if (symbolDeclarations.has(sourceId)) { + const symbols = symbolDeclarations.get(sourceId); + + if (symbols) { + return symbols; + } + } + + const symbols = extractSymbols(sourceId); + symbolDeclarations.set(sourceId, symbols); + return symbols; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/index.js b/devtools/client/debugger/new/src/workers/parser/index.js new file mode 100644 index 000000000000..6e03dee24321 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/index.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.replaceOriginalVariableName = exports.getPausePoints = exports.getFramework = exports.mapOriginalExpression = exports.hasSyntaxError = exports.clearSources = exports.setSource = exports.hasSource = exports.getNextStep = exports.clearASTs = exports.clearScopes = exports.clearSymbols = exports.findOutOfScopeLocations = exports.getScopes = exports.getSymbols = exports.getClosestExpression = exports.stop = exports.start = undefined; + +var _devtoolsUtils = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-utils"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + WorkerDispatcher +} = _devtoolsUtils.workerUtils; +const dispatcher = new WorkerDispatcher(); +const start = exports.start = dispatcher.start.bind(dispatcher); +const stop = exports.stop = dispatcher.stop.bind(dispatcher); +const getClosestExpression = exports.getClosestExpression = dispatcher.task("getClosestExpression"); +const getSymbols = exports.getSymbols = dispatcher.task("getSymbols"); +const getScopes = exports.getScopes = dispatcher.task("getScopes"); +const findOutOfScopeLocations = exports.findOutOfScopeLocations = dispatcher.task("findOutOfScopeLocations"); +const clearSymbols = exports.clearSymbols = dispatcher.task("clearSymbols"); +const clearScopes = exports.clearScopes = dispatcher.task("clearScopes"); +const clearASTs = exports.clearASTs = dispatcher.task("clearASTs"); +const getNextStep = exports.getNextStep = dispatcher.task("getNextStep"); +const hasSource = exports.hasSource = dispatcher.task("hasSource"); +const setSource = exports.setSource = dispatcher.task("setSource"); +const clearSources = exports.clearSources = dispatcher.task("clearSources"); +const hasSyntaxError = exports.hasSyntaxError = dispatcher.task("hasSyntaxError"); +const mapOriginalExpression = exports.mapOriginalExpression = dispatcher.task("mapOriginalExpression"); +const getFramework = exports.getFramework = dispatcher.task("getFramework"); +const getPausePoints = exports.getPausePoints = dispatcher.task("getPausePoints"); +const replaceOriginalVariableName = exports.replaceOriginalVariableName = dispatcher.task("replaceOriginalVariableName"); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/mapOriginalExpression.js b/devtools/client/debugger/new/src/workers/parser/mapOriginalExpression.js new file mode 100644 index 000000000000..c6610d0bc80f --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/mapOriginalExpression.js @@ -0,0 +1,114 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = mapOriginalExpression; + +var _ast = require("./utils/ast"); + +var _getScopes = require("./getScopes/index"); + +var _generator = require("@babel/generator/index"); + +var _generator2 = _interopRequireDefault(_generator); + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// NOTE: this will only work if we are replacing an original identifier +function replaceNode(ancestors, node) { + const ancestor = ancestors[ancestors.length - 1]; + + if (typeof ancestor.index === "number") { + ancestor.node[ancestor.key][ancestor.index] = node; + } else { + ancestor.node[ancestor.key] = node; + } +} + +function getFirstExpression(ast) { + const statements = ast.program.body; + + if (statements.length == 0) { + return null; + } + + return statements[0].expression; +} + +function locationKey(start) { + return `${start.line}:${start.column}`; +} + +function mapOriginalExpression(expression, mappings) { + const ast = (0, _ast.parseScript)(expression); + const scopes = (0, _getScopes.buildScopeList)(ast, ""); + const nodes = new Map(); + const replacements = new Map(); // The ref-only global bindings are the ones that are accessed, but not + // declared anywhere in the parsed code, meaning they are either global, + // or declared somewhere in a scope outside the parsed code, so we + // rewrite all of those specifically to avoid rewritting declarations that + // shadow outer mappings. + + for (const name of Object.keys(scopes[0].bindings)) { + const { + refs + } = scopes[0].bindings[name]; + const mapping = mappings[name]; + + if (!refs.every(ref => ref.type === "ref") || !mapping || mapping === name) { + continue; + } + + let node = nodes.get(name); + + if (!node) { + node = getFirstExpression((0, _ast.parseScript)(mapping)); + nodes.set(name, node); + } + + for (const ref of refs) { + let { + line, + column + } = ref.start; // This shouldn't happen, just keeping Flow happy. + + if (typeof column !== "number") { + column = 0; + } + + replacements.set(locationKey({ + line, + column + }), node); + } + } + + if (replacements.size === 0) { + // Avoid the extra code generation work and also avoid potentially + // reformatting the user's code unnecessarily. + return expression; + } + + t.traverse(ast, (node, ancestors) => { + if (!t.isIdentifier(node) && !t.isThisExpression(node)) { + return; + } + + const replacement = replacements.get(locationKey(node.loc.start)); + + if (replacement) { + replaceNode(ancestors, t.cloneNode(replacement)); + } + }); + return (0, _generator2.default)(ast).code; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/moz.build b/devtools/client/debugger/new/src/workers/parser/moz.build new file mode 100644 index 000000000000..82a0942688c4 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/moz.build @@ -0,0 +1,22 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + 'getScopes', + 'utils', +] + +DevToolsModules( + 'findOutOfScopeLocations.js', + 'frameworks.js', + 'getSymbols.js', + 'index.js', + 'mapOriginalExpression.js', + 'pausePoints.js', + 'sources.js', + 'steps.js', + 'validate.js', + 'worker.js', +) diff --git a/devtools/client/debugger/new/src/workers/parser/pausePoints.js b/devtools/client/debugger/new/src/workers/parser/pausePoints.js new file mode 100644 index 000000000000..ccce33f27a09 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/pausePoints.js @@ -0,0 +1,194 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getPausePoints = getPausePoints; + +var _ast = require("./utils/ast"); + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _isEqual = require("devtools/client/shared/vendor/lodash").isEqual; + +var _isEqual2 = _interopRequireDefault(_isEqual); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const isForStatement = node => t.isForStatement(node) || t.isForOfStatement(node); + +const isControlFlow = node => isForStatement(node) || t.isWhileStatement(node) || t.isIfStatement(node) || t.isSwitchCase(node) || t.isSwitchStatement(node) || t.isTryStatement(node) || t.isWithStatement(node); + +const isAssignment = node => t.isVariableDeclarator(node) || t.isAssignmentExpression(node) || t.isAssignmentPattern(node); + +const isImport = node => t.isImport(node) || t.isImportDeclaration(node); + +const isReturn = node => t.isReturnStatement(node); + +const isCall = node => t.isCallExpression(node) || t.isJSXElement(node); + +const inStepExpression = parent => t.isArrayExpression(parent) || t.isObjectProperty(parent) || t.isCallExpression(parent) || t.isJSXElement(parent); + +const inExpression = (parent, grandParent) => inStepExpression(parent) || t.isJSXAttribute(grandParent) || t.isTemplateLiteral(parent); + +const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node); + +function getPausePoints(sourceId) { + const state = {}; + (0, _ast.traverseAst)(sourceId, { + enter: onEnter + }, state); + return state; +} +/* eslint-disable complexity */ + + +function onEnter(node, ancestors, state) { + const parent = ancestors[ancestors.length - 1]; + const parentNode = parent && parent.node; + const grandParent = ancestors[ancestors.length - 2]; + const startLocation = node.loc.start; + + if (isImport(node) || t.isClassDeclaration(node) || isExport(node) || t.isDebuggerStatement(node) || t.isThrowStatement(node) || t.isExpressionStatement(node) || t.isBreakStatement(node) || t.isContinueStatement(node)) { + return addStopPoint(state, startLocation); + } + + if (isControlFlow(node)) { + if (isForStatement(node)) { + addStopPoint(state, startLocation); + } else { + addEmptyPoint(state, startLocation); + } + + const test = node.test || node.discriminant; + + if (test) { + addStopPoint(state, test.loc.start); + } + + return; + } + + if (t.isBlockStatement(node)) { + return addEmptyPoint(state, startLocation); + } + + if (isReturn(node)) { + // We do not want to pause at the return and the call e.g. return foo() + if (isCall(node.argument)) { + return addEmptyPoint(state, startLocation); + } + + return addStopPoint(state, startLocation); + } + + if (isAssignment(node)) { + // We only want to pause at literal assignments `var a = foo()` + const value = node.right || node.init; + + if (isCall(value) || t.isFunction(parentNode)) { + return addEmptyPoint(state, startLocation); + } + + return addStopPoint(state, startLocation); + } + + if (isCall(node)) { + let location = startLocation; // When functions are chained, we want to use the property location + // e.g `foo().bar()` + + if (t.isMemberExpression(node.callee)) { + location = node.callee.property.loc.start; + } // NOTE: we do not want to land inside an expression e.g. [], {}, call + + + const step = !inExpression(parent.node, grandParent && grandParent.node); // NOTE: we add a point at the beginning of the expression + // and each of the calls because the engine does not support + // column-based member expression calls. + + addPoint(state, startLocation, { + break: true, + step + }); + + if (location && !(0, _isEqual2.default)(location, startLocation)) { + addPoint(state, location, { + break: true, + step + }); + } + + return; + } + + if (t.isClassProperty(node)) { + return addBreakPoint(state, startLocation); + } + + if (t.isFunction(node)) { + const { + line, + column + } = node.loc.end; + addBreakPoint(state, startLocation); + return addStopPoint(state, { + line, + column: column - 1 + }); + } + + if (t.isProgram(node)) { + const lastStatement = node.body[node.body.length - 1]; + + if (lastStatement) { + return addStopPoint(state, lastStatement.loc.end); + } + } + + if (!hasPoint(state, startLocation) && inStepExpression(parentNode)) { + return addEmptyPoint(state, startLocation); + } +} + +function hasPoint(state, { + line, + column +}) { + return state[line] && state[line][column]; +} + +function addPoint(state, { + line, + column +}, types) { + if (!state[line]) { + state[line] = {}; + } + + state[line][column] = types; + return state; +} + +function addStopPoint(state, location) { + return addPoint(state, location, { + break: true, + step: true + }); +} + +function addEmptyPoint(state, location) { + return addPoint(state, location, {}); +} + +function addBreakPoint(state, location) { + return addPoint(state, location, { + break: true + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/sources.js b/devtools/client/debugger/new/src/workers/parser/sources.js new file mode 100644 index 000000000000..8b2e6af297b0 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/sources.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.hasSource = hasSource; +exports.setSource = setSource; +exports.getSource = getSource; +exports.clearSources = clearSources; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +let cachedSources = new Map(); + +function hasSource(sourceId) { + return cachedSources.has(sourceId); +} + +function setSource(source) { + cachedSources.set(source.id, source); +} + +function getSource(sourceId) { + if (!cachedSources.has(sourceId)) { + throw new Error(`Parser: source ${sourceId} was not provided.`); + } + + return cachedSources.get(sourceId); +} + +function clearSources() { + cachedSources = new Map(); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/steps.js b/devtools/client/debugger/new/src/workers/parser/steps.js new file mode 100644 index 000000000000..cab1a6c4d335 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/steps.js @@ -0,0 +1,64 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getNextStep = getNextStep; + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _closest = require("./utils/closest"); + +var _helpers = require("./utils/helpers"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getNextStep(sourceId, pausedPosition) { + const currentExpression = getSteppableExpression(sourceId, pausedPosition); + + if (!currentExpression) { + return null; + } + + const currentStatement = currentExpression.find(p => { + return p.inList && t.isStatement(p.node); + }); + + if (!currentStatement) { + throw new Error("Assertion failure - this should always find at least Program"); + } + + return _getNextStep(currentStatement, sourceId, pausedPosition); +} + +function getSteppableExpression(sourceId, pausedPosition) { + const closestPath = (0, _closest.getClosestPath)(sourceId, pausedPosition); + + if (!closestPath) { + return null; + } + + if ((0, _helpers.isAwaitExpression)(closestPath) || (0, _helpers.isYieldExpression)(closestPath)) { + return closestPath; + } + + return closestPath.find(p => t.isAwaitExpression(p.node) || t.isYieldExpression(p.node)); +} + +function _getNextStep(statement, sourceId, position) { + const nextStatement = statement.getSibling(1); + + if (nextStatement) { + return _objectSpread({}, nextStatement.node.loc.start, { + sourceId: sourceId + }); + } + + return null; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/ast.js b/devtools/client/debugger/new/src/workers/parser/utils/ast.js new file mode 100644 index 000000000000..00108f0b742e --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/ast.js @@ -0,0 +1,169 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.parseScript = parseScript; +exports.getAst = getAst; +exports.clearASTs = clearASTs; +exports.traverseAst = traverseAst; + +var _parseScriptTags = require("parse-script-tags/index"); + +var _parseScriptTags2 = _interopRequireDefault(_parseScriptTags); + +var _babylon = require("babylon/index"); + +var babylon = _interopRequireWildcard(_babylon); + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _isEmpty = require("devtools/client/shared/vendor/lodash").isEmpty; + +var _isEmpty2 = _interopRequireDefault(_isEmpty); + +var _sources = require("../sources"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +let ASTs = new Map(); + +function _parse(code, opts) { + return babylon.parse(code, _objectSpread({}, opts, { + tokens: true + })); +} + +const sourceOptions = { + generated: { + sourceType: "unambiguous", + tokens: true, + plugins: ["objectRestSpread"] + }, + original: { + sourceType: "unambiguous", + tokens: true, + plugins: ["jsx", "flow", "doExpressions", "decorators", "objectRestSpread", "classProperties", "exportDefaultFrom", "exportNamespaceFrom", "asyncGenerators", "functionBind", "functionSent", "dynamicImport", "react-jsx"] + } +}; + +function parse(text, opts) { + let ast; + + if (!text) { + return; + } + + try { + ast = _parse(text, opts); + } catch (error) { + console.error(error); + ast = {}; + } + + return ast; +} // Custom parser for parse-script-tags that adapts its input structure to +// our parser's signature + + +function htmlParser({ + source, + line +}) { + return parse(source, { + startLine: line + }); +} + +const VUE_COMPONENT_START = /^\s* p !== "flow" && p !== "decorators" && p !== "decorators2" && (p !== "jsx" || contentType.match(/typescript-jsx/))), "decorators", "typescript"] + }); + + ast = parse(source.text, options); + } + + ASTs.set(source.id, ast); + return ast; +} + +function clearASTs() { + ASTs = new Map(); +} + +function traverseAst(sourceId, visitor, state) { + const ast = getAst(sourceId); + + if ((0, _isEmpty2.default)(ast)) { + return null; + } + + t.traverse(ast, visitor, state); + return ast; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/closest.js b/devtools/client/debugger/new/src/workers/parser/utils/closest.js new file mode 100644 index 000000000000..f6b0642183c7 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/closest.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getClosestPath = getClosestPath; + +var _simplePath = require("./simple-path"); + +var _simplePath2 = _interopRequireDefault(_simplePath); + +var _ast = require("./ast"); + +var _contains = require("./contains"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getClosestPath(sourceId, location) { + let closestPath = null; + (0, _ast.traverseAst)(sourceId, { + enter(node, ancestors) { + if ((0, _contains.nodeContainsPosition)(node, location)) { + const path = (0, _simplePath2.default)(ancestors); + + if (path && (!closestPath || path.depth > closestPath.depth)) { + closestPath = path; + } + } + } + + }); + + if (!closestPath) { + throw new Error("Assertion failure - This should always fine a path"); + } + + return closestPath; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/contains.js b/devtools/client/debugger/new/src/workers/parser/utils/contains.js new file mode 100644 index 000000000000..5ef236fbef06 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/contains.js @@ -0,0 +1,43 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.containsPosition = containsPosition; +exports.containsLocation = containsLocation; +exports.nodeContainsPosition = nodeContainsPosition; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function startsBefore(a, b) { + let before = a.start.line < b.line; + + if (a.start.line === b.line) { + before = a.start.column >= 0 && b.column >= 0 ? a.start.column <= b.column : true; + } + + return before; +} + +function endsAfter(a, b) { + let after = a.end.line > b.line; + + if (a.end.line === b.line) { + after = a.end.column >= 0 && b.column >= 0 ? a.end.column >= b.column : true; + } + + return after; +} + +function containsPosition(a, b) { + return startsBefore(a, b) && endsAfter(a, b); +} + +function containsLocation(a, b) { + return containsPosition(a, b.start) && containsPosition(a, b.end); +} + +function nodeContainsPosition(node, position) { + return containsPosition(node.loc, position); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js b/devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js new file mode 100644 index 000000000000..b0e7a18a8cbe --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js @@ -0,0 +1,60 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.formatSymbols = formatSymbols; + +var _getSymbols = require("../getSymbols"); + +var _sources = require("../sources"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function formatLocation(loc) { + if (!loc) { + return ""; + } + + const { + start, + end + } = loc; + const startLoc = `(${start.line}, ${start.column})`; + const endLoc = `(${end.line}, ${end.column})`; + return `[${startLoc}, ${endLoc}]`; +} + +function summarize(symbol) { + if (typeof symbol == "boolean") { + return symbol ? "true" : "false"; + } + + const loc = formatLocation(symbol.location); + const params = symbol.parameterNames ? `(${symbol.parameterNames.join(", ")})` : ""; + const expression = symbol.expression || ""; + const klass = symbol.klass || ""; + const name = symbol.name == undefined ? "" : symbol.name; + const names = symbol.specifiers ? symbol.specifiers.join(", ") : ""; + const values = symbol.values ? symbol.values.join(", ") : ""; + return `${loc} ${expression} ${name}${params} ${klass} ${names} ${values}`.trim(); // eslint-disable-line max-len +} + +function formatKey(name, symbols) { + if (name == "hasJsx") { + return `hasJsx: ${symbols.hasJsx ? "true" : "false"}`; + } + + if (name == "hasTypes") { + return `hasTypes: ${symbols.hasTypes ? "true" : "false"}`; + } + + return `${name}:\n${symbols[name].map(summarize).join("\n")}`; +} + +function formatSymbols(source) { + (0, _sources.setSource)(source); + const symbols = (0, _getSymbols.getSymbols)(source.id); + return Object.keys(symbols).map(name => formatKey(name, symbols)).join("\n\n"); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/getFunctionName.js b/devtools/client/debugger/new/src/workers/parser/utils/getFunctionName.js new file mode 100644 index 000000000000..4427c79e0151 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/getFunctionName.js @@ -0,0 +1,105 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = getFunctionName; + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Perform ES6's anonymous function name inference for all +// locations where static analysis is possible. +// eslint-disable-next-line complexity +function getFunctionName(node, parent) { + if (t.isIdentifier(node.id)) { + return node.id.name; + } + + if (t.isObjectMethod(node, { + computed: false + }) || t.isClassMethod(node, { + computed: false + })) { + const key = node.key; + + if (t.isIdentifier(key)) { + return key.name; + } + + if (t.isStringLiteral(key)) { + return key.value; + } + + if (t.isNumericLiteral(key)) { + return `${key.value}`; + } + } + + if (t.isObjectProperty(parent, { + computed: false, + value: node + }) || // TODO: Babylon 6 doesn't support computed class props. It is included + // here so that it is most flexible. Once Babylon 7 is used, this + // can change to use computed: false like ObjectProperty. + t.isClassProperty(parent, { + value: node + }) && !parent.computed) { + const key = parent.key; + + if (t.isIdentifier(key)) { + return key.name; + } + + if (t.isStringLiteral(key)) { + return key.value; + } + + if (t.isNumericLiteral(key)) { + return `${key.value}`; + } + } + + if (t.isAssignmentExpression(parent, { + operator: "=", + right: node + })) { + if (t.isIdentifier(parent.left)) { + return parent.left.name; + } // This case is not supported in standard ES6 name inference, but it + // is included here since it is still a helpful case during debugging. + + + if (t.isMemberExpression(parent.left, { + computed: false + })) { + return parent.left.property.name; + } + } + + if (t.isAssignmentPattern(parent, { + right: node + }) && t.isIdentifier(parent.left)) { + return parent.left.name; + } + + if (t.isVariableDeclarator(parent, { + init: node + }) && t.isIdentifier(parent.id)) { + return parent.id.name; + } + + if (t.isExportDefaultDeclaration(parent, { + declaration: node + }) && t.isFunctionDeclaration(node)) { + return "default"; + } + + return "anonymous"; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/helpers.js b/devtools/client/debugger/new/src/workers/parser/utils/helpers.js new file mode 100644 index 000000000000..02b117c678ce --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/helpers.js @@ -0,0 +1,191 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isFunction = isFunction; +exports.isAwaitExpression = isAwaitExpression; +exports.isYieldExpression = isYieldExpression; +exports.isObjectShorthand = isObjectShorthand; +exports.getObjectExpressionValue = getObjectExpressionValue; +exports.getVariableNames = getVariableNames; +exports.getComments = getComments; +exports.getSpecifiers = getSpecifiers; +exports.isVariable = isVariable; +exports.isComputedExpression = isComputedExpression; +exports.getMemberExpression = getMemberExpression; +exports.getVariables = getVariables; + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +var _generator = require("@babel/generator/index"); + +var _generator2 = _interopRequireDefault(_generator); + +var _flatten = require("devtools/client/shared/vendor/lodash").flatten; + +var _flatten2 = _interopRequireDefault(_flatten); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function isFunction(node) { + return t.isFunction(node) || t.isArrowFunctionExpression(node) || t.isObjectMethod(node) || t.isClassMethod(node); +} + +function isAwaitExpression(path) { + const { + node, + parent + } = path; + return t.isAwaitExpression(node) || t.isAwaitExpression(parent.init) || t.isAwaitExpression(parent); +} + +function isYieldExpression(path) { + const { + node, + parent + } = path; + return t.isYieldExpression(node) || t.isYieldExpression(parent.init) || t.isYieldExpression(parent); +} + +function isObjectShorthand(parent) { + return t.isObjectProperty(parent) && parent.key.start == parent.value.start && parent.key.loc.identifierName === parent.value.loc.identifierName; +} + +function getObjectExpressionValue(node) { + const { + value + } = node; + + if (t.isIdentifier(value)) { + return value.name; + } + + if (t.isCallExpression(value)) { + return ""; + } + + const code = (0, _generator2.default)(value).code; + const shouldWrap = t.isObjectExpression(value); + return shouldWrap ? `(${code})` : code; +} + +function getVariableNames(path) { + if (t.isObjectProperty(path.node) && !isFunction(path.node.value)) { + if (path.node.key.type === "StringLiteral") { + return [{ + name: path.node.key.value, + location: path.node.loc + }]; + } else if (path.node.value.type === "Identifier") { + return [{ + name: path.node.value.name, + location: path.node.loc + }]; + } else if (path.node.value.type === "AssignmentPattern") { + return [{ + name: path.node.value.left.name, + location: path.node.loc + }]; + } + + return [{ + name: path.node.key.name, + location: path.node.loc + }]; + } + + if (!path.node.declarations) { + return path.node.params.map(dec => ({ + name: dec.name, + location: dec.loc + })); + } + + const declarations = path.node.declarations.filter(dec => dec.id.type !== "ObjectPattern").map(getVariables); + return (0, _flatten2.default)(declarations); +} + +function getComments(ast) { + if (!ast || !ast.comments) { + return []; + } + + return ast.comments.map(comment => ({ + name: comment.location, + location: comment.loc + })); +} + +function getSpecifiers(specifiers) { + if (!specifiers) { + return []; + } + + return specifiers.map(specifier => specifier.local && specifier.local.name); +} + +function isVariable(path) { + const node = path.node; + return t.isVariableDeclaration(node) || isFunction(path) && path.node.params != null && path.node.params.length || t.isObjectProperty(node) && !isFunction(path.node.value); +} + +function isComputedExpression(expression) { + return /^\[/m.test(expression); +} + +function getMemberExpression(root) { + function _getMemberExpression(node, expr) { + if (t.isMemberExpression(node)) { + expr = [node.property.name].concat(expr); + return _getMemberExpression(node.object, expr); + } + + if (t.isCallExpression(node)) { + return []; + } + + if (t.isThisExpression(node)) { + return ["this"].concat(expr); + } + + return [node.name].concat(expr); + } + + const expr = _getMemberExpression(root, []); + + return expr.join("."); +} + +function getVariables(dec) { + if (!dec.id) { + return []; + } + + if (t.isArrayPattern(dec.id)) { + if (!dec.id.elements) { + return []; + } // NOTE: it's possible that an element is empty + // e.g. const [, a] = arr + + + return dec.id.elements.filter(element => element).map(element => { + return { + name: t.isAssignmentPattern(element) ? element.left.name : element.name || element.argument.name, + location: element.loc + }; + }); + } + + return [{ + name: dec.id.name, + location: dec.loc + }]; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/inferClassName.js b/devtools/client/debugger/new/src/workers/parser/utils/inferClassName.js new file mode 100644 index 000000000000..a6ed8fce7639 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/inferClassName.js @@ -0,0 +1,98 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.inferClassName = inferClassName; + +var _types = require("@babel/types/index"); + +var t = _interopRequireWildcard(_types); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// the function class is inferred from a call like +// createClass or extend +function fromCallExpression(callExpression) { + const whitelist = ["extend", "createClass"]; + const callee = callExpression.node.callee; + + if (!callee) { + return null; + } + + const name = t.isMemberExpression(callee) ? callee.property.name : callee.name; + + if (!whitelist.includes(name)) { + return null; + } + + const variable = callExpression.findParent(p => t.isVariableDeclarator(p.node)); + + if (variable) { + return variable.node.id.name; + } + + const assignment = callExpression.findParent(p => t.isAssignmentExpression(p.node)); + + if (!assignment) { + return null; + } + + const left = assignment.node.left; + + if (left.name) { + return name; + } + + if (t.isMemberExpression(left)) { + return left.property.name; + } + + return null; +} // the function class is inferred from a prototype assignment +// e.g. TodoClass.prototype.render = function() {} + + +function fromPrototype(assignment) { + const left = assignment.node.left; + + if (!left) { + return null; + } + + if (t.isMemberExpression(left) && left.object && t.isMemberExpression(left.object) && left.object.property.identifier === "prototype") { + return left.object.object.name; + } + + return null; +} // infer class finds an appropriate class for functions +// that are defined inside of a class like thing. +// e.g. `class Foo`, `TodoClass.prototype.foo`, +// `Todo = createClass({ foo: () => {}})` + + +function inferClassName(path) { + const classDeclaration = path.findParent(p => t.isClassDeclaration(p.node)); + + if (classDeclaration) { + return classDeclaration.node.id.name; + } + + const callExpression = path.findParent(p => t.isCallExpression(p.node)); + + if (callExpression) { + return fromCallExpression(callExpression); + } + + const assignment = path.findParent(p => t.isAssignmentExpression(p.node)); + + if (assignment) { + return fromPrototype(assignment); + } + + return null; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/utils/moz.build b/devtools/client/debugger/new/src/workers/parser/utils/moz.build new file mode 100644 index 000000000000..01f1ee5932d0 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/moz.build @@ -0,0 +1,19 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'ast.js', + 'closest.js', + 'contains.js', + 'formatSymbols.js', + 'getFunctionName.js', + 'helpers.js', + 'inferClassName.js', + 'simple-path.js', +) diff --git a/devtools/client/debugger/new/src/workers/parser/utils/simple-path.js b/devtools/client/debugger/new/src/workers/parser/utils/simple-path.js new file mode 100644 index 000000000000..ed211b393a9a --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/utils/simple-path.js @@ -0,0 +1,161 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = createSimplePath; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function createSimplePath(ancestors) { + if (ancestors.length === 0) { + return null; + } // Slice the array because babel-types traverse may continue mutating + // the ancestors array in later traversal logic. + + + return new SimplePath(ancestors.slice()); +} + +/** + * Mimics @babel/traverse's NodePath API in a simpler fashion that isn't as + * heavy, but still allows the ease of passing paths around to process nested + * AST structures. + */ +class SimplePath { + constructor(ancestors, index = ancestors.length - 1) { + if (index < 0 || index >= ancestors.length) { + console.error(ancestors); + throw new Error("Created invalid path"); + } + + this._ancestors = ancestors; + this._ancestor = ancestors[index]; + this._index = index; + } + + get parentPath() { + let path = this._parentPath; + + if (path === undefined) { + if (this._index === 0) { + path = null; + } else { + path = new SimplePath(this._ancestors, this._index - 1); + } + + this._parentPath = path; + } + + return path; + } + + get parent() { + return this._ancestor.node; + } + + get node() { + const { + node, + key, + index + } = this._ancestor; + + if (typeof index === "number") { + return node[key][index]; + } + + return node[key]; + } + + set node(replacement) { + if (this.type !== "Identifier") { + throw new Error("Replacing anything other than leaf nodes is undefined behavior " + "in t.traverse()"); + } + + const { + node, + key, + index + } = this._ancestor; + + if (typeof index === "number") { + node[key][index] = replacement; + } else { + node[key] = replacement; + } + } + + get type() { + return this.node.type; + } + + get inList() { + return typeof this._ancestor.index === "number"; + } + + get containerIndex() { + const { + index + } = this._ancestor; + + if (typeof index !== "number") { + throw new Error("Cannot get index of non-array node"); + } + + return index; + } + + get depth() { + return this._index; + } + + replace(node) { + this.node = node; + } + + find(predicate) { + for (let path = this; path; path = path.parentPath) { + if (predicate(path)) { + return path; + } + } + + return null; + } + + findParent(predicate) { + if (!this.parentPath) { + throw new Error("Cannot use findParent on root path"); + } + + return this.parentPath.find(predicate); + } + + getSibling(offset) { + const { + node, + key, + index + } = this._ancestor; + + if (typeof index !== "number") { + throw new Error("Non-array nodes do not have siblings"); + } + + const container = node[key]; + const siblingIndex = index + offset; + + if (siblingIndex < 0 || siblingIndex >= container.length) { + return null; + } + + return new SimplePath(this._ancestors.slice(0, -1).concat([{ + node, + key, + index: siblingIndex + }])); + } + +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/validate.js b/devtools/client/debugger/new/src/workers/parser/validate.js new file mode 100644 index 000000000000..274c35e1bdf6 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/validate.js @@ -0,0 +1,20 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.hasSyntaxError = hasSyntaxError; + +var _ast = require("./utils/ast"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function hasSyntaxError(input) { + try { + (0, _ast.parseScript)(input); + return false; + } catch (e) { + return `${e.name} : ${e.message}`; + } +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/worker.js b/devtools/client/debugger/new/src/workers/parser/worker.js new file mode 100644 index 000000000000..907b84a9c7e8 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/parser/worker.js @@ -0,0 +1,54 @@ +"use strict"; + +var _getSymbols = require("./getSymbols"); + +var _ast = require("./utils/ast"); + +var _getScopes = require("./getScopes/index"); + +var _getScopes2 = _interopRequireDefault(_getScopes); + +var _sources = require("./sources"); + +var _findOutOfScopeLocations = require("./findOutOfScopeLocations"); + +var _findOutOfScopeLocations2 = _interopRequireDefault(_findOutOfScopeLocations); + +var _steps = require("./steps"); + +var _validate = require("./validate"); + +var _frameworks = require("./frameworks"); + +var _pausePoints = require("./pausePoints"); + +var _mapOriginalExpression = require("./mapOriginalExpression"); + +var _mapOriginalExpression2 = _interopRequireDefault(_mapOriginalExpression); + +var _devtoolsUtils = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-utils"]; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + workerHandler +} = _devtoolsUtils.workerUtils; +self.onmessage = workerHandler({ + findOutOfScopeLocations: _findOutOfScopeLocations2.default, + getSymbols: _getSymbols.getSymbols, + getScopes: _getScopes2.default, + clearSymbols: _getSymbols.clearSymbols, + clearScopes: _getScopes.clearScopes, + clearASTs: _ast.clearASTs, + hasSource: _sources.hasSource, + setSource: _sources.setSource, + clearSources: _sources.clearSources, + getNextStep: _steps.getNextStep, + hasSyntaxError: _validate.hasSyntaxError, + getFramework: _frameworks.getFramework, + getPausePoints: _pausePoints.getPausePoints, + mapOriginalExpression: _mapOriginalExpression2.default +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/pretty-print/index.js b/devtools/client/debugger/new/src/workers/pretty-print/index.js new file mode 100644 index 000000000000..916fe5ccc7dc --- /dev/null +++ b/devtools/client/debugger/new/src/workers/pretty-print/index.js @@ -0,0 +1,42 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.stop = exports.start = undefined; +exports.prettyPrint = prettyPrint; + +var _devtoolsUtils = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-utils"]; + +var _source = require("../../utils/source"); + +var _assert = require("../../utils/assert"); + +var _assert2 = _interopRequireDefault(_assert); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + WorkerDispatcher +} = _devtoolsUtils.workerUtils; +const dispatcher = new WorkerDispatcher(); +const start = exports.start = dispatcher.start.bind(dispatcher); +const stop = exports.stop = dispatcher.stop.bind(dispatcher); + +const _prettyPrint = dispatcher.task("prettyPrint"); + +async function prettyPrint({ + source, + url +}) { + const indent = 2; + (0, _assert2.default)((0, _source.isJavaScript)(source), "Can't prettify non-javascript files."); + return await _prettyPrint({ + url, + indent, + sourceText: source.text + }); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/pretty-print/moz.build b/devtools/client/debugger/new/src/workers/pretty-print/moz.build new file mode 100644 index 000000000000..d1f8b5992ded --- /dev/null +++ b/devtools/client/debugger/new/src/workers/pretty-print/moz.build @@ -0,0 +1,13 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'index.js', + 'worker.js', +) diff --git a/devtools/client/debugger/new/src/workers/pretty-print/worker.js b/devtools/client/debugger/new/src/workers/pretty-print/worker.js new file mode 100644 index 000000000000..005d36d8f373 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/pretty-print/worker.js @@ -0,0 +1,57 @@ +"use strict"; + +var _prettyFast = require("pretty-fast/index"); + +var _prettyFast2 = _interopRequireDefault(_prettyFast); + +var _devtoolsUtils = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-utils"]; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + workerHandler +} = _devtoolsUtils.workerUtils; + +function prettyPrint({ + url, + indent, + sourceText +}) { + const prettified = (0, _prettyFast2.default)(sourceText, { + url: url, + indent: " ".repeat(indent) + }); + return { + code: prettified.code, + mappings: invertMappings(prettified.map._mappings) + }; +} + +function invertMappings(mappings) { + return mappings._array.map(m => { + const mapping = { + generated: { + line: m.originalLine, + column: m.originalColumn + } + }; + + if (m.source) { + mapping.source = m.source; + mapping.original = { + line: m.generatedLine, + column: m.generatedColumn + }; + mapping.name = m.name; + } + + return mapping; + }); +} + +self.onmessage = workerHandler({ + prettyPrint +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/search/build-query.js b/devtools/client/debugger/new/src/workers/search/build-query.js new file mode 100644 index 000000000000..da0790124bab --- /dev/null +++ b/devtools/client/debugger/new/src/workers/search/build-query.js @@ -0,0 +1,84 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = buildQuery; + +var _escapeRegExp = require("devtools/client/shared/vendor/lodash").escapeRegExp; + +var _escapeRegExp2 = _interopRequireDefault(_escapeRegExp); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +/** + * Ignore doing outline matches for less than 3 whitespaces + * + * @memberof utils/source-search + * @static + */ +function ignoreWhiteSpace(str) { + return /^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str; +} + +function wholeMatch(query, wholeWord) { + if (query === "" || !wholeWord) { + return query; + } + + return `\\b${query}\\b`; +} + +function buildFlags(caseSensitive, isGlobal) { + if (caseSensitive && isGlobal) { + return "g"; + } + + if (!caseSensitive && isGlobal) { + return "gi"; + } + + if (!caseSensitive && !isGlobal) { + return "i"; + } + + return; +} + +function buildQuery(originalQuery, modifiers, { + isGlobal = false, + ignoreSpaces = false +}) { + const { + caseSensitive, + regexMatch, + wholeWord + } = modifiers; + + if (originalQuery === "") { + return new RegExp(originalQuery); + } + + let query = originalQuery; + + if (ignoreSpaces) { + query = ignoreWhiteSpace(query); + } + + if (!regexMatch) { + query = (0, _escapeRegExp2.default)(query); + } + + query = wholeMatch(query, wholeWord); + const flags = buildFlags(caseSensitive, isGlobal); + + if (flags) { + return new RegExp(query, flags); + } + + return new RegExp(query); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/search/get-matches.js b/devtools/client/debugger/new/src/workers/search/get-matches.js new file mode 100644 index 000000000000..5340e1d8e475 --- /dev/null +++ b/devtools/client/debugger/new/src/workers/search/get-matches.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = getMatches; + +var _buildQuery = require("./build-query"); + +var _buildQuery2 = _interopRequireDefault(_buildQuery); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getMatches(query, text, modifiers) { + if (!query || !text || !modifiers) { + return []; + } + + const regexQuery = (0, _buildQuery2.default)(query, modifiers, { + isGlobal: true + }); + const matchedLocations = []; + const lines = text.split("\n"); + + for (let i = 0; i < lines.length; i++) { + let singleMatch; + const line = lines[i]; + + while ((singleMatch = regexQuery.exec(line)) !== null) { + matchedLocations.push({ + line: i, + ch: singleMatch.index + }); + } + } + + return matchedLocations; +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/search/index.js b/devtools/client/debugger/new/src/workers/search/index.js new file mode 100644 index 000000000000..e3c9b0c5bbaa --- /dev/null +++ b/devtools/client/debugger/new/src/workers/search/index.js @@ -0,0 +1,20 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findSourceMatches = exports.getMatches = exports.stop = exports.start = undefined; + +var _devtoolsUtils = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-utils"]; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + WorkerDispatcher +} = _devtoolsUtils.workerUtils; +const dispatcher = new WorkerDispatcher(); +const start = exports.start = dispatcher.start.bind(dispatcher); +const stop = exports.stop = dispatcher.stop.bind(dispatcher); +const getMatches = exports.getMatches = dispatcher.task("getMatches"); +const findSourceMatches = exports.findSourceMatches = dispatcher.task("findSourceMatches"); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/search/moz.build b/devtools/client/debugger/new/src/workers/search/moz.build new file mode 100644 index 000000000000..07f72e9c9ecd --- /dev/null +++ b/devtools/client/debugger/new/src/workers/search/moz.build @@ -0,0 +1,16 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += [ + +] + +DevToolsModules( + 'build-query.js', + 'get-matches.js', + 'index.js', + 'project-search.js', + 'worker.js', +) diff --git a/devtools/client/debugger/new/src/workers/search/project-search.js b/devtools/client/debugger/new/src/workers/search/project-search.js new file mode 100644 index 000000000000..74ea648bb31a --- /dev/null +++ b/devtools/client/debugger/new/src/workers/search/project-search.js @@ -0,0 +1,43 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findSourceMatches = findSourceMatches; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +// Maybe reuse file search's functions? +function findSourceMatches(source, queryText) { + const { + id, + loadedState, + text + } = source; + + if (loadedState != "loaded" || !text || queryText == "") { + return []; + } + + const lines = text.split("\n"); + let result = undefined; + const query = new RegExp(queryText, "g"); + const matches = lines.map((_text, line) => { + const indices = []; + + while (result = query.exec(_text)) { + indices.push({ + sourceId: id, + line: line + 1, + column: result.index, + match: result[0], + value: _text, + text: result.input + }); + } + + return indices; + }).filter(_matches => _matches.length > 0); + return [].concat(...matches); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/search/worker.js b/devtools/client/debugger/new/src/workers/search/worker.js new file mode 100644 index 000000000000..b56a27b86d8a --- /dev/null +++ b/devtools/client/debugger/new/src/workers/search/worker.js @@ -0,0 +1,22 @@ +"use strict"; + +var _getMatches = require("./get-matches"); + +var _getMatches2 = _interopRequireDefault(_getMatches); + +var _projectSearch = require("./project-search"); + +var _devtoolsUtils = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-utils"]; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +const { + workerHandler +} = _devtoolsUtils.workerUtils; +self.onmessage = workerHandler({ + getMatches: _getMatches2.default, + findSourceMatches: _projectSearch.findSourceMatches +}); \ No newline at end of file diff --git a/devtools/client/shared/components/reps/reps.js b/devtools/client/shared/components/reps/reps.js index adf20b2e4b63..99469d029690 100644 --- a/devtools/client/shared/components/reps/reps.js +++ b/devtools/client/shared/components/reps/reps.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap /******/ __webpack_require__.p = "/assets/build"; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 3655); +/******/ return __webpack_require__(__webpack_require__.s = 3730); /******/ }) /************************************************************************/ /******/ ({ @@ -6886,6 +6886,14 @@ function reducer(state = {}, action) { module.exports = reducer; +/***/ }), + +/***/ 3730: +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(3655); + + /***/ }) /******/ }); diff --git a/devtools/client/shared/source-map/index.js b/devtools/client/shared/source-map/index.js index 0be59f49ea10..5bf05fe54410 100644 --- a/devtools/client/shared/source-map/index.js +++ b/devtools/client/shared/source-map/index.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap /******/ __webpack_require__.p = "/assets/build"; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 3646); +/******/ return __webpack_require__(__webpack_require__.s = 3727); /******/ }) /************************************************************************/ /******/ ({ @@ -769,6 +769,14 @@ module.exports = { streamingWorkerHandler }; +/***/ }), + +/***/ 3727: +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(3646); + + /***/ }) /******/ }); diff --git a/devtools/client/shared/source-map/worker.js b/devtools/client/shared/source-map/worker.js index efe74f18095a..3cdb8a5dfd8b 100644 --- a/devtools/client/shared/source-map/worker.js +++ b/devtools/client/shared/source-map/worker.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap /******/ __webpack_require__.p = "/assets/build"; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 3709); +/******/ return __webpack_require__(__webpack_require__.s = 3726); /******/ }) /************************************************************************/ /******/ ({ @@ -4408,6 +4408,14 @@ class WasmRemap { exports.WasmRemap = WasmRemap; +/***/ }), + +/***/ 3726: +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(3709); + + /***/ }) /******/ });