diff --git a/AUTHORS b/AUTHORS index fb49ee06d1a..b4a7b354820 100644 --- a/AUTHORS +++ b/AUTHORS @@ -34,3 +34,4 @@ Karntino Areros Luke Swiderski Anthony Xie Krishnal Ciccolella +Will Hernandez‬ diff --git a/DEPS b/DEPS index 0b5fb71608f..83d507e2c58 100644 --- a/DEPS +++ b/DEPS @@ -6,13 +6,13 @@ use_relative_paths = True vars = { 'build_url': 'https://chromium.googlesource.com/chromium/src/build.git', - 'build_revision': '0401de79c7264d72452bc01a4a054a44f3861c31', + 'build_revision': 'e3b5e06bae36be022a637de9ee5589cd87f4a094', 'buildtools_url': 'https://chromium.googlesource.com/chromium/src/buildtools.git', 'buildtools_revision': '98881a1297863de584fad20fb671e8c44ad1a7d0', 'depot_tools_url': 'https://chromium.googlesource.com/chromium/tools/depot_tools.git', - 'depot_tools_revision': '77cd4b459b10e96b4023da12e4ca280ef3d0489a', + 'depot_tools_revision': '9396c2b0646a73f3cbe53b06424c53bddb8064d3', 'inspector_protocol_url': 'https://chromium.googlesource.com/deps/inspector_protocol', 'inspector_protocol_revision': '351a2b717e7cd0e59c3d81505c1a803673667dac', @@ -27,11 +27,11 @@ vars = { # Chromium build number for unit tests. It should be regularly updated to # the content of https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/LAST_CHANGE - 'chromium_linux': '821100', + 'chromium_linux': '823001', # the content of https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win_x64/LAST_CHANGE - 'chromium_win': '821083', + 'chromium_win': '822999', # the content of https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/LAST_CHANGE - 'chromium_mac': '821071', + 'chromium_mac': '822999', } # Only these hosts are allowed for dependencies in this DEPS file. diff --git a/all_devtools_files.gni b/all_devtools_files.gni index a0f5b507d73..308fb2a56c9 100644 --- a/all_devtools_files.gni +++ b/all_devtools_files.gni @@ -70,7 +70,7 @@ all_devtools_files = [ "front_end/components/imagePreview.css", "front_end/components/jsUtils.css", "front_end/components/module.json", - "front_end/console_counters/errorWarningCounter.css", + "front_end/console_counters/warningErrorCounter.css", "front_end/console_counters/module.json", "front_end/console_test_runner/console_test_runner.js", "front_end/console_test_runner/module.json", @@ -254,6 +254,8 @@ all_devtools_files = [ "front_end/issues/descriptions/cspEvalViolation.md", "front_end/issues/descriptions/cspInlineViolation.md", "front_end/issues/descriptions/cspURLViolation.md", + "front_end/issues/descriptions/cspTrustedTypesSinkViolation.md", + "front_end/issues/descriptions/cspTrustedTypesPolicyViolation.md", "front_end/issues/descriptions/mixedContent.md", "front_end/issues/issuesPane.css", "front_end/issues/issuesTree.css", diff --git a/all_devtools_modules.gni b/all_devtools_modules.gni index ead742ff9e2..b2d0dc43fdb 100644 --- a/all_devtools_modules.gni +++ b/all_devtools_modules.gni @@ -76,6 +76,7 @@ all_typescript_module_sources = [ "common/Runnable.js", "common/SegmentedRange.js", "common/Settings.js", + "common/SimpleHistoryManager.js", "common/StringOutputStream.js", "common/TextDictionary.js", "common/Throttler.js", @@ -133,10 +134,6 @@ all_typescript_module_sources = [ # dirac - end "dom_extension/DOMExtension.js", "elements/Adorner.js", - "elements/CSSAngle.js", - "elements/CSSAngleRegex.js", - "elements/CSSAngleUtils.js", - "elements/CSSAngle_bridge.js", "elements/CSSPropertyIconResolver.js", "elements/ClassesPaneWidget.js", "elements/ColorSwatchPopoverIcon.js", @@ -232,6 +229,10 @@ all_typescript_module_sources = [ "i18n/i18nImpl.js", "inline_editor/BezierEditor.js", "inline_editor/BezierUI.js", + "inline_editor/CSSAngle.js", + "inline_editor/CSSAngleRegex.js", + "inline_editor/CSSAngleUtils.js", + "inline_editor/CSSAngle_bridge.js", "inline_editor/CSSShadowEditor.js", "inline_editor/CSSShadowModel.js", "inline_editor/CSSVarSwatch.js", @@ -267,6 +268,7 @@ all_typescript_module_sources = [ "lighthouse/LighthouseProtocolService.js", "lighthouse/LighthouseReportRenderer.js", "lighthouse/LighthouseReportSelector.js", + "lighthouse/LighthouseReporterTypes.js", "lighthouse/LighthouseStartView.js", "lighthouse/LighthouseStatusView.js", "lighthouse/RadioSetting.js", @@ -354,6 +356,7 @@ all_typescript_module_sources = [ "platform/UIString.js", "platform/array-utilities.js", "platform/date-utilities.js", + "platform/map-utilities.js", "platform/number-utilities.js", "platform/set-utilities.js", "platform/string-utilities.js", @@ -521,7 +524,6 @@ all_typescript_module_sources = [ "sources/ScriptFormatterEditorAction.js", "sources/ScriptOriginPlugin.js", "sources/SearchSourcesView.js", - "sources/SimpleHistoryManager.js", "sources/SnippetsPlugin.js", "sources/SourceMapNamesResolver.js", "sources/SourcesNavigator.js", @@ -599,7 +601,10 @@ all_typescript_module_sources = [ "third_party/marked/package/lib/marked.esm.js", "third_party/puppeteer/package/lib/esm/puppeteer/api-docs-entry.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/Accessibility.js", + "third_party/puppeteer/package/lib/esm/puppeteer/common/AriaQueryHandler.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/Browser.js", + "third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js", + "third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserWebSocketTransport.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/Connection.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectionTransport.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/ConsoleMessage.js", @@ -624,6 +629,7 @@ all_typescript_module_sources = [ "third_party/puppeteer/package/lib/esm/puppeteer/common/NetworkManager.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/Page.js", + "third_party/puppeteer/package/lib/esm/puppeteer/common/Product.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/Puppeteer.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/PuppeteerViewport.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/QueryHandler.js", @@ -632,20 +638,25 @@ all_typescript_module_sources = [ "third_party/puppeteer/package/lib/esm/puppeteer/common/TimeoutSettings.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/Tracing.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/USKeyboardLayout.js", - "third_party/puppeteer/package/lib/esm/puppeteer/common/WebSocketTransport.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/WebWorker.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/assert.js", + "third_party/puppeteer/package/lib/esm/puppeteer/common/fetch.js", "third_party/puppeteer/package/lib/esm/puppeteer/common/helper.js", "third_party/puppeteer/package/lib/esm/puppeteer/environment.js", - "third_party/puppeteer/package/lib/esm/puppeteer/index-core.js", - "third_party/puppeteer/package/lib/esm/puppeteer/index.js", - "third_party/puppeteer/package/lib/esm/puppeteer/initialize.js", + "third_party/puppeteer/package/lib/esm/puppeteer/initialize-node.js", + "third_party/puppeteer/package/lib/esm/puppeteer/initialize-web.js", + "third_party/puppeteer/package/lib/esm/puppeteer/node-puppeteer-core.js", + "third_party/puppeteer/package/lib/esm/puppeteer/node.js", "third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserFetcher.js", "third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserRunner.js", "third_party/puppeteer/package/lib/esm/puppeteer/node/LaunchOptions.js", "third_party/puppeteer/package/lib/esm/puppeteer/node/Launcher.js", + "third_party/puppeteer/package/lib/esm/puppeteer/node/NodeWebSocketTransport.js", "third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js", + "third_party/puppeteer/package/lib/esm/puppeteer/node/Puppeteer.js", + "third_party/puppeteer/package/lib/esm/puppeteer/node/install.js", "third_party/puppeteer/package/lib/esm/puppeteer/revisions.js", + "third_party/puppeteer/package/lib/esm/puppeteer/web.js", "third_party/puppeteer/package/lib/esm/vendor/mitt/src/index.js", "third_party/wasmparser/package/dist/esm/WasmDis.js", "third_party/wasmparser/package/dist/esm/WasmParser.js", diff --git a/devtools_grd_files.gni b/devtools_grd_files.gni index c6ede852415..33fc0b8aff3 100644 --- a/devtools_grd_files.gni +++ b/devtools_grd_files.gni @@ -30,6 +30,13 @@ grd_files_release_sources = [ "front_end/Images/cssoverview_icons_2x.png", "front_end/Images/elements_panel_icon.svg", "front_end/Images/errorWave.svg", + "front_end/Images/flex-align-content-center-icon.svg", + "front_end/Images/flex-align-content-end-icon.svg", + "front_end/Images/flex-align-content-space-around-icon.svg", + "front_end/Images/flex-align-content-space-between-icon.svg", + "front_end/Images/flex-align-content-space-evenly-icon.svg", + "front_end/Images/flex-align-content-start-icon.svg", + "front_end/Images/flex-align-content-stretch-icon.svg", "front_end/Images/flex-direction-icon.svg", "front_end/Images/ic_info_black_18dp.svg", "front_end/Images/ic_page_next_16x16_icon.svg", @@ -431,6 +438,7 @@ grd_files_debug_sources = [ "front_end/common/Runnable.js", "front_end/common/SegmentedRange.js", "front_end/common/Settings.js", + "front_end/common/SimpleHistoryManager.js", "front_end/common/StringOutputStream.js", "front_end/common/TextDictionary.js", "front_end/common/Throttler.js", @@ -488,10 +496,6 @@ grd_files_debug_sources = [ # dirac end "front_end/dom_extension/DOMExtension.js", "front_end/elements/Adorner.js", - "front_end/elements/CSSAngle.js", - "front_end/elements/CSSAngleRegex.js", - "front_end/elements/CSSAngleUtils.js", - "front_end/elements/CSSAngle_bridge.js", "front_end/elements/CSSPropertyIconResolver.js", "front_end/elements/ClassesPaneWidget.js", "front_end/elements/ColorSwatchPopoverIcon.js", @@ -587,6 +591,10 @@ grd_files_debug_sources = [ "front_end/i18n/i18nImpl.js", "front_end/inline_editor/BezierEditor.js", "front_end/inline_editor/BezierUI.js", + "front_end/inline_editor/CSSAngle.js", + "front_end/inline_editor/CSSAngleRegex.js", + "front_end/inline_editor/CSSAngleUtils.js", + "front_end/inline_editor/CSSAngle_bridge.js", "front_end/inline_editor/CSSShadowEditor.js", "front_end/inline_editor/CSSShadowModel.js", "front_end/inline_editor/CSSVarSwatch.js", @@ -622,6 +630,7 @@ grd_files_debug_sources = [ "front_end/lighthouse/LighthouseProtocolService.js", "front_end/lighthouse/LighthouseReportRenderer.js", "front_end/lighthouse/LighthouseReportSelector.js", + "front_end/lighthouse/LighthouseReporterTypes.js", "front_end/lighthouse/LighthouseStartView.js", "front_end/lighthouse/LighthouseStatusView.js", "front_end/lighthouse/RadioSetting.js", @@ -709,6 +718,7 @@ grd_files_debug_sources = [ "front_end/platform/UIString.js", "front_end/platform/array-utilities.js", "front_end/platform/date-utilities.js", + "front_end/platform/map-utilities.js", "front_end/platform/number-utilities.js", "front_end/platform/set-utilities.js", "front_end/platform/string-utilities.js", @@ -876,7 +886,6 @@ grd_files_debug_sources = [ "front_end/sources/ScriptFormatterEditorAction.js", "front_end/sources/ScriptOriginPlugin.js", "front_end/sources/SearchSourcesView.js", - "front_end/sources/SimpleHistoryManager.js", "front_end/sources/SnippetsPlugin.js", "front_end/sources/SourceMapNamesResolver.js", "front_end/sources/SourcesNavigator.js", @@ -957,7 +966,10 @@ grd_files_debug_sources = [ "front_end/third_party/marked/package/lib/marked.esm.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/api-docs-entry.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Accessibility.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/AriaQueryHandler.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Browser.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserWebSocketTransport.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Connection.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectionTransport.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConsoleMessage.js", @@ -982,6 +994,7 @@ grd_files_debug_sources = [ "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/NetworkManager.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Page.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Product.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Puppeteer.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/PuppeteerViewport.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/QueryHandler.js", @@ -990,20 +1003,25 @@ grd_files_debug_sources = [ "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/TimeoutSettings.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/Tracing.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/USKeyboardLayout.js", - "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/WebSocketTransport.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/WebWorker.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/assert.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/fetch.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/helper.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/environment.js", - "front_end/third_party/puppeteer/package/lib/esm/puppeteer/index-core.js", - "front_end/third_party/puppeteer/package/lib/esm/puppeteer/index.js", - "front_end/third_party/puppeteer/package/lib/esm/puppeteer/initialize.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/initialize-node.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/initialize-web.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node-puppeteer-core.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserFetcher.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserRunner.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/LaunchOptions.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/Launcher.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/NodeWebSocketTransport.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/Puppeteer.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/install.js", "front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js", + "front_end/third_party/puppeteer/package/lib/esm/puppeteer/web.js", "front_end/third_party/puppeteer/package/lib/esm/vendor/mitt/src/index.js", "front_end/third_party/wasmparser/package/dist/esm/WasmDis.js", "front_end/third_party/wasmparser/package/dist/esm/WasmParser.js", diff --git a/devtools_image_files.gni b/devtools_image_files.gni index 65c369f70c5..5b234b7049e 100644 --- a/devtools_image_files.gni +++ b/devtools_image_files.gni @@ -25,6 +25,13 @@ devtools_image_files = [ "elements_panel_icon.svg", "errorWave.svg", "flex-direction-icon.svg", + "flex-align-content-center-icon.svg", + "flex-align-content-start-icon.svg", + "flex-align-content-end-icon.svg", + "flex-align-content-space-around-icon.svg", + "flex-align-content-space-between-icon.svg", + "flex-align-content-space-evenly-icon.svg", + "flex-align-content-stretch-icon.svg", "ic_info_black_18dp.svg", "ic_page_next_16x16_icon.svg", "ic_page_prev_16x16_icon.svg", diff --git a/docs/workflows.md b/docs/workflows.md index 2fae15a739d..fb95e91efb2 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -55,10 +55,12 @@ This works with Chromium 79 or later. /chrome --custom-devtools-frontend=file://$(realpath out/Default/resources/inspector) ``` -Note that `(realpath out/Default/resources/inspector)` expands to the absolute path to build artifacts for DevTools frontend. +Note that `$(realpath out/Default/resources/inspector)` expands to the absolute path to build artifacts for DevTools frontend. Open DevTools via F12 on Windows/Linux or Cmd+Option+I on Mac. +If you get errors along the line of `Uncaught TypeError: Cannot read property 'setInspectedTabId'` you probably specified an incorrect path - the path has to be absolute. On Mac and Linux, the file url will start with __three__ slashes: `file:///Users/...`. + Tip: You can inspect DevTools with DevTools by undocking DevTools and then opening a second instance of DevTools (F12 on Windows/Linux, Cmd+Option+I on Mac). ##### Running from remote URL diff --git a/front_end/Images/flex-align-content-center-icon.svg b/front_end/Images/flex-align-content-center-icon.svg new file mode 100644 index 00000000000..922e419de2b --- /dev/null +++ b/front_end/Images/flex-align-content-center-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/flex-align-content-end-icon.svg b/front_end/Images/flex-align-content-end-icon.svg new file mode 100644 index 00000000000..5432b002b43 --- /dev/null +++ b/front_end/Images/flex-align-content-end-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/flex-align-content-space-around-icon.svg b/front_end/Images/flex-align-content-space-around-icon.svg new file mode 100644 index 00000000000..e57c8b52a15 --- /dev/null +++ b/front_end/Images/flex-align-content-space-around-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/flex-align-content-space-between-icon.svg b/front_end/Images/flex-align-content-space-between-icon.svg new file mode 100644 index 00000000000..d9b6d0fd2a0 --- /dev/null +++ b/front_end/Images/flex-align-content-space-between-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/flex-align-content-space-evenly-icon.svg b/front_end/Images/flex-align-content-space-evenly-icon.svg new file mode 100644 index 00000000000..b9cfddff271 --- /dev/null +++ b/front_end/Images/flex-align-content-space-evenly-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/flex-align-content-start-icon.svg b/front_end/Images/flex-align-content-start-icon.svg new file mode 100644 index 00000000000..bded6abdd68 --- /dev/null +++ b/front_end/Images/flex-align-content-start-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/flex-align-content-stretch-icon.svg b/front_end/Images/flex-align-content-stretch-icon.svg new file mode 100644 index 00000000000..e0067f7b053 --- /dev/null +++ b/front_end/Images/flex-align-content-stretch-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/src/flex-align-content-center-icon.svg b/front_end/Images/src/flex-align-content-center-icon.svg new file mode 100644 index 00000000000..265336cff9b --- /dev/null +++ b/front_end/Images/src/flex-align-content-center-icon.svg @@ -0,0 +1,70 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/front_end/Images/src/flex-align-content-end-icon.svg b/front_end/Images/src/flex-align-content-end-icon.svg new file mode 100644 index 00000000000..0acfecedff0 --- /dev/null +++ b/front_end/Images/src/flex-align-content-end-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/src/flex-align-content-space-around-icon.svg b/front_end/Images/src/flex-align-content-space-around-icon.svg new file mode 100644 index 00000000000..e57c8b52a15 --- /dev/null +++ b/front_end/Images/src/flex-align-content-space-around-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/src/flex-align-content-space-between-icon.svg b/front_end/Images/src/flex-align-content-space-between-icon.svg new file mode 100644 index 00000000000..0c5c03a8faf --- /dev/null +++ b/front_end/Images/src/flex-align-content-space-between-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/src/flex-align-content-space-evenly-icon.svg b/front_end/Images/src/flex-align-content-space-evenly-icon.svg new file mode 100644 index 00000000000..b9cfddff271 --- /dev/null +++ b/front_end/Images/src/flex-align-content-space-evenly-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front_end/Images/src/flex-align-content-start-icon.svg b/front_end/Images/src/flex-align-content-start-icon.svg new file mode 100644 index 00000000000..f401611a45b --- /dev/null +++ b/front_end/Images/src/flex-align-content-start-icon.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/front_end/Images/src/flex-align-content-stretch-icon.svg b/front_end/Images/src/flex-align-content-stretch-icon.svg new file mode 100644 index 00000000000..ee3820bb997 --- /dev/null +++ b/front_end/Images/src/flex-align-content-stretch-icon.svg @@ -0,0 +1,53 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/front_end/Images/src/optimize_svg.hashes b/front_end/Images/src/optimize_svg.hashes index ea936a5680b..47e418d1e25 100644 --- a/front_end/Images/src/optimize_svg.hashes +++ b/front_end/Images/src/optimize_svg.hashes @@ -1,12 +1,17 @@ { + "flex-align-content-space-around-icon.svg": "ecf68a0514d0bcf578fb77e75290e533", + "flex-align-content-end-icon.svg": "c6efb40815035fe28454fc9c426b9f6e", "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", "breaking_change_icon.svg": "8106678156bfc2a3d88b36972ebc12c0", "securityIcons.svg": "27676f7c1f1542659c7c49a8052259dc", "largeIcons.svg": "61874ded98adb22e3f958e28ecbb674c", + "flex-align-content-space-evenly-icon.svg": "35f5aae14e7c29c4cc4ca6684f8ed75d", "elements_panel_icon.svg": "6cee6a38a17e8571ce36cf71f30108f2", "refresh_12x12_icon.svg": "d07eaba74a308fb03fa04b1c1965dc72", + "flex-align-content-stretch-icon.svg": "becd714181ae4aaa1ec5e2a19fe19427", "mediumIcons.svg": "d3ea5f402107bd3a73950cc672957adc", + "flex-align-content-center-icon.svg": "182ac1dd37996dd901efe1023f79d19d", "chevrons.svg": "79b4b527771e30b6388ce664077b3409", "accelerometer-back.svg": "342973eb940ef43b409b28c2c6b0d520", "link_icon.svg": "165ad815ffdf0da89c04ac104389f54e", @@ -19,6 +24,8 @@ "accelerometer-front.svg": "a4dcdac47131aa923346c15e01bc644a", "smallIcons.svg": "10719c45b1004a4c4dd236e590deded1", "treeoutlineTriangles.svg": "aa6c8f8df9ae7c50f14397131808e764", + "flex-align-content-space-between-icon.svg": "0444b31ebc14c4094dbf75bbff012f7f", "ic_undo_16x16_icon.svg": "948e32c1878baa9d3717ff8377ab1feb", + "flex-align-content-start-icon.svg": "cea3050540097d6661f6bf4ad98d3407", "lighthouse_logo.svg": "b889aaf8631e71e3427eb96d3433e319" } \ No newline at end of file diff --git a/front_end/Tests.js b/front_end/Tests.js index cef3b768181..85f8c913478 100644 --- a/front_end/Tests.js +++ b/front_end/Tests.js @@ -932,7 +932,7 @@ MobileThrottling.networkPresets[1], [ 'online event: online = true', - 'connection change event: type = cellular; downlinkMax = 0.390625; effectiveType = 2g' + 'connection change event: type = cellular; downlinkMax = 0.3814697265625; effectiveType = 2g' ], step3); } @@ -940,7 +940,7 @@ function step3() { testPreset( MobileThrottling.networkPresets[0], - ['connection change event: type = cellular; downlinkMax = 1.4400000000000002; effectiveType = 3g'], + ['connection change event: type = cellular; downlinkMax = 1.373291015625; effectiveType = 3g'], test.releaseControl.bind(test)); } }; diff --git a/front_end/animation/AnimationGroupPreviewUI.js b/front_end/animation/AnimationGroupPreviewUI.js index 0dcb1bea990..97facd6c7a5 100644 --- a/front_end/animation/AnimationGroupPreviewUI.js +++ b/front_end/animation/AnimationGroupPreviewUI.js @@ -4,6 +4,7 @@ // @ts-nocheck // TODO(crbug.com/1011811): Enable TypeScript compiler checks +import * as UI from '../ui/ui.js'; import {AnimationGroup} from './AnimationModel.js'; // eslint-disable-line no-unused-vars import {AnimationUI} from './AnimationUI.js'; @@ -22,7 +23,7 @@ export class AnimationGroupPreviewUI { this._removeButton = this.element.createChild('div', 'animation-remove-button'); this._removeButton.textContent = '\u2715'; this._replayOverlayElement = this.element.createChild('div', 'animation-buffer-preview-animation'); - this._svg = this.element.createSVGChild('svg'); + this._svg = UI.UIUtils.createSVGChild(this.element, 'svg'); this._svg.setAttribute('width', '100%'); this._svg.setAttribute('preserveAspectRatio', 'none'); this._svg.setAttribute('height', '100%'); @@ -69,7 +70,7 @@ export class AnimationGroupPreviewUI { const timeToPixelRatio = 100 / Math.max(this._groupDuration(), 750); for (let i = 0; i < numberOfAnimations; i++) { const effect = this._model.animations()[i].source(); - const line = this._svg.createSVGChild('line'); + const line = UI.UIUtils.createSVGChild(this._svg, 'line'); line.setAttribute('x1', effect.delay() * timeToPixelRatio); line.setAttribute('x2', (effect.delay() + effect.duration()) * timeToPixelRatio); const y = Math.floor(this._viewBoxHeight / Math.max(6, numberOfAnimations) * i + 1); diff --git a/front_end/animation/AnimationTimeline.js b/front_end/animation/AnimationTimeline.js index 29b93f86db2..d81cb7914cd 100644 --- a/front_end/animation/AnimationTimeline.js +++ b/front_end/animation/AnimationTimeline.js @@ -29,7 +29,7 @@ export class AnimationTimeline extends UI.Widget.VBox { this.registerRequiredCSS('animation/animationTimeline.css'); this.element.classList.add('animations-timeline'); - this._grid = this.contentElement.createSVGChild('svg', 'animation-timeline-grid'); + this._grid = UI.UIUtils.createSVGChild(this.contentElement, 'svg', 'animation-timeline-grid'); this._playbackRate = 1; this._allPaused = false; @@ -690,7 +690,7 @@ export class AnimationTimeline extends UI.Widget.VBox { this._grid.removeChildren(); let lastDraw = undefined; for (let time = 0; time < this.duration(); time += gridSize) { - const line = this._grid.createSVGChild('rect', 'animation-timeline-grid-line'); + const line = UI.UIUtils.createSVGChild(this._grid, 'rect', 'animation-timeline-grid-line'); line.setAttribute('x', (time * this.pixelMsRatio() + 10).toString()); line.setAttribute('y', '23'); line.setAttribute('height', '100%'); @@ -700,7 +700,7 @@ export class AnimationTimeline extends UI.Widget.VBox { const gridWidth = time * this.pixelMsRatio(); if (lastDraw === undefined || gridWidth - lastDraw > 50) { lastDraw = gridWidth; - const label = this._grid.createSVGChild('text', 'animation-timeline-grid-label'); + const label = UI.UIUtils.createSVGChild(this._grid, 'text', 'animation-timeline-grid-label'); label.textContent = Number.millisToString(time); label.setAttribute('x', (gridWidth + 10).toString()); label.setAttribute('y', '16'); diff --git a/front_end/animation/AnimationUI.js b/front_end/animation/AnimationUI.js index 41163bd266b..0401571bce2 100644 --- a/front_end/animation/AnimationUI.js +++ b/front_end/animation/AnimationUI.js @@ -1,8 +1,6 @@ // Copyright (c) 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks import * as Common from '../common/common.js'; import * as InlineEditor from '../inline_editor/inline_editor.js'; @@ -26,25 +24,27 @@ export class AnimationUI { this._timeline = timeline; this._parentElement = parentElement; - if (this._animation.source().keyframesRule()) { - this._keyframes = this._animation.source().keyframesRule().keyframes(); + const keyframesRule = this._animation.source().keyframesRule(); + if (keyframesRule) { + this._keyframes = keyframesRule.keyframes(); } - this._nameElement = parentElement.createChild('div', 'animation-name'); + /** @type {!HTMLElement} */ + this._nameElement = /** @type {!HTMLElement} */ (parentElement.createChild('div', 'animation-name')); this._nameElement.textContent = this._animation.name(); - this._svg = parentElement.createSVGChild('svg', 'animation-ui'); - this._svg.setAttribute('height', Options.AnimationSVGHeight); - this._svg.style.marginLeft = '-' + Options.AnimationMargin + 'px'; + this._svg = UI.UIUtils.createSVGChild(parentElement, 'svg', 'animation-ui'); + this._svg.setAttribute('height', Options.AnimationSVGHeight.toString()); + /** @type {!HTMLElement} */ (this._svg).style.marginLeft = '-' + Options.AnimationMargin + 'px'; this._svg.addEventListener('contextmenu', this._onContextMenu.bind(this)); - this._activeIntervalGroup = this._svg.createSVGChild('g'); + this._activeIntervalGroup = UI.UIUtils.createSVGChild(this._svg, 'g'); UI.UIUtils.installDragHandle( this._activeIntervalGroup, this._mouseDown.bind(this, Events.AnimationDrag, null), this._mouseMove.bind(this), this._mouseUp.bind(this), '-webkit-grabbing', '-webkit-grab'); - Animation.AnimationUI.installDragHandleKeyboard( - this._activeIntervalGroup, this._keydownMove.bind(this, Animation.AnimationUI.Events.AnimationDrag, null)); + AnimationUI.installDragHandleKeyboard( + this._activeIntervalGroup, this._keydownMove.bind(this, Events.AnimationDrag, null)); - /** @type {!Array.<{group: ?Element, animationLine: ?Element, keyframePoints: !Object., keyframeRender: !Object.}>} */ + /** @type {!Array.<{group: ?HTMLElement, animationLine: ?HTMLElement, keyframePoints: !Object., keyframeRender: !Object.}>} */ this._cachedElements = []; this._movementInMs = 0; @@ -57,14 +57,20 @@ export class AnimationUI { * @return {string} */ static Color(animation) { - const names = Object.keys(Colors); - const color = Colors[names[String.hashCode(animation.name() || animation.id()) % names.length]]; - return color.asString(Common.Color.Format.RGB); + const names = Array.from(Colors.keys()); + const hashCode = String.hashCode(animation.name() || animation.id()); + const cappedHashCode = hashCode % names.length; + const colorName = names[cappedHashCode]; + const color = Colors.get(colorName); + if (!color) { + throw new Error('Unable to locate color'); + } + return color.asString(Common.Color.Format.RGB) || ''; } /** * @param {!Element} element - * @param {function(...?)} elementDrag + * @param {function(!Event):void} elementDrag */ static installDragHandleKeyboard(element, elementDrag) { element.addEventListener('keydown', elementDrag, false); @@ -85,51 +91,55 @@ export class AnimationUI { } /** - * @param {!Element} parentElement + * @param {!HTMLElement} parentElement * @param {string} className */ _createLine(parentElement, className) { - const line = parentElement.createSVGChild('line', className); - line.setAttribute('x1', Options.AnimationMargin); - line.setAttribute('y1', Options.AnimationHeight); - line.setAttribute('y2', Options.AnimationHeight); - line.style.stroke = this._color; + const line = UI.UIUtils.createSVGChild(parentElement, 'line', className); + line.setAttribute('x1', Options.AnimationMargin.toString()); + line.setAttribute('y1', Options.AnimationHeight.toString()); + line.setAttribute('y2', Options.AnimationHeight.toString()); + /** @type {!HTMLElement} */ (line).style.stroke = this._color; return line; } /** * @param {number} iteration - * @param {!Element} parentElement + * @param {!HTMLElement} parentElement */ _drawAnimationLine(iteration, parentElement) { const cache = this._cachedElements[iteration]; if (!cache.animationLine) { - cache.animationLine = this._createLine(parentElement, 'animation-line'); + cache.animationLine = /** @type {!HTMLElement} */ (this._createLine(parentElement, 'animation-line')); + } + if (!cache.animationLine) { + return; } + cache.animationLine.setAttribute( 'x2', (this._duration() * this._timeline.pixelMsRatio() + Options.AnimationMargin).toFixed(2)); } /** - * @param {!Element} parentElement + * @param {!HTMLElement} parentElement */ _drawDelayLine(parentElement) { - if (!this._delayLine) { + if (!this._delayLine || !this._endDelayLine) { this._delayLine = this._createLine(parentElement, 'animation-delay-line'); this._endDelayLine = this._createLine(parentElement, 'animation-delay-line'); } const fill = this._animation.source().fill(); this._delayLine.classList.toggle('animation-fill', fill === 'backwards' || fill === 'both'); const margin = Options.AnimationMargin; - this._delayLine.setAttribute('x1', margin); + this._delayLine.setAttribute('x1', margin.toString()); this._delayLine.setAttribute('x2', (this._delay() * this._timeline.pixelMsRatio() + margin).toFixed(2)); const forwardsFill = fill === 'forwards' || fill === 'both'; this._endDelayLine.classList.toggle('animation-fill', forwardsFill); const leftMargin = Math.min( this._timeline.width(), (this._delay() + this._duration() * this._animation.source().iterations()) * this._timeline.pixelMsRatio()); - this._endDelayLine.style.transform = 'translateX(' + leftMargin.toFixed(2) + 'px)'; - this._endDelayLine.setAttribute('x1', margin); + /** @type {!HTMLElement} */ (this._endDelayLine).style.transform = 'translateX(' + leftMargin.toFixed(2) + 'px)'; + this._endDelayLine.setAttribute('x1', margin.toString()); this._endDelayLine.setAttribute( 'x2', forwardsFill ? (this._timeline.width() - leftMargin + margin).toFixed(2) : (this._animation.source().endDelay() * this._timeline.pixelMsRatio() + margin).toFixed(2)); @@ -148,12 +158,13 @@ export class AnimationUI { return; } - const circle = - parentElement.createSVGChild('circle', keyframeIndex <= 0 ? 'animation-endpoint' : 'animation-keyframe-point'); + /** @type {!HTMLElement} */ + const circle = /** @type {!HTMLElement} */ (UI.UIUtils.createSVGChild( + parentElement, 'circle', keyframeIndex <= 0 ? 'animation-endpoint' : 'animation-keyframe-point')); circle.setAttribute('cx', x.toFixed(2)); - circle.setAttribute('cy', Options.AnimationHeight); + circle.setAttribute('cy', Options.AnimationHeight.toString()); circle.style.stroke = this._color; - circle.setAttribute('r', Options.AnimationMargin / 2); + circle.setAttribute('r', (Options.AnimationMargin / 2).toString()); circle.tabIndex = 0; UI.ARIAUtils.setAccessibleName( circle, keyframeIndex <= 0 ? ls`Animation Endpoint slider` : ls`Animation Keyframe slider`); @@ -162,12 +173,13 @@ export class AnimationUI { circle.style.fill = this._color; } - this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle; + this._cachedElements[iteration].keyframePoints[keyframeIndex] = /** @type {!HTMLElement} */ (circle); if (!attachEvents) { return; } + /** @type {string} */ let eventType; if (keyframeIndex === 0) { eventType = Events.StartEndpointMove; @@ -179,37 +191,39 @@ export class AnimationUI { UI.UIUtils.installDragHandle( circle, this._mouseDown.bind(this, eventType, keyframeIndex), this._mouseMove.bind(this), this._mouseUp.bind(this), 'ew-resize'); - Animation.AnimationUI.installDragHandleKeyboard(circle, this._keydownMove.bind(this, eventType, keyframeIndex)); + AnimationUI.installDragHandleKeyboard(circle, this._keydownMove.bind(this, eventType, keyframeIndex)); } /** * @param {number} iteration * @param {number} keyframeIndex - * @param {!Element} parentElement + * @param {!HTMLElement} parentElement * @param {number} leftDistance * @param {number} width * @param {string} easing */ _renderKeyframe(iteration, keyframeIndex, parentElement, leftDistance, width, easing) { /** - * @param {!Element} parentElement + * @param {!HTMLElement} parentElement * @param {number} x * @param {string} strokeColor */ function createStepLine(parentElement, x, strokeColor) { - const line = parentElement.createSVGChild('line'); - line.setAttribute('x1', x); - line.setAttribute('x2', x); - line.setAttribute('y1', Options.AnimationMargin); - line.setAttribute('y2', Options.AnimationHeight); + /** @type {!HTMLElement} */ + const line = /** @type {!HTMLElement} */ (UI.UIUtils.createSVGChild(parentElement, 'line')); + line.setAttribute('x1', x.toString()); + line.setAttribute('x2', x.toString()); + line.setAttribute('y1', Options.AnimationMargin.toString()); + line.setAttribute('y2', Options.AnimationHeight.toString()); line.style.stroke = strokeColor; } const bezier = UI.Geometry.CubicBezier.parse(easing); const cache = this._cachedElements[iteration].keyframeRender; if (!cache[keyframeIndex]) { - cache[keyframeIndex] = bezier ? parentElement.createSVGChild('path', 'animation-keyframe') : - parentElement.createSVGChild('g', 'animation-keyframe-step'); + const svg = bezier ? UI.UIUtils.createSVGChild(parentElement, 'path', 'animation-keyframe') : + UI.UIUtils.createSVGChild(parentElement, 'g', 'animation-keyframe-step'); + cache[keyframeIndex] = /** @type {!HTMLElement} */ (svg); } const group = cache[keyframeIndex]; group.tabIndex = 0; @@ -227,10 +241,13 @@ export class AnimationUI { } else { const stepFunction = StepTimingFunction.parse(easing); group.removeChildren(); - /** @const */ const offsetMap = {'start': 0, 'middle': 0.5, 'end': 1}; - /** @const */ const offsetWeight = offsetMap[stepFunction.stepAtPosition]; - for (let i = 0; i < stepFunction.steps; i++) { - createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color); + /** @type {!Object.} */ + const offsetMap = {'start': 0, 'middle': 0.5, 'end': 1}; + if (stepFunction) { + const offsetWeight = offsetMap[stepFunction.stepAtPosition]; + for (let i = 0; i < stepFunction.steps; i++) { + createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color); + } } } } @@ -239,13 +256,13 @@ export class AnimationUI { const maxWidth = this._timeline.width() - Options.AnimationMargin; this._svg.setAttribute('width', (maxWidth + 2 * Options.AnimationMargin).toFixed(2)); - this._activeIntervalGroup.style.transform = + /** @type {!HTMLElement} */ (this._activeIntervalGroup).style.transform = 'translateX(' + (this._delay() * this._timeline.pixelMsRatio()).toFixed(2) + 'px)'; this._nameElement.style.transform = 'translateX(' + (this._delay() * this._timeline.pixelMsRatio() + Options.AnimationMargin).toFixed(2) + 'px)'; this._nameElement.style.width = (this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + 'px'; - this._drawDelayLine(this._svg); + this._drawDelayLine(/** @type {!HTMLElement} */ (this._svg)); if (this._animation.type() === 'CSSTransition') { this._renderTransition(); @@ -254,7 +271,7 @@ export class AnimationUI { this._renderIteration(this._activeIntervalGroup, 0); if (!this._tailGroup) { - this._tailGroup = this._activeIntervalGroup.createSVGChild('g', 'animation-tail-iterations'); + this._tailGroup = UI.UIUtils.createSVGChild(this._activeIntervalGroup, 'g', 'animation-tail-iterations'); } const iterationWidth = this._duration() * this._timeline.pixelMsRatio(); let iteration; @@ -264,22 +281,25 @@ export class AnimationUI { this._renderIteration(this._tailGroup, iteration); } while (iteration < this._cachedElements.length) { - this._cachedElements.pop().group.remove(); + const poppedElement = this._cachedElements.pop(); + if (poppedElement && poppedElement.group) { + poppedElement.group.remove(); + } } } _renderTransition() { + const activeIntervalGroup = /** @type {!HTMLElement} */ (this._activeIntervalGroup); if (!this._cachedElements[0]) { this._cachedElements[0] = {animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null}; } - this._drawAnimationLine(0, this._activeIntervalGroup); + this._drawAnimationLine(0, activeIntervalGroup); this._renderKeyframe( - 0, 0, this._activeIntervalGroup, Options.AnimationMargin, this._duration() * this._timeline.pixelMsRatio(), + 0, 0, activeIntervalGroup, Options.AnimationMargin, this._duration() * this._timeline.pixelMsRatio(), this._animation.source().easing()); - this._drawPoint(0, this._activeIntervalGroup, Options.AnimationMargin, 0, true); + this._drawPoint(0, activeIntervalGroup, Options.AnimationMargin, 0, true); this._drawPoint( - 0, this._activeIntervalGroup, this._duration() * this._timeline.pixelMsRatio() + Options.AnimationMargin, -1, - true); + 0, activeIntervalGroup, this._duration() * this._timeline.pixelMsRatio() + Options.AnimationMargin, -1, true); } /** @@ -288,20 +308,30 @@ export class AnimationUI { */ _renderIteration(parentElement, iteration) { if (!this._cachedElements[iteration]) { - this._cachedElements[iteration] = - {animationLine: null, keyframePoints: {}, keyframeRender: {}, group: parentElement.createSVGChild('g')}; + this._cachedElements[iteration] = { + animationLine: null, + keyframePoints: {}, + keyframeRender: {}, + group: /** @type {!HTMLElement} */ (UI.UIUtils.createSVGChild(parentElement, 'g')) + }; } const group = this._cachedElements[iteration].group; + if (!group) { + return; + } + group.style.transform = 'translateX(' + (iteration * this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + 'px)'; this._drawAnimationLine(iteration, group); - console.assert(this._keyframes.length > 1); - for (let i = 0; i < this._keyframes.length - 1; i++) { - const leftDistance = this._offset(i) * this._duration() * this._timeline.pixelMsRatio() + Options.AnimationMargin; - const width = this._duration() * (this._offset(i + 1) - this._offset(i)) * this._timeline.pixelMsRatio(); - this._renderKeyframe(iteration, i, group, leftDistance, width, this._keyframes[i].easing()); - if (i || (!i && iteration === 0)) { - this._drawPoint(iteration, group, leftDistance, i, iteration === 0); + if (this._keyframes && this._keyframes.length > 1) { + for (let i = 0; i < this._keyframes.length - 1; i++) { + const leftDistance = + this._offset(i) * this._duration() * this._timeline.pixelMsRatio() + Options.AnimationMargin; + const width = this._duration() * (this._offset(i + 1) - this._offset(i)) * this._timeline.pixelMsRatio(); + this._renderKeyframe(iteration, i, group, leftDistance, width, this._keyframes[i].easing()); + if (i || (!i && iteration === 0)) { + this._drawPoint(iteration, group, leftDistance, i, iteration === 0); + } } } this._drawPoint( @@ -340,6 +370,10 @@ export class AnimationUI { * @return {number} offset */ _offset(i) { + if (!this._keyframes) { + throw new Error('Unable to calculate offset; keyframes do not exist'); + } + let offset = this._keyframes[i].offsetAsNumber(); if (this._mouseEventType === Events.KeyframeMove && i === this._keyframeMoved) { console.assert(i > 0 && i < this._keyframes.length - 1, 'First and last keyframe cannot be moved'); @@ -356,7 +390,8 @@ export class AnimationUI { * @param {!Event} event */ _mouseDown(mouseEventType, keyframeIndex, event) { - if (event.buttons === 2) { + const mouseEvent = /** @type {!MouseEvent} */ (event); + if (mouseEvent.buttons === 2) { return false; } if (this._svg.enclosingNodeOrSelfWithClass('animation-node-removed')) { @@ -364,7 +399,7 @@ export class AnimationUI { } this._mouseEventType = mouseEventType; this._keyframeMoved = keyframeIndex; - this._downMouseX = event.clientX; + this._downMouseX = mouseEvent.clientX; event.consume(true); if (this._node) { Common.Revealer.reveal(this._node); @@ -376,7 +411,8 @@ export class AnimationUI { * @param {!Event} event */ _mouseMove(event) { - this._setMovementAndRedraw((event.clientX - this._downMouseX) / this._timeline.pixelMsRatio()); + const mouseEvent = /** @type {!MouseEvent} */ (event); + this._setMovementAndRedraw((mouseEvent.clientX - (this._downMouseX || 0)) / this._timeline.pixelMsRatio()); } /** @@ -394,11 +430,14 @@ export class AnimationUI { * @param {!Event} event */ _mouseUp(event) { - this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio(); + const mouseEvent = /** @type {!MouseEvent} */ (event); + this._movementInMs = (mouseEvent.clientX - (this._downMouseX || 0)) / this._timeline.pixelMsRatio(); // Commit changes if (this._mouseEventType === Events.KeyframeMove) { - this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved)); + if (this._keyframes && this._keyframeMoved !== null && typeof this._keyframeMoved !== 'undefined') { + this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved)); + } } else { this._animation.setTiming(this._duration(), this._delay()); } @@ -411,10 +450,16 @@ export class AnimationUI { delete this._keyframeMoved; } + /** + * @param {!Events} mouseEventType + * @param {?number} keyframeIndex + * @param {!Event} event + */ _keydownMove(mouseEventType, keyframeIndex, event) { + const keyboardEvent = /** @type {!KeyboardEvent} */ (event); this._mouseEventType = mouseEventType; this._keyframeMoved = keyframeIndex; - switch (event.key) { + switch (keyboardEvent.key) { case 'ArrowLeft': case 'ArrowUp': this._movementInMs = -this._keyboardMovementRateMs; @@ -426,8 +471,10 @@ export class AnimationUI { default: return; } - if (this._mouseEventType === Animation.AnimationUI.Events.KeyframeMove) { - this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved)); + if (this._mouseEventType === Events.KeyframeMove) { + if (this._keyframes && this._keyframeMoved !== null) { + this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved)); + } } else { this._animation.setTiming(this._duration(), this._delay()); } @@ -478,15 +525,11 @@ export const Options = { GridCanvasHeight: 40 }; -export const Colors = { - 'Purple': Common.Color.Color.parse('#9C27B0'), - 'Light Blue': Common.Color.Color.parse('#03A9F4'), - 'Deep Orange': Common.Color.Color.parse('#FF5722'), - 'Blue': Common.Color.Color.parse('#5677FC'), - 'Lime': Common.Color.Color.parse('#CDDC39'), - 'Blue Grey': Common.Color.Color.parse('#607D8B'), - 'Pink': Common.Color.Color.parse('#E91E63'), - 'Green': Common.Color.Color.parse('#0F9D58'), - 'Brown': Common.Color.Color.parse('#795548'), - 'Cyan': Common.Color.Color.parse('#00BCD4') -}; +/** @type {!Map} */ +export const Colors = new Map([ + ['Purple', Common.Color.Color.parse('#9C27B0')], ['Light Blue', Common.Color.Color.parse('#03A9F4')], + ['Deep Orange', Common.Color.Color.parse('#FF5722')], ['Blue', Common.Color.Color.parse('#5677FC')], + ['Lime', Common.Color.Color.parse('#CDDC39')], ['Blue Grey', Common.Color.Color.parse('#607D8B')], + ['Pink', Common.Color.Color.parse('#E91E63')], ['Green', Common.Color.Color.parse('#0F9D58')], + ['Brown', Common.Color.Color.parse('#795548')], ['Cyan', Common.Color.Color.parse('#00BCD4')] +]); diff --git a/front_end/bindings/DebuggerLanguagePlugins.js b/front_end/bindings/DebuggerLanguagePlugins.js index c7d23312547..a341dec3027 100644 --- a/front_end/bindings/DebuggerLanguagePlugins.js +++ b/front_end/bindings/DebuggerLanguagePlugins.js @@ -17,12 +17,12 @@ class SourceType { /** * @param {!TypeInfo} typeInfo * @param {!Array} members + * @param {!Map<*, !SourceType>} typeMap */ - constructor(typeInfo, members) { - /** @type {!TypeInfo} */ + constructor(typeInfo, members, typeMap) { this.typeInfo = typeInfo; - /** @type {!Array} */ this.members = members; + this.typeMap = typeMap; } /** Create a type graph @@ -36,7 +36,7 @@ class SourceType { /** @type Map<*, !SourceType> */ const typeMap = new Map(); for (const typeInfo of typeInfos) { - typeMap.set(typeInfo.typeId, new SourceType(typeInfo, [])); + typeMap.set(typeInfo.typeId, new SourceType(typeInfo, [], typeMap)); } for (const sourceType of typeMap.values()) { @@ -66,15 +66,134 @@ function getRawLocation(callFrame) { }; } +/** + * @param {!SDK.DebuggerModel.CallFrame} callFrame + * @param {!SDK.RemoteObject.RemoteObject} object + * @return {!Promise<*>} + */ +async function resolveRemoteObject(callFrame, object) { + if (typeof object.value !== 'undefined') { + return object.value; + } + + const response = await callFrame.debuggerModel.target().runtimeAgent().invoke_callFunctionOn( + {functionDeclaration: 'function() { return this; }', objectId: object.objectId, returnByValue: true}); + const {result} = response; + if (!result) { + return undefined; + } + return result.value; +} + +class EvalNodeBase extends SDK.RemoteObject.RemoteObjectImpl { + /** + * @param {!SDK.DebuggerModel.CallFrame} callFrame + * @param {!DebuggerLanguagePlugin} plugin + * @param {!SourceType} sourceType + * @param {!Protocol.Runtime.RemoteObject} object + * @param {?{className: string, symbol: string }} formatterTag + */ + constructor(callFrame, sourceType, plugin, object, formatterTag) { + super( + callFrame.debuggerModel.runtimeModel(), object.objectId, object.type, object.subtype, object.value, + object.unserializableValue, object.description, object.preview, object.customPreview, object.className); + + this._plugin = plugin; + this._sourceType = sourceType; + this._callFrame = callFrame; + + /** @type {?{className: string, symbol: string }} */ + this.formatterTag = formatterTag; + } + + /** + * @param {...string} properties + * @return {!Promise>} + */ + async findProperties(...properties) { + /** @type {!Object} */ + const result = {}; + for (const prop of (await this.getOwnProperties(false)).properties || []) { + if (properties.indexOf(prop.name) >= 0) { + if (prop.value) { + result[prop.name] = /** @type {!EvalNodeBase|undefined} */ (prop.value); + } + } + } + return result; + } + + /** + * @override + * @param {!Protocol.Runtime.RemoteObject} newObject + */ + async _createRemoteObject(newObject) { + const base = await this._getEvalBaseFromObject(newObject); + if (!base) { + return new EvalNodeBase(this._callFrame, this._sourceType, this._plugin, newObject, this.formatterTag); + } + const newSourceType = this._sourceType.typeMap.get(base.rootType.typeId); + if (!newSourceType) { + throw new Error('Unknown typeId in eval base'); + } + if (base.rootType.hasValue && !base.rootType.canExpand && base) { + return EvalNode.evaluate(this._callFrame, this._plugin, newSourceType, base, []); + } + + return new EvalNode(this._callFrame, this._plugin, newSourceType, base, []); + } + + /** + * @param {!Protocol.Runtime.RemoteObject} object + */ + async _getEvalBaseFromObject(object) { + const {objectId} = object; + if (!object || !this.formatterTag) { + return null; + } + + const {className, symbol} = this.formatterTag; + if (className !== object.className) { + return null; + } + + const response = await this.debuggerModel().target().runtimeAgent().invoke_callFunctionOn( + {functionDeclaration: 'function(sym) { return this[sym]; }', objectId, arguments: [{objectId: symbol}]}); + const {result} = response; + if (!result || result.type === 'undefined') { + return null; + } + + const baseObject = new EvalNodeBase(this._callFrame, this._sourceType, this._plugin, result, null); + const {payload, rootType} = await baseObject.findProperties('payload', 'rootType'); + if (typeof payload === 'undefined' || typeof rootType === 'undefined') { + return null; + } + const value = await resolveRemoteObject(this._callFrame, payload); + const {typeId} = await rootType.findProperties('typeId', 'rootType'); + if (typeof value === 'undefined' || typeof typeId === 'undefined') { + return null; + } + + const newSourceType = this._sourceType.typeMap.get(typeId.value); + if (!newSourceType) { + return null; + } + + return {payload: value, rootType: newSourceType.typeInfo}; + } +} + class EvalNode extends SDK.RemoteObject.RemoteObjectImpl { /** * @param {!SDK.DebuggerModel.CallFrame} callFrame * @param {!DebuggerLanguagePlugin} plugin + * @param {!SourceType} sourceType * @param {!EvalBase} base * @param {!Array} field * @return {!Promise} */ - static async evaluate(callFrame, plugin, base, field) { + static async evaluate(callFrame, plugin, sourceType, base, field) { const location = getRawLocation(callFrame); let evalCode = await plugin.getFormatter({base, field}, location); @@ -84,14 +203,46 @@ class EvalNode extends SDK.RemoteObject.RemoteObjectImpl { const response = await callFrame.debuggerModel.target().debuggerAgent().invoke_evaluateOnCallFrame({ callFrameId: callFrame.id, expression: evalCode.js, - generatePreview: true, + generatePreview: false, includeCommandLineAPI: true, objectGroup: 'console', returnByValue: false, silent: false }); - return callFrame.debuggerModel.runtimeModel().createRemoteObject(response.result); + + const {result} = response; + const object = new EvalNodeBase(callFrame, sourceType, plugin, result, null); + const unpackedResultObject = await unpackResultObject(object); + const node = unpackedResultObject || object; + + if (typeof node.value === 'undefined') { + node.description = sourceType.typeInfo.typeNames[0]; + } + + return node; + + /** + * @param {!EvalNodeBase} object + * @return {!Promise} + */ + async function unpackResultObject(object) { + const {tag, value} = await object.findProperties('tag', 'value'); + if (!tag || !value) { + return null; + } + const {className, symbol} = await tag.findProperties('className', 'symbol'); + if (!className || !symbol) { + return null; + } + const resolvedClassName = className.value; + if (typeof resolvedClassName !== 'string' || typeof symbol.objectId === 'undefined') { + return null; + } + + value.formatterTag = {symbol: symbol.objectId, className: resolvedClassName}; + return value; + } } /** @@ -113,7 +264,7 @@ class EvalNode extends SDK.RemoteObject.RemoteObjectImpl { return new SDK.RemoteObject.LocalJSONObject(undefined); } if (sourceType.typeInfo.hasValue && !sourceType.typeInfo.canExpand && base) { - return EvalNode.evaluate(callFrame, plugin, base, []); + return EvalNode.evaluate(callFrame, plugin, sourceType, base, []); } return new EvalNode(callFrame, plugin, sourceType, base, []); @@ -130,10 +281,11 @@ class EvalNode extends SDK.RemoteObject.RemoteObjectImpl { const typeName = sourceType.typeInfo.typeNames[0] || ''; const variableType = 'object'; super( - callFrame.debuggerModel.runtimeModel(), /* objectId=*/ undefined, + callFrame.debuggerModel.runtimeModel(), + /* objectId=*/ undefined, /* type=*/ variableType, /* subtype=*/ undefined, /* value=*/ null, /* unserializableValue=*/ undefined, - /* description=*/ typeName); + /* description=*/ typeName, /* preview=*/ undefined, /* customPreview=*/ undefined, /* className=*/ typeName); this._variableType = variableType; this._callFrame = callFrame; this._plugin = plugin; @@ -159,7 +311,8 @@ class EvalNode extends SDK.RemoteObject.RemoteObjectImpl { */ async _expandMember(sourceType, fieldInfo) { if (sourceType.typeInfo.hasValue && !sourceType.typeInfo.canExpand && this._base) { - return EvalNode.evaluate(this._callFrame, this._plugin, this._base, this._fieldChain.concat(fieldInfo)); + return EvalNode.evaluate( + this._callFrame, this._plugin, sourceType, this._base, this._fieldChain.concat(fieldInfo)); } return new EvalNode(this._callFrame, this._plugin, sourceType, this._base, this._fieldChain.concat(fieldInfo)); } diff --git a/front_end/color_picker/ContrastOverlay.js b/front_end/color_picker/ContrastOverlay.js index 2de506dfe7f..e1819c82f4a 100644 --- a/front_end/color_picker/ContrastOverlay.js +++ b/front_end/color_picker/ContrastOverlay.js @@ -3,6 +3,7 @@ // found in the LICENSE file. import * as Common from '../common/common.js'; +import * as UI from '../ui/ui.js'; import {ContrastInfo, Events} from './ContrastInfo.js'; // eslint-disable-line no-unused-vars @@ -17,12 +18,13 @@ export class ContrastOverlay { this._visible = false; - this._contrastRatioSVG = - /** @type {!HTMLElement} */ (colorElement).createSVGChild('svg', 'spectrum-contrast-container fill'); + this._contrastRatioSVG = UI.UIUtils.createSVGChild(colorElement, 'svg', 'spectrum-contrast-container fill'); /** @type {!Map} */ this._contrastRatioLines = new Map(); - this._contrastRatioLines.set('aa', this._contrastRatioSVG.createSVGChild('path', 'spectrum-contrast-line')); - this._contrastRatioLines.set('aaa', this._contrastRatioSVG.createSVGChild('path', 'spectrum-contrast-line')); + this._contrastRatioLines.set( + 'aa', UI.UIUtils.createSVGChild(this._contrastRatioSVG, 'path', 'spectrum-contrast-line')); + this._contrastRatioLines.set( + 'aaa', UI.UIUtils.createSVGChild(this._contrastRatioSVG, 'path', 'spectrum-contrast-line')); this._width = 0; this._height = 0; diff --git a/front_end/color_picker/Spectrum.js b/front_end/color_picker/Spectrum.js index e7eccd47dbb..c0c6971a858 100644 --- a/front_end/color_picker/Spectrum.js +++ b/front_end/color_picker/Spectrum.js @@ -50,10 +50,10 @@ export class Spectrum extends UI.Widget.VBox { * @param {!Element} parentElement */ function appendSwitcherIcon(parentElement) { - const icon = parentElement.createSVGChild('svg'); + const icon = UI.UIUtils.createSVGChild(parentElement, 'svg'); icon.setAttribute('height', 16); icon.setAttribute('width', 16); - const path = icon.createSVGChild('path'); + const path = UI.UIUtils.createSVGChild(icon, 'path'); path.setAttribute('d', 'M5,6 L11,6 L8,2 Z M5,10 L11,10 L8,14 Z'); return icon; } diff --git a/front_end/common/BUILD.gn b/front_end/common/BUILD.gn index 918404eb83b..7ec746959e1 100644 --- a/front_end/common/BUILD.gn +++ b/front_end/common/BUILD.gn @@ -28,6 +28,7 @@ devtools_module("common") { "Runnable.js", "SegmentedRange.js", "Settings.js", + "SimpleHistoryManager.js", "StringOutputStream.js", "TextDictionary.js", "Throttler.js", diff --git a/front_end/sources/SimpleHistoryManager.js b/front_end/common/SimpleHistoryManager.js similarity index 96% rename from front_end/sources/SimpleHistoryManager.js rename to front_end/common/SimpleHistoryManager.js index f2ed508576d..14bceceb543 100644 --- a/front_end/sources/SimpleHistoryManager.js +++ b/front_end/common/SimpleHistoryManager.js @@ -39,7 +39,8 @@ export class HistoryEntry { throw new Error('not implemented'); } - reveal() {} + reveal() { + } } /** @@ -53,6 +54,10 @@ export class SimpleHistoryManager { /** @type {!Array} */ this._entries = []; this._activeEntryIndex = -1; + + // Lock is used to make sure that reveal() does not + // make any changes to the history while we are + // rolling back or rolling over. this._coalescingReadonly = 0; this._historyDepth = historyDepth; } diff --git a/front_end/common/common.js b/front_end/common/common.js index b49085fcaeb..4c260250b35 100644 --- a/front_end/common/common.js +++ b/front_end/common/common.js @@ -25,6 +25,7 @@ import * as Revealer from './Revealer.js'; import * as Runnable from './Runnable.js'; import * as SegmentedRange from './SegmentedRange.js'; import * as Settings from './Settings.js'; +import * as SimpleHistoryManager from './SimpleHistoryManager.js'; import * as StringOutputStream from './StringOutputStream.js'; import * as TextDictionary from './TextDictionary.js'; import * as Throttler from './Throttler.js'; @@ -77,6 +78,7 @@ export { Runnable, SegmentedRange, Settings, + SimpleHistoryManager, StringOutputStream, TextDictionary, Throttler, diff --git a/front_end/common/module.json b/front_end/common/module.json index b075f1acf57..2a5a22daffd 100644 --- a/front_end/common/module.json +++ b/front_end/common/module.json @@ -30,6 +30,7 @@ "Revealer.js", "Runnable.js", "StringOutputStream.js", + "SimpleHistoryManager.js", "CharacterIdMap.js", "Lazy.js", "Base64.js" diff --git a/front_end/component_helpers/get-stylesheet.ts b/front_end/component_helpers/get-stylesheet.ts index 8c41b59d4e2..467fc019b5b 100644 --- a/front_end/component_helpers/get-stylesheet.ts +++ b/front_end/component_helpers/get-stylesheet.ts @@ -98,7 +98,7 @@ export const CSS_RESOURCES_TO_LOAD_INTO_RUNTIME = [ 'components/jsUtils.css', 'persistence/editFileSystemView.css', 'persistence/workspaceSettingsTab.css', - 'console_counters/errorWarningCounter.css', + 'console_counters/warningErrorCounter.css', 'mobile_throttling/throttlingSettingsTab.css', 'emulation/deviceModeToolbar.css', 'emulation/deviceModeView.css', diff --git a/front_end/console/ConsoleViewMessage.js b/front_end/console/ConsoleViewMessage.js index 0ab4c683eaf..2149df73bf1 100644 --- a/front_end/console/ConsoleViewMessage.js +++ b/front_end/console/ConsoleViewMessage.js @@ -499,9 +499,9 @@ export class ConsoleViewMessage { return /** @type {!HTMLElement} */ ((new ObjectUI.CustomPreviewComponent.CustomPreviewComponent(output)).element); } - const type = forceObjectFormat ? 'object' : (output.subtype || output.type); + const outputType = forceObjectFormat ? 'object' : (output.subtype || output.type); let element; - switch (type) { + switch (outputType) { case 'error': element = this._formatParameterAsError(output); break; @@ -527,6 +527,9 @@ export class ConsoleViewMessage { case 'node': element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false); break; + case 'trustedtype': + element = this._formatParameterAsObject(output, false); + break; case 'string': element = this._formatParameterAsString(output); break; @@ -542,9 +545,9 @@ export class ConsoleViewMessage { break; default: element = this._formatParameterAsValue(output); - console.error('Tried to format remote object of unknown type.'); + console.error(`Tried to format remote object of unknown type ${outputType}.`); } - element.classList.add('object-value-' + type); + element.classList.add(`object-value-${outputType}`); element.classList.add('source-code'); return element; } @@ -570,6 +573,21 @@ export class ConsoleViewMessage { return result; } + /** + * @param {!SDK.RemoteObject.RemoteObject} obj + * @return {!HTMLElement} + * @suppress {accessControls} + */ + _formatParameterAsTrustedType(obj) { + const result = /** @type {!HTMLElement} */ (document.createElement('span')); + const trustedContentSpan = document.createElement('span'); + trustedContentSpan.appendChild(this._formatParameterAsString(obj)); + trustedContentSpan.classList.add('object-value-string'); + UI.UIUtils.createTextChild(result, `${obj.className} `); + result.appendChild(trustedContentSpan); + return result; + } + /** * @param {!SDK.RemoteObject.RemoteObject} obj * @param {boolean=} includePreview @@ -585,6 +603,8 @@ export class ConsoleViewMessage { const functionElement = titleElement.createChild('span'); ObjectUI.ObjectPropertiesSection.ObjectPropertiesSection.formatObjectAsFunction(obj, functionElement, false); titleElement.classList.add('object-value-function'); + } else if (obj.subtype === 'trustedtype') { + titleElement.appendChild(this._formatParameterAsTrustedType(obj)); } else { UI.UIUtils.createTextChild(titleElement, obj.description || ''); } @@ -597,7 +617,7 @@ export class ConsoleViewMessage { if (this._message.type === SDK.ConsoleModel.MessageType.QueryObjectResult) { note.title = ls`This value will not be collected until console is cleared.`; } else { - note.title = ls`Value below was evaluated just now.`; + note.title = ls`This value was evaluated just now and may have changed since output to console.`; } const section = new ObjectUI.ObjectPropertiesSection.ObjectPropertiesSection(obj, titleElement, this._linkifier); @@ -663,7 +683,7 @@ export class ConsoleViewMessage { return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name.toString()), false); } return this._previewFormatter.renderPropertyPreview( - property.type, 'subtype' in property ? property.subtype : undefined, property.value); + property.type, 'subtype' in property ? property.subtype : undefined, null, property.value); } /** @@ -734,7 +754,8 @@ export class ConsoleViewMessage { * @return {!HTMLElement} */ _formatAsArrayEntry(output) { - return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description); + return this._previewFormatter.renderPropertyPreview( + output.type, output.subtype, output.className, output.description); } /** @@ -772,13 +793,14 @@ export class ConsoleViewMessage { const subtype = object.subtype; let description = ''; if (type !== 'function' && object.description) { - if (type === 'string' || subtype === 'regexp') { + if (type === 'string' || subtype === 'regexp' || subtype === 'trustedtype') { description = object.description.trimMiddle(maxLength); } else { description = object.description.trimEndWithMaxLength(maxLength); } } - rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description)); + rootElement.appendChild( + this._previewFormatter.renderPropertyPreview(type, subtype, object.className, description)); } } diff --git a/front_end/console/console_strings.grdp b/front_end/console/console_strings.grdp index 6c77d221d02..4c7e682e26e 100644 --- a/front_end/console/console_strings.grdp +++ b/front_end/console/console_strings.grdp @@ -75,9 +75,6 @@ $1s3 hidden - - Value below was evaluated just now. - Hide all @@ -141,6 +138,9 @@ 1 info + + This value was evaluated just now and may have changed since output to console. + Eagerly evaluate console prompt text diff --git a/front_end/console_counters/BUILD.gn b/front_end/console_counters/BUILD.gn index b697f978482..bbde1e0e0f2 100644 --- a/front_end/console_counters/BUILD.gn +++ b/front_end/console_counters/BUILD.gn @@ -18,7 +18,7 @@ devtools_module("console_counters") { } copy_to_gen("legacy_css") { - sources = [ "errorWarningCounter.css" ] + sources = [ "warningErrorCounter.css" ] } devtools_entrypoint("bundle") { diff --git a/front_end/console_counters/WarningErrorCounter.js b/front_end/console_counters/WarningErrorCounter.js index b84a746e407..3b845d4bde0 100644 --- a/front_end/console_counters/WarningErrorCounter.js +++ b/front_end/console_counters/WarningErrorCounter.js @@ -28,9 +28,10 @@ export class WarningErrorCounter { */ function createCounter(parent, delegate) { const container = parent.createChild('div'); - const shadowRoot = UI.Utils.createShadowRootWithCoreStyles(container, 'console_counters/errorWarningCounter.css'); + container.classList.add('main-toolbar-counter'); + const shadowRoot = UI.Utils.createShadowRootWithCoreStyles(container, 'console_counters/warningErrorCounter.css'); const button = shadowRoot.createChild('button'); - button.classList.add('hidden'); + button.classList.add('toolbar-counter-button', 'hidden'); button.addEventListener('click', delegate, false); return button; } @@ -90,7 +91,7 @@ export class WarningErrorCounter { */ _createItem(shadowRoot, iconType) { const item = document.createElement('span'); - item.classList.add('counter-item'); + item.classList.add('toolbar-counter-item'); UI.ARIAUtils.markAsHidden(item); const icon = /** @type {!UI.UIUtils.DevToolsIconLabel} */ (item.createChild('span', '', 'dt-icon-label')); icon.type = iconType; @@ -106,7 +107,7 @@ export class WarningErrorCounter { */ _updateItem(item, count, first) { item.item.classList.toggle('hidden', !count); - item.item.classList.toggle('counter-item-first', first); + item.item.classList.toggle('toolbar-counter-item-first', first); item.text.textContent = String(count); } diff --git a/front_end/console_counters/module.json b/front_end/console_counters/module.json index 3db530552f3..c7d2506f00d 100644 --- a/front_end/console_counters/module.json +++ b/front_end/console_counters/module.json @@ -20,6 +20,6 @@ "WarningErrorCounter.js" ], "resources": [ - "errorWarningCounter.css" + "warningErrorCounter.css" ] } diff --git a/front_end/console_counters/errorWarningCounter.css b/front_end/console_counters/warningErrorCounter.css similarity index 71% rename from front_end/console_counters/errorWarningCounter.css rename to front_end/console_counters/warningErrorCounter.css index 6ae03d5f463..dc4e9982134 100644 --- a/front_end/console_counters/errorWarningCounter.css +++ b/front_end/console_counters/warningErrorCounter.css @@ -8,7 +8,7 @@ margin-left: 6px; } -button { +.toolbar-counter-button { cursor: pointer; background-color: #f3f3f3; border: 1px solid #d0d0d0; @@ -17,15 +17,15 @@ button { margin-right: 2px; } -button:hover, -button:focus-visible { +.toolbar-counter-button:hover, +.toolbar-counter-button:focus-visible { background-color: #eaeaea; } -.counter-item { +.toolbar-counter-item { margin-left: 6px; } -.counter-item.counter-item-first { +.toolbar-counter-item.toolbar-counter-item-first { margin-left: 0; } diff --git a/front_end/data_grid/DataGrid.js b/front_end/data_grid/DataGrid.js index 1be612d1b04..ee217eb2061 100644 --- a/front_end/data_grid/DataGrid.js +++ b/front_end/data_grid/DataGrid.js @@ -1050,6 +1050,24 @@ export class DataGridImpl extends Common.ObjectWrapper.ObjectWrapper { } } + /** + * @param {!Set} columnsVisibility + */ + setColumnsVisiblitySet(columnsVisibility) { + this.visibleColumnsArray = []; + for (const column of this._columnsArray) { + if (columnsVisibility.has(column.id)) { + this.visibleColumnsArray.push(column); + } + } + this._refreshHeader(); + this._applyColumnWeights(); + const nodes = this._enumerateChildren(this.rootNode(), [], -1); + for (const node of nodes) { + node.refresh(); + } + } + get scrollContainer() { return this._scrollContainer; } diff --git a/front_end/dom_extension/DOMExtension.js b/front_end/dom_extension/DOMExtension.js index 3e0e20cb93e..96b418a0a65 100644 --- a/front_end/dom_extension/DOMExtension.js +++ b/front_end/dom_extension/DOMExtension.js @@ -438,17 +438,6 @@ Element.prototype.totalOffset = function() { return {left: rect.left, top: rect.top}; }; -/** - * @param {string} childType - * @param {string=} className - * @return {!Element} - */ -Element.prototype.createSVGChild = function(childType, className) { - const child = this.ownerDocument.createSVGElement(childType, className); - this.appendChild(child); - return child; -}; - /** * @unrestricted */ diff --git a/front_end/elements/BUILD.gn b/front_end/elements/BUILD.gn index 2078e9a316a..bed3c7185f3 100644 --- a/front_end/elements/BUILD.gn +++ b/front_end/elements/BUILD.gn @@ -9,10 +9,6 @@ import("../../third_party/typescript/typescript.gni") devtools_module("elements") { sources = [ "Adorner.js", - "CSSAngle.ts", - "CSSAngleRegex.js", - "CSSAngleUtils.ts", - "CSSAngle_bridge.js", "CSSPropertyIconResolver.js", "ClassesPaneWidget.js", "ColorSwatchPopoverIcon.js", diff --git a/front_end/elements/CSSPropertyIconResolver.js b/front_end/elements/CSSPropertyIconResolver.js index 2167bea5172..3f108f3e6de 100644 --- a/front_end/elements/CSSPropertyIconResolver.js +++ b/front_end/elements/CSSPropertyIconResolver.js @@ -112,6 +112,22 @@ export function rotateFlexDirectionIcon(direction) { }; } +/** + * @param {string} iconName + * @param {!PhysicalFlexDirection} direction + * @return {!IconInfo} + */ +export function rotateFlexAlignContentIcon(iconName, direction) { + return { + iconName, + rotate: direction === PhysicalFlexDirection.RIGHT_TO_LEFT ? + 90 : + (direction === PhysicalFlexDirection.LEFT_TO_RIGHT ? -90 : 0), + scaleX: 1, + scaleY: 1, + }; +} + /** * * @param {string} value @@ -129,6 +145,24 @@ function flexDirectionIcon(value) { return getIcon; } +/** + * + * @param {string} iconName + * @return {function(!Map):!IconInfo} + */ +function flexAlignContentIcon(iconName) { + /** + * @param {!Map} computedStyles + * @return {!IconInfo} + */ + function getIcon(computedStyles) { + const directions = getPhysicalFlexDirections(computedStyles); + return rotateFlexAlignContentIcon( + iconName, computedStyles.get('flex-direction') === 'column' ? directions.row : directions.column); + } + return getIcon; +} + /** * @type {!Map):!IconInfo>} */ @@ -141,6 +175,13 @@ textToIconResolver.set('flex-direction: row-reverse', flexDirectionIcon('row-rev textToIconResolver.set('flex-direction: initial', flexDirectionIcon('row')); textToIconResolver.set('flex-direction: unset', flexDirectionIcon('row')); textToIconResolver.set('flex-direction: revert', flexDirectionIcon('row')); +textToIconResolver.set('align-content: center', flexAlignContentIcon('flex-align-content-center-icon')); +textToIconResolver.set('align-content: space-around', flexAlignContentIcon('flex-align-content-space-around-icon')); +textToIconResolver.set('align-content: space-between', flexAlignContentIcon('flex-align-content-space-between-icon')); +textToIconResolver.set('align-content: stretch', flexAlignContentIcon('flex-align-content-stretch-icon')); +textToIconResolver.set('align-content: space-evenly', flexAlignContentIcon('flex-align-content-space-evenly-icon')); +textToIconResolver.set('align-content: flex-end', flexAlignContentIcon('flex-align-content-end-icon')); +textToIconResolver.set('align-content: flex-start', flexAlignContentIcon('flex-align-content-start-icon')); /** * @param {string} text diff --git a/front_end/elements/ColorSwatchPopoverIcon.js b/front_end/elements/ColorSwatchPopoverIcon.js index 66b86895b7d..5b1a433e8cf 100644 --- a/front_end/elements/ColorSwatchPopoverIcon.js +++ b/front_end/elements/ColorSwatchPopoverIcon.js @@ -214,14 +214,15 @@ export class ColorSwatchPopoverIcon { if (!color) { return; } + + const colorName = this._spectrum ? this._spectrum.colorName() : undefined; + const text = colorName && colorName.startsWith('--') ? `var(${colorName})` : color.asString(); + this._swatch.renderColor(color); - const value = this._swatch.querySelector('span'); + const value = this._swatch.firstElementChild; if (value) { - value.textContent = color.asString(); - } - const colorName = this._spectrum ? this._spectrum.colorName() : undefined; - if (colorName && colorName.startsWith('--')) { - this._swatch.childNodes[0].textContent = `var(${colorName})`; + value.remove(); + this._swatch.createChild('span').textContent = text; } this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false); diff --git a/front_end/elements/DOMPath.js b/front_end/elements/DOMPath.js index 4ebc4fefeac..87d5dd115ac 100644 --- a/front_end/elements/DOMPath.js +++ b/front_end/elements/DOMPath.js @@ -27,7 +27,7 @@ export const cssPath = function(node, optimized) { } const steps = []; - let contextNode = node; + let contextNode = /** @type {?SDK.DOMModel.DOMNode} */ (node); while (contextNode) { const step = _cssPathStep(contextNode, !!optimized, contextNode === node); if (!step) { @@ -152,7 +152,7 @@ export const _cssPathStep = function(node, optimized, isTargetNode) { let ownIndex = -1; let elementIndex = -1; const siblings = parent.children(); - for (let i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) { + for (let i = 0; siblings && (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) { const sibling = siblings[i]; if (sibling.nodeType() !== Node.ELEMENT_NODE) { continue; @@ -216,7 +216,7 @@ export const xPath = function(node, optimized) { } const steps = []; - let contextNode = node; + let contextNode = /** @type {?SDK.DOMModel.DOMNode} */ (node); while (contextNode) { const step = _xPathValue(contextNode, optimized); if (!step) { diff --git a/front_end/elements/ElementsBreadcrumbsUtils.ts b/front_end/elements/ElementsBreadcrumbsUtils.ts index 9160c0c4ef8..9c4985b3779 100644 --- a/front_end/elements/ElementsBreadcrumbsUtils.ts +++ b/front_end/elements/ElementsBreadcrumbsUtils.ts @@ -5,7 +5,7 @@ import {ls} from '../platform/platform.js'; export interface DOMNode { - parentNode?: DOMNode; + parentNode: DOMNode|null; id: number; nodeType: number; pseudoType?: string; diff --git a/front_end/elements/ElementsBreadcrumbs_bridge.js b/front_end/elements/ElementsBreadcrumbs_bridge.js index a64360033a2..8bb6533c9dc 100644 --- a/front_end/elements/ElementsBreadcrumbs_bridge.js +++ b/front_end/elements/ElementsBreadcrumbs_bridge.js @@ -20,7 +20,7 @@ import './ElementsBreadcrumbs.js'; export let ElementsBreadcrumbsData; /** * @typedef {{ -* parentNode:(!DOMNode|undefined), +* parentNode:?DOMNode, * id:number, * nodeType:number, * pseudoType:(string|undefined), diff --git a/front_end/elements/ElementsPanel.js b/front_end/elements/ElementsPanel.js index 45cbfb6ada1..a591c8219e9 100644 --- a/front_end/elements/ElementsPanel.js +++ b/front_end/elements/ElementsPanel.js @@ -52,7 +52,7 @@ import {Events as StylesSidebarPaneEvents, StylesSidebarPane} from './StylesSide */ const legacyNodeToNewBreadcrumbsNode = node => { return { - parentNode: node.parentNode, + parentNode: node.parentNode ? legacyNodeToNewBreadcrumbsNode(node.parentNode) : null, id: /** @type {number} */ (node.id), nodeType: node.nodeType(), pseudoType: node.pseudoType(), @@ -116,7 +116,7 @@ export class ElementsPanel extends UI.Panel.Panel { crumbsContainer.appendChild(this._breadcrumbs); - this._stylesWidget = new StylesSidebarPane(); + this._stylesWidget = StylesSidebarPane.instance(); this._computedStyleWidget = new ComputedStyleWidget(); this._metricsWidget = new MetricsSidebarPane(); diff --git a/front_end/elements/ElementsTreeElement.js b/front_end/elements/ElementsTreeElement.js index ced53b0bfc1..b97b14732ab 100644 --- a/front_end/elements/ElementsTreeElement.js +++ b/front_end/elements/ElementsTreeElement.js @@ -1318,7 +1318,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement { this._node.shadowRootType()) { this.childrenListElement.classList.add('shadow-root'); let depth = 4; - for (let node = this._node; depth && node; node = node.parentNode) { + for (let node = /** @type {?SDK.DOMModel.DOMNode} */ (this._node); depth && node; node = node.parentNode) { if (node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE) { depth--; } @@ -1783,7 +1783,11 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement { if (ElementsTreeElement.canShowInlineText(node)) { const textNodeElement = titleDOM.createChild('span', 'webkit-html-text-node'); - const result = this._convertWhitespaceToEntities(node.firstChild.nodeValue()); + const firstChild = node.firstChild; + if (!firstChild) { + throw new Error('ElementsTreeElement._nodeTitleInfo expects node.firstChild to be defined.'); + } + const result = this._convertWhitespaceToEntities(firstChild.nodeValue()); textNodeElement.textContent = result.text; UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value'); UI.UIUtils.createTextChild(titleDOM, '\u200B'); diff --git a/front_end/elements/ElementsTreeElementHighlighter.js b/front_end/elements/ElementsTreeElementHighlighter.js index 7597ccf9caf..c44ef54437e 100644 --- a/front_end/elements/ElementsTreeElementHighlighter.js +++ b/front_end/elements/ElementsTreeElementHighlighter.js @@ -71,7 +71,7 @@ export class ElementsTreeElementHighlighter { this._currentHighlightedElement = null; this._alreadyExpandedParentElement = null; if (node) { - let deepestExpandedParent = node; + let deepestExpandedParent = /** @type {?SDK.DOMModel.DOMNode} */ (node); const treeElementByNode = this._treeOutline.treeElementByNode; /** diff --git a/front_end/elements/ElementsTreeOutline.js b/front_end/elements/ElementsTreeOutline.js index adf71448e34..a5e853a87e8 100644 --- a/front_end/elements/ElementsTreeOutline.js +++ b/front_end/elements/ElementsTreeOutline.js @@ -901,6 +901,10 @@ export class ElementsTreeOutline extends UI.TreeOutline.TreeOutline { // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date. this.runPendingUpdates(); + if (!index) { + return; + } + const newNode = parentNode ? parentNode.children()[index] || parentNode : null; if (!newNode) { return; diff --git a/front_end/elements/StylePropertyTreeElement.js b/front_end/elements/StylePropertyTreeElement.js index 53489104818..1275011ba94 100644 --- a/front_end/elements/StylePropertyTreeElement.js +++ b/front_end/elements/StylePropertyTreeElement.js @@ -13,7 +13,6 @@ import * as TextUtils from '../text_utils/text_utils.js'; import * as UI from '../ui/ui.js'; import {BezierPopoverIcon, ColorSwatchPopoverIcon, ShadowSwatchPopoverHelper} from './ColorSwatchPopoverIcon.js'; -import {createCSSAngle} from './CSSAngle_bridge.js'; import {CSSPropertyPrompt, StylePropertiesSection, StylesSidebarPane, StylesSidebarPropertyRenderer,} from './StylesSidebarPane.js'; // eslint-disable-line no-unused-vars /** @type {!WeakMap} */ @@ -144,9 +143,10 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement { /** * @param {string} text + * @param {?Node=} valueChild * @return {!Node} */ - _processColor(text) { + _processColor(text, valueChild) { const useUserSettingFormat = this._editable(); const shiftClickMessage = Common.UIString.UIString('Shift + Click to change color format.'); const tooltip = @@ -154,13 +154,18 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement { const swatch = InlineEditor.ColorSwatch.createColorSwatch(); swatch.renderColor(text, useUserSettingFormat, tooltip); - const value = swatch.createChild('span'); - value.textContent = swatch.color ? swatch.color.asString(swatch.format) : text; + + if (!valueChild) { + valueChild = swatch.createChild('span'); + valueChild.textContent = swatch.color ? swatch.color.asString(swatch.format) : text; + } + swatch.appendChild(valueChild); /** @param {!Event} event */ const onFormatchanged = event => { const {data} = /** @type {*} */ (event); - value.textContent = data.text; + swatch.firstElementChild && swatch.firstElementChild.remove(); + swatch.createChild('span').textContent = data.text; }; swatch.addEventListener('format-changed', onFormatchanged); @@ -177,17 +182,21 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement { * @return {!Node} */ _processVar(text) { - const swatch = InlineEditor.CSSVarSwatch.createCSSVarSwatch(); - UI.UIUtils.createTextChild(swatch, text); - const computedSingleValue = this._matchedStyles.computeSingleVariableValue(this._style, text); if (!computedSingleValue) { throw new Error('Unable to compute single value'); } const {computedValue, fromFallback} = computedSingleValue; - swatch.data = {text, computedValue, fromFallback, onLinkClick: this._handleVarDefinitionClick.bind(this)}; - return swatch; + const varSwatch = InlineEditor.CSSVarSwatch.createCSSVarSwatch(); + UI.UIUtils.createTextChild(varSwatch, text); + varSwatch.data = {text, computedValue, fromFallback, onLinkClick: this._handleVarDefinitionClick.bind(this)}; + + if (!computedValue || !Common.Color.Color.parse(computedValue)) { + return varSwatch; + } + + return this._processColor(computedValue, varSwatch); } /** @@ -302,17 +311,20 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement { } /** - * @param {string} propertyValue + * @param {string} angleText */ - _processAngle(propertyValue) { + _processAngle(angleText) { if (!this._editable()) { - return document.createTextNode(propertyValue); + return document.createTextNode(angleText); } - const cssAngle = createCSSAngle(); + const cssAngle = InlineEditor.CSSAngle.createCSSAngle(); const valueElement = document.createElement('span'); - valueElement.textContent = propertyValue; + valueElement.textContent = angleText; + const computedPropertyValue = this._matchedStyles.computeValue(this.property.ownerStyle, this.property.value) || ''; cssAngle.data = { - angleText: propertyValue, + propertyName: this.property.name, + propertyValue: computedPropertyValue, + angleText, containingPane: /** @type {!HTMLElement} */ (this._parentPane.element.enclosingNodeOrSelfWithClass('style-panes-wrapper')), }; @@ -321,13 +333,17 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement { /** * @param {!Event} event */ - const popOverToggled = event => { + const popoverToggled = event => { const section = this.section(); if (!section) { return; } const {data} = /** @type {*} */ (event); + if (data.open) { + this._parentPane.hideAllPopovers(); + this._parentPane.activeCSSAngle = cssAngle; + } section.element.classList.toggle('has-open-popover', data.open); this._parentPane.setEditingStyle(data.open); @@ -336,14 +352,17 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement { /** * @param {!Event} event */ - const valueChanged = event => { + const valueChanged = async event => { const {data} = /** @type {*} */ (event); valueElement.textContent = data.value; - this.applyStyleText(this.renderedPropertyText(), false); + await this.applyStyleText(this.renderedPropertyText(), false); + const computedPropertyValue = + this._matchedStyles.computeValue(this.property.ownerStyle, this.property.value) || ''; + cssAngle.updateProperty(this.property.name, computedPropertyValue); }; - cssAngle.addEventListener('popover-toggled', popOverToggled); + cssAngle.addEventListener('popover-toggled', popoverToggled); cssAngle.addEventListener('value-changed', valueChanged); return cssAngle; diff --git a/front_end/elements/StylesSidebarPane.js b/front_end/elements/StylesSidebarPane.js index 1b2a821c48c..c0803cc4325 100644 --- a/front_end/elements/StylesSidebarPane.js +++ b/front_end/elements/StylesSidebarPane.js @@ -41,7 +41,6 @@ import * as TextUtils from '../text_utils/text_utils.js'; import * as UI from '../ui/ui.js'; import {ComputedStyleModel} from './ComputedStyleModel.js'; -import {CSSAngleRegex} from './CSSAngleRegex.js'; import {findIcon} from './CSSPropertyIconResolver.js'; import {linkifyDeferredNodeReference} from './DOMLinkifier.js'; import {ElementsSidebarPane} from './ElementsSidebarPane.js'; @@ -68,7 +67,23 @@ const HIGHLIGHTABLE_PROPERTIES = [ {property: 'grid-template-rows', mode: 'grid-template-rows'}, ]; +/** @type {!StylesSidebarPane} */ +let _stylesSidebarPaneInstance; + export class StylesSidebarPane extends ElementsSidebarPane { + /** + * @return {!StylesSidebarPane} + */ + static instance() { + if (!_stylesSidebarPaneInstance) { + _stylesSidebarPaneInstance = new StylesSidebarPane(); + } + return _stylesSidebarPaneInstance; + } + + /** + * @private + */ constructor() { super(true /* delegatesFocus */); this.setMinimumSize(96, 26); @@ -98,8 +113,12 @@ export class StylesSidebarPane extends ElementsSidebarPane { this._sectionsContainer.addEventListener('keydown', this._sectionsContainerKeyDown.bind(this), false); this._sectionsContainer.addEventListener('focusin', this._sectionsContainerFocusChanged.bind(this), false); this._sectionsContainer.addEventListener('focusout', this._sectionsContainerFocusChanged.bind(this), false); + /** @type {!WeakMap} */ + this.sectionByElement = new WeakMap(); this._swatchPopoverHelper = new InlineEditor.SwatchPopoverHelper.SwatchPopoverHelper(); + this._swatchPopoverHelper.addEventListener( + InlineEditor.SwatchPopoverHelper.Events.WillShowPopover, this.hideAllPopovers, this); this._linkifier = new Components.Linkifier.Linkifier(_maxLinkLength, /* useLinkDecorator */ true); /** @type {!StylePropertyHighlighter} */ this._decorator = new StylePropertyHighlighter(this); @@ -119,7 +138,7 @@ export class StylesSidebarPane extends ElementsSidebarPane { /** @type {?IdleCallbackManager} */ this._idleCallbackManager = null; this._needsForceUpdate = false; - StylesSidebarPane._instance = this; + _stylesSidebarPaneInstance = this; UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.forceUpdate, this); this.contentElement.addEventListener('copy', this._clipboardCopy.bind(this)); this._resizeThrottler = new Common.Throttler.Throttler(100); @@ -131,6 +150,9 @@ export class StylesSidebarPane extends ElementsSidebarPane { } return null; }, () => this.node()); + + /** @type {?InlineEditor.CSSAngle.CSSAngleClosureInterface} */ + this.activeCSSAngle = null; } /** @@ -153,7 +175,8 @@ export class StylesSidebarPane extends ElementsSidebarPane { * @return {!Element} */ static createExclamationMark(property, title) { - const exclamationElement = createElement('span', 'dt-icon-label'); + const exclamationElement = + /** @type {!UI.UIUtils.DevToolsIconLabel} */ (document.createElement('span', {is: 'dt-icon-label'})); exclamationElement.className = 'exclamation-mark'; if (!StylesSidebarPane.ignoreErrorsForProperty(property)) { exclamationElement.type = 'smallicon-warning'; @@ -216,7 +239,7 @@ export class StylesSidebarPane extends ElementsSidebarPane { /** * @param {string} placeholder * @param {!Element} container - * @param {function(?RegExp)} filterCallback + * @param {function(?RegExp):void} filterCallback * @return {!Element} */ static createPropertyFilterElement(placeholder, container, filterCallback) { @@ -235,26 +258,15 @@ export class StylesSidebarPane extends ElementsSidebarPane { * @param {!Event} event */ function keydownHandler(event) { - if (event.key !== 'Escape' || !input.value) { + const keyboardEvent = /** @type {!KeyboardEvent} */ (event); + if (keyboardEvent.key !== 'Escape' || !input.value) { return; } - event.consume(true); + keyboardEvent.consume(true); input.value = ''; searchHandler(); } input.addEventListener('keydown', keydownHandler, false); - - input.setFilterValue = setFilterValue; - - /** - * @param {string} value - */ - function setFilterValue(value) { - input.value = value; - input.focus(); - searchHandler(); - } - return input; } @@ -267,6 +279,9 @@ export class StylesSidebarPane extends ElementsSidebarPane { this.update(); } + /** + * @param {string} propertyName + */ jumpToProperty(propertyName) { this._decorator.findAndHighlightPropertyName(propertyName); } @@ -286,7 +301,7 @@ export class StylesSidebarPane extends ElementsSidebarPane { if (!activeElement) { return; } - const section = activeElement._section; + const section = this.sectionByElement.get(activeElement); if (!section) { return; } @@ -816,9 +831,17 @@ export class StylesSidebarPane extends ElementsSidebarPane { * @override */ willHide() { + this.hideAllPopovers(); + super.willHide(); + } + + hideAllPopovers() { this._swatchPopoverHelper.hide(); this._imagePreviewPopover.hide(); - super.willHide(); + if (this.activeCSSAngle) { + this.activeCSSAngle.minify(); + this.activeCSSAngle = null; + } } /** @@ -967,7 +990,7 @@ export class SectionBlock { * @return {!SectionBlock} */ static createPseudoTypeBlock(pseudoType) { - const separatorElement = createElement('div'); + const separatorElement = document.createElement('div'); separatorElement.className = 'sidebar-separator'; separatorElement.textContent = Common.UIString.UIString('Pseudo ::%s element', pseudoType); return new SectionBlock(separatorElement); @@ -978,7 +1001,7 @@ export class SectionBlock { * @return {!SectionBlock} */ static createKeyframesBlock(keyframesName) { - const separatorElement = createElement('div'); + const separatorElement = document.createElement('div'); separatorElement.className = 'sidebar-separator'; separatorElement.textContent = `@keyframes ${keyframesName}`; return new SectionBlock(separatorElement); @@ -989,7 +1012,7 @@ export class SectionBlock { * @return {!Promise} */ static async _createInheritedNodeBlock(node) { - const separatorElement = createElement('div'); + const separatorElement = document.createElement('div'); separatorElement.className = 'sidebar-separator'; UI.UIUtils.createTextChild(separatorElement, ls`Inherited from${' '}`); const link = await Common.Linkifier.Linkifier.linkify(node, {preventKeyboardFocus: true}); @@ -1087,7 +1110,7 @@ export class StylePropertiesSection { this.element.tabIndex = -1; UI.ARIAUtils.markAsTreeitem(this.element); this.element.addEventListener('keydown', this._onKeyDown.bind(this), false); - this.element._section = this; + parentPane.sectionByElement.set(this.element, this); this._innerElement = this.element.createChild('div'); this._titleElement = this._innerElement.createChild('div', 'styles-section-title ' + (rule ? 'styles-selector' : '')); @@ -1102,7 +1125,7 @@ export class StylePropertiesSection { this._showAllButton = UI.UIUtils.createTextButton('', this._showAllItems.bind(this), 'styles-show-all'); this._innerElement.appendChild(this._showAllButton); - const selectorContainer = createElement('div'); + const selectorContainer = document.createElement('div'); this._selectorElement = document.createElement('span'); this._selectorElement.classList.add('selector'); this._selectorElement.textContent = this._headerText(); @@ -1397,8 +1420,9 @@ export class StylePropertiesSection { let childElement = parent.firstChild; while (childElement) { - if (childElement._section) { - return childElement._section; + const childSection = this._parentPane.sectionByElement.get(childElement); + if (childSection) { + return childSection; } childElement = childElement.nextSibling; } @@ -1417,8 +1441,9 @@ export class StylePropertiesSection { let childElement = parent.lastChild; while (childElement) { - if (childElement._section) { - return childElement._section; + const childSection = this._parentPane.sectionByElement.get(childElement); + if (childSection) { + return childSection; } childElement = childElement.previousSibling; } @@ -1427,27 +1452,33 @@ export class StylePropertiesSection { } /** - * @return {?StylePropertiesSection} + * @return {!StylePropertiesSection|undefined} */ nextSibling() { let curElement = this.element; do { curElement = curElement.nextSibling; - } while (curElement && !curElement._section); + } while (curElement && !this._parentPane.sectionByElement.has(curElement)); - return curElement ? curElement._section : null; + if (curElement) { + return this._parentPane.sectionByElement.get(curElement); + } + return; } /** - * @return {?StylePropertiesSection} + * @return {!StylePropertiesSection|undefined} */ previousSibling() { let curElement = this.element; do { curElement = curElement.previousSibling; - } while (curElement && !curElement._section); + } while (curElement && !this._parentPane.sectionByElement.has(curElement)); - return curElement ? curElement._section : null; + if (curElement) { + return this._parentPane.sectionByElement.get(curElement); + } + return; } /** @@ -2783,7 +2814,7 @@ export class StylesSidebarPropertyRenderer { * @return {!Element} */ renderName() { - const nameElement = createElement('span'); + const nameElement = document.createElement('span'); nameElement.className = 'webkit-css-property'; nameElement.textContent = this._propertyName; nameElement.normalize(); @@ -2794,7 +2825,7 @@ export class StylesSidebarPropertyRenderer { * @return {!Element} */ renderValue() { - const valueElement = createElement('span'); + const valueElement = document.createElement('span'); valueElement.className = 'value'; if (!this._propertyValue) { return valueElement; @@ -2831,7 +2862,7 @@ export class StylesSidebarPropertyRenderer { } if (this._angleHandler && metadata.isAngleAwareProperty(this._propertyName)) { // TODO(changhaohan): crbug.com/1138628 refactor this to handle unitless 0 cases - regexes.push(CSSAngleRegex); + regexes.push(InlineEditor.CSSAngleRegex.CSSAngleRegex); processors.push(this._angleHandler); } const results = TextUtils.TextUtils.Utils.splitStringByRegexes(this._propertyValue, regexes); @@ -2908,14 +2939,14 @@ export class ButtonProvider { * @param {!Common.EventTarget.EventTargetEvent} event */ _clicked(event) { - StylesSidebarPane._instance._createNewRuleInViaInspectorStyleSheet(); + StylesSidebarPane.instance()._createNewRuleInViaInspectorStyleSheet(); } /** * @param {!Event} event */ _longClicked(event) { - StylesSidebarPane._instance._onAddButtonLongClick(event); + StylesSidebarPane.instance()._onAddButtonLongClick(event); } /** diff --git a/front_end/elements/module.json b/front_end/elements/module.json index 239a715b096..5a61363d4fb 100644 --- a/front_end/elements/module.json +++ b/front_end/elements/module.json @@ -314,8 +314,6 @@ "ColorSwatchPopoverIcon.js", "ComputedStyleModel.js", "Adorner.js", - "CSSAngleRegex.js", - "CSSAngle_bridge.js", "CSSPropertyIconResolver.js", "DOMLinkifier.js", "DOMPath.js", diff --git a/front_end/emulation/DeviceModeView.js b/front_end/emulation/DeviceModeView.js index ba4e36aa143..f9ce764ee74 100644 --- a/front_end/emulation/DeviceModeView.js +++ b/front_end/emulation/DeviceModeView.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Host from '../host/host.js'; import * as Platform from '../platform/platform.js'; @@ -14,6 +11,7 @@ import {DeviceModeModel, Events, MaxDeviceSize, MinDeviceSize, Type} from './Dev import {DeviceModeToolbar} from './DeviceModeToolbar.js'; import {MediaQueryInspector} from './MediaQueryInspector.js'; + /** * @unrestricted */ @@ -24,6 +22,9 @@ export class DeviceModeView extends UI.Widget.VBox { /** @type {?UI.Widget.VBox} */ this.wrapperInstance; + /** @type {!WeakMap} */ + this.blockElementToWidth = new WeakMap(); + this.setMinimumSize(150, 150); this.element.classList.add('device-mode-view'); this.registerRequiredCSS('emulation/deviceModeView.css'); @@ -44,52 +45,95 @@ export class DeviceModeView extends UI.Widget.VBox { this._leftRuler.element.classList.add('device-mode-ruler-left'); this._createUI(); UI.ZoomManager.ZoomManager.instance().addEventListener(UI.ZoomManager.Events.ZoomChanged, this._zoomChanged, this); + + /** @type {!Array} */ + this._presetBlocks; + /** @type {!HTMLElement} */ + this._responsivePresetsContainer; + /** @type {!HTMLElement} */ + this._screenArea; + /** @type {!HTMLElement} */ + this._pageArea; + /** @type {!HTMLElement} */ + this._outlineImage; + /** @type {!HTMLElement} */ + this._contentClip; + /** @type {!HTMLElement} */ + this._contentArea; + /** @type {!HTMLElement} */ + this._rightResizerElement; + /** @type {!HTMLElement} */ + this._leftResizerElement; + /** @type {!HTMLElement} */ + this._bottomResizerElement; + /** @type {!HTMLElement} */ + this._bottomRightResizerElement; + /** @type {!HTMLElement} */ + this._bottomLeftResizerElement; + /** @type {boolean|undefined} */ + this._cachedResizable; + /** @type {!HTMLElement} */ + this._mediaInspectorContainer; + /** @type {!HTMLElement} */ + this._screenImage; + /** @type {!DeviceModeToolbar} */ + this._toolbar; } _createUI() { this._toolbar = new DeviceModeToolbar(this._model, this._showMediaInspectorSetting, this._showRulersSetting); this.contentElement.appendChild(this._toolbar.element()); - this._contentClip = this.contentElement.createChild('div', 'device-mode-content-clip vbox'); - this._responsivePresetsContainer = this._contentClip.createChild('div', 'device-mode-presets-container'); + this._contentClip = + /** @type {!HTMLElement} */ (this.contentElement.createChild('div', 'device-mode-content-clip vbox')); + this._responsivePresetsContainer = + /** @type {!HTMLElement} */ (this._contentClip.createChild('div', 'device-mode-presets-container')); this._populatePresetsContainer(); - this._mediaInspectorContainer = this._contentClip.createChild('div', 'device-mode-media-container'); - this._contentArea = this._contentClip.createChild('div', 'device-mode-content-area'); + this._mediaInspectorContainer = + /** @type {!HTMLElement} */ (this._contentClip.createChild('div', 'device-mode-media-container')); + this._contentArea = /** @type {!HTMLElement} */ (this._contentClip.createChild('div', 'device-mode-content-area')); - this._outlineImage = this._contentArea.createChild('img', 'device-mode-outline-image hidden fill'); + this._outlineImage = + /** @type {!HTMLElement} */ (this._contentArea.createChild('img', 'device-mode-outline-image hidden fill')); this._outlineImage.addEventListener('load', this._onImageLoaded.bind(this, this._outlineImage, true), false); this._outlineImage.addEventListener('error', this._onImageLoaded.bind(this, this._outlineImage, false), false); - this._screenArea = this._contentArea.createChild('div', 'device-mode-screen-area'); - this._screenImage = this._screenArea.createChild('img', 'device-mode-screen-image hidden'); + this._screenArea = /** @type {!HTMLElement} */ (this._contentArea.createChild('div', 'device-mode-screen-area')); + this._screenImage = + /** @type {!HTMLElement} */ (this._screenArea.createChild('img', 'device-mode-screen-image hidden')); this._screenImage.addEventListener('load', this._onImageLoaded.bind(this, this._screenImage, true), false); this._screenImage.addEventListener('error', this._onImageLoaded.bind(this, this._screenImage, false), false); this._bottomRightResizerElement = - this._screenArea.createChild('div', 'device-mode-resizer device-mode-bottom-right-resizer'); + /** @type {!HTMLElement} */ ( + this._screenArea.createChild('div', 'device-mode-resizer device-mode-bottom-right-resizer')); this._bottomRightResizerElement.createChild('div', ''); this._createResizer(this._bottomRightResizerElement, 2, 1); this._bottomLeftResizerElement = - this._screenArea.createChild('div', 'device-mode-resizer device-mode-bottom-left-resizer'); + /** @type {!HTMLElement} */ ( + this._screenArea.createChild('div', 'device-mode-resizer device-mode-bottom-left-resizer')); this._bottomLeftResizerElement.createChild('div', ''); this._createResizer(this._bottomLeftResizerElement, -2, 1); - this._rightResizerElement = this._screenArea.createChild('div', 'device-mode-resizer device-mode-right-resizer'); + this._rightResizerElement = /** @type {!HTMLElement} */ ( + this._screenArea.createChild('div', 'device-mode-resizer device-mode-right-resizer')); this._rightResizerElement.createChild('div', ''); this._createResizer(this._rightResizerElement, 2, 0); - this._leftResizerElement = this._screenArea.createChild('div', 'device-mode-resizer device-mode-left-resizer'); + this._leftResizerElement = /** @type {!HTMLElement} */ ( + this._screenArea.createChild('div', 'device-mode-resizer device-mode-left-resizer')); this._leftResizerElement.createChild('div', ''); this._createResizer(this._leftResizerElement, -2, 0); - this._bottomResizerElement = this._screenArea.createChild('div', 'device-mode-resizer device-mode-bottom-resizer'); + this._bottomResizerElement = /** @type {!HTMLElement} */ ( + this._screenArea.createChild('div', 'device-mode-resizer device-mode-bottom-resizer')); this._bottomResizerElement.createChild('div', ''); this._createResizer(this._bottomResizerElement, 0, 1); this._bottomResizerElement.addEventListener('dblclick', this._model.setHeight.bind(this._model, 0), false); this._bottomResizerElement.title = Common.UIString.UIString('Double-click for full height'); - this._pageArea = this._screenArea.createChild('div', 'device-mode-page-area'); + this._pageArea = /** @type {!HTMLElement} */ (this._screenArea.createChild('div', 'device-mode-page-area')); this._pageArea.createChild('slot'); } @@ -104,10 +148,10 @@ export class DeviceModeView extends UI.Widget.VBox { const inner = this._responsivePresetsContainer.createChild('div', 'device-mode-presets-container-inner'); for (let i = sizes.length - 1; i >= 0; --i) { const outer = inner.createChild('div', 'fill device-mode-preset-bar-outer'); - const block = outer.createChild('div', 'device-mode-preset-bar'); + const block = /** @type {!HTMLElement} */ (outer.createChild('div', 'device-mode-preset-bar')); block.createChild('span').textContent = titles[i] + ' \u2013 ' + sizes[i] + 'px'; block.addEventListener('click', applySize.bind(this, sizes[i]), false); - block.__width = sizes[i]; + this.blockElementToWidth.set(block, sizes[i]); this._presetBlocks.push(block); } @@ -175,7 +219,7 @@ export class DeviceModeView extends UI.Widget.VBox { (event.data.currentY - this._slowPositionStart.y) / 10 + this._slowPositionStart.y - event.data.startY; } - if (widthFactor) { + if (widthFactor && this._resizeStart) { const dipOffsetX = cssOffsetX * UI.ZoomManager.ZoomManager.instance().zoomFactor(); let newWidth = this._resizeStart.width + dipOffsetX * widthFactor; newWidth = Math.round(newWidth / this._model.scale()); @@ -184,7 +228,7 @@ export class DeviceModeView extends UI.Widget.VBox { } } - if (heightFactor) { + if (heightFactor && this._resizeStart) { const dipOffsetY = cssOffsetY * UI.ZoomManager.ZoomManager.instance().zoomFactor(); let newHeight = this._resizeStart.height + dipOffsetY * heightFactor; newHeight = Math.round(newHeight / this._model.scale()); @@ -210,7 +254,7 @@ export class DeviceModeView extends UI.Widget.VBox { _updateUI() { /** - * @param {!Element} element + * @param {!HTMLElement} element * @param {!UI.Geometry.Rect} rect */ function applyRect(element, rect) { @@ -231,7 +275,7 @@ export class DeviceModeView extends UI.Widget.VBox { let updateRulers = false; const cssScreenRect = this._model.screenRect().scale(1 / zoomFactor); - if (!cssScreenRect.isEqual(this._cachedCssScreenRect)) { + if (!this._cachedCssScreenRect || !cssScreenRect.isEqual(this._cachedCssScreenRect)) { applyRect(this._screenArea, cssScreenRect); updateRulers = true; callDoResize = true; @@ -239,14 +283,14 @@ export class DeviceModeView extends UI.Widget.VBox { } const cssVisiblePageRect = this._model.visiblePageRect().scale(1 / zoomFactor); - if (!cssVisiblePageRect.isEqual(this._cachedCssVisiblePageRect)) { + if (!this._cachedCssVisiblePageRect || !cssVisiblePageRect.isEqual(this._cachedCssVisiblePageRect)) { applyRect(this._pageArea, cssVisiblePageRect); callDoResize = true; this._cachedCssVisiblePageRect = cssVisiblePageRect; } const outlineRect = this._model.outlineRect().scale(1 / zoomFactor); - if (!outlineRect.isEqual(this._cachedOutlineRect)) { + if (!this._cachedOutlineRect || !outlineRect.isEqual(this._cachedOutlineRect)) { applyRect(this._outlineImage, outlineRect); callDoResize = true; this._cachedOutlineRect = outlineRect; @@ -293,7 +337,11 @@ export class DeviceModeView extends UI.Widget.VBox { updateRulers = true; callDoResize = true; for (const block of this._presetBlocks) { - block.style.width = block.__width * this._model.scale() + 'px'; + const blockWidth = this.blockElementToWidth.get(block); + if (!blockWidth) { + throw new Error('Could not get width for block.'); + } + block.style.width = blockWidth * this._model.scale() + 'px'; } this._cachedScale = this._model.scale(); } @@ -361,6 +409,9 @@ export class DeviceModeView extends UI.Widget.VBox { const rect = this._contentArea.getBoundingClientRect(); const availableSize = new UI.Geometry.Size(Math.max(rect.width * zoomFactor, 1), Math.max(rect.height * zoomFactor, 1)); + if (!this._handleHeight || !this._handleWidth) { + return; + } const preferredSize = new UI.Geometry.Size( Math.max((rect.width - 2 * this._handleWidth) * zoomFactor, 1), Math.max((rect.height - this._handleHeight) * zoomFactor, 1)); @@ -411,7 +462,7 @@ export class DeviceModeView extends UI.Widget.VBox { } /** - * @return {!Promise} + * @return {!Promise} */ async captureScreenshot() { const screenshot = await this._model.captureScreenshot(false); @@ -429,10 +480,13 @@ export class DeviceModeView extends UI.Widget.VBox { const contentLeft = screenRect.left + visiblePageRect.left - outlineRect.left; const contentTop = screenRect.top + visiblePageRect.top - outlineRect.top; - const canvas = createElement('canvas'); + const canvas = document.createElement('canvas'); canvas.width = Math.floor(outlineRect.width); canvas.height = Math.floor(outlineRect.height); const ctx = canvas.getContext('2d'); + if (!ctx) { + throw new Error('Could not get 2d context from canvas.'); + } ctx.imageSmoothingEnabled = false; if (this._model.outlineImage()) { @@ -442,12 +496,12 @@ export class DeviceModeView extends UI.Widget.VBox { await this._paintImage(ctx, this._model.screenImage(), screenRect.relativeTo(outlineRect)); } ctx.drawImage(pageImage, Math.floor(contentLeft), Math.floor(contentTop)); - this._saveScreenshot(canvas); + this._saveScreenshot(/** @type {!HTMLCanvasElement} */ (canvas)); }; } /** - * @return {!Promise} + * @return {!Promise} */ async captureFullSizeScreenshot() { const screenshot = await this._model.captureScreenshot(true); @@ -459,7 +513,7 @@ export class DeviceModeView extends UI.Widget.VBox { /** * @param {!Protocol.Page.Viewport=} clip - * @return {!Promise} + * @return {!Promise} */ async captureAreaScreenshot(clip) { const screenshot = await this._model.captureScreenshot(false, clip); @@ -476,13 +530,16 @@ export class DeviceModeView extends UI.Widget.VBox { const pageImage = new Image(); pageImage.src = 'data:image/png;base64,' + screenshot; pageImage.onload = () => { - const canvas = createElement('canvas'); + const canvas = document.createElement('canvas'); canvas.width = pageImage.naturalWidth; canvas.height = pageImage.naturalHeight; const ctx = canvas.getContext('2d'); + if (!ctx) { + throw new Error('Could not get 2d context for base64 screenshot.'); + } ctx.imageSmoothingEnabled = false; ctx.drawImage(pageImage, 0, 0); - this._saveScreenshot(canvas); + this._saveScreenshot(/** @type {!HTMLCanvasElement} */ (canvas)); }; } @@ -490,23 +547,23 @@ export class DeviceModeView extends UI.Widget.VBox { * @param {!CanvasRenderingContext2D} ctx * @param {string} src * @param {!UI.Geometry.Rect} rect - * @return {!Promise} + * @return {!Promise} */ _paintImage(ctx, src, rect) { - return new Promise(fulfill => { + return new Promise(resolve => { const image = new Image(); image.crossOrigin = 'Anonymous'; image.srcset = src; - image.onerror = fulfill; + image.onerror = () => resolve(); image.onload = () => { ctx.drawImage(image, rect.left, rect.top, rect.width, rect.height); - fulfill(); + resolve(); }; }); } /** - * @param {!Element} canvas + * @param {!HTMLCanvasElement} canvas */ _saveScreenshot(canvas) { const url = this._model.inspectedURL(); @@ -516,10 +573,11 @@ export class DeviceModeView extends UI.Widget.VBox { fileName = Platform.StringUtilities.trimURL(withoutFragment); } - if (this._model.type() === Type.Device) { - fileName += Common.UIString.UIString('(%s)', this._model.device().title); + const device = this._model.device(); + if (device && this._model.type() === Type.Device) { + fileName += Common.UIString.UIString('(%s)', device.title); } - const link = createElement('a'); + const link = document.createElement('a'); link.download = fileName + '.png'; canvas.toBlob(blob => { link.href = URL.createObjectURL(blob); @@ -534,7 +592,7 @@ export class DeviceModeView extends UI.Widget.VBox { export class Ruler extends UI.Widget.VBox { /** * @param {boolean} horizontal - * @param {function(number)} applyCallback + * @param {function(number):void} applyCallback */ constructor(horizontal, applyCallback) { super(); @@ -546,6 +604,10 @@ export class Ruler extends UI.Widget.VBox { this._count = 0; this._throttler = new Common.Throttler.Throttler(0); this._applyCallback = applyCallback; + /** @type {number|undefined} */ + this._renderedScale; + /** @type {number|undefined} */ + this._renderedZoomFactor; } /** @@ -598,7 +660,10 @@ export class Ruler extends UI.Widget.VBox { for (let i = count; i < this._count; i++) { if (!(i % step)) { - this._contentElement.lastChild.remove(); + const lastChild = this._contentElement.lastChild; + if (lastChild) { + lastChild.remove(); + } } } @@ -615,7 +680,7 @@ export class Ruler extends UI.Widget.VBox { } if (!(i % 20)) { const text = marker.createChild('div', 'device-mode-ruler-text'); - text.textContent = i * 5; + text.textContent = String(i * 5); text.addEventListener('click', this._onMarkerClick.bind(this, i * 5), false); } } diff --git a/front_end/externs.js b/front_end/externs.js index 006915b1b1f..d8fe5bc83dd 100644 --- a/front_end/externs.js +++ b/front_end/externs.js @@ -895,213 +895,12 @@ const base64ToSize = function(content) {}; */ const unescapeCssString = function(input) {}; - -// Lighthouse Report Renderer - /** * @constructor * @param {!Document} document */ const DOM = function(document) {}; -/** - * @constructor - * @param {!DOM} dom - */ -const ReportRenderer = function(dom) {}; - -ReportRenderer.prototype = { - /** - * @param {!ReportRenderer.ReportJSON} report - * @param {!Element} container Parent element to render the report into. - */ - renderReport: function(report, container) {}, - - /** - * @param {!Document|!Element} context - */ - setTemplateContext: function(context) {}, - -}; - -/** - * @constructor - * @param {!DOM} dom - */ -const ReportUIFeatures = function(dom) { - /** @type {!ReportRenderer.ReportJSON} */ - this.json; - - /** @type {!Document} */ - this._document; -}; - -ReportUIFeatures.prototype = { - /** - * @param {!Document|!Element} context - */ - setTemplateContext: function(context) {}, - - /** - * @param {!ReportRenderer.ReportJSON} report - */ - initFeatures: function(report) {}, - - _resetUIState: function() {}, -}; - -/** - * @typedef {{ - * rawValue: (number|boolean|undefined), - * id: string, - * title: string, - * description: string, - * explanation: (string|undefined), - * errorMessage: (string|undefined), - * displayValue: (string|Array|undefined), - * scoreDisplayMode: string, - * error: boolean, - * score: (number|null), - * details: (!DetailsRenderer.DetailsJSON|undefined), - * }} - */ -ReportRenderer.AuditResultJSON; - -/** - * @typedef {{ - * id: string, - * score: (number|null), - * weight: number, - * group: (string|undefined), - * result: ReportRenderer.AuditResultJSON - * }} - */ -ReportRenderer.AuditJSON; - -/** - * @typedef {{ - * title: string, - * id: string, - * score: (number|null), - * description: (string|undefined), - * manualDescription: string, - * auditRefs: !Array - * }} - */ -ReportRenderer.CategoryJSON; - -/** - * @typedef {{ - * title: string, - * description: (string|undefined), - * }} - */ -ReportRenderer.GroupJSON; - -/** - * @typedef {{ - * lighthouseVersion: string, - * userAgent: string, - * fetchTime: string, - * timing: {total: number}, - * requestedUrl: string, - * finalUrl: string, - * runWarnings: (!Array|undefined), - * artifacts: {traces: {defaultPass: {traceEvents: !Array}}}, - * audits: !Object, - * categories: !Object, - * categoryGroups: !Object, - * }} - */ -ReportRenderer.ReportJSON; - -/** - * @typedef {{ - * traces: {defaultPass: {traceEvents: !Array}}, - * }} - */ -ReportRenderer.RunnerResultArtifacts; - -/** - * @typedef {{ - * lhr: !ReportRenderer.ReportJSON, - * artifacts: ReportRenderer.RunnerResultArtifacts, - * report: string, - * stack: string - * }} - */ -ReportRenderer.RunnerResult; - - -/** - * @constructor - * @param {!DOM} dom - * @param {!DetailsRenderer} detailsRenderer - */ -const CategoryRenderer = function(dom, detailsRenderer) {}; - - -/** - * @constructor - * @param {!DOM} dom - */ -const DetailsRenderer = function(dom) {}; - -DetailsRenderer.prototype = { - /** - * @param {!DetailsRenderer.NodeDetailsJSON} item - * @return {!Element} - */ - renderNode: function(item) {}, -}; - -/** - * @typedef {{ - * type: string, - * value: (string|number|undefined), - * summary: (DetailsRenderer.OpportunitySummary|undefined), - * granularity: (number|undefined), - * displayUnit: (string|undefined) - * }} - */ -DetailsRenderer.DetailsJSON; - -/** - * @typedef {{ - * type: string, - * path: (string|undefined), - * selector: (string|undefined), - * snippet:(string|undefined) - * }} - */ -DetailsRenderer.NodeDetailsJSON; - -/** - * @typedef {{ - * sourceUrl: (string|undefined), - * sourceLine: (string|undefined), - * sourceColumn: (string|undefined), - * }} - */ -DetailsRenderer.SourceLocationDetailsJSON; - -/** @typedef {{ - * wastedMs: (number|undefined), - * wastedBytes: (number|undefined), - * }} - */ -DetailsRenderer.OpportunitySummary; - -const LighthouseReportGenerator = class { - /** - * @param {!ReportRenderer.ReportJSON} lhr - * @return {string} - */ - generateReportHtml(lhr) { - return ''; - } -}; - /** @interface */ class InspectorFrontendHostAPI { /** diff --git a/front_end/formatter/FormatterWorkerPool.js b/front_end/formatter/FormatterWorkerPool.js index e7d07e362ad..44fc308256d 100644 --- a/front_end/formatter/FormatterWorkerPool.js +++ b/front_end/formatter/FormatterWorkerPool.js @@ -1,23 +1,36 @@ // Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks import * as Common from '../common/common.js'; const MaxWorkers = 2; +/** @type {!FormatterWorkerPool} */ +let formatterWorkerPoolInstance; + /** * @unrestricted */ export class FormatterWorkerPool { constructor() { + /** @type {!Array} */ this._taskQueue = []; /** @type {!Map} */ this._workerTasks = new Map(); } + /** + * @return {!FormatterWorkerPool} + */ + static instance() { + if (!formatterWorkerPoolInstance) { + formatterWorkerPoolInstance = new FormatterWorkerPool(); + } + + return formatterWorkerPoolInstance; + } + /** * @return {!Common.Worker.WorkerWrapper} */ @@ -42,8 +55,10 @@ export class FormatterWorkerPool { } const task = this._taskQueue.shift(); - this._workerTasks.set(freeWorker, task); - freeWorker.postMessage({method: task.method, params: task.params}); + if (task) { + this._workerTasks.set(freeWorker, task); + freeWorker.postMessage({method: task.method, params: task.params}); + } } /** @@ -52,6 +67,9 @@ export class FormatterWorkerPool { */ _onWorkerMessage(worker, event) { const task = this._workerTasks.get(worker); + if (!task) { + return; + } if (task.isChunked && event.data && !event.data['isLastChunk']) { task.callback(event.data); return; @@ -75,13 +93,15 @@ export class FormatterWorkerPool { const newWorker = this._createWorker(); this._workerTasks.set(newWorker, null); this._processNextTask(); - task.callback(null); + if (task) { + task.callback(null); + } } /** * @param {string} methodName * @param {!Object} params - * @param {function(boolean, *)} callback + * @param {function(boolean, *):void} callback */ _runChunkedTask(methodName, params, callback) { const task = new Task(methodName, params, onData, true); @@ -96,8 +116,8 @@ export class FormatterWorkerPool { callback(true, null); return; } - const isLastChunk = !!data['isLastChunk']; - const chunk = data['chunk']; + const isLastChunk = 'isLastChunk' in data && !!data['isLastChunk']; + const chunk = 'chunk' in data && data['chunk']; callback(isLastChunk, chunk); } } @@ -108,14 +128,11 @@ export class FormatterWorkerPool { * @return {!Promise<*>} */ _runTask(methodName, params) { - let callback; - const promise = new Promise(fulfill => { - callback = fulfill; + return new Promise(resolve => { + const task = new Task(methodName, params, resolve, false); + this._taskQueue.push(task); + this._processNextTask(); }); - const task = new Task(methodName, params, callback, false); - this._taskQueue.push(task); - this._processNextTask(); - return promise; } /** @@ -147,7 +164,7 @@ export class FormatterWorkerPool { /** * @param {string} content - * @param {function(boolean, !Array)} callback + * @param {function(boolean, !Array):void} callback */ parseCSS(content, callback) { this._runChunkedTask('parseCSS', {content: content}, onDataChunk); @@ -164,7 +181,7 @@ export class FormatterWorkerPool { /** * @param {string} content - * @param {function(boolean, !Array)} callback + * @param {function(boolean, !Array):void} callback */ javaScriptOutline(content, callback) { this._runChunkedTask('javaScriptOutline', {content: content}, onDataChunk); @@ -182,7 +199,7 @@ export class FormatterWorkerPool { /** * @param {string} content * @param {string} mimeType - * @param {function(boolean, !Array)} callback + * @param {function(boolean, !Array):void} callback * @return {boolean} */ outlineForMimetype(content, mimeType, callback) { @@ -212,10 +229,10 @@ export class FormatterWorkerPool { * @param {!Array} rules */ function cssCallback(isLastChunk, rules) { - callback( - isLastChunk, - rules.map( - rule => ({line: rule.lineNumber, column: rule.columnNumber, title: rule.selectorText || rule.atRule}))); + callback(isLastChunk, rules.map(rule => { + const title = 'selectorText' in rule ? rule.selectorText : rule.atRule; + return {line: rule.lineNumber, subtitle: undefined, column: rule.columnNumber, title}; + })); } } @@ -252,7 +269,7 @@ class Task { /** * @param {string} method * @param {!Object} params - * @param {function(?MessageEvent)} callback + * @param {function(?MessageEvent):void} callback * @param {boolean=} isChunked */ constructor(method, params, callback, isChunked) { @@ -304,22 +321,6 @@ class CSSProperty { } } -// eslint-disable-next-line no-unused-vars -class CSSStyleRule { - constructor() { - /** @type {string} */ - this.selectorText; - /** @type {!TextRange} */ - this.styleRange; - /** @type {number} */ - this.lineNumber; - /** @type {number} */ - this.columnNumber; - /** @type {!Array.} */ - this.properties; - } -} - // eslint-disable-next-line no-unused-vars class SCSSProperty { constructor() { @@ -350,29 +351,35 @@ class SCSSRule { * @return {!FormatterWorkerPool} */ export function formatterWorkerPool() { - if (!Formatter._formatterWorkerPool) { - Formatter._formatterWorkerPool = new FormatterWorkerPool(); - } - return Formatter._formatterWorkerPool; + return FormatterWorkerPool.instance(); } /** @typedef {{line: number, column: number, title: string, subtitle: (string|undefined) }} */ +// @ts-ignore typedef export let OutlineItem; /** @typedef {{original: !Array, formatted: !Array}} */ +// @ts-ignore typedef export let FormatMapping; +/** @typedef {{selectorText: string, styleRange: !TextRange, lineNumber: number, columnNumber: number, properties: !Array}} */ +// @ts-ignore typedef +export let CSSStyleRule; + /** * @typedef {{atRule: string, lineNumber: number, columnNumber: number}} */ +// @ts-ignore typedef export let CSSAtRule; /** * @typedef {(CSSStyleRule|CSSAtRule)} */ +// @ts-ignore typedef export let CSSRule; /** * @typedef {{startLine: number, startColumn: number, endLine: number, endColumn: number}} */ +// @ts-ignore typedef export let TextRange; diff --git a/front_end/formatter/SourceFormatter.js b/front_end/formatter/SourceFormatter.js index 1a53ca72e3d..2df76926b73 100644 --- a/front_end/formatter/SourceFormatter.js +++ b/front_end/formatter/SourceFormatter.js @@ -1,8 +1,6 @@ // Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks import * as Bindings from '../bindings/bindings.js'; import * as Common from '../common/common.js'; @@ -12,6 +10,9 @@ import * as Workspace from '../workspace/workspace.js'; import {FormatterInterface, FormatterSourceMapping} from './ScriptFormatter.js'; // eslint-disable-line no-unused-vars +/** @type {!WeakMap} */ +const objectToFormattingResult = new WeakMap(); + export class SourceFormatData { /** * @param {!Workspace.UISourceCode.UISourceCode} originalSourceCode @@ -33,12 +34,10 @@ export class SourceFormatData { * @return {?SourceFormatData} */ static _for(object) { - return object[SourceFormatData._formatDataSymbol]; + return objectToFormattingResult.get(object) || null; } } -SourceFormatData._formatDataSymbol = Symbol('formatData'); - /** @type {?SourceFormatter} */ let sourceFormatterInstance = null; @@ -99,7 +98,7 @@ export class SourceFormatter { * @param {!SourceFormatData} formatData */ async _discardFormatData(formatData) { - delete formatData.formattedSourceCode[SourceFormatData._formatDataSymbol]; + objectToFormattingResult.delete(formatData.formattedSourceCode); await this._scriptMapping._setSourceMappingEnabled(formatData, false); this._styleMapping._setSourceMappingEnabled(formatData, false); this._project.removeFile(formatData.formattedSourceCode.url()); @@ -118,8 +117,7 @@ export class SourceFormatter { * @return {!Workspace.UISourceCode.UISourceCode} */ getOriginalUISourceCode(uiSourceCode) { - const formatData = - /** @type {?SourceFormatData} */ (uiSourceCode[SourceFormatData._formatDataSymbol]); + const formatData = objectToFormattingResult.get(uiSourceCode); if (!formatData) { return uiSourceCode; } @@ -136,57 +134,54 @@ export class SourceFormatter { return cacheEntry.promise; } - let fulfillFormatPromise; - const resultPromise = new Promise(fulfill => { - fulfillFormatPromise = fulfill; - }); - this._formattedSourceCodes.set(uiSourceCode, {promise: resultPromise, formatData: null}); - const {content} = await uiSourceCode.requestContent(); - // ------------ ASYNC ------------ - FormatterInterface.format( - uiSourceCode.contentType(), uiSourceCode.mimeType(), content || '', formatDone.bind(this)); - return resultPromise; - /** - * @this SourceFormatter - * @param {string} formattedContent - * @param {!FormatterSourceMapping} formatterMapping + * @type {!Promise} */ - async function formatDone(formattedContent, formatterMapping) { - const cacheEntry = this._formattedSourceCodes.get(uiSourceCode); - if (!cacheEntry || cacheEntry.promise !== resultPromise) { - return; - } - let formattedURL; - let count = 0; - let suffix = ''; - do { - formattedURL = `${uiSourceCode.url()}:formatted${suffix}`; - suffix = `:${count++}`; - } while (this._project.uiSourceCodeForURL(formattedURL)); - const contentProvider = TextUtils.StaticContentProvider.StaticContentProvider.fromString( - formattedURL, uiSourceCode.contentType(), formattedContent); - const formattedUISourceCode = this._project.createUISourceCode(formattedURL, contentProvider.contentType()); - const formatData = new SourceFormatData(uiSourceCode, formattedUISourceCode, formatterMapping); - formattedUISourceCode[SourceFormatData._formatDataSymbol] = formatData; - this._project.addUISourceCodeWithProvider( - formattedUISourceCode, contentProvider, /* metadata */ null, uiSourceCode.mimeType()); - await this._scriptMapping._setSourceMappingEnabled(formatData, true); - await this._styleMapping._setSourceMappingEnabled(formatData, true); - cacheEntry.formatData = formatData; - - for (const decoration of uiSourceCode.allDecorations()) { - const range = decoration.range(); - const startLocation = formatterMapping.originalToFormatted(range.startLine, range.startColumn); - const endLocation = formatterMapping.originalToFormatted(range.endLine, range.endColumn); - - formattedUISourceCode.addDecoration( - new TextUtils.TextRange.TextRange(startLocation[0], startLocation[1], endLocation[0], endLocation[1]), - /** @type {string} */ (decoration.type()), decoration.data()); - } + const resultPromise = new Promise(async resolve => { + const {content} = await uiSourceCode.requestContent(); - fulfillFormatPromise(formatData); - } + FormatterInterface.format( + uiSourceCode.contentType(), uiSourceCode.mimeType(), content || '', + async (formattedContent, formatterMapping) => { + const cacheEntry = this._formattedSourceCodes.get(uiSourceCode); + if (!cacheEntry || cacheEntry.promise !== resultPromise) { + return; + } + let formattedURL; + let count = 0; + let suffix = ''; + do { + formattedURL = `${uiSourceCode.url()}:formatted${suffix}`; + suffix = `:${count++}`; + } while (this._project.uiSourceCodeForURL(formattedURL)); + const contentProvider = TextUtils.StaticContentProvider.StaticContentProvider.fromString( + formattedURL, uiSourceCode.contentType(), formattedContent); + const formattedUISourceCode = this._project.createUISourceCode(formattedURL, contentProvider.contentType()); + const formatData = new SourceFormatData(uiSourceCode, formattedUISourceCode, formatterMapping); + objectToFormattingResult.set(formattedUISourceCode, formatData); + this._project.addUISourceCodeWithProvider( + formattedUISourceCode, contentProvider, /* metadata */ null, uiSourceCode.mimeType()); + await this._scriptMapping._setSourceMappingEnabled(formatData, true); + await this._styleMapping._setSourceMappingEnabled(formatData, true); + cacheEntry.formatData = formatData; + + for (const decoration of uiSourceCode.allDecorations()) { + const range = decoration.range(); + const startLocation = formatterMapping.originalToFormatted(range.startLine, range.startColumn); + const endLocation = formatterMapping.originalToFormatted(range.endLine, range.endColumn); + + formattedUISourceCode.addDecoration( + new TextUtils.TextRange.TextRange(startLocation[0], startLocation[1], endLocation[0], endLocation[1]), + /** @type {string} */ (decoration.type()), decoration.data()); + } + + resolve(formatData); + }); + }); + + this._formattedSourceCodes.set(uiSourceCode, {promise: resultPromise, formatData: null}); + + return resultPromise; } } @@ -206,7 +201,7 @@ class ScriptMapping { rawLocationToUILocation(rawLocation) { const script = rawLocation.script(); const formatData = script && SourceFormatData._for(script); - if (!formatData) { + if (!formatData || !script) { return null; } if (script.isInlineScriptWithSourceURL()) { @@ -260,7 +255,8 @@ class ScriptMapping { .filter(script => script.isInlineScript() && !script.hasSourceURL); // Here we have an inline script, which was formatted together with the containing document, so we must not // translate locations as they are relative to the start of the document. - const locations = scripts.map(script => script.rawLocation(originalLine, originalColumn)).filter(l => !!l); + const locations = /** @type {!Array} */ ( + scripts.map(script => script.rawLocation(originalLine, originalColumn)).filter(l => !!l)); console.assert(locations.every(l => l && !!l.script())); return locations; } @@ -279,11 +275,11 @@ class ScriptMapping { } if (enabled) { for (const script of scripts) { - script[SourceFormatData._formatDataSymbol] = formatData; + objectToFormattingResult.set(script, formatData); } } else { for (const script of scripts) { - delete script[SourceFormatData._formatDataSymbol]; + objectToFormattingResult.delete(script); } } const updatePromises = scripts.map( @@ -306,17 +302,19 @@ class ScriptMapping { } } if (uiSourceCode.contentType().isScript()) { - console.assert( - !uiSourceCode[SourceFormatData._formatDataSymbol] || - uiSourceCode[SourceFormatData._formatDataSymbol] === uiSourceCode); + console.assert(!objectToFormattingResult.has(uiSourceCode)); const rawLocations = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance() .uiLocationToRawLocationsForUnformattedJavaScript(uiSourceCode, 0, 0); - return rawLocations.map(location => location.script()).filter(script => !!script); + return /** @type {!Array} */ ( + rawLocations.map(location => location.script()).filter(script => !!script)); } return []; } } +/** @type {!WeakMap>} */ +const sourceCodeToHeaders = new WeakMap(); + /** * @implements {Bindings.CSSWorkspaceBinding.SourceMapping} */ @@ -354,8 +352,13 @@ class StyleMapping { } const [originalLine, originalColumn] = formatData.mapping.formattedToOriginal(uiLocation.lineNumber, uiLocation.columnNumber); - const headers = formatData.originalSourceCode[this._headersSymbol].filter( - header => header.containsLocation(originalLine, originalColumn)); + const allHeaders = sourceCodeToHeaders.get(formatData.originalSourceCode); + + if (!allHeaders) { + return []; + } + + const headers = allHeaders.filter(header => header.containsLocation(originalLine, originalColumn)); return headers.map(header => new SDK.CSSModel.CSSLocation(header, originalLine, originalColumn)); } @@ -367,13 +370,15 @@ class StyleMapping { const original = formatData.originalSourceCode; const headers = this._headersForUISourceCode(original); if (enable) { - original[this._headersSymbol] = headers; + sourceCodeToHeaders.set(original, headers); headers.forEach(header => { - header[SourceFormatData._formatDataSymbol] = formatData; + objectToFormattingResult.set(header, formatData); }); } else { - original[this._headersSymbol] = null; - headers.forEach(header => delete header[SourceFormatData._formatDataSymbol]); + sourceCodeToHeaders.delete(original); + headers.forEach(header => { + objectToFormattingResult.delete(header); + }); } const updatePromises = headers.map(header => Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().updateLocations(header)); @@ -395,7 +400,8 @@ class StyleMapping { } else if (uiSourceCode.contentType().isStyleSheet()) { const rawLocations = Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().uiLocationToRawLocations( uiSourceCode.uiLocation(0, 0)); - return rawLocations.map(rawLocation => rawLocation.header()).filter(header => !!header); + return /** @type {!Array} */ ( + rawLocations.map(rawLocation => rawLocation.header()).filter(header => !!header)); } return []; } diff --git a/front_end/generated/InspectorBackendCommands.js b/front_end/generated/InspectorBackendCommands.js index 7dc232f2dc4..314a863f7fa 100644 --- a/front_end/generated/InspectorBackendCommands.js +++ b/front_end/generated/InspectorBackendCommands.js @@ -901,6 +901,7 @@ export function registerCommands(inspectorBackend) { inspectorBackend.registerEnum( 'Emulation.VirtualTimePolicy', {Advance: 'advance', Pause: 'pause', PauseIfNetworkFetchesPending: 'pauseIfNetworkFetchesPending'}); + inspectorBackend.registerEnum('Emulation.DisabledImageType', {Avif: 'avif', Webp: 'webp'}); inspectorBackend.registerEvent('Emulation.virtualTimeBudgetExpired', []); inspectorBackend.registerCommand('Emulation.canEmulate', [], ['result']); inspectorBackend.registerCommand('Emulation.clearDeviceMetricsOverride', [], []); @@ -1001,6 +1002,8 @@ export function registerCommands(inspectorBackend) { 'Emulation.setVisibleSize', [{'name': 'width', 'type': 'number', 'optional': false}, {'name': 'height', 'type': 'number', 'optional': false}], []); + inspectorBackend.registerCommand( + 'Emulation.setDisabledImageTypes', [{'name': 'imageTypes', 'type': 'object', 'optional': false}], []); inspectorBackend.registerCommand( 'Emulation.setUserAgentOverride', [ @@ -1396,6 +1399,32 @@ export function registerCommands(inspectorBackend) { CorpNotSameOriginAfterDefaultedToSameOriginByCoep: 'corp-not-same-origin-after-defaulted-to-same-origin-by-coep', CorpNotSameSite: 'corp-not-same-site' }); + inspectorBackend.registerEnum('Network.CorsError', { + DisallowedByMode: 'DisallowedByMode', + InvalidResponse: 'InvalidResponse', + WildcardOriginNotAllowed: 'WildcardOriginNotAllowed', + MissingAllowOriginHeader: 'MissingAllowOriginHeader', + MultipleAllowOriginValues: 'MultipleAllowOriginValues', + InvalidAllowOriginValue: 'InvalidAllowOriginValue', + AllowOriginMismatch: 'AllowOriginMismatch', + InvalidAllowCredentials: 'InvalidAllowCredentials', + CorsDisabledScheme: 'CorsDisabledScheme', + PreflightInvalidStatus: 'PreflightInvalidStatus', + PreflightDisallowedRedirect: 'PreflightDisallowedRedirect', + PreflightWildcardOriginNotAllowed: 'PreflightWildcardOriginNotAllowed', + PreflightMissingAllowOriginHeader: 'PreflightMissingAllowOriginHeader', + PreflightMultipleAllowOriginValues: 'PreflightMultipleAllowOriginValues', + PreflightInvalidAllowOriginValue: 'PreflightInvalidAllowOriginValue', + PreflightAllowOriginMismatch: 'PreflightAllowOriginMismatch', + PreflightInvalidAllowCredentials: 'PreflightInvalidAllowCredentials', + PreflightMissingAllowExternal: 'PreflightMissingAllowExternal', + PreflightInvalidAllowExternal: 'PreflightInvalidAllowExternal', + InvalidAllowMethodsPreflightResponse: 'InvalidAllowMethodsPreflightResponse', + InvalidAllowHeadersPreflightResponse: 'InvalidAllowHeadersPreflightResponse', + MethodDisallowedByPreflightResponse: 'MethodDisallowedByPreflightResponse', + HeaderDisallowedByPreflightResponse: 'HeaderDisallowedByPreflightResponse', + RedirectContainsCredentials: 'RedirectContainsCredentials' + }); inspectorBackend.registerEnum( 'Network.ServiceWorkerResponseSource', {CacheStorage: 'cache-storage', HttpCache: 'http-cache', FallbackCode: 'fallback-code', Network: 'network'}); @@ -1460,7 +1489,8 @@ export function registerCommands(inspectorBackend) { inspectorBackend.registerEvent( 'Network.eventSourceMessageReceived', ['requestId', 'timestamp', 'eventName', 'eventId', 'data']); inspectorBackend.registerEvent( - 'Network.loadingFailed', ['requestId', 'timestamp', 'type', 'errorText', 'canceled', 'blockedReason']); + 'Network.loadingFailed', + ['requestId', 'timestamp', 'type', 'errorText', 'canceled', 'blockedReason', 'corsErrorStatus']); inspectorBackend.registerEvent( 'Network.loadingFinished', ['requestId', 'timestamp', 'encodedDataLength', 'shouldReportCorbBlocking']); inspectorBackend.registerEvent('Network.requestIntercepted', [ diff --git a/front_end/generated/protocol-mapping.d.ts b/front_end/generated/protocol-mapping.d.ts index 9173041df3a..8fba360573c 100644 --- a/front_end/generated/protocol-mapping.d.ts +++ b/front_end/generated/protocol-mapping.d.ts @@ -1444,6 +1444,8 @@ export namespace ProtocolMapping { * on Android. */ 'Emulation.setVisibleSize': {paramsType: [Protocol.Emulation.SetVisibleSizeRequest]; returnType: void;}; + 'Emulation.setDisabledImageTypes': + {paramsType: [Protocol.Emulation.SetDisabledImageTypesRequest]; returnType: void;}; /** * Allows overriding user agent with the given string. */ diff --git a/front_end/generated/protocol-proxy-api.d.ts b/front_end/generated/protocol-proxy-api.d.ts index d2d24224343..a68a612b6e0 100644 --- a/front_end/generated/protocol-proxy-api.d.ts +++ b/front_end/generated/protocol-proxy-api.d.ts @@ -1281,6 +1281,9 @@ declare namespace ProtocolProxyApi { invoke_setVisibleSize(params: Protocol.Emulation.SetVisibleSizeRequest): Promise; + invoke_setDisabledImageTypes(params: Protocol.Emulation.SetDisabledImageTypesRequest): + Promise; + /** * Allows overriding user agent with the given string. */ diff --git a/front_end/generated/protocol.d.ts b/front_end/generated/protocol.d.ts index 3f87c1dd256..7e8b1951f16 100644 --- a/front_end/generated/protocol.d.ts +++ b/front_end/generated/protocol.d.ts @@ -4558,6 +4558,14 @@ declare namespace Protocol { mobile: boolean; } + /** + * Enum of image types that can be disabled. + */ + export enum DisabledImageType { + Avif = 'avif', + Webp = 'webp', + } + export interface CanEmulateResponse extends ProtocolResponseWithError { /** * True if emulation is supported. @@ -4817,6 +4825,13 @@ declare namespace Protocol { height: integer; } + export interface SetDisabledImageTypesRequest { + /** + * Image types to disable. + */ + imageTypes: DisabledImageType[]; + } + export interface SetUserAgentOverrideRequest { /** * User agent to use. @@ -6619,6 +6634,41 @@ declare namespace Protocol { CorpNotSameSite = 'corp-not-same-site', } + /** + * The reason why request was blocked. + */ + export enum CorsError { + DisallowedByMode = 'DisallowedByMode', + InvalidResponse = 'InvalidResponse', + WildcardOriginNotAllowed = 'WildcardOriginNotAllowed', + MissingAllowOriginHeader = 'MissingAllowOriginHeader', + MultipleAllowOriginValues = 'MultipleAllowOriginValues', + InvalidAllowOriginValue = 'InvalidAllowOriginValue', + AllowOriginMismatch = 'AllowOriginMismatch', + InvalidAllowCredentials = 'InvalidAllowCredentials', + CorsDisabledScheme = 'CorsDisabledScheme', + PreflightInvalidStatus = 'PreflightInvalidStatus', + PreflightDisallowedRedirect = 'PreflightDisallowedRedirect', + PreflightWildcardOriginNotAllowed = 'PreflightWildcardOriginNotAllowed', + PreflightMissingAllowOriginHeader = 'PreflightMissingAllowOriginHeader', + PreflightMultipleAllowOriginValues = 'PreflightMultipleAllowOriginValues', + PreflightInvalidAllowOriginValue = 'PreflightInvalidAllowOriginValue', + PreflightAllowOriginMismatch = 'PreflightAllowOriginMismatch', + PreflightInvalidAllowCredentials = 'PreflightInvalidAllowCredentials', + PreflightMissingAllowExternal = 'PreflightMissingAllowExternal', + PreflightInvalidAllowExternal = 'PreflightInvalidAllowExternal', + InvalidAllowMethodsPreflightResponse = 'InvalidAllowMethodsPreflightResponse', + InvalidAllowHeadersPreflightResponse = 'InvalidAllowHeadersPreflightResponse', + MethodDisallowedByPreflightResponse = 'MethodDisallowedByPreflightResponse', + HeaderDisallowedByPreflightResponse = 'HeaderDisallowedByPreflightResponse', + RedirectContainsCredentials = 'RedirectContainsCredentials', + } + + export interface CorsErrorStatus { + corsError: CorsError; + failedParameter: string; + } + /** * Source of serviceworker response. */ @@ -7790,6 +7840,10 @@ declare namespace Protocol { * The reason why loading was blocked, if any. */ blockedReason?: BlockedReason; + /** + * The reason why loading was blocked by CORS, if any. + */ + corsErrorStatus?: CorsErrorStatus; } /** diff --git a/front_end/host/UserMetrics.js b/front_end/host/UserMetrics.js index 95f7a3e7daa..e1ba1b6a8bd 100644 --- a/front_end/host/UserMetrics.js +++ b/front_end/host/UserMetrics.js @@ -638,7 +638,12 @@ export const IssueResourceOpened = { SameSiteCookieRequest: 4, HeavyAdElement: 5, ContentSecurityPolicyDirective: 6, - ContentSecurityPolicyElement: 7 + ContentSecurityPolicyElement: 7, + CrossOriginEmbedderPolicyLearnMore: 8, + MixedContentLearnMore: 9, + SameSiteCookieLearnMore: 10, + HeavyAdLearnMore: 11, + ContentSecurityPolicyLearnMore: 12 }; /** @enum {number} */ diff --git a/front_end/inline_editor/BUILD.gn b/front_end/inline_editor/BUILD.gn index 4ab64d96fc1..771dc95d392 100644 --- a/front_end/inline_editor/BUILD.gn +++ b/front_end/inline_editor/BUILD.gn @@ -10,6 +10,10 @@ devtools_module("inline_editor") { sources = [ "BezierEditor.js", "BezierUI.js", + "CSSAngle.ts", + "CSSAngleRegex.js", + "CSSAngleUtils.ts", + "CSSAngle_bridge.js", "CSSShadowEditor.js", "CSSShadowModel.js", "CSSVarSwatch.ts", diff --git a/front_end/inline_editor/BezierEditor.js b/front_end/inline_editor/BezierEditor.js index c044aa67d62..9cf8926c060 100644 --- a/front_end/inline_editor/BezierEditor.js +++ b/front_end/inline_editor/BezierEditor.js @@ -41,7 +41,7 @@ export class BezierEditor extends UI.Widget.VBox { // Curve UI this._curveUI = new BezierUI(150, 250, 50, 7, true); - this._curve = this._outerContainer.createSVGChild('svg', 'bezier-curve'); + this._curve = UI.UIUtils.createSVGChild(this._outerContainer, 'svg', 'bezier-curve'); UI.UIUtils.installDragHandle( this._curve, this._dragStart.bind(this), this._dragMove.bind(this), this._dragEnd.bind(this), 'default'); @@ -162,7 +162,7 @@ export class BezierEditor extends UI.Widget.VBox { _createCategory(presetGroup) { const presetElement = document.createElement('div'); presetElement.classList.add('bezier-preset-category'); - const iconElement = presetElement.createSVGChild('svg', 'bezier-preset monospace'); + const iconElement = UI.UIUtils.createSVGChild(presetElement, 'svg', 'bezier-preset monospace'); const category = {presets: presetGroup, presetIndex: 0, icon: presetElement}; this._presetUI.drawCurve(UI.Geometry.CubicBezier.parse(category.presets[0].value), iconElement); iconElement.addEventListener('click', this._presetCategorySelected.bind(this, category)); @@ -176,10 +176,10 @@ export class BezierEditor extends UI.Widget.VBox { * @return {!Element} */ _createPresetModifyIcon(parentElement, className, drawPath) { - const icon = parentElement.createSVGChild('svg', 'bezier-preset-modify ' + className); + const icon = UI.UIUtils.createSVGChild(parentElement, 'svg', 'bezier-preset-modify ' + className); icon.setAttribute('width', 20); icon.setAttribute('height', 20); - const path = icon.createSVGChild('path'); + const path = UI.UIUtils.createSVGChild(icon, 'path'); path.setAttribute('d', drawPath); return icon; } diff --git a/front_end/inline_editor/BezierUI.js b/front_end/inline_editor/BezierUI.js index 065328a0dfb..1c9790f2b39 100644 --- a/front_end/inline_editor/BezierUI.js +++ b/front_end/inline_editor/BezierUI.js @@ -72,7 +72,7 @@ export class BezierUI { * @param {number} y2 */ _drawLine(parentElement, className, x1, y1, x2, y2) { - const line = parentElement.createSVGChild('line', className); + const line = UI.UIUtils.createSVGChild(parentElement, 'line', className); line.setAttribute('x1', x1 + this.radius); line.setAttribute('y1', y1 + this.radius + this.marginTop); line.setAttribute('x2', x2 + this.radius); @@ -88,7 +88,7 @@ export class BezierUI { */ _drawControlPoints(parentElement, startX, startY, controlX, controlY) { this._drawLine(parentElement, 'bezier-control-line', startX, startY, controlX, controlY); - const circle = parentElement.createSVGChild('circle', 'bezier-control-circle'); + const circle = UI.UIUtils.createSVGChild(parentElement, 'circle', 'bezier-control-circle'); circle.setAttribute('cx', controlX + this.radius); circle.setAttribute('cy', controlY + this.radius + this.marginTop); circle.setAttribute('r', this.radius); @@ -107,13 +107,13 @@ export class BezierUI { svg.setAttribute('width', this.width); svg.setAttribute('height', this.height); svg.removeChildren(); - const group = svg.createSVGChild('g'); + const group = UI.UIUtils.createSVGChild(svg, 'g'); if (this.linearLine) { this._drawLine(group, 'linear-line', 0, height, width, 0); } - const curve = group.createSVGChild('path', 'bezier-path'); + const curve = UI.UIUtils.createSVGChild(group, 'path', 'bezier-path'); const curvePoints = [ new UI.Geometry.Point( bezier.controlPoints[0].x * width + this.radius, diff --git a/front_end/elements/CSSAngle.ts b/front_end/inline_editor/CSSAngle.ts similarity index 90% rename from front_end/elements/CSSAngle.ts rename to front_end/inline_editor/CSSAngle.ts index 0c0e356a7df..999fa2d14a6 100644 --- a/front_end/elements/CSSAngle.ts +++ b/front_end/inline_editor/CSSAngle.ts @@ -12,6 +12,7 @@ const styleMap = LitHtml.Directives.styleMap; const MiniIconWidth = 11; const ClockDialLength = 6; +const ContextAwareProperties = new Set(['color', 'background', 'background-color']); export class PopoverToggledEvent extends Event { data: {open: boolean}; @@ -32,6 +33,8 @@ export class ValueChangedEvent extends Event { } export interface CSSAngleData { + propertyName: string; + propertyValue: string; angleText: string; containingPane: HTMLElement; } @@ -40,8 +43,10 @@ export class CSSAngle extends HTMLElement { private readonly shadow = this.attachShadow({mode: 'open'}); private angle = 0; private unit = AngleUnit.Deg; - private mousemoveThrottler = new Common.Throttler.Throttler(16.67 /* 60fps */); + private propertyName = ''; + private propertyValue = ''; private containingPane?: HTMLElement; + private mousemoveThrottler = new Common.Throttler.Throttler(16.67 /* 60fps */); private popoverOpen = false; private popoverStyleTop = ''; private clockRadius = 77 / 2; // By default the clock is 77 * 77. @@ -55,8 +60,9 @@ export class CSSAngle extends HTMLElement { } this.angle = parsedResult.value; this.unit = parsedResult.unit; + this.propertyName = data.propertyName; + this.propertyValue = data.propertyValue; this.containingPane = data.containingPane; - // TODO(changhaohan): crbug.com/1138633 render based on the type of the property value this.render(); } @@ -75,7 +81,7 @@ export class CSSAngle extends HTMLElement { if (!miniIcon || !this.containingPane) { return; } - this.popoverOpen = true; + this.dispatchEvent(new PopoverToggledEvent(true)); document.addEventListener('mousedown', this.onMinifyingAction); this.containingPane.addEventListener('scroll', this.onMinifyingAction); @@ -89,10 +95,16 @@ export class CSSAngle extends HTMLElement { const topElementOffset = this.containingPane.getBoundingClientRect().top; this.popoverStyleTop = `${miniIconBottom - topElementOffset}px`; } + + this.popoverOpen = true; this.render(); } minify(): void { + if (this.popoverOpen === false) { + return; + } + this.popoverOpen = false; this.dispatchEvent(new PopoverToggledEvent(false)); document.removeEventListener('mousedown', this.onMinifyingAction); @@ -102,6 +114,12 @@ export class CSSAngle extends HTMLElement { this.render(); } + updateProperty(name: string, value: string): void { + this.propertyName = name; + this.propertyValue = value; + this.render(); + } + private onMiniIconClick(event: Event): void { event.stopPropagation(); this.popoverOpen ? this.minify() : this.popover(); @@ -136,7 +154,6 @@ export class CSSAngle extends HTMLElement { const degree = -Math.atan2(mouseX - clockCenterX, mouseY - clockCenterY) * 180 / Math.PI + 180; const rawAngle = getAngleFromDegrees(degree, this.unit); this.angle = roundAngleByUnit(rawAngle, this.unit); - this.render(); this.dispatchEvent(new ValueChangedEvent(`${this.angle}${this.unit}`)); } @@ -225,17 +242,21 @@ export class CSSAngle extends HTMLElement { bottom: 0; } - .center { - width: 0.7em; - height: 0.7em; - border-radius: 10px; + .center, .hand { box-shadow: 0 0 2px hsl(0 0% 0% / 20%); } - :host-context(.-theme-with-dark-background) .center { + :host-context(.-theme-with-dark-background) .center, + :host-context(.-theme-with-dark-background) .hand { box-shadow: 0 0 2px hsl(0 0% 0% / 60%); } + .center { + width: 0.7em; + height: 0.7em; + border-radius: 10px; + } + .dial { width: 2px; height: ${ClockDialLength}px; @@ -247,7 +268,6 @@ export class CSSAngle extends HTMLElement { height: 50%; width: 0.3em; background: var(--accent-fg-color); - box-shadow: var(--drop-shadow); } .hand::before { @@ -294,6 +314,15 @@ export class CSSAngle extends HTMLElement { } private renderPopover() { + const clockStyles = { + background: '', + }; + // TODO(crbug.com/1143010): for now we ignore values with "url"; when we refactor + // CSS value parsing we should properly apply atomic contextual background. + if (ContextAwareProperties.has(this.propertyName) && !this.propertyValue.match(/url\(.*\)/i)) { + clockStyles.background = this.propertyValue; + } + const {translateX, translateY} = get2DTranslationsForAngle(this.angle, this.unit, this.clockRadius / 2); const handStyles = { transform: `translate(${translateX}px, ${translateY}px) rotate(${this.angle}${this.unit})`, @@ -305,6 +334,7 @@ export class CSSAngle extends HTMLElement {
${this.renderDials()} diff --git a/front_end/elements/CSSAngleRegex.js b/front_end/inline_editor/CSSAngleRegex.js similarity index 100% rename from front_end/elements/CSSAngleRegex.js rename to front_end/inline_editor/CSSAngleRegex.js diff --git a/front_end/elements/CSSAngleUtils.ts b/front_end/inline_editor/CSSAngleUtils.ts similarity index 75% rename from front_end/elements/CSSAngleUtils.ts rename to front_end/inline_editor/CSSAngleUtils.ts index 4f16d8a117f..e1419e7e6a0 100644 --- a/front_end/elements/CSSAngleUtils.ts +++ b/front_end/inline_editor/CSSAngleUtils.ts @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import * as UI from '../ui/ui.js'; + import {CSSAngleRegex} from './CSSAngleRegex.js'; export const enum AngleUnit { @@ -23,21 +25,14 @@ export const parseText = (text: string): {value: number, unit: AngleUnit}|null = }; }; -export const degreesToGradians = (deg: number): number => deg / 9 * 10; -export const degreesToRadians = (deg: number): number => deg / 180 * Math.PI; -export const degreesToTurns = (deg: number): number => deg / 360; - -export const gradiansToRadians = (grad: number): number => grad * Math.PI / 200; -export const turnsToRadians = (turns: number): number => turns * 2 * Math.PI; - export const getAngleFromDegrees = (deg: number, targetUnit: AngleUnit): number => { switch (targetUnit) { case AngleUnit.Grad: - return degreesToGradians(deg); + return UI.Geometry.degreesToGradians(deg); case AngleUnit.Rad: - return degreesToRadians(deg); + return UI.Geometry.degreesToRadians(deg); case AngleUnit.Turn: - return degreesToTurns(deg); + return UI.Geometry.degreesToTurns(deg); } return deg; @@ -46,11 +41,11 @@ export const getAngleFromDegrees = (deg: number, targetUnit: AngleUnit): number export const getRadiansFromAngle = (angle: number, unit: AngleUnit): number => { switch (unit) { case AngleUnit.Deg: - return degreesToRadians(angle); + return UI.Geometry.degreesToRadians(angle); case AngleUnit.Grad: - return gradiansToRadians(angle); + return UI.Geometry.gradiansToRadians(angle); case AngleUnit.Turn: - return turnsToRadians(angle); + return UI.Geometry.turnsToRadians(angle); } return angle; diff --git a/front_end/elements/CSSAngle_bridge.js b/front_end/inline_editor/CSSAngle_bridge.js similarity index 80% rename from front_end/elements/CSSAngle_bridge.js rename to front_end/inline_editor/CSSAngle_bridge.js index 20bf77138fb..108eae98e83 100644 --- a/front_end/elements/CSSAngle_bridge.js +++ b/front_end/inline_editor/CSSAngle_bridge.js @@ -6,12 +6,14 @@ * WARNING: do not modify this file by hand! * it was automatically generated by the bridge generator * if you made changes to the source code and need to update this file, run: -* npm run generate-bridge-file front_end/elements/CSSAngle.ts +* npm run generate-bridge-file front_end/inline_editor/CSSAngle.ts */ import './CSSAngle.js'; /** * @typedef {{ +* propertyName:string, +* propertyValue:string, * angleText:string, * containingPane:!HTMLElement, * }} @@ -31,6 +33,13 @@ export class CSSAngleClosureInterface extends HTMLElement { minify() { } /** + * @param {string} name + * @param {string} value + * @return {void} + */ + updateProperty(name, value) { + } + /** * @param {!CSSAngleData} data */ set data(data) { diff --git a/front_end/inline_editor/CSSVarSwatch.ts b/front_end/inline_editor/CSSVarSwatch.ts index d054212167f..bdaaf4186b1 100644 --- a/front_end/inline_editor/CSSVarSwatch.ts +++ b/front_end/inline_editor/CSSVarSwatch.ts @@ -3,12 +3,10 @@ // found in the LICENSE file. import * as Common from '../common/common.js'; -import * as ComponentHelpers from '../component_helpers/component_helpers.js'; import * as LitHtml from '../third_party/lit-html/lit-html.js'; const {render, html, Directives} = LitHtml; const ls = Common.ls; -const getStyleSheets = ComponentHelpers.GetStylesheet.getStyleSheets; const VARIABLE_FUNCTION_REGEX = /(var\()(--[^,)]+)(.*)/; @@ -28,28 +26,16 @@ interface ParsedVariableFunction { export class CSSVarSwatch extends HTMLElement { private readonly shadow = this.attachShadow({mode: 'open'}); private text: string = ''; - private color: Common.Color.Color|null = null; private computedValue: string|null = null; private fromFallback: boolean = false; private onLinkClick: (varialeName: string, event: Event) => void = () => undefined; - constructor() { - super(); - this.shadow.adoptedStyleSheets = [ - ...getStyleSheets('inline_editor/colorSwatch.css', {patchThemeSupport: false}), - ]; - } - set data(data: SwatchRenderData) { this.text = data.text; this.computedValue = data.computedValue; this.fromFallback = data.fromFallback; this.onLinkClick = data.onLinkClick; - if (this.computedValue) { - this.color = Common.Color.Color.parse(this.computedValue); - } - this.render(); } @@ -88,19 +74,6 @@ export class CSSVarSwatch extends HTMLElement { variableName}`; } - private renderColorSwatch() { - if (!this.color) { - return ''; - } - - // Disabled until https://crbug.com/1079231 is fixed. - // clang-format off - return html` - - `; - // clang-format on - } - private render() { const functionParts = this.parseVariableFunctionParts(); if (!functionParts) { @@ -109,7 +82,6 @@ export class CSSVarSwatch extends HTMLElement { } const link = this.renderLink(functionParts.name); - const colorSwatch = this.renderColorSwatch(); // Disabled until https://crbug.com/1079231 is fixed. // clang-format off @@ -119,7 +91,7 @@ export class CSSVarSwatch extends HTMLElement { cursor: pointer; text-decoration: underline; } - ${colorSwatch}${functionParts.pre}${link}${functionParts.post}`, + ${functionParts.pre}${link}${functionParts.post}`, this.shadow, { eventContext: this }); // clang-format on } diff --git a/front_end/inline_editor/SwatchPopoverHelper.js b/front_end/inline_editor/SwatchPopoverHelper.js index 6f021d6a6db..bf5bebed531 100644 --- a/front_end/inline_editor/SwatchPopoverHelper.js +++ b/front_end/inline_editor/SwatchPopoverHelper.js @@ -59,6 +59,8 @@ export class SwatchPopoverHelper extends Common.ObjectWrapper.ObjectWrapper { this.hide(true); } + this.dispatchEventToListeners(Events.WillShowPopover); + this._isHidden = false; this._anchorElement = anchorElement; this._view = view; @@ -140,3 +142,8 @@ export class SwatchPopoverHelper extends Common.ObjectWrapper.ObjectWrapper { } } } + +/** @enum {symbol} */ +export const Events = { + WillShowPopover: Symbol('WillShowPopover'), +}; diff --git a/front_end/inline_editor/inline_editor.js b/front_end/inline_editor/inline_editor.js index 5ca892a7cd0..34bf219685b 100644 --- a/front_end/inline_editor/inline_editor.js +++ b/front_end/inline_editor/inline_editor.js @@ -5,6 +5,8 @@ import * as BezierEditor from './BezierEditor.js'; import * as BezierUI from './BezierUI.js'; import * as ColorSwatch from './ColorSwatch_bridge.js'; +import * as CSSAngle from './CSSAngle_bridge.js'; +import * as CSSAngleRegex from './CSSAngleRegex.js'; import * as CSSShadowEditor from './CSSShadowEditor.js'; import * as CSSShadowModel from './CSSShadowModel.js'; import * as CSSVarSwatch from './CSSVarSwatch_bridge.js'; @@ -15,6 +17,8 @@ export { BezierEditor, BezierUI, ColorSwatch, + CSSAngle, + CSSAngleRegex, CSSShadowEditor, CSSShadowModel, CSSVarSwatch, diff --git a/front_end/inline_editor/module.json b/front_end/inline_editor/module.json index 73280df88dc..c1cf15a3cae 100644 --- a/front_end/inline_editor/module.json +++ b/front_end/inline_editor/module.json @@ -8,6 +8,8 @@ "BezierEditor.js", "BezierUI.js", "ColorSwatch_bridge.js", + "CSSAngleRegex.js", + "CSSAngle_bridge.js", "CSSShadowEditor.js", "CSSShadowModel.js", "CSSVarSwatch_bridge.js", diff --git a/front_end/input/InputModel.js b/front_end/input/InputModel.js index 8d83b4fc397..beae37ce868 100644 --- a/front_end/input/InputModel.js +++ b/front_end/input/InputModel.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as SDK from '../sdk/sdk.js'; export class InputModel extends SDK.SDKModel.SDKModel { @@ -14,12 +11,14 @@ export class InputModel extends SDK.SDKModel.SDKModel { constructor(target) { super(target); this._inputAgent = target.inputAgent(); - /** @type {?number} */ - this._eventDispatchTimer = null; + /** @type {number} */ + this._eventDispatchTimer = 0; /** @type {!Array}*/ this._dispatchEventDataList = []; - /** @type {?function()} */ + /** @type {?function():void} */ this._finishCallback = null; + /** @type {number} */ + this._dispatchingIndex; this._reset(); } @@ -31,7 +30,7 @@ export class InputModel extends SDK.SDKModel.SDKModel { this._replayPaused = false; /** @type {number} */ this._dispatchingIndex = 0; - clearTimeout(this._eventDispatchTimer); + window.clearTimeout(this._eventDispatchTimer); } /** @@ -44,6 +43,10 @@ export class InputModel extends SDK.SDKModel.SDKModel { this._processThreadEvents(tracingModel, thread); } } + /** + * @param {!EventData} a + * @param {!EventData} b + */ function compareTimestamp(a, b) { return a.timestamp - b.timestamp; } @@ -51,7 +54,7 @@ export class InputModel extends SDK.SDKModel.SDKModel { } /** - * @param {?function()} finishCallback + * @param {?function():void} finishCallback */ startReplay(finishCallback) { this._reset(); @@ -64,7 +67,7 @@ export class InputModel extends SDK.SDKModel.SDKModel { } pause() { - clearTimeout(this._eventDispatchTimer); + window.clearTimeout(this._eventDispatchTimer); if (this._dispatchingIndex >= this._dispatchEventDataList.length) { this._replayStopped(); } else { @@ -106,7 +109,7 @@ export class InputModel extends SDK.SDKModel.SDKModel { * @return {boolean} */ _isMouseEvent(eventData) { - if (!InputModel.MouseEventTypes.has(eventData.type)) { + if (!MOUSE_EVENT_TYPE_TO_REQUEST_TYPE.has(eventData.type)) { return false; } if (!('x' in eventData && 'y' in eventData)) { @@ -120,7 +123,7 @@ export class InputModel extends SDK.SDKModel.SDKModel { * @return {boolean} */ _isKeyboardEvent(eventData) { - if (!InputModel.KeyboardEventTypes.has(eventData.type)) { + if (!KEYBOARD_EVENT_TYPE_TO_REQUEST_TYPE.has(eventData.type)) { return false; } if (!('code' in eventData && 'key' in eventData)) { @@ -132,16 +135,16 @@ export class InputModel extends SDK.SDKModel.SDKModel { _dispatchNextEvent() { const eventData = this._dispatchEventDataList[this._dispatchingIndex]; this._lastEventTime = eventData.timestamp; - if (InputModel.MouseEventTypes.has(eventData.type)) { + if (MOUSE_EVENT_TYPE_TO_REQUEST_TYPE.has(eventData.type)) { this._dispatchMouseEvent(/** @type {!MouseEventData} */ (eventData)); - } else if (InputModel.KeyboardEventTypes.has(eventData.type)) { + } else if (KEYBOARD_EVENT_TYPE_TO_REQUEST_TYPE.has(eventData.type)) { this._dispatchKeyEvent(/** @type {!KeyboardEventData} */ (eventData)); } ++this._dispatchingIndex; if (this._dispatchingIndex < this._dispatchEventDataList.length) { const waitTime = (this._dispatchEventDataList[this._dispatchingIndex].timestamp - this._lastEventTime) / 1000; - this._eventDispatchTimer = setTimeout(this._dispatchNextEvent.bind(this), waitTime); + this._eventDispatchTimer = window.setTimeout(this._dispatchNextEvent.bind(this), waitTime); } else { this._replayStopped(); } @@ -151,14 +154,18 @@ export class InputModel extends SDK.SDKModel.SDKModel { * @param {!MouseEventData} eventData */ async _dispatchMouseEvent(eventData) { - console.assert(InputModel.MouseEventTypes.has(eventData.type)); - const buttons = {0: 'left', 1: 'middle', 2: 'right', 3: 'back', 4: 'forward'}; + const type = MOUSE_EVENT_TYPE_TO_REQUEST_TYPE.get(eventData.type); + if (!type) { + throw new Error(`Could not find mouse event type for eventData ${eventData.type}`); + } + const buttonActionName = BUTTONID_TO_ACTION_NAME.get(eventData.button); const params = { - type: InputModel.MouseEventTypes.get(eventData.type), + type, x: eventData.x, y: eventData.y, modifiers: eventData.modifiers, - button: (eventData.type === 'mousedown' || eventData.type === 'mouseup') ? buttons[eventData.button] : 'none', + button: (eventData.type === 'mousedown' || eventData.type === 'mouseup') ? buttonActionName : + Protocol.Input.MouseButton.None, buttons: eventData.buttons, clickCount: eventData.clickCount, deltaX: eventData.deltaX, @@ -171,10 +178,13 @@ export class InputModel extends SDK.SDKModel.SDKModel { * @param {!KeyboardEventData} eventData */ async _dispatchKeyEvent(eventData) { - console.assert(InputModel.KeyboardEventTypes.has(eventData.type)); + const type = KEYBOARD_EVENT_TYPE_TO_REQUEST_TYPE.get(eventData.type); + if (!type) { + throw new Error(`Could not find key event type for eventData ${eventData.type}`); + } const text = eventData.type === 'keypress' ? eventData.key[0] : undefined; const params = { - type: InputModel.KeyboardEventTypes.get(eventData.type), + type, modifiers: eventData.modifiers, text: text, unmodifiedText: text ? text.toLowerCase() : undefined, @@ -185,25 +195,45 @@ export class InputModel extends SDK.SDKModel.SDKModel { } _replayStopped() { - clearTimeout(this._eventDispatchTimer); + window.clearTimeout(this._eventDispatchTimer); this._reset(); - this._finishCallback(); + if (this._finishCallback) { + this._finishCallback(); + } } } -InputModel.MouseEventTypes = new Map([ - ['mousedown', 'mousePressed'], ['mouseup', 'mouseReleased'], ['mousemove', 'mouseMoved'], ['wheel', 'mouseWheel'] +/** @type {!Map} */ +const MOUSE_EVENT_TYPE_TO_REQUEST_TYPE = new Map([ + ['mousedown', Protocol.Input.DispatchMouseEventRequestType.MousePressed], + ['mouseup', Protocol.Input.DispatchMouseEventRequestType.MouseReleased], + ['mousemove', Protocol.Input.DispatchMouseEventRequestType.MouseMoved], + ['wheel', Protocol.Input.DispatchMouseEventRequestType.MouseWheel], ]); -InputModel.KeyboardEventTypes = new Map([['keydown', 'keyDown'], ['keyup', 'keyUp'], ['keypress', 'char']]); +/** @type {!Map} */ +const KEYBOARD_EVENT_TYPE_TO_REQUEST_TYPE = new Map([ + ['keydown', Protocol.Input.DispatchKeyEventRequestType.KeyDown], + ['keyup', Protocol.Input.DispatchKeyEventRequestType.KeyUp], + ['keypress', Protocol.Input.DispatchKeyEventRequestType.Char], +]); -SDK.SDKModel.SDKModel.register(InputModel, SDK.SDKModel.Capability.Input, false); +/** @type {!Map} */ +const BUTTONID_TO_ACTION_NAME = new Map([ + [0, Protocol.Input.MouseButton.Left], [1, Protocol.Input.MouseButton.Middle], [2, Protocol.Input.MouseButton.Right], + [3, Protocol.Input.MouseButton.Back], [4, Protocol.Input.MouseButton.Forward] +]); -/** @typedef {{type: string, modifiers: number, timestamp: number}} */ -export let EventData; +SDK.SDKModel.SDKModel.register(InputModel, SDK.SDKModel.Capability.Input, false); -/** @typedef {{x: number, y: number, button: number, buttons: number, clickCount: number, deltaX: number, deltaY: number}} */ +/** @typedef {{type: string, modifiers: number, timestamp: number, x: number, y: number, button: number, buttons: number, clickCount: number, deltaX: number, deltaY: number}} */ +// @ts-ignore typedef export let MouseEventData; -/** @typedef {{code: string, key: string, modifiers: number}} */ +/** @typedef {{type: string, modifiers: number, timestamp: number, code: string, key: string}} */ +// @ts-ignore typedef export let KeyboardEventData; + +/** @typedef {(!MouseEventData|!KeyboardEventData)} */ +// @ts-ignore typedef +export let EventData; diff --git a/front_end/inspector_main/RenderingOptions.js b/front_end/inspector_main/RenderingOptions.js index fe46a2a481d..12bd6572daf 100644 --- a/front_end/inspector_main/RenderingOptions.js +++ b/front_end/inspector_main/RenderingOptions.js @@ -106,6 +106,16 @@ export class RenderingOptionsView extends UI.Widget.VBox { Common.Settings.Settings.instance().moduleSetting('emulatedVisionDeficiency')); this.contentElement.createChild('div').classList.add('panel-section-separator'); + + this._appendCheckbox( + ls`Disable AVIF image format`, ls`Requires a page reload to apply and disables caching for image requests.`, + Common.Settings.Settings.instance().moduleSetting('avifFormatDisabled')); + + this._appendCheckbox( + ls`Disable WebP image format`, ls`Requires a page reload to apply and disables caching for image requests.`, + Common.Settings.Settings.instance().moduleSetting('webpFormatDisabled')); + + this.contentElement.createChild('div').classList.add('panel-section-separator'); } /** diff --git a/front_end/inspector_main/inspector_main_strings.grdp b/front_end/inspector_main/inspector_main_strings.grdp index 0e9a6bae458..3ecf0b69422 100644 --- a/front_end/inspector_main/inspector_main_strings.grdp +++ b/front_end/inspector_main/inspector_main_strings.grdp @@ -1,5 +1,11 @@ + + Requires a page reload to apply and disables caching for image requests. + + + Disable AVIF image format + Frame Rendering Stats @@ -111,6 +117,9 @@ Emulates a focused page. + + Disable WebP image format + Auto-open DevTools for popups diff --git a/front_end/issues/IssuesPane.js b/front_end/issues/IssuesPane.js index 7d21ef05099..7a907416ebc 100644 --- a/front_end/issues/IssuesPane.js +++ b/front_end/issues/IssuesPane.js @@ -19,6 +19,7 @@ const AffectedItem = { Cookie: 'Cookie', Directive: 'Directive', Element: 'Element', + LearnMore: 'LearnMore', Request: 'Request', Source: 'Source' }; @@ -292,7 +293,7 @@ class AffectedElementsView extends AffectedResourcesView { this._issue = issue; } - _sendTelmetry() { + _sendTelemetry() { Host.userMetrics.issuesPanelResourceOpened(this._issue.getCategory(), AffectedItem.Element); } @@ -316,10 +317,10 @@ class AffectedElementsView extends AffectedResourcesView { const deferredDOMNode = new SDK.DOMModel.DeferredDOMNode(mainTarget, backendNodeId); const anchorElement = await Common.Linkifier.Linkifier.linkify(deferredDOMNode); anchorElement.textContent = nodeName; - anchorElement.addEventListener('click', this._sendTelmetry); + anchorElement.addEventListener('click', this._sendTelemetry); anchorElement.addEventListener('keydown', event => { if (isEnterKey(event)) { - this._sendTelmetry(); + this._sendTelemetry(); } }); const cellElement = document.createElement('td'); @@ -524,6 +525,13 @@ class AffectedDirectivesView extends AffectedResourcesView { this._appendSourceCodeColumnTitle(header); this._appendDirectiveColumnTitle(header); this._appendStatusColumnTitle(header); + } else if (this._issue.code() === SDK.ContentSecurityPolicyIssue.trustedTypesSinkViolationCode) { + this._appendSourceCodeColumnTitle(header); + this._appendStatusColumnTitle(header); + } else if (this._issue.code() === SDK.ContentSecurityPolicyIssue.trustedTypesPolicyViolationCode) { + this._appendSourceCodeColumnTitle(header); + this._appendDirectiveColumnTitle(header); + this._appendStatusColumnTitle(header); } else { this.updateAffectedResourceCount(0); return; @@ -560,6 +568,13 @@ class AffectedDirectivesView extends AffectedResourcesView { this._appendSourceLocation(element, cspIssueDetails.sourceCodeLocation); this._appendViolatedDirective(element, cspIssueDetails.violatedDirective); this._appendStatus(element, cspIssueDetails.isReportOnly); + } else if (this._issue.code() === SDK.ContentSecurityPolicyIssue.trustedTypesSinkViolationCode) { + this._appendSourceLocation(element, cspIssueDetails.sourceCodeLocation); + this._appendStatus(element, cspIssueDetails.isReportOnly); + } else if (this._issue.code() === SDK.ContentSecurityPolicyIssue.trustedTypesPolicyViolationCode) { + this._appendSourceLocation(element, cspIssueDetails.sourceCodeLocation); + this._appendViolatedDirective(element, cspIssueDetails.violatedDirective); + this._appendStatus(element, cspIssueDetails.isReportOnly); } else { return; } @@ -1241,13 +1256,21 @@ class IssueView extends UI.TreeOutline.TreeElement { const linkList = linkWrapper.listItemElement.createChild('ul', 'link-list'); for (const description of this._description.links) { - // TODO(crbug.com/1108501): Allow x-link elements to subscribe to the events 'click' and 'keydown' if the key - // is the 'Enter' key, or add some mechanism that allows to add telemetry to this element. - const link = UI.XLink.XLink.create(description.link, ls`Learn more: ${description.linkTitle}`, 'link'); + const link = UI.Fragment.html + `${ + ls`Learn more: ${description.linkTitle}`}`; const linkIcon = Elements.Icon.createIcon(); linkIcon.data = {iconName: 'link_icon', color: 'var(--issue-link)', width: '16px', height: '16px'}; linkIcon.classList.add('link-icon'); link.prepend(linkIcon); + self.onInvokeElement(link, event => { + Host.userMetrics.issuesPanelResourceOpened(this._issue.getCategory(), AffectedItem.LearnMore); + const mainTarget = SDK.SDKModel.TargetManager.instance().mainTarget(); + if (mainTarget) { + mainTarget.targetAgent().invoke_createTarget({url: description.link}); + } + event.consume(true); + }); const linkListItem = linkList.createChild('li'); linkListItem.appendChild(link); diff --git a/front_end/issues/descriptions/cspTrustedTypesPolicyViolation.md b/front_end/issues/descriptions/cspTrustedTypesPolicyViolation.md new file mode 100644 index 00000000000..3d8b90a7aa0 --- /dev/null +++ b/front_end/issues/descriptions/cspTrustedTypesPolicyViolation.md @@ -0,0 +1,5 @@ +# Trusted Type policy creation blocked by Content Security Policy + +Your site tries to create a Trusted Type policy that has not been allowed by the Content Security Policy. The Content Security Policy may restrict the set of valid names for Trusted Type policies, and forbid more than one policy of each name. + +To solve this, make sure that the names of the policies listed below are declared in the `trusted-types` CSP directive. To allow redefining policies add the `allow-duplicates` keyword. If you want to remove all restrictions on policy names, remove the `trusted-types` directive entirely (not recommended). \ No newline at end of file diff --git a/front_end/issues/descriptions/cspTrustedTypesSinkViolation.md b/front_end/issues/descriptions/cspTrustedTypesSinkViolation.md new file mode 100644 index 00000000000..dd9dc8df9a9 --- /dev/null +++ b/front_end/issues/descriptions/cspTrustedTypesSinkViolation.md @@ -0,0 +1,8 @@ +# Trusted Type expected, but String received + +Your site tries to use a plain string in a DOM modification where a Trusted Type is expected. Requiring Trusted Types for DOM modifications helps to prevent cross-site scripting attacks. + +To solve this, provide a Trusted Type to all the DOM modifications listed below. You can convert a string into a Trusted Type by: + +* defining a policy and using its corresponding `createHTML`, `createScript` or `createScriptURL` function. +* defining a policy named `default` which will be automatically called. \ No newline at end of file diff --git a/front_end/issues/module.json b/front_end/issues/module.json index 91200ef3633..52ca7f80438 100644 --- a/front_end/issues/module.json +++ b/front_end/issues/module.json @@ -46,6 +46,8 @@ "descriptions/cspEvalViolation.md", "descriptions/cspInlineViolation.md", "descriptions/cspURLViolation.md", + "descriptions/cspTrustedTypesSinkViolation.md", + "descriptions/cspTrustedTypesPolicyViolation.md", "descriptions/mixedContent.md", "issuesPane.css", "issuesTree.css" diff --git a/front_end/langpacks/shared_strings.grdp b/front_end/langpacks/shared_strings.grdp index ab4dbf6cada..449c6b5aee4 100644 --- a/front_end/langpacks/shared_strings.grdp +++ b/front_end/langpacks/shared_strings.grdp @@ -160,6 +160,9 @@ Next frame + + kB + Details @@ -466,9 +469,6 @@ Not optimized - - KB - Orientation diff --git a/front_end/layer_viewer/LayerViewHost.js b/front_end/layer_viewer/LayerViewHost.js index daa4a0713a8..5997ab8d13e 100644 --- a/front_end/layer_viewer/LayerViewHost.js +++ b/front_end/layer_viewer/LayerViewHost.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as SDK from '../sdk/sdk.js'; import * as UI from '../ui/ui.js'; // eslint-disable-line no-unused-vars @@ -46,7 +43,7 @@ export class Selection { /** * @param {?Selection} a - * @param {?LayerViewer.LayerView.Selection} b + * @param {?Selection} b * @return {boolean} */ static isEqual(a, b) { @@ -93,7 +90,7 @@ export class LayerSelection extends Selection { * @param {!SDK.LayerTreeBase.Layer} layer */ constructor(layer) { - console.assert(layer, 'LayerSelection with empty layer'); + console.assert(!!layer, 'LayerSelection with empty layer'); super(Type.Layer, layer); } @@ -127,7 +124,7 @@ export class ScrollRectSelection extends Selection { */ _isEqual(other) { return other._type === Type.ScrollRect && this.layer().id() === other.layer().id() && - this.scrollRectIndex === other.scrollRectIndex; + this.scrollRectIndex === /** @type {!ScrollRectSelection} */ (other).scrollRectIndex; } } @@ -151,7 +148,7 @@ export class SnapshotSelection extends Selection { */ _isEqual(other) { return other._type === Type.Snapshot && this.layer().id() === other.layer().id() && - this._snapshot === other._snapshot; + this._snapshot === /** @type {!SnapshotSelection} */ (other)._snapshot; } /** @@ -173,6 +170,8 @@ export class LayerViewHost { this._hoveredObject = null; this._showInternalLayersSetting = Common.Settings.Settings.instance().createSetting('layersShowInternalLayers', false); + /** @type {!Map} */ + this._snapshotLayers = new Map(); } /** @@ -200,6 +199,9 @@ export class LayerViewHost { * @param {?SDK.LayerTreeBase.LayerTreeBase} layerTree */ setLayerTree(layerTree) { + if (!layerTree) { + return; + } this._target = layerTree.target(); const selectedLayer = this._selectedObject && this._selectedObject.layer(); if (selectedLayer && (!layerTree || !layerTree.layerById(selectedLayer.id()))) { @@ -265,7 +267,7 @@ export class LayerViewHost { } /** - * @return {!Common.Settings.Setting} + * @return {!Common.Settings.Setting<*>} */ showInternalLayersSetting() { return this._showInternalLayersSetting; diff --git a/front_end/layers/LayersPanel.js b/front_end/layers/LayersPanel.js index b5772cac26a..7df7726b686 100644 --- a/front_end/layers/LayersPanel.js +++ b/front_end/layers/LayersPanel.js @@ -28,9 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as LayerViewer from '../layer_viewer/layer_viewer.js'; import * as SDK from '../sdk/sdk.js'; // eslint-disable-line no-unused-vars @@ -149,9 +146,15 @@ export class LayersPanel extends UI.Panel.PanelWithSidebar { _update() { if (this._model) { this._layerViewHost.setLayerTree(this._model.layerTree()); - const url = this._model.target().model(SDK.ResourceTreeModel.ResourceTreeModel).mainFrame.url; - // Add the currently visualized url as an attribute to make it accessibles to e2e tests - this.element.setAttribute('test-current-url', url); + const resourceModel = this._model.target().model(SDK.ResourceTreeModel.ResourceTreeModel); + if (resourceModel) { + const mainFrame = resourceModel.mainFrame; + if (mainFrame) { + const url = mainFrame.url; + // Add the currently visualized url as an attribute to make it accessibles to e2e tests + this.element.setAttribute('test-current-url', url); + } + } } return Promise.resolve(); } @@ -164,7 +167,8 @@ export class LayersPanel extends UI.Panel.PanelWithSidebar { return; } const layer = /** @type {!SDK.LayerTreeBase.Layer} */ (event.data); - if (this._layerViewHost.selection() && this._layerViewHost.selection().layer() === layer) { + const selection = this._layerViewHost.selection(); + if (selection && selection.layer() === layer) { this._layerDetailsView.update(); } this._layers3DView.updateLayerSnapshot(layer); @@ -206,7 +210,9 @@ export class LayersPanel extends UI.Panel.PanelWithSidebar { * @param {string=} imageURL */ _showImage(imageURL) { - this._layers3DView.showImageForLayer(this._layerBeingProfiled, imageURL); + if (this._layerBeingProfiled) { + this._layers3DView.showImageForLayer(this._layerBeingProfiled, imageURL); + } } /** diff --git a/front_end/legacy/legacy-defs.d.ts b/front_end/legacy/legacy-defs.d.ts index 6861aa1631d..b18038ad1a1 100644 --- a/front_end/legacy/legacy-defs.d.ts +++ b/front_end/legacy/legacy-defs.d.ts @@ -11,6 +11,10 @@ interface Window { UI: {themeSupport: unknown} } +declare class DOM { + constructor(doc: Document); +} + interface Array { peekLast(): T | undefined; intersectOrdered(array: T[], comparator: (a: T, b: T) => number): T[]; @@ -122,7 +126,6 @@ interface Document { interface HTMLElement { createChild(tagName: string, className?: string, content?: string): HTMLElement; - createSVGChild(childType: string, className?: string): HTMLElement; } interface Element { diff --git a/front_end/lighthouse/BUILD.gn b/front_end/lighthouse/BUILD.gn index e0477a0d897..18320303549 100644 --- a/front_end/lighthouse/BUILD.gn +++ b/front_end/lighthouse/BUILD.gn @@ -12,6 +12,7 @@ devtools_module("lighthouse") { "LighthouseProtocolService.js", "LighthouseReportRenderer.js", "LighthouseReportSelector.js", + "LighthouseReporterTypes.js", "LighthouseStartView.js", "LighthouseStatusView.js", "RadioSetting.js", diff --git a/front_end/lighthouse/LighthouseController.js b/front_end/lighthouse/LighthouseController.js index 5bfcb0091e1..064932fab32 100644 --- a/front_end/lighthouse/LighthouseController.js +++ b/front_end/lighthouse/LighthouseController.js @@ -2,17 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as SDK from '../sdk/sdk.js'; +import {ProtocolService} from './LighthouseProtocolService.js'; // eslint-disable-line no-unused-vars + /** * @implements {SDK.SDKModel.SDKModelObserver} * @unrestricted */ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper { + /** + * @param {!ProtocolService} protocolService + */ constructor(protocolService) { super(); @@ -60,8 +62,9 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper { if (this._manager !== serviceWorkerManager) { return; } - - Common.EventTarget.EventTarget.removeEventListeners(this._serviceWorkerListeners); + if (this._serviceWorkerListeners) { + Common.EventTarget.EventTarget.removeEventListeners(this._serviceWorkerListeners); + } this._manager = null; this.recomputePageAuditability(); } @@ -130,15 +133,13 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper { if (clearStorageSetting && !clearStorageSetting.setting.get()) { return ''; } + if (!this._manager) { + return ''; + } const mainTarget = this._manager.target(); const usageData = await mainTarget.storageAgent().invoke_getUsageAndQuota({origin: mainTarget.inspectedURL()}); - const storageTypeNames = { - local_storage: Common.UIString.UIString('Local Storage'), - indexeddb: Common.UIString.UIString('IndexedDB'), - websql: Common.UIString.UIString('Web SQL'), - }; const locations = usageData.usageBreakdown.filter(usage => usage.usage) - .map(usage => storageTypeNames[usage.storageType]) + .map(usage => STORAGE_TYPE_NAMES.get(usage.storageType)) .filter(Boolean); if (locations.length === 1) { return Common.UIString.UIString( @@ -157,6 +158,9 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper { * @return {!Promise} */ async _evaluateInspectedURL() { + if (!this._manager) { + return ''; + } const mainTarget = this._manager.target(); const runtimeModel = mainTarget.model(SDK.RuntimeModel.RuntimeModel); const executionContext = runtimeModel && runtimeModel.defaultExecutionContext(); @@ -175,10 +179,15 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper { includeCommandLineAPI: false, silent: false, returnByValue: true, - generatePreview: false + generatePreview: false, + allowUnsafeEvalBlockedByCSP: undefined, + disableBreaks: undefined, + replMode: undefined, + throwOnSideEffect: undefined, + timeout: undefined, }, /* userGesture */ false, /* awaitPromise */ false); - if (!result.exceptionDetails && result.object) { + if ((!('exceptionDetails' in result) || !result.exceptionDetails) && 'object' in result && result.object) { inspectedURL = result.object.value; result.object.release(); } @@ -250,6 +259,12 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper { } } +const STORAGE_TYPE_NAMES = new Map([ + [Protocol.Storage.StorageType.Local_storage, Common.UIString.UIString('Local Storage')], + [Protocol.Storage.StorageType.Indexeddb, Common.UIString.UIString('IndexedDB')], + [Protocol.Storage.StorageType.Websql, Common.UIString.UIString('Web SQL')], +]); + /** @type {!Array.} */ export const Presets = [ // configID maps to Lighthouse's Object.keys(config.categories)[0] value @@ -257,31 +272,36 @@ export const Presets = [ setting: Common.Settings.Settings.instance().createSetting('lighthouse.cat_perf', true), configID: 'performance', title: ls`Performance`, - description: ls`How long does this app take to show content and become usable` + description: ls`How long does this app take to show content and become usable`, + plugin: false, }, { setting: Common.Settings.Settings.instance().createSetting('lighthouse.cat_pwa', true), configID: 'pwa', title: ls`Progressive Web App`, - description: ls`Does this page meet the standard of a Progressive Web App` + description: ls`Does this page meet the standard of a Progressive Web App`, + plugin: false, }, { setting: Common.Settings.Settings.instance().createSetting('lighthouse.cat_best_practices', true), configID: 'best-practices', title: ls`Best practices`, - description: ls`Does this page follow best practices for modern web development` + description: ls`Does this page follow best practices for modern web development`, + plugin: false, }, { setting: Common.Settings.Settings.instance().createSetting('lighthouse.cat_a11y', true), configID: 'accessibility', title: ls`Accessibility`, - description: ls`Is this page usable by people with disabilities or impairments` + description: ls`Is this page usable by people with disabilities or impairments`, + plugin: false, }, { setting: Common.Settings.Settings.instance().createSetting('lighthouse.cat_seo', true), configID: 'seo', title: ls`SEO`, - description: ls`Is this page optimized for search engine results ranking` + description: ls`Is this page optimized for search engine results ranking`, + plugin: false, }, { setting: Common.Settings.Settings.instance().createSetting('lighthouse.cat_pubads', false), @@ -296,6 +316,7 @@ export const Presets = [ export const RuntimeSettings = [ { setting: Common.Settings.Settings.instance().createSetting('lighthouse.device_type', 'mobile'), + title: ls`Apply mobile emulation`, description: ls`Apply mobile emulation during auditing`, setFlags: (flags, value) => { // See Audits.AuditsPanel._setupEmulationAndProtocolConnection() @@ -305,6 +326,7 @@ export const RuntimeSettings = [ {label: ls`Mobile`, value: 'mobile'}, {label: ls`Desktop`, value: 'desktop'}, ], + learnMore: undefined, }, { // This setting is disabled, but we keep it around to show in the UI. @@ -318,6 +340,7 @@ export const RuntimeSettings = [ setFlags: (flags, value) => { flags.throttlingMethod = value ? 'simulate' : 'devtools'; }, + options: undefined, }, { setting: Common.Settings.Settings.instance().createSetting('lighthouse.clear_storage', true), @@ -326,6 +349,8 @@ export const RuntimeSettings = [ setFlags: (flags, value) => { flags.disableStorageReset = !value; }, + options: undefined, + learnMore: undefined, }, ]; @@ -337,8 +362,10 @@ export const RuntimeSettings = [ RequestLighthouseCancel: Symbol('RequestLighthouseCancel'), }; - /** @typedef {{setting: !Common.Settings.Setting, configID: string, title: string, description: string}} */ + /** @typedef {{setting: !Common.Settings.Setting, configID: string, title: string, description: string, plugin: boolean}} */ + // @ts-ignore typedef export let Preset; - /** @typedef {{setting: !Common.Settings.Setting, description: string, setFlags: function(!Object, string), options: (!Array|undefined), title: (string|undefined)}} */ + /** @typedef {{setting: !Common.Settings.Setting, description: string, setFlags: function(!Object, string):void, options: (!Array|undefined), title: (string|undefined), learnMore: (string|undefined)}} */ + // @ts-ignore typedef export let RuntimeSetting; diff --git a/front_end/lighthouse/LighthousePanel.js b/front_end/lighthouse/LighthousePanel.js index b6d3e33a643..47d65079b43 100644 --- a/front_end/lighthouse/LighthousePanel.js +++ b/front_end/lighthouse/LighthousePanel.js @@ -14,6 +14,7 @@ import * as UI from '../ui/ui.js'; import {Events, LighthouseController} from './LighthouseController.js'; import {ProtocolService} from './LighthouseProtocolService.js'; +import * as ReportRenderer from './LighthouseReporterTypes.js'; // eslint-disable-line no-unused-vars import {LighthouseReportRenderer, LighthouseReportUIFeatures} from './LighthouseReportRenderer.js'; import {Item, ReportSelector} from './LighthouseReportSelector.js'; import {StartView} from './LighthouseStartView.js'; diff --git a/front_end/lighthouse/LighthouseProtocolService.js b/front_end/lighthouse/LighthouseProtocolService.js index 0a4c80f20d3..a0feca191ee 100644 --- a/front_end/lighthouse/LighthouseProtocolService.js +++ b/front_end/lighthouse/LighthouseProtocolService.js @@ -9,6 +9,8 @@ import * as Common from '../common/common.js'; import * as ProtocolClient from '../protocol_client/protocol_client.js'; // eslint-disable-line no-unused-vars import * as SDK from '../sdk/sdk.js'; +import * as ReportRenderer from './LighthouseReporterTypes.js'; // eslint-disable-line no-unused-vars + export class ProtocolService extends Common.ObjectWrapper.ObjectWrapper { constructor() { super(); @@ -60,7 +62,7 @@ export class ProtocolService extends Common.ObjectWrapper.ObjectWrapper { } /** - * @param {function (string): undefined} callback + * @param {function (string): void} callback */ registerStatusCallback(callback) { this._status = callback; diff --git a/front_end/lighthouse/LighthouseReportRenderer.js b/front_end/lighthouse/LighthouseReportRenderer.js index 62a53a7e527..e90f956195d 100644 --- a/front_end/lighthouse/LighthouseReportRenderer.js +++ b/front_end/lighthouse/LighthouseReportRenderer.js @@ -16,12 +16,14 @@ import * as Timeline from '../timeline/timeline.js'; import * as UI from '../ui/ui.js'; import * as Workspace from '../workspace/workspace.js'; +import * as ReportRenderer from './LighthouseReporterTypes.js'; // eslint-disable-line no-unused-vars + const MaxLengthForLinks = 40; /** * @override */ -export class LighthouseReportRenderer extends ReportRenderer { +export class LighthouseReportRenderer extends self.ReportRenderer { /** * @param {!Element} el Parent element to render the report into. * @param {!ReportRenderer.RunnerResultArtifacts=} artifacts @@ -63,7 +65,7 @@ export class LighthouseReportRenderer extends ReportRenderer { const domModel = mainTarget.model(SDK.DOMModel.DOMModel); for (const origElement of el.getElementsByClassName('lh-node')) { - /** @type {!DetailsRenderer.NodeDetailsJSON} */ + /** @type {!ReportRenderer.NodeDetailsJSON} */ const detailsItem = origElement.dataset; if (!detailsItem.path) { continue; @@ -91,7 +93,7 @@ export class LighthouseReportRenderer extends ReportRenderer { */ static async linkifySourceLocationDetails(el) { for (const origElement of el.getElementsByClassName('lh-source-location')) { - /** @type {!DetailsRenderer.SourceLocationDetailsJSON} */ + /** @type {!ReportRenderer.SourceLocationDetailsJSON} */ const detailsItem = origElement.dataset; if (!detailsItem.sourceUrl || !detailsItem.sourceLine || !detailsItem.sourceColumn) { continue; @@ -120,7 +122,7 @@ export class LighthouseReportRenderer extends ReportRenderer { /** * @override */ -export class LighthouseReportUIFeatures extends ReportUIFeatures { +export class LighthouseReportUIFeatures extends self.ReportUIFeatures { /** * @param {!DOM} dom */ diff --git a/front_end/lighthouse/LighthouseReportSelector.js b/front_end/lighthouse/LighthouseReportSelector.js index 6b688f5526a..d720efa8da7 100644 --- a/front_end/lighthouse/LighthouseReportSelector.js +++ b/front_end/lighthouse/LighthouseReportSelector.js @@ -2,16 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as UI from '../ui/ui.js'; +import * as ReportRenderer from './LighthouseReporterTypes.js'; // eslint-disable-line no-unused-vars + export class ReportSelector { + /** + * @param {function():void} renderNewLighthouseView + */ constructor(renderNewLighthouseView) { this._renderNewLighthouseView = renderNewLighthouseView; - this._newLighthouseItem = createElement('option'); + this._newLighthouseItem = document.createElement('option'); this._comboBox = new UI.Toolbar.ToolbarComboBox(this._handleChange.bind(this), ls`Reports`, 'lighthouse-report'); this._comboBox.setMaxWidth(180); this._comboBox.setMinWidth(140); @@ -23,7 +25,7 @@ export class ReportSelector { this._comboBox.selectElement().removeChildren(); this._comboBox.setEnabled(false); - this._newLighthouseItem = createElement('option'); + this._newLighthouseItem = document.createElement('option'); this._newLighthouseItem.label = Common.UIString.UIString('(new report)'); this._comboBox.selectElement().appendChild(this._newLighthouseItem); this._comboBox.select(this._newLighthouseItem); @@ -105,8 +107,8 @@ export class ReportSelector { export class Item { /** * @param {!ReportRenderer.ReportJSON} lighthouseResult - * @param {function()} renderReport - * @param {function()} showLandingCallback + * @param {function():void} renderReport + * @param {function():void} showLandingCallback */ constructor(lighthouseResult, renderReport, showLandingCallback) { this._lighthouseResult = lighthouseResult; @@ -115,7 +117,7 @@ export class Item { const url = new Common.ParsedURL.ParsedURL(lighthouseResult.finalUrl); const timestamp = lighthouseResult.fetchTime; - this._element = createElement('option'); + this._element = document.createElement('option'); this._element.label = `${new Date(timestamp).toLocaleTimeString()} - ${url.domain()}`; } diff --git a/front_end/lighthouse/LighthouseReporterTypes.js b/front_end/lighthouse/LighthouseReporterTypes.js new file mode 100644 index 00000000000..af4d11b7842 --- /dev/null +++ b/front_end/lighthouse/LighthouseReporterTypes.js @@ -0,0 +1,226 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export class ReportRenderer { + /** + * @param {!DOM} dom + */ + constructor(dom) { + } + + /** + * @param {!ReportJSON} report + * @param {!Element} container Parent element to render the report into. + * @return {!Element} + */ + renderReport(report, container) { + throw new Error('Not implemented yet!'); + } + + /** + * @param {!Document|!Element} context + */ + setTemplateContext(context) { + } +} + +/** @type {function(new:ReportRenderer, !DOM)} */ +// @ts-ignore +self.ReportRenderer; + +export class ReportUIFeatures { + /** + * @param {!DOM} dom + */ + constructor(dom) { + /** @type {!ReportJSON} */ + this.json; + /** @type {!Document} */ + this._document; + } + + /** + * @param {!Document|!Element} context + */ + setTemplateContext(context) { + } + + /** + * @param {!ReportJSON} report + */ + initFeatures(report) { + } + + _resetUIState() { + } +} + +/** @type {function(new:ReportUIFeatures)} */ +// @ts-ignore +self.ReportUIFeatures; + +export class CategoryRenderer { + /** + * @param {!DOM} dom + * @param {!DetailsRenderer} detailsRenderer + */ + constructor(dom, detailsRenderer) { + } +} + +export class DetailsRenderer { + /** + * @param {!DOM} dom + */ + constructor(dom) { + } + + /** + * @param {!NodeDetailsJSON} item + * @return {!Element} + */ + renderNode(item) { + throw new Error('Not implemented yet!'); + } +} + +export class LighthouseReportGenerator { + /** + * @param {!ReportJSON} lhr + * @return {string} + */ + generateReportHtml(lhr) { + return ''; + } +} + +/** + * @typedef {{ + * rawValue: (number|boolean|undefined), + * id: string, + * title: string, + * description: string, + * explanation: (string|undefined), + * errorMessage: (string|undefined), + * displayValue: (string|Array|undefined), + * scoreDisplayMode: string, + * error: boolean, + * score: (number|null), + * details: (!DetailsJSON|undefined), + * }} + */ +// @ts-ignore typedef +export let AuditResultJSON; + +/** + * @typedef {{ + * id: string, + * score: (number|null), + * weight: number, + * group: (string|undefined), + * result: !AuditResultJSON + * }} + */ +// @ts-ignore typedef +export let AuditJSON; + +/** + * @typedef {{ + * title: string, + * id: string, + * score: (number|null), + * description: (string|undefined), + * manualDescription: string, + * auditRefs: !Array + * }} + */ +// @ts-ignore typedef +export let CategoryJSON; + +/** + * @typedef {{ + * title: string, + * description: (string|undefined), + * }} + */ +// @ts-ignore typedef +export let GroupJSON; + +/** + * @typedef {{ + * lighthouseVersion: string, + * userAgent: string, + * fetchTime: string, + * timing: {total: number}, + * requestedUrl: string, + * finalUrl: string, + * runWarnings: (!Array|undefined), + * artifacts: {traces: {defaultPass: {traceEvents: !Array}}}, + * audits: !Object, + * categories: !Object, + * categoryGroups: !Object, + * }} + */ +// @ts-ignore typedef +export let ReportJSON; + +/** + * @typedef {{ + * type: string, + * value: (string|number|undefined), + * summary: (!OpportunitySummary|undefined), + * granularity: (number|undefined), + * displayUnit: (string|undefined) + * }} + */ +// @ts-ignore typedef +export let DetailsJSON; + +/** + * @typedef {{ + * traces: {defaultPass: {traceEvents: !Array}}, + * }} + */ +// @ts-ignore typedef +export let RunnerResultArtifacts; + +/** + * @typedef {{ + * lhr: !ReportJSON, + * artifacts: RunnerResultArtifacts, + * report: string, + * stack: string + * }} + */ +// @ts-ignore typedef +export let RunnerResult; + +/** + * @typedef {{ + * type: string, + * path: (string|undefined), + * selector: (string|undefined), + * snippet:(string|undefined) + * }} + */ +// @ts-ignore typedef +export let NodeDetailsJSON; + +/** + * @typedef {{ + * sourceUrl: (string|undefined), + * sourceLine: (string|undefined), + * sourceColumn: (string|undefined), + * }} + */ +// @ts-ignore typedef +export let SourceLocationDetailsJSON; + +/** @typedef {{ + * wastedMs: (number|undefined), + * wastedBytes: (number|undefined), + * }} +*/ +// @ts-ignore typedef +export let OpportunitySummary; diff --git a/front_end/lighthouse/lighthouse-legacy.js b/front_end/lighthouse/lighthouse-legacy.js index ff1dafd292f..8f9359f5dba 100644 --- a/front_end/lighthouse/lighthouse-legacy.js +++ b/front_end/lighthouse/lighthouse-legacy.js @@ -9,7 +9,7 @@ import * as LighthouseModule from './lighthouse.js'; self.Lighthouse = self.Lighthouse || {}; Lighthouse = Lighthouse || {}; -/** @type {!LighthouseReportGenerator} */ +/** @type {!LighthouseModule.LighthouseReporterTypes.LighthouseReportGenerator} */ Lighthouse.ReportGenerator; /** diff --git a/front_end/lighthouse/lighthouse.js b/front_end/lighthouse/lighthouse.js index 862c1a98470..03e4abb5c2e 100644 --- a/front_end/lighthouse/lighthouse.js +++ b/front_end/lighthouse/lighthouse.js @@ -8,6 +8,7 @@ import '../third_party/lighthouse/report-assets/report-generator.js'; import * as LighthouseController from './LighthouseController.js'; import * as LighthousePanel from './LighthousePanel.js'; import * as LighthouseProtocolService from './LighthouseProtocolService.js'; +import * as LighthouseReporterTypes from './LighthouseReporterTypes.js'; import * as LighthouseReportRenderer from './LighthouseReportRenderer.js'; import * as LighthouseReportSelector from './LighthouseReportSelector.js'; import * as LighthouseStartView from './LighthouseStartView.js'; @@ -18,6 +19,7 @@ export { LighthouseController, LighthousePanel, LighthouseProtocolService, + LighthouseReporterTypes, LighthouseReportRenderer, LighthouseReportSelector, LighthouseStartView, diff --git a/front_end/lighthouse/lighthouse_strings.grdp b/front_end/lighthouse/lighthouse_strings.grdp index 99366ee3da3..5287c4cd6f9 100644 --- a/front_end/lighthouse/lighthouse_strings.grdp +++ b/front_end/lighthouse/lighthouse_strings.grdp @@ -27,6 +27,9 @@ The print popup window is open. Please close it to continue. + + Apply mobile emulation + 70% of mobile pages take nearly 7 seconds for the visual content above the fold to display on the screen. [Source: Think with Google] diff --git a/front_end/lighthouse/module.json b/front_end/lighthouse/module.json index fcc9f2cc6ae..91f420a0a94 100644 --- a/front_end/lighthouse/module.json +++ b/front_end/lighthouse/module.json @@ -32,7 +32,8 @@ "LighthouseReportRenderer.js", "LighthouseStartView.js", "LighthouseStatusView.js", - "LighthouseProtocolService.js" + "LighthouseProtocolService.js", + "LighthouseReporterTypes.js" ], "resources": [ "../third_party/lighthouse/report-assets/template.html", diff --git a/front_end/linear_memory_inspector/BUILD.gn b/front_end/linear_memory_inspector/BUILD.gn index fa3b78acde9..9ccf985d255 100644 --- a/front_end/linear_memory_inspector/BUILD.gn +++ b/front_end/linear_memory_inspector/BUILD.gn @@ -15,6 +15,7 @@ devtools_module("linear_memory_inspector") { ] deps = [ + "../common:bundle", "../components:bundle", "../elements:bundle", "../third_party/lit-html:bundle", diff --git a/front_end/linear_memory_inspector/LinearMemoryInspector.ts b/front_end/linear_memory_inspector/LinearMemoryInspector.ts index 9d531426ac4..a2bdc89f26d 100644 --- a/front_end/linear_memory_inspector/LinearMemoryInspector.ts +++ b/front_end/linear_memory_inspector/LinearMemoryInspector.ts @@ -5,20 +5,43 @@ import './LinearMemoryNavigator.js'; import './LinearMemoryViewer.js'; +import * as Common from '../common/common.js'; import * as LitHtml from '../third_party/lit-html/lit-html.js'; const {render, html} = LitHtml; -import type {LinearMemoryNavigatorData} from './LinearMemoryNavigator.js'; -import {LinearMemoryViewerData} from './LinearMemoryViewer.js'; +import {HistoryNavigationEvent, LinearMemoryNavigatorData, Navigation, PageNavigationEvent} from './LinearMemoryNavigator.js'; +import {ByteSelectedEvent, LinearMemoryViewer, LinearMemoryViewerData} from './LinearMemoryViewer.js'; export interface LinearMemoryInspectorData { memory: Uint8Array; address: number; } +class AddressHistoryEntry implements Common.SimpleHistoryManager.HistoryEntry { + private address = 0; + private callback; + + constructor(address: number, callback: (x: number) => void) { + if (address < 0) { + throw new Error('Address should be a greater or equal to zero'); + } + this.address = address; + this.callback = callback; + } + + valid() { + return true; + } + + reveal() { + this.callback(this.address); + } +} + export class LinearMemoryInspector extends HTMLElement { private readonly shadow = this.attachShadow({mode: 'open'}); + private readonly history = new Common.SimpleHistoryManager.SimpleHistoryManager(10); private memory = new Uint8Array(); private address = 0; @@ -52,14 +75,43 @@ export class LinearMemoryInspector extends HTMLElement { }
- - + + this.jumpToAddress(e.data)}>
`, this.shadow, { eventContext: this, }); // clang-format on } + + private navigateHistory(e: HistoryNavigationEvent) { + return e.data === Navigation.Forward ? this.history.rollover() : this.history.rollback(); + } + + private navigatePage(e: PageNavigationEvent) { + const viewer = this.shadow.querySelector('devtools-linear-memory-inspector-viewer'); + if (!viewer) { + return; + } + + const newAddress = e.data === Navigation.Forward ? + Math.min(this.address + viewer.getNumBytesPerPage(), this.memory.length - 1) : + Math.max(this.address - viewer.getNumBytesPerPage(), 0); + this.jumpToAddress(newAddress); + } + + private jumpToAddress(address: number) { + const historyEntry = new AddressHistoryEntry(address, x => this.jumpToAddress(x)); + this.history.push(historyEntry); + + this.address = address; + this.render(); + } } customElements.define('devtools-linear-memory-inspector-inspector', LinearMemoryInspector); diff --git a/front_end/linear_memory_inspector/LinearMemoryNavigator.ts b/front_end/linear_memory_inspector/LinearMemoryNavigator.ts index c8ed32c37e9..e1495bfb7d6 100644 --- a/front_end/linear_memory_inspector/LinearMemoryNavigator.ts +++ b/front_end/linear_memory_inspector/LinearMemoryNavigator.ts @@ -20,7 +20,7 @@ export class PageNavigationEvent extends Event { data: Navigation constructor(navigation: Navigation) { - super('page-navigation', {}); + super('pageNavigation', {}); this.data = navigation; } } @@ -29,7 +29,7 @@ export class HistoryNavigationEvent extends Event { data: Navigation constructor(navigation: Navigation) { - super('history-navigation', {}); + super('historyNavigation', {}); this.data = navigation; } } diff --git a/front_end/linear_memory_inspector/LinearMemoryViewer.ts b/front_end/linear_memory_inspector/LinearMemoryViewer.ts index 3bd697fe2b7..a9f26bf674f 100644 --- a/front_end/linear_memory_inspector/LinearMemoryViewer.ts +++ b/front_end/linear_memory_inspector/LinearMemoryViewer.ts @@ -16,11 +16,54 @@ export class ByteSelectedEvent extends Event { data: number constructor(address: number) { - super('byte-selected'); + super('byteSelected'); this.data = address; } } +interface PageViewData { + address: number; + numRows: number; + numBytesPerRow: number; +} + +// Helper class to gather the data on the view which is actually shown, +// which corresponds to one 'page' in the viewer. +class PageView { + readonly pageStartAddress: number; + readonly selectedRow: number; + readonly selectedAddress: number; + readonly numRows: number; + readonly numBytesPerRow: number; + + constructor(data: PageViewData) { + this.numRows = data.numRows; + this.numBytesPerRow = data.numBytesPerRow; + this.selectedAddress = data.address; + + const bytesPerPage = this.getNumBytesPerPage(); + const pageNumber = Math.floor(this.selectedAddress / bytesPerPage); + this.pageStartAddress = pageNumber * this.getNumBytesPerPage(); + + const selectedAddressOffset = this.getOffsetFromPageStart(this.selectedAddress); + this.selectedRow = Math.floor(selectedAddressOffset / this.numBytesPerRow); + } + + getRowIndexRange(row: number) { + const startIndex = this.pageStartAddress + row * this.numBytesPerRow; + const endIndex = startIndex + this.numBytesPerRow; + return {startIndex, endIndex}; + } + + getNumBytesPerPage() { + return this.numBytesPerRow * this.numRows; + } + + private getOffsetFromPageStart(address: number) { + return Math.max(address - this.pageStartAddress, 0); + } +} + export class LinearMemoryViewer extends HTMLElement { private static BYTE_GROUP_MARGIN = 8; private readonly shadow = this.attachShadow({mode: 'open'}); @@ -32,9 +75,7 @@ export class LinearMemoryViewer extends HTMLElement { private address = 0; private byteGroupSize = 4; - private currentRow = 0; - private numRows = 1; - private numBytesPerRow = this.byteGroupSize; + private pageView = new PageView({address: this.address, numRows: 1, numBytesPerRow: this.byteGroupSize}); set data(data: LinearMemoryViewerData) { this.memory = data.memory; @@ -47,20 +88,21 @@ export class LinearMemoryViewer extends HTMLElement { this.resizeObserver.disconnect(); } + getNumBytesPerPage() { + return this.pageView.getNumBytesPerPage(); + } + private update() { - this.currentRow = this.getRowForAddress(this.address); - this.recomputeSize(); + this.updatePageView(); this.render(); this.engageResizeObserver(); } - private getRowForAddress(address: number) { - return Math.floor((address) / this.numBytesPerRow); - } - /** Recomputes the number of rows and (byte) columns that fit into the current view. */ - private recomputeSize() { + private updatePageView() { + const fallbackPageView = new PageView({address: this.address, numRows: 1, numBytesPerRow: this.byteGroupSize}); if (this.clientWidth === 0 || this.clientHeight === 0 || !this.shadowRoot) { + this.pageView = fallbackPageView; return; } @@ -79,6 +121,7 @@ export class LinearMemoryViewer extends HTMLElement { const rowElement = this.shadowRoot.querySelector('.row'); if (!firstByteCell || !textCell || !divider || !rowElement) { + this.pageView = fallbackPageView; return; } @@ -91,14 +134,15 @@ export class LinearMemoryViewer extends HTMLElement { const dividerWidth = divider.getBoundingClientRect().width; const widthToFill = this.clientWidth - firstByteCell.getBoundingClientRect().left - dividerWidth; if (widthToFill < groupWidth) { - this.numBytesPerRow = this.byteGroupSize; - this.numRows = 1; + this.pageView = fallbackPageView; return; } - this.numBytesPerRow = Math.floor(widthToFill / groupWidth) * this.byteGroupSize; - const maxNumRows = Math.ceil(this.memory.length / this.numBytesPerRow); - this.numRows = Math.min(Math.floor(this.clientHeight / rowElement.getBoundingClientRect().height), maxNumRows); + const numBytesPerRow = Math.floor(widthToFill / groupWidth) * this.byteGroupSize; + const maxNumRows = Math.ceil(this.memory.length / numBytesPerRow); + const numRows = Math.min(Math.floor(this.clientHeight / rowElement.getBoundingClientRect().height), maxNumRows); + + this.pageView = new PageView({address: this.address, numRows, numBytesPerRow}); } private engageResizeObserver() { @@ -181,19 +225,18 @@ export class LinearMemoryViewer extends HTMLElement { private renderView() { const itemTemplates = []; - for (let i = 0; i < this.numRows; ++i) { + for (let i = 0; i < this.pageView.numRows; ++i) { itemTemplates.push(this.renderRow(i)); } return html`${itemTemplates}`; } private renderRow(row: number) { - const startIndex = row * this.numBytesPerRow; - const endIndex = startIndex + this.numBytesPerRow; + const {startIndex, endIndex} = this.pageView.getRowIndexRange(row); const classMap = { - 'address': true, - selected: this.currentRow === row, + address: true, + selected: this.pageView.selectedRow === row, }; return html`
diff --git a/front_end/media/PlayerPropertiesView.js b/front_end/media/PlayerPropertiesView.js index 4dbe9b95e4e..243241bfb0a 100644 --- a/front_end/media/PlayerPropertiesView.js +++ b/front_end/media/PlayerPropertiesView.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as UI from '../ui/ui.js'; @@ -38,6 +35,9 @@ export const PlayerPropertyKeys = { * @unrestricted */ export class PropertyRenderer extends UI.Widget.VBox { + /** + * @param {string} title + */ constructor(title) { super(); this.contentElement.classList.add('media-property-renderer'); @@ -45,18 +45,23 @@ export class PropertyRenderer extends UI.Widget.VBox { this._contents = this.contentElement.createChild('span', 'media-property-renderer-contents'); UI.UIUtils.createTextChild(this._title, title); this._title = title; + /** @type {?string} */ this._value = null; this._pseudo_color_protection_element = null; this.contentElement.classList.add('media-property-renderer-hidden'); } + /** + * @param {string} propname + * @param {string} propvalue + */ updateData(propname, propvalue) { // convert all empty possibilities into nulls for easier handling. if (propvalue === '' || propvalue === null) { return this._updateData(propname, null); } try { - propvalue = JSON.parse(propvalue); + propvalue = /** @type {string} */ (JSON.parse(propvalue)); } catch (err) { // TODO(tmathmeyer) typecheck the type of propvalue against // something defined or sourced from the c++ definitions. @@ -65,6 +70,10 @@ export class PropertyRenderer extends UI.Widget.VBox { return this._updateData(propname, propvalue); } + /** + * @param {string} propname + * @param {?string} propvalue + */ _updateData(propname, propvalue) { if (propvalue === null) { this.changeContents(null); @@ -76,6 +85,9 @@ export class PropertyRenderer extends UI.Widget.VBox { } } + /** + * @param {?string} value + */ changeContents(value) { if (value === null) { this.contentElement.classList.add('media-property-renderer-hidden'); @@ -83,7 +95,8 @@ export class PropertyRenderer extends UI.Widget.VBox { this._pseudo_color_protection_element = document.createElement('div'); this._pseudo_color_protection_element.classList.add('media-property-renderer'); this._pseudo_color_protection_element.classList.add('media-property-renderer-hidden'); - this.contentElement.parentNode.insertBefore(this._pseudo_color_protection_element, this.contentElement); + /** @type {!HTMLElement} */ (this.contentElement.parentNode) + .insertBefore(this._pseudo_color_protection_element, this.contentElement); } } else { if (this._pseudo_color_protection_element !== null) { @@ -92,7 +105,7 @@ export class PropertyRenderer extends UI.Widget.VBox { } this.contentElement.classList.remove('media-property-renderer-hidden'); this._contents.removeChildren(); - const spanElement = createElement('span'); + const spanElement = document.createElement('span'); spanElement.textContent = value; this._contents.appendChild(spanElement); } @@ -100,6 +113,10 @@ export class PropertyRenderer extends UI.Widget.VBox { } export class FormattedPropertyRenderer extends PropertyRenderer { + /** + * @param {string} title + * @param {function(string):string} formatfunction + */ constructor(title, formatfunction) { super(Common.UIString.UIString(title)); this._formatfunction = formatfunction; @@ -107,6 +124,8 @@ export class FormattedPropertyRenderer extends PropertyRenderer { /** * @override + * @param {string} propname + * @param {?string} propvalue */ _updateData(propname, propvalue) { if (propvalue === null) { @@ -121,6 +140,10 @@ export class FormattedPropertyRenderer extends PropertyRenderer { * @unrestricted */ export class DefaultPropertyRenderer extends PropertyRenderer { + /** + * @param {string} title + * @param {string} default_text + */ constructor(title, default_text) { super(Common.UIString.UIString(title)); this.changeContents(default_text); @@ -131,6 +154,9 @@ export class DefaultPropertyRenderer extends PropertyRenderer { * @unrestricted */ export class DimensionPropertyRenderer extends PropertyRenderer { + /** + * @param {string} title + */ constructor(title) { super(Common.UIString.UIString(title)); this._width = 0; @@ -139,15 +165,17 @@ export class DimensionPropertyRenderer extends PropertyRenderer { /** * @override + * @param {string} propname + * @param {?string} propvalue */ _updateData(propname, propvalue) { let needsUpdate = false; - if (propname === 'width' && propvalue !== this._width) { - this._width = propvalue; + if (propname === 'width' && Number(propvalue) !== this._width) { + this._width = Number(propvalue); needsUpdate = true; } - if (propname === 'height' && propvalue !== this._height) { - this._height = propvalue; + if (propname === 'height' && Number(propvalue) !== this._height) { + this._height = Number(propvalue); needsUpdate = true; } // If both properties arent set, don't bother updating, since @@ -164,6 +192,9 @@ export class DimensionPropertyRenderer extends PropertyRenderer { * @unrestricted */ export class AttributesView extends UI.Widget.VBox { + /** + * @param {!Array} elements + */ constructor(elements) { super(); this.contentElement.classList.add('media-attributes-view'); @@ -174,16 +205,23 @@ export class AttributesView extends UI.Widget.VBox { } export class TrackManager { + /** + * @param {!PlayerPropertiesView} propertiesView + * @param {string} type + */ constructor(propertiesView, type) { this._type = type; this._view = propertiesView; - this._previousTabs = []; } + /** + * @param {string} name + * @param {string} value + */ updateData(name, value) { const tabs = this._view.GetTabs(this._type); - const newTabs = /** @type {!Array.} */ (JSON.parse(value)); + const newTabs = /** @type {!Array.>} */ (JSON.parse(value)); let enumerate = 1; for (const tabData of newTabs) { this.addNewTab(tabs, tabData, enumerate); @@ -191,6 +229,11 @@ export class TrackManager { } } + /** + * @param {(!GenericTrackMenu|!NoTracksPlaceholderMenu)} tabs + * @param {!Object} tabData + * @param {number} tabNumber + */ addNewTab(tabs, tabData, tabNumber) { const tabElements = []; for (const [name, data] of Object.entries(tabData)) { @@ -203,18 +246,27 @@ export class TrackManager { } export class VideoTrackManager extends TrackManager { + /** + * @param {!PlayerPropertiesView} propertiesView + */ constructor(propertiesView) { super(propertiesView, 'video'); } } export class TextTrackManager extends TrackManager { + /** + * @param {!PlayerPropertiesView} propertiesView + */ constructor(propertiesView) { super(propertiesView, 'text'); } } export class AudioTrackManager extends TrackManager { + /** + * @param {!PlayerPropertiesView} propertiesView + */ constructor(propertiesView) { super(propertiesView, 'audio'); } @@ -228,12 +280,20 @@ const TrackTypeLocalized = { class GenericTrackMenu extends UI.TabbedPane.TabbedPane { + /** + * @param {string} decoderName + * @param {string} trackName + */ constructor(decoderName, trackName = ls`Track`) { super(); this._decoderName = decoderName; this._trackName = trackName; } + /** + * @param {number} trackNumber + * @param {!UI.Widget.Widget} element + */ addNewTab(trackNumber, element) { const localizedTrackLower = Common.UIString.UIString('track'); this.appendTab( @@ -243,6 +303,10 @@ class GenericTrackMenu extends UI.TabbedPane.TabbedPane { } class DecoderTrackMenu extends GenericTrackMenu { + /** + * @param {string} decoderName + * @param {!UI.Widget.Widget} informationalElement + */ constructor(decoderName, informationalElement) { super(decoderName); @@ -255,6 +319,10 @@ class DecoderTrackMenu extends GenericTrackMenu { } class NoTracksPlaceholderMenu extends UI.Widget.VBox { + /** + * @param {!GenericTrackMenu} wrapping + * @param {string} placeholder_text + */ constructor(wrapping, placeholder_text) { super(); this._isPlaceholder = true; @@ -263,6 +331,10 @@ class NoTracksPlaceholderMenu extends UI.Widget.VBox { this._wrapping.show(this.contentElement); } + /** + * @param {number} trackNumber + * @param {!UI.Widget.Widget} element + */ addNewTab(trackNumber, element) { if (this._isPlaceholder) { this._wrapping.closeTab('_placeholder'); @@ -280,6 +352,17 @@ export class PlayerPropertiesView extends UI.Widget.VBox { super(); this.contentElement.classList.add('media-properties-frame'); this.registerRequiredCSS('media/playerPropertiesView.css'); + /** @type {!Array} */ + this._mediaElements = []; + /** @type {!Array} */ + this._videoDecoderElements = []; + /** @type {!Array} */ + this._audioDecoderElements = []; + /** @type {!Array} */ + this._textTrackElements = []; + /** @type {!Map} */ + this._attributeMap = new Map(); + this.populateAttributesAndElements(); this._videoProperties = new AttributesView(this._mediaElements); this._videoDecoderProperties = new AttributesView(this._videoDecoderElements); @@ -291,18 +374,30 @@ export class PlayerPropertiesView extends UI.Widget.VBox { this._audioDecoderTabs = new DecoderTrackMenu(TrackTypeLocalized.Audio, this._audioDecoderProperties); this._audioDecoderTabs.show(this.contentElement); + /** + * @type {(?GenericTrackMenu|?NoTracksPlaceholderMenu)} + */ this._textTrackTabs = null; } + /** + * @return {(!GenericTrackMenu|!NoTracksPlaceholderMenu)} + */ _lazyCreateTrackTabs() { - if (this._textTrackTabs === null) { + let textTracksTabs = this._textTrackTabs; + if (textTracksTabs === null) { const textTracks = new GenericTrackMenu(ls`Text track`); - this._textTrackTabs = new NoTracksPlaceholderMenu(textTracks, ls`No text tracks`); - this._textTrackTabs.show(this.contentElement); + textTracksTabs = new NoTracksPlaceholderMenu(textTracks, ls`No text tracks`); + textTracksTabs.show(this.contentElement); + this._textTracksTabs = textTracksTabs; } - return this._textTrackTabs; + return textTracksTabs; } + /** + * @param {string} type + * @return {(!GenericTrackMenu|!NoTracksPlaceholderMenu)} + */ GetTabs(type) { if (type === 'audio') { return this._audioDecoderTabs; @@ -328,43 +423,47 @@ export class PlayerPropertiesView extends UI.Widget.VBox { renderer.updateData(property.name, property.value); } + /** + * @param {string|number} bitsPerSecond + */ formatKbps(bitsPerSecond) { if (bitsPerSecond === '') { return '0 kbps'; } - const kbps = Math.floor(bitsPerSecond / 1000); + const kbps = Math.floor(Number(bitsPerSecond) / 1000); return `${kbps} kbps`; } + /** + * @param {string|number} seconds + */ formatTime(seconds) { if (seconds === '') { return '0:00'; } - const date = new Date(null); - date.setSeconds(seconds); + const date = new Date(''); + date.setSeconds(Number(seconds)); return date.toISOString().substr(11, 8); } + /** + * @param {string} bytes + */ formatFileSize(bytes) { if (bytes === '') { return '0 bytes'; } - const power = Math.floor(Math.log(bytes) / Math.log(1024)); + const actualBytes = Number(bytes); + if (actualBytes < 1000) { + return `${bytes} bytes`; + } + const power = Math.floor(Math.log10(actualBytes) / 3); const suffix = ['bytes', 'kB', 'MB', 'GB', 'TB'][power]; - const bytesDecimal = (bytes / Math.pow(1000, power)).toFixed(2); + const bytesDecimal = (actualBytes / Math.pow(1000, power)).toFixed(2); return `${bytesDecimal} ${suffix}`; } populateAttributesAndElements() { - // Lists of Media.PropertyRenderer - this._mediaElements = []; - this._videoDecoderElements = []; - this._audioDecoderElements = []; - this._textTrackElements = []; - - // Map from incoming change_id => Media.PropertyRenderer - this._attributeMap = new Map(); - /* Media properties */ const resolution = new PropertyRenderer(ls`Resolution`); this._mediaElements.push(resolution); diff --git a/front_end/mobile_throttling/ThrottlingSettingsTab.js b/front_end/mobile_throttling/ThrottlingSettingsTab.js index 721cff3da5c..384f86bb73f 100644 --- a/front_end/mobile_throttling/ThrottlingSettingsTab.js +++ b/front_end/mobile_throttling/ThrottlingSettingsTab.js @@ -100,9 +100,9 @@ export class ThrottlingSettingsTab extends UI.Widget.VBox { commitEdit(conditions, editor, isNew) { conditions.title = editor.control('title').value.trim(); const download = editor.control('download').value.trim(); - conditions.download = download ? parseInt(download, 10) * (1024 / 8) : -1; + conditions.download = download ? parseInt(download, 10) * (1000 / 8) : -1; const upload = editor.control('upload').value.trim(); - conditions.upload = upload ? parseInt(upload, 10) * (1024 / 8) : -1; + conditions.upload = upload ? parseInt(upload, 10) * (1000 / 8) : -1; const latency = editor.control('latency').value.trim(); conditions.latency = latency ? parseInt(latency, 10) : 0; @@ -121,8 +121,8 @@ export class ThrottlingSettingsTab extends UI.Widget.VBox { beginEdit(conditions) { const editor = this._createEditor(); editor.control('title').value = conditions.title; - editor.control('download').value = conditions.download <= 0 ? '' : String(conditions.download / (1024 / 8)); - editor.control('upload').value = conditions.upload <= 0 ? '' : String(conditions.upload / (1024 / 8)); + editor.control('download').value = conditions.download <= 0 ? '' : String(conditions.download / (1000 / 8)); + editor.control('upload').value = conditions.upload <= 0 ? '' : String(conditions.upload / (1000 / 8)); editor.control('latency').value = conditions.latency ? String(conditions.latency) : ''; return editor; } @@ -259,13 +259,13 @@ export function throughputText(throughput, plainText) { if (throughput < 0) { return ''; } - const throughputInKbps = throughput / (1024 / 8); + const throughputInKbps = throughput / (1000 / 8); const delimiter = plainText ? '' : ' '; - if (throughputInKbps < 1024) { - return Common.UIString.UIString('%d%skb/s', throughputInKbps, delimiter); + if (throughputInKbps < 1000) { + return Common.UIString.UIString('%d%skB/s', throughputInKbps, delimiter); } - if (throughputInKbps < 1024 * 10) { - return Common.UIString.UIString('%.1f%sMb/s', throughputInKbps / 1024, delimiter); + if (throughputInKbps < 1000 * 10) { + return Common.UIString.UIString('%.1f%sMB/s', throughputInKbps / 1000, delimiter); } - return Common.UIString.UIString('%d%sMb/s', (throughputInKbps / 1024) | 0, delimiter); + return Common.UIString.UIString('%d%sMB/s', (throughputInKbps / 1000) | 0, delimiter); } diff --git a/front_end/mobile_throttling/mobile_throttling_strings.grdp b/front_end/mobile_throttling/mobile_throttling_strings.grdp index 2fa60eae87f..7030b26bec3 100644 --- a/front_end/mobile_throttling/mobile_throttling_strings.grdp +++ b/front_end/mobile_throttling/mobile_throttling_strings.grdp @@ -24,12 +24,6 @@ Requests may be rewritten by local overrides - - $1d25$2s''' '''kb/s - - - $1d25$2s''' '''Mb/s - No throttling @@ -42,6 +36,9 @@ Go offline + + $1d25$2s kB/s + Latency must be an integer between $1s0ms to $2s1000000ms inclusive @@ -63,6 +60,9 @@ Advanced + + $1d25$2s MB/s + kb/s @@ -87,12 +87,12 @@ $1d2× slowdown - - $1.1f25.4$2s''' '''Mb/s - CPU throttling is enabled + + $1.1f25.4$2s MB/s + optional diff --git a/front_end/network/NetworkDataGridNode.js b/front_end/network/NetworkDataGridNode.js index 46c7e3d349c..73973db3ac2 100644 --- a/front_end/network/NetworkDataGridNode.js +++ b/front_end/network/NetworkDataGridNode.js @@ -941,10 +941,11 @@ export class NetworkRequestNode extends NetworkNode { /** * @param {!HTMLElement} element * @param {string} text + * @param {string=} title */ - _setTextAndTitle(element, text) { + _setTextAndTitle(element, text, title) { UI.UIUtils.createTextChild(element, text); - element.title = text; + element.title = title || text; } /** @@ -1160,7 +1161,8 @@ export class NetworkRequestNode extends NetworkNode { cell.classList.toggle( 'network-dim-cell', !this._isFailed() && (this._request.cached() || !this._request.statusCode)); - if (this._request.failed && !this._request.canceled && !this._request.wasBlocked()) { + const corsErrorStatus = this._request.corsErrorStatus(); + if (this._request.failed && !this._request.canceled && !this._request.wasBlocked() && !corsErrorStatus) { const failText = Common.UIString.UIString('(failed)'); if (this._request.localizedFailDescription) { UI.UIUtils.createTextChild(cell, failText); @@ -1234,6 +1236,10 @@ export class NetworkRequestNode extends NetworkNode { } else { this._setTextAndTitle(cell, Common.UIString.UIString('(blocked:%s)', reason)); } + } else if (corsErrorStatus) { + this._setTextAndTitle( + cell, Common.UIString.UIString('CORS error'), + ls`Cross-Origin Resource Sharing error: ${corsErrorStatus.corsError}`); } else if (this._request.finished) { this._setTextAndTitle(cell, Common.UIString.UIString('Finished')); } else { diff --git a/front_end/network/NetworkLogView.js b/front_end/network/NetworkLogView.js index b633cf9005e..5d0f3e1abc1 100644 --- a/front_end/network/NetworkLogView.js +++ b/front_end/network/NetworkLogView.js @@ -46,6 +46,7 @@ import {HARWriter} from './HARWriter.js'; import {Events, NetworkGroupNode, NetworkLogViewInterface, NetworkNode, NetworkRequestNode} from './NetworkDataGridNode.js'; // eslint-disable-line no-unused-vars import {NetworkFrameGrouper} from './NetworkFrameGrouper.js'; import {NetworkLogViewColumns} from './NetworkLogViewColumns.js'; +import {FilterOptions} from './NetworkPanel.js'; // eslint-disable-line no-unused-vars import {NetworkTimeBoundary, NetworkTimeCalculator, NetworkTransferDurationCalculator, NetworkTransferTimeCalculator,} from './NetworkTimeCalculator.js'; // eslint-disable-line no-unused-vars /** @@ -1674,7 +1675,7 @@ export class NetworkLogView extends UI.Widget.VBox { !BrowserSDK.RelatedIssue.hasIssueOfCategory(request, SDK.Issue.IssueCategory.SameSiteCookie)) { return false; } - if (this._onlyBlockedRequestsUI.checked() && !request.wasBlocked()) { + if (this._onlyBlockedRequestsUI.checked() && !request.wasBlocked() && !request.corsErrorStatus()) { return false; } if (request.statusText === 'Service Worker Fallback Required') { @@ -1798,10 +1799,10 @@ export class NetworkLogView extends UI.Widget.VBox { _createSizeFilter(value) { let multiplier = 1; if (value.endsWith('k')) { - multiplier = 1024; + multiplier = 1000; value = value.substring(0, value.length - 1); } else if (value.endsWith('m')) { - multiplier = 1024 * 1024; + multiplier = 1000 * 1000; value = value.substring(0, value.length - 1); } const quantity = Number(value); @@ -1851,9 +1852,14 @@ export class NetworkLogView extends UI.Widget.VBox { /** * @override * @param {!SDK.NetworkRequest.NetworkRequest} request + * @param {!FilterOptions=} options - Optional parameters to change filter behavior */ - selectRequest(request) { - this.setTextFilterValue(''); + selectRequest(request, options) { + const defaultOptions = {clearFilter: true}; + const {clearFilter} = options || defaultOptions; + if (clearFilter) { + this.setTextFilterValue(''); + } const node = this._reveal(request); if (node) { node.select(); diff --git a/front_end/network/NetworkPanel.js b/front_end/network/NetworkPanel.js index 5677012d2de..eae9aacea80 100644 --- a/front_end/network/NetworkPanel.js +++ b/front_end/network/NetworkPanel.js @@ -172,10 +172,19 @@ export class NetworkPanel extends UI.Panel.Panel { this._preserveLogSetting = Common.Settings.Settings.instance().moduleSetting('network_log.preserve-log'); + this._toggleRecordSetting = Common.Settings.Settings.instance().moduleSetting('network.toggle-recording-setting'); + this._toggleRecordSetting.addChangeListener(({data}) => { + if (data !== this._toggleRecordAction.toggled()) { + this._toggleRecord(data); + } + }); + this._throttlingSelect = this._createThrottlingConditionsSelect(); this._setupToolbarButtons(splitWidget); - this._toggleRecord(true); + if (this._toggleRecordSetting.get()) { + this._toggleRecord(true); + } this._toggleShowOverview(); this._toggleLargerRequests(); this._toggleRecordFilmStrip(); @@ -227,10 +236,11 @@ export class NetworkPanel extends UI.Panel.Panel { /** * @param {!SDK.NetworkRequest.NetworkRequest} request * @param {!NetworkItemViewTabs} tab + * @param {!FilterOptions=} options - Optional parameters to change filter behavior */ - static async selectAndShowRequest(request, tab) { + static async selectAndShowRequest(request, tab, options) { const panel = NetworkPanel._instance(); - await panel.selectAndActivateRequest(request, tab); + await panel.selectAndActivateRequest(request, tab, options); } /** @@ -353,22 +363,19 @@ export class NetworkPanel extends UI.Panel.Panel { return toolbarItem; } - _toggleRecording() { - if (!this._preserveLogSetting.get() && !this._toggleRecordAction.toggled()) { - SDK.NetworkLog.NetworkLog.instance().reset(); - } - this._toggleRecord(!this._toggleRecordAction.toggled()); - } - /** * @param {boolean} toggled */ _toggleRecord(toggled) { + if (!this._preserveLogSetting.get() && !this._toggleRecordAction.toggled() && toggled) { + SDK.NetworkLog.NetworkLog.instance().reset(); + } this._toggleRecordAction.setToggled(toggled); this._networkLogView.setRecording(toggled); if (!toggled && this._filmStripRecorder) { this._filmStripRecorder.stopRecording(this._filmStripAvailable.bind(this)); } + this._toggleRecordSetting.set(toggled); // TODO(einbinder) This should be moved to a setting/action that NetworkLog owns but NetworkPanel controls, but // always be present in the command menu. SDK.NetworkLog.NetworkLog.instance().setIsRecording(toggled); @@ -415,7 +422,6 @@ export class NetworkPanel extends UI.Panel.Panel { * @param {!Common.EventTarget.EventTargetEvent} event */ _willReloadPage(event) { - this._toggleRecord(true); if (this._pendingStopTimer) { clearTimeout(this._pendingStopTimer); delete this._pendingStopTimer; @@ -529,11 +535,12 @@ export class NetworkPanel extends UI.Panel.Panel { /** * @param {!SDK.NetworkRequest.NetworkRequest} request * @param {!NetworkItemViewTabs=} shownTab + * @param {!FilterOptions=} options - Optional parameters to change filter behavior * @return {!Promise} */ - async selectAndActivateRequest(request, shownTab) { + async selectAndActivateRequest(request, shownTab, options) { await UI.ViewManager.ViewManager.instance().showView('network'); - this._networkLogView.selectRequest(request); + this._networkLogView.selectRequest(request, options); this._showRequestPanel(shownTab); return this._networkItemView; } @@ -911,7 +918,7 @@ export class ActionDelegate { } switch (actionId) { case 'network.toggle-recording': { - panel._toggleRecording(); + panel._toggleRecord(!panel._toggleRecordSetting.get()); return true; } case 'network.hide-request-details': { @@ -1008,3 +1015,11 @@ export class SearchNetworkView extends Search.SearchView.SearchView { return new NetworkSearchScope(); } } + +/** + * @typedef {{ + * clearFilter: boolean, + * }} + */ +// @ts-ignore typedef +export let FilterOptions; diff --git a/front_end/network/module.json b/front_end/network/module.json index bd3a4610516..5c5cd048f23 100644 --- a/front_end/network/module.json +++ b/front_end/network/module.json @@ -70,6 +70,15 @@ } ] }, + { + "type": "setting", + "category": "Network", + "title": "Record network log", + "settingName": "network.toggle-recording-setting", + "settingType": "boolean", + "storageType": "session", + "defaultValue": true + }, { "type": "action", "actionId": "network.toggle-recording", diff --git a/front_end/network/network_strings.grdp b/front_end/network/network_strings.grdp index 70a512f2a84..58a6be308d7 100644 --- a/front_end/network/network_strings.grdp +++ b/front_end/network/network_strings.grdp @@ -435,9 +435,15 @@ Only provisional headers are available because this request was not sent over the network and instead was served from a local cache, which doesn’t store the original request headers. Disable cache to see full request headers. + + Cross-Origin Resource Sharing error: $1sPreflightDisallowedRedirect + Active client experiment variation IDs. + + CORS error + Retrieval Time: $1sFri Apr 10 2020 17:20:27 GMT-0700 (Pacific Daylight Time) diff --git a/front_end/object_ui/JavaScriptREPL.js b/front_end/object_ui/JavaScriptREPL.js index a486a4b2889..d2ee0ada027 100644 --- a/front_end/object_ui/JavaScriptREPL.js +++ b/front_end/object_ui/JavaScriptREPL.js @@ -98,11 +98,12 @@ export class JavaScriptREPL { } const formatter = new RemoteObjectPreviewFormatter(); - const {preview, type, subtype, description} = result.object; - if (preview && type === 'object' && subtype !== 'node') { + const {preview, type, subtype, className, description} = result.object; + if (preview && type === 'object' && subtype !== 'node' && subtype !== 'trustedtype') { formatter.appendObjectPreview(fragment, preview, false /* isEntry */); } else { - const nonObjectPreview = formatter.renderPropertyPreview(type, subtype, description.trimEndWithMaxLength(400)); + const nonObjectPreview = + formatter.renderPropertyPreview(type, subtype, className, description.trimEndWithMaxLength(400)); fragment.appendChild(nonObjectPreview); } return fragment; diff --git a/front_end/object_ui/ObjectPropertiesSection.js b/front_end/object_ui/ObjectPropertiesSection.js index f31aa04245e..ba8a96d58ca 100644 --- a/front_end/object_ui/ObjectPropertiesSection.js +++ b/front_end/object_ui/ObjectPropertiesSection.js @@ -39,6 +39,8 @@ import {CustomPreviewComponent} from './CustomPreviewComponent.js'; import {JavaScriptREPL} from './JavaScriptREPL.js'; import {createSpansForNodeTitle, RemoteObjectPreviewFormatter} from './RemoteObjectPreviewFormatter.js'; +const EXPANDABLE_MAX_LENGTH = 50; + /** * @unrestricted */ @@ -359,6 +361,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow const type = value.type; const subtype = value.subtype; const description = value.description; + const className = value.className; if (type === 'object' && subtype === 'internal#location') { const rawLocation = value.debuggerModel().createRawLocationByScriptId( value.value.scriptId, value.value.lineNumber, value.value.columnNumber); @@ -368,6 +371,8 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow propertyValue = new ObjectPropertyValue(createUnknownInternalLocationElement()); } else if (type === 'string' && typeof description === 'string') { propertyValue = createStringElement(); + } else if (type === 'object' && subtype === 'trustedtype') { + propertyValue = createTrustedTypeElement(); } else if (type === 'function') { propertyValue = new ObjectPropertyValue(ObjectPropertiesSection.valueElementForFunctionDescription(description)); } else if (type === 'object' && subtype === 'node' && description) { @@ -389,7 +394,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow } else if ( description.length > (self.ObjectUI.ObjectPropertiesSection._maxRenderableStringLength || maxRenderableStringLength)) { - propertyValue = new ExpandableTextPropertyValue(valueElement, description, 50); + propertyValue = new ExpandableTextPropertyValue(valueElement, description, EXPANDABLE_MAX_LENGTH); } else { propertyValue = new ObjectPropertyValue(valueElement); propertyValue.element.textContent = description; @@ -428,7 +433,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow valueElement.createChild('span', 'object-value-string-quote').textContent = '"'; if (description.length > (self.ObjectUI.ObjectPropertiesSection._maxRenderableStringLength || maxRenderableStringLength)) { - propertyValue = new ExpandableTextPropertyValue(valueElement, text, 50); + propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH); } else { UI.UIUtils.createTextChild(valueElement, text); propertyValue = new ObjectPropertyValue(valueElement); @@ -438,6 +443,28 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow return propertyValue; } + /** + * @return {!ObjectPropertyValue} + */ + function createTrustedTypeElement() { + const valueElement = /** @type {!HTMLElement} */ (document.createElement('span')); + valueElement.classList.add('object-value-trustedtype'); + const text = `${className} "${description}"`; + let propertyValue; + if (text.length > + (self.ObjectUI.ObjectPropertiesSection._maxRenderableStringLength || maxRenderableStringLength)) { + propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH); + } else { + const contentString = createStringElement(); + UI.UIUtils.createTextChild(valueElement, `${className} `); + valueElement.appendChild(contentString.element); + propertyValue = new ObjectPropertyValue(valueElement); + valueElement.title = text; + } + + return propertyValue; + } + /** * @return {!Element} */ diff --git a/front_end/object_ui/RemoteObjectPreviewFormatter.js b/front_end/object_ui/RemoteObjectPreviewFormatter.js index 245d1d34303..813e10e6e3b 100644 --- a/front_end/object_ui/RemoteObjectPreviewFormatter.js +++ b/front_end/object_ui/RemoteObjectPreviewFormatter.js @@ -51,9 +51,10 @@ export class RemoteObjectPreviewFormatter { */ appendObjectPreview(parentElement, preview, isEntry) { const description = preview.description; - const subTypesWithoutValuePreview = new Set(['null', 'regexp', 'error', 'internal#entry']); + const subTypesWithoutValuePreview = new Set(['null', 'regexp', 'error', 'internal#entry', 'trustedtype']); if (preview.type !== 'object' || subTypesWithoutValuePreview.has(preview.subtype) || isEntry) { - parentElement.appendChild(this.renderPropertyPreview(preview.type, preview.subtype, description)); + parentElement.appendChild( + this.renderPropertyPreview(preview.type, preview.subtype, preview.className, description)); return; } const isArrayOrTypedArray = preview.subtype === 'array' || preview.subtype === 'typedarray'; @@ -262,16 +263,18 @@ export class RemoteObjectPreviewFormatter { */ _renderPropertyPreviewOrAccessor(propertyPath) { const property = propertyPath.peekLast(); - return this.renderPropertyPreview(property.type, /** @type {string} */ (property.subtype), property.value); + return this.renderPropertyPreview( + property.type, /** @type {string} */ (property.subtype), property.className, property.value); } /** * @param {string} type * @param {string=} subtype + * @param {(?string|undefined)=} className * @param {string=} description * @return {!HTMLElement} */ - renderPropertyPreview(type, subtype, description) { + renderPropertyPreview(type, subtype, className, description) { const span = /** @type {!HTMLElement} */ (document.createElement('span')); span.classList.add('object-value-' + (subtype || type)); description = description || ''; @@ -287,6 +290,11 @@ export class RemoteObjectPreviewFormatter { return span; } + if (type === 'object' && subtype === 'trustedtype' && className) { + createSpanForTrustedType(span, description, className); + return span; + } + if (type === 'object' && subtype === 'node' && description) { createSpansForNodeTitle(span, description); return span; @@ -334,3 +342,16 @@ export const createSpansForNodeTitle = function(container, nodeTitle) { container.createChild('span', 'webkit-html-attribute-name').textContent = match[3]; } }; + +/** + * @param {!Element} span + * @param {string} description + * @param {string} className + */ +export const createSpanForTrustedType = function(span, description, className) { + UI.UIUtils.createTextChildren(span, `${className} `); + const trustedContentSpan = document.createElement('span'); + trustedContentSpan.classList.add('object-value-string'); + UI.UIUtils.createTextChildren(trustedContentSpan, '"', description.replace(/\n/g, '\u21B5'), '"'); + span.appendChild(trustedContentSpan); +}; diff --git a/front_end/perf_ui/LineLevelProfile.js b/front_end/perf_ui/LineLevelProfile.js index a0c2f079af5..ec848759fb9 100644 --- a/front_end/perf_ui/LineLevelProfile.js +++ b/front_end/perf_ui/LineLevelProfile.js @@ -310,7 +310,7 @@ export class LineDecorator { value /= 1e3; fractionDigits = value >= 20 ? 0 : 1; } else { - units = ls`KB`; + units = ls`kB`; fractionDigits = 0; } element.textContent = Common.UIString.UIString(`%.${fractionDigits}f`, value); diff --git a/front_end/platform/BUILD.gn b/front_end/platform/BUILD.gn index af73a115e79..0271c2e3ce3 100644 --- a/front_end/platform/BUILD.gn +++ b/front_end/platform/BUILD.gn @@ -10,6 +10,7 @@ devtools_module("platform") { "UIString.js", "array-utilities.js", "date-utilities.js", + "map-utilities.js", "number-utilities.js", "set-utilities.js", "string-utilities.js", diff --git a/front_end/platform/map-utilities.js b/front_end/platform/map-utilities.js new file mode 100644 index 00000000000..7b8fc79fd20 --- /dev/null +++ b/front_end/platform/map-utilities.js @@ -0,0 +1,18 @@ +// Copyright (c) 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {Multimap} from './utilities.js'; +/** + * @param {!Map} map + * @return {!Multimap} + * @template K,V + */ +export const inverse = function(map) { + const result = new Multimap(); + for (const key of map.keys()) { + const value = map.get(key); + result.set(value, key); + } + return result; +}; diff --git a/front_end/platform/module.json b/front_end/platform/module.json index cda40266ec5..5516057718c 100644 --- a/front_end/platform/module.json +++ b/front_end/platform/module.json @@ -4,6 +4,7 @@ "platform.js", "utilities.js", "date-utilities.js", + "map-utilities.js", "set-utilities.js", "string-utilities.js", "number-utilities.js", diff --git a/front_end/platform/platform.js b/front_end/platform/platform.js index 662590ac591..ef4df1faaac 100644 --- a/front_end/platform/platform.js +++ b/front_end/platform/platform.js @@ -32,6 +32,7 @@ import './utilities.js'; import * as ArrayUtilities from './array-utilities.js'; import * as DateUtilities from './date-utilities.js'; +import * as MapUtilities from './map-utilities.js'; import * as NumberUtilities from './number-utilities.js'; import * as SetUtilities from './set-utilities.js'; import * as StringUtilities from './string-utilities.js'; @@ -43,4 +44,4 @@ import * as UIString from './UIString.js'; export const {ls} = UIString; export {Multimap} from './utilities.js'; -export {ArrayUtilities, DateUtilities, NumberUtilities, SetUtilities, StringUtilities, UIString}; +export {ArrayUtilities, DateUtilities, MapUtilities, NumberUtilities, SetUtilities, StringUtilities, UIString}; diff --git a/front_end/platform/utilities.js b/front_end/platform/utilities.js index 2c15df2b4d6..85a8e250db2 100644 --- a/front_end/platform/utilities.js +++ b/front_end/platform/utilities.js @@ -33,6 +33,7 @@ * extensions but in the mean time if an old func in here depends on one * that has been migrated it will need to be imported */ +import {inverse} from './map-utilities.js'; import {caseInsensetiveComparator, escapeCharacters, regexSpecialCharacters, sprintf} from './string-utilities.js'; // Still used in the test runners that can't use ES modules :( @@ -455,15 +456,11 @@ Set.prototype.firstValue = function() { }; /** - * @return {!Platform.Multimap} + * @return {!Multimap} + * @template K,V */ Map.prototype.inverse = function() { - const result = new Platform.Multimap(); - for (const key of this.keys()) { - const value = this.get(key); - result.set(value, key); - } - return result; + return inverse(this); }; /** diff --git a/front_end/profiler/HeapProfileView.js b/front_end/profiler/HeapProfileView.js index 23a42b86467..24650de3842 100644 --- a/front_end/profiler/HeapProfileView.js +++ b/front_end/profiler/HeapProfileView.js @@ -563,7 +563,7 @@ export class HeapFlameChartDataProvider extends ProfileFlameChartDataProvider { * @return {string} */ formatValue(value, precision) { - return Common.UIString.UIString('%s\xa0KB', Number.withThousandsSeparator(value / 1e3)); + return Common.UIString.UIString('%s\xa0kB', Number.withThousandsSeparator(value / 1e3)); } /** diff --git a/front_end/profiler/HeapSnapshotView.js b/front_end/profiler/HeapSnapshotView.js index db8563050f1..55229076960 100644 --- a/front_end/profiler/HeapSnapshotView.js +++ b/front_end/profiler/HeapSnapshotView.js @@ -1786,7 +1786,7 @@ export class HeapSnapshotStatisticsView extends UI.Widget.VBox { * @return {string} */ static _valueFormatter(value) { - return Common.UIString.UIString('%s KB', Number.withThousandsSeparator(Math.round(value / 1024))); + return Common.UIString.UIString('%s kB', Number.withThousandsSeparator(Math.round(value / 1000))); } /** diff --git a/front_end/profiler/IsolateSelector.js b/front_end/profiler/IsolateSelector.js index 7e718cce2e5..8bb0e85bf27 100644 --- a/front_end/profiler/IsolateSelector.js +++ b/front_end/profiler/IsolateSelector.js @@ -146,7 +146,7 @@ export class IsolateSelector extends UI.Widget.VBox { */ static _formatTrendElement(trendValueMs, element) { const changeRateBytesPerSecond = trendValueMs * 1e3; - const changeRateThresholdBytesPerSecond = 1024; + const changeRateThresholdBytesPerSecond = 1000; if (Math.abs(changeRateBytesPerSecond) < changeRateThresholdBytesPerSecond) { return; } diff --git a/front_end/profiler/LiveHeapProfileView.js b/front_end/profiler/LiveHeapProfileView.js index 488cb47dc08..427e1a01a30 100644 --- a/front_end/profiler/LiveHeapProfileView.js +++ b/front_end/profiler/LiveHeapProfileView.js @@ -313,7 +313,7 @@ export class GridNode extends DataGrid.SortableDataGrid.SortableDataGridNode { break; case 'size': cell.textContent = Number.withThousandsSeparator(Math.round(this._size / 1e3)); - cell.createChild('span', 'size-units').textContent = ls`KB`; + cell.createChild('span', 'size-units').textContent = ls`kB`; break; case 'isolates': cell.textContent = `${this._isolateCount}`; diff --git a/front_end/profiler/profiler_strings.grdp b/front_end/profiler/profiler_strings.grdp index 92bf2f69a62..eb39b55c8f7 100644 --- a/front_end/profiler/profiler_strings.grdp +++ b/front_end/profiler/profiler_strings.grdp @@ -1,14 +1,8 @@ - - $1s1,021 KB - Freed Size - - $1s1,021 KB - # Deleted @@ -87,6 +81,9 @@ Stop CPU profiling + + $1s1,021 kB + Restore all functions @@ -100,7 +97,7 @@ All objects - decreasing by $1s1.0 KB per second + decreasing by $1s1.0 kB per second Show native functions in JS Profile @@ -229,7 +226,7 @@ Strings - ⬇$1s2 KB/s + ⬇$1s2 kB/s Heap profiler is recording @@ -269,6 +266,9 @@ Size of the object plus the graph it retains in bytes + + $1s1,021 kB + Start @@ -288,7 +288,7 @@ HEAP SNAPSHOTS - increasing by $1s1.0 KB per second + increasing by $1s1.0 kB per second Retainers @@ -330,7 +330,7 @@ Code - ⬆$1s2 KB/s + ⬆$1s2 kB/s Profile diff --git a/front_end/protocol_client/InspectorBackend.js b/front_end/protocol_client/InspectorBackend.js index 58e88eeb660..63192dbcbd3 100644 --- a/front_end/protocol_client/InspectorBackend.js +++ b/front_end/protocol_client/InspectorBackend.js @@ -738,6 +738,13 @@ export class TargetBase { throw new Error('Implemented in InspectorBackend.js'); } + /** + * @return {!ProtocolProxyApi.DeviceOrientationApi} + */ + deviceOrientationAgent() { + throw new Error('Implemented in InspectorBackend.js'); + } + /** * @return {!ProtocolProxyApi.DOMApi} */ @@ -766,6 +773,13 @@ export class TargetBase { throw new Error('Implemented in InspectorBackend.js'); } + /** + * @return {!ProtocolProxyApi.EmulationApi} + */ + emulationAgent() { + throw new Error('Implemented in InspectorBackend.js'); + } + /** * @return {!ProtocolProxyApi.HeapProfilerApi} */ diff --git a/front_end/resources/AppManifestView.js b/front_end/resources/AppManifestView.js index 3978c0c720f..02c03cb5d54 100644 --- a/front_end/resources/AppManifestView.js +++ b/front_end/resources/AppManifestView.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Components from '../components/components.js'; import * as InlineEditor from '../inline_editor/inline_editor.js'; @@ -42,6 +39,7 @@ export class AppManifestView extends UI.Widget.VBox { this._presentationSection = this._reportView.appendSection(Common.UIString.UIString('Presentation')); this._iconsSection = this._reportView.appendSection(Common.UIString.UIString('Icons'), 'report-section-icons'); + /** @type {!Array} */ this._shortcutSections = []; this._nameField = this._identitySection.appendField(Common.UIString.UIString('Name')); @@ -62,6 +60,8 @@ export class AppManifestView extends UI.Widget.VBox { this._throttler = new Common.Throttler.Throttler(1000); SDK.SDKModel.TargetManager.instance().observeTargets(this); + /** @type {!Array} */ + this._registeredListeners = []; } /** @@ -115,6 +115,9 @@ export class AppManifestView extends UI.Widget.VBox { * @param {boolean} immediately */ async _updateManifest(immediately) { + if (!this._resourceTreeModel) { + return; + } const {url, data, errors} = await this._resourceTreeModel.fetchAppManifest(); const installabilityErrors = await this._resourceTreeModel.getInstallabilityErrors(); const manifestIcons = await this._resourceTreeModel.getManifestIcons(); @@ -128,6 +131,7 @@ export class AppManifestView extends UI.Widget.VBox { * @param {?string} data * @param {!Array} errors * @param {!Array} installabilityErrors + * @param {!{primaryIcon: ?string}} manifestIcons */ async _renderManifest(url, data, errors, installabilityErrors, manifestIcons) { if (!data && !errors.length) { @@ -164,7 +168,8 @@ export class AppManifestView extends UI.Widget.VBox { const startURL = stringProperty('start_url'); if (startURL) { const completeURL = /** @type {string} */ (Common.ParsedURL.ParsedURL.completeURL(url, startURL)); - const link = Components.Linkifier.Linkifier.linkifyURL(completeURL, {text: startURL}); + const link = Components.Linkifier.Linkifier.linkifyURL( + completeURL, /** @type {!Components.Linkifier.LinkifyURLOptions} */ ({text: startURL})); link.tabIndex = 0; this._startURLField.appendChild(link); } @@ -209,9 +214,9 @@ export class AppManifestView extends UI.Widget.VBox { UI.UIUtils.formatLocalized('Need help? Read our %s.', [documentationLink])); if (manifestIcons && manifestIcons.primaryIcon) { - const wrapper = createElement('div'); + const wrapper = document.createElement('div'); wrapper.classList.add('image-wrapper'); - const image = createElement('img'); + const image = document.createElement('img'); image.style.maxWidth = '200px'; image.style.maxHeight = '200px'; image.src = 'data:image/png;base64,' + manifestIcons.primaryIcon; @@ -241,7 +246,8 @@ export class AppManifestView extends UI.Widget.VBox { } const urlField = shortcutSection.appendFlexedField('URL'); const shortcutUrl = /** @type {string} */ (Common.ParsedURL.ParsedURL.completeURL(url, shortcut.url)); - const link = Components.Linkifier.Linkifier.linkifyURL(shortcutUrl, {text: shortcut.url}); + const link = Components.Linkifier.Linkifier.linkifyURL( + shortcutUrl, /** @type {!Components.Linkifier.LinkifyURLOptions} */ ({text: shortcut.url})); link.tabIndex = 0; urlField.appendChild(link); @@ -388,7 +394,7 @@ export class AppManifestView extends UI.Widget.VBox { console.error(`Installability error id '${installabilityError.errorId}' is not recognized`); break; } - if (errorMessages) { + if (errorMessage) { errorMessages.push(errorMessage); } } @@ -396,13 +402,13 @@ export class AppManifestView extends UI.Widget.VBox { } /** - * @param {?string} url - * @return {!Promise} + * @param {string} url + * @return {!Promise} */ async _loadImage(url) { - const wrapper = createElement('div'); + const wrapper = document.createElement('div'); wrapper.classList.add('image-wrapper'); - const image = createElement('img'); + const image = /** @type {!HTMLImageElement} */ (document.createElement('img')); const result = new Promise((resolve, reject) => { image.onload = resolve; image.onerror = reject; @@ -431,6 +437,10 @@ export class AppManifestView extends UI.Widget.VBox { return iconErrors; } const iconUrl = Common.ParsedURL.ParsedURL.completeURL(baseUrl, icon['src']); + if (!iconUrl) { + iconErrors.push(ls`Icon URL '${icon['src']}' failed to parse`); + return iconErrors; + } const result = await this._loadImage(iconUrl); if (!result) { iconErrors.push(ls`Icon ${iconUrl} failed to load`); @@ -445,7 +455,7 @@ export class AppManifestView extends UI.Widget.VBox { } else if (!/^\d+x\d+$/.test(icon.sizes)) { iconErrors.push(ls`Icon ${iconUrl} should specify its size as \`{width}x{height}\``); } else { - const [width, height] = icon.sizes.split('x').map(x => parseInt(x, 10)); + const [width, height] = icon.sizes.split('x').map(/** @param {*} x*/ x => parseInt(x, 10)); if (width !== height) { iconErrors.push(ls`Icon ${iconUrl} dimensions should be square`); } else if (image.naturalWidth !== width && image.naturalHeight !== height) { diff --git a/front_end/resources/DatabaseModel.js b/front_end/resources/DatabaseModel.js index 9a81059761e..409b38e56a4 100644 --- a/front_end/resources/DatabaseModel.js +++ b/front_end/resources/DatabaseModel.js @@ -93,7 +93,7 @@ export class Database { /** * @param {string} query - * @param {function(!Array.=, !Array.<*>=):void} onSuccess + * @param {function(!Array., !Array.<*>):void} onSuccess * @param {function(string):void} onError */ async executeSql(query, onSuccess, onError) { @@ -105,7 +105,8 @@ export class Database { } const sqlError = response.sqlError; if (!sqlError) { - onSuccess(response.columnNames, response.values); + // We know from the back-end that if there is no error, neither columnNames nor values can be undefined. + onSuccess(response.columnNames || [], response.values || []); return; } let message; diff --git a/front_end/resources/DatabaseQueryView.js b/front_end/resources/DatabaseQueryView.js index 24aebb26cc8..67439f11841 100644 --- a/front_end/resources/DatabaseQueryView.js +++ b/front_end/resources/DatabaseQueryView.js @@ -253,12 +253,11 @@ export class DatabaseQueryView extends UI.Widget.VBox { /** * * @param {string} query - * @param {?Array} columnNames - * @param {?Array<*>} values + * @param {!Array} columnNames + * @param {!Array<*>} values */ _queryFinished(query, columnNames, values) { - const dataGrid = - DataGrid.SortableDataGrid.SortableDataGrid.create(columnNames || [], values || [], ls`Database Query`); + const dataGrid = DataGrid.SortableDataGrid.SortableDataGrid.create(columnNames, values, ls`Database Query`); const trimmedQuery = query.trim(); let view = null; diff --git a/front_end/resources/DatabaseTableView.js b/front_end/resources/DatabaseTableView.js index 17161f3c1a7..2e3cfc9016c 100644 --- a/front_end/resources/DatabaseTableView.js +++ b/front_end/resources/DatabaseTableView.js @@ -23,22 +23,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as DataGrid from '../data_grid/data_grid.js'; import * as UI from '../ui/ui.js'; +import {Database, DatabaseModel, Events as DatabaseModelEvents} from './DatabaseModel.js'; // eslint-disable-line no-unused-vars /** * @unrestricted */ export class DatabaseTableView extends UI.View.SimpleView { + /** + * @param {!Database} database + * @param {string} tableName + */ constructor(database, tableName) { super(Common.UIString.UIString('Database')); this.database = database; this.tableName = tableName; + this._lastVisibleColumns = ''; + /** @type {!Map} */ + this._columnsMap = new Map(); this.element.classList.add('storage-view', 'table'); @@ -51,8 +56,8 @@ export class DatabaseTableView extends UI.View.SimpleView { this._visibleColumnsInput.addEventListener( UI.Toolbar.ToolbarInput.Event.TextChanged, this._onVisibleColumnsChanged, this); - /** @type {?DataGrid.DataGrid.DataGridImpl} */ - this._dataGrid; + /** @type {?DataGrid.SortableDataGrid.SortableDataGrid>} */ + this._dataGrid = null; } /** @@ -84,6 +89,11 @@ export class DatabaseTableView extends UI.View.SimpleView { this._queryError.bind(this)); } + /** + * + * @param {!Array} columnNames + * @param {!Array<*>} values + */ _queryFinished(columnNames, values) { this.detachChildWidgets(); this.element.removeChildren(); @@ -99,7 +109,7 @@ export class DatabaseTableView extends UI.View.SimpleView { this._dataGrid.asWidget().show(this.element); this._dataGrid.autoSizeColumns(5); - this._columnsMap = new Map(); + this._columnsMap.clear(); for (let i = 1; i < columnNames.length; ++i) { this._columnsMap.set(columnNames[i], String(i)); } @@ -116,19 +126,19 @@ export class DatabaseTableView extends UI.View.SimpleView { const text = this._visibleColumnsInput.value(); const parts = text.split(/[\s,]+/); const matches = new Set(); - const columnsVisibility = {}; - columnsVisibility['0'] = true; - for (let i = 0; i < parts.length; ++i) { - const part = parts[i]; - if (this._columnsMap.has(part)) { + const columnsVisibility = new Set(); + columnsVisibility.add('0'); + for (const part of parts) { + const mappedColumn = this._columnsMap.get(part); + if (mappedColumn !== undefined) { matches.add(part); - columnsVisibility[this._columnsMap.get(part)] = true; + columnsVisibility.add(mappedColumn); } } const newVisibleColumns = [...matches].sort().join(', '); if (newVisibleColumns.length === 0) { for (const v of this._columnsMap.values()) { - columnsVisibility[v] = true; + columnsVisibility.add(v); } } if (newVisibleColumns === this._lastVisibleColumns) { @@ -137,15 +147,15 @@ export class DatabaseTableView extends UI.View.SimpleView { const visibleColumnsRegistry = this._visibleColumnsSetting.get(); visibleColumnsRegistry[this.tableName] = text; this._visibleColumnsSetting.set(visibleColumnsRegistry); - this._dataGrid.setColumnsVisiblity(columnsVisibility); + this._dataGrid.setColumnsVisiblitySet(columnsVisibility); this._lastVisibleColumns = newVisibleColumns; } - _queryError(error) { + _queryError() { this.detachChildWidgets(); this.element.removeChildren(); - const errorMsgElement = createElement('div'); + const errorMsgElement = document.createElement('div'); errorMsgElement.className = 'storage-table-error'; errorMsgElement.textContent = ls`An error occurred trying to\nread the "${this.tableName}" table.`; this.element.appendChild(errorMsgElement); diff --git a/front_end/resources/FrameDetailsView.js b/front_end/resources/FrameDetailsView.js index f46263f6421..98a1cd74b28 100644 --- a/front_end/resources/FrameDetailsView.js +++ b/front_end/resources/FrameDetailsView.js @@ -118,9 +118,13 @@ export class FrameDetailsView extends UI.ThrottledWidget.ThrottledWidget { * * @param {!HTMLElement} field * @param {function((!Protocol.Network.CrossOriginEmbedderPolicyValue|!Protocol.Network.CrossOriginOpenerPolicyValue)):boolean} isEnabled - * @param {!Protocol.Network.CrossOriginEmbedderPolicyStatus|!Protocol.Network.CrossOriginOpenerPolicyStatus} info + * @param {?Protocol.Network.CrossOriginEmbedderPolicyStatus|?Protocol.Network.CrossOriginOpenerPolicyStatus} info */ static fillCrossOriginPolicy(field, isEnabled, info) { + if (!info) { + field.textContent = ''; + return; + } const enabled = isEnabled(info.value); field.textContent = enabled ? info.value : info.reportOnlyValue; if (!enabled && isEnabled(info.reportOnlyValue)) { @@ -145,15 +149,18 @@ export class FrameDetailsView extends UI.ThrottledWidget.ThrottledWidget { return; } /** - * @param {!Protocol.Network.CrossOriginEmbedderPolicyValue|!Protocol.Network.CrossOriginOpenerPolicyValue} value - */ + * @param {!Protocol.Network.CrossOriginEmbedderPolicyValue|!Protocol.Network.CrossOriginOpenerPolicyValue} value + */ const coepIsEnabled = value => value !== Protocol.Network.CrossOriginEmbedderPolicyValue.None; FrameDetailsView.fillCrossOriginPolicy(this._coepPolicy, coepIsEnabled, info.coep); + this._isolationSection.setFieldVisible(ls`Cross-Origin Embedder Policy`, !!info.coep); + /** - * @param {!Protocol.Network.CrossOriginEmbedderPolicyValue|!Protocol.Network.CrossOriginOpenerPolicyValue} value - */ + * @param {!Protocol.Network.CrossOriginEmbedderPolicyValue|!Protocol.Network.CrossOriginOpenerPolicyValue} value + */ const coopIsEnabled = value => value !== Protocol.Network.CrossOriginOpenerPolicyValue.UnsafeNone; FrameDetailsView.fillCrossOriginPolicy(this._coopPolicy, coopIsEnabled, info.coop); + this._isolationSection.setFieldVisible(ls`Cross-Origin Opener Policy`, !!info.coop); } /** diff --git a/front_end/resources/ServiceWorkersView.js b/front_end/resources/ServiceWorkersView.js index 73f09cf5d04..0758812d528 100644 --- a/front_end/resources/ServiceWorkersView.js +++ b/front_end/resources/ServiceWorkersView.js @@ -2,15 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Components from '../components/components.js'; import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js'; +import * as Network from '../network/network.js'; import * as SDK from '../sdk/sdk.js'; import * as UI from '../ui/ui.js'; +let throttleDisabledForDebugging = false; +/** + * @param {boolean} enable + */ +export const setThrottleDisabledForDebugging = enable => { + throttleDisabledForDebugging = enable; +}; + /** * @implements {SDK.SDKModel.SDKModelObserver} */ @@ -30,14 +36,15 @@ export class ServiceWorkersView extends UI.Widget.VBox { /** @type {!Map} */ this._sections = new Map(); - /** @type {symbol} */ - this._registrationSymbol = Symbol('Resources.ServiceWorkersView'); /** @type {?SDK.ServiceWorkerManager.ServiceWorkerManager} */ this._manager = null; /** @type {?SDK.SecurityOriginManager.SecurityOriginManager} */ this._securityOriginManager = null; + /** @type {!WeakMap} */ + this._sectionToRegistration = new WeakMap(); + const othersDiv = this.contentElement.createChild('div', 'service-workers-other-origin'); const othersView = new UI.ReportView.ReportView(); othersView.setHeaderVisible(false); @@ -47,8 +54,8 @@ export class ServiceWorkersView extends UI.Widget.VBox { const seeOthers = UI.Fragment.html `See all registrations`; self.onInvokeElement(seeOthers, event => { - const agent = SDK.SDKModel.TargetManager.instance().mainTarget().targetAgent(); - agent.invoke_createTarget({url: 'chrome://serviceworker-internals?devtools'}); + const mainTarget = SDK.SDKModel.TargetManager.instance().mainTarget(); + mainTarget && mainTarget.targetAgent().invoke_createTarget({url: 'chrome://serviceworker-internals?devtools'}); event.consume(true); }); othersSectionRow.appendChild(seeOthers); @@ -71,6 +78,21 @@ export class ServiceWorkersView extends UI.Widget.VBox { this._eventListeners = new Map(); SDK.SDKModel.TargetManager.instance().observeModels(SDK.ServiceWorkerManager.ServiceWorkerManager, this); this._updateListVisibility(); + + /** + * @param {!Event} event + */ + const drawerChangeHandler = event => { + // @ts-ignore: No support for custom event listener + const isDrawerOpen = event.detail && event.detail.isDrawerOpen; + if (this._manager && !isDrawerOpen && this._manager.serviceWorkerNetworkRequestsPanelOpen) { + const networkLocation = UI.ViewManager.ViewManager.instance().locationNameForViewId('network'); + UI.ViewManager.ViewManager.instance().showViewInLocation('network', networkLocation, false); + Network.NetworkPanel.NetworkPanel.revealAndFilter([]); + this._manager.serviceWorkerNetworkRequestsPanelOpen = false; + } + }; + document.body.addEventListener(UI.InspectorView.Events.DrawerChange, drawerChangeHandler); } /** @@ -82,7 +104,9 @@ export class ServiceWorkersView extends UI.Widget.VBox { return; } this._manager = serviceWorkerManager; - this._securityOriginManager = serviceWorkerManager.target().model(SDK.SecurityOriginManager.SecurityOriginManager); + this._securityOriginManager = + /** @type {!SDK.SecurityOriginManager.SecurityOriginManager} */ ( + serviceWorkerManager.target().model(SDK.SecurityOriginManager.SecurityOriginManager)); for (const registration of this._manager.registrations().values()) { this._updateRegistration(registration); @@ -109,13 +133,12 @@ export class ServiceWorkersView extends UI.Widget.VBox { return; } - Common.EventTarget.EventTarget.removeEventListeners(this._eventListeners.get(serviceWorkerManager)); + Common.EventTarget.EventTarget.removeEventListeners(this._eventListeners.get(serviceWorkerManager) || []); this._eventListeners.delete(serviceWorkerManager); this._manager = null; this._securityOriginManager = null; } - /** * @param {!SDK.ServiceWorkerManager.ServiceWorkerRegistration} registration * @return {number} @@ -149,7 +172,7 @@ export class ServiceWorkersView extends UI.Widget.VBox { const movedSections = []; for (const section of this._sections.values()) { const expectedView = this._getReportViewForOrigin(section._registration.securityOrigin); - hasThis |= expectedView === this._currentWorkersView; + hasThis = hasThis || expectedView === this._currentWorkersView; if (section._section.parentWidget() !== expectedView) { movedSections.push(section); } @@ -161,9 +184,11 @@ export class ServiceWorkersView extends UI.Widget.VBox { this._updateRegistration(registration, true); } - this._currentWorkersView.sortSections((a, b) => { - const aTimestamp = this._getTimeStamp(a[this._registrationSymbol]); - const bTimestamp = this._getTimeStamp(b[this._registrationSymbol]); + this._currentWorkersView.sortSections((aSection, bSection) => { + const aRegistration = this._sectionToRegistration.get(aSection); + const bRegistration = this._sectionToRegistration.get(bSection); + const aTimestamp = aRegistration ? this._getTimeStamp(aRegistration) : 0; + const bTimestamp = bRegistration ? this._getTimeStamp(bRegistration) : 0; // the newest (largest timestamp value) should be the first return bTimestamp - aTimestamp; }); @@ -190,6 +215,9 @@ export class ServiceWorkersView extends UI.Widget.VBox { } _gcRegistrations() { + if (!this._manager || !this._securityOriginManager) { + return; + } let hasNonDeletedRegistrations = false; const securityOrigins = new Set(this._securityOriginManager.securityOrigins()); for (const registration of this._manager.registrations().values()) { @@ -219,8 +247,9 @@ export class ServiceWorkersView extends UI.Widget.VBox { * @return {?UI.ReportView.ReportView} */ _getReportViewForOrigin(origin) { - if (this._securityOriginManager.securityOrigins().includes(origin) || - this._securityOriginManager.unreachableMainSecurityOrigin() === origin) { + if (this._securityOriginManager && + (this._securityOriginManager.securityOrigins().includes(origin) || + this._securityOriginManager.unreachableMainSecurityOrigin() === origin)) { return this._currentWorkersView; } return null; @@ -240,7 +269,7 @@ export class ServiceWorkersView extends UI.Widget.VBox { } const uiSection = reportView.appendSection(title); uiSection.setUiGroupTitle(ls`Service worker for ${title}`); - uiSection[this._registrationSymbol] = registration; + this._sectionToRegistration.set(uiSection, registration); section = new Section( /** @type {!SDK.ServiceWorkerManager.ServiceWorkerManager} */ (this._manager), uiSection, registration); this._sections.set(registration, section); @@ -309,6 +338,10 @@ export class Section { this._toolbar = section.createToolbar(); this._toolbar.renderAsLinks(); + this._networkRequests = new UI.Toolbar.ToolbarButton( + Common.UIString.UIString('Network requests'), undefined, Common.UIString.UIString('Network requests')); + this._networkRequests.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._networkRequestsClicked, this); + this._toolbar.appendToolbarItem(this._networkRequests); this._updateButton = new UI.Toolbar.ToolbarButton(Common.UIString.UIString('Update'), undefined, Common.UIString.UIString('Update')); this._updateButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._updateButtonClicked, this); @@ -342,7 +375,7 @@ export class Section { * @param {string} label * @param {string} initialValue * @param {string} placeholder - * @param {function(string)} callback + * @param {function(string):void} callback */ _createSyncNotificationField(label, initialValue, placeholder, callback) { const form = @@ -357,14 +390,17 @@ export class Section { editor.placeholder = placeholder; UI.ARIAUtils.setAccessibleName(editor, label); - form.addEventListener('submit', e => { - callback(editor.value || ''); - e.consume(true); - }); + form.addEventListener( + 'submit', + /** @param {!Event} e */ + e => { + callback(editor.value || ''); + e.consume(true); + }); } _scheduleUpdate() { - if (ServiceWorkersView._noThrottle) { + if (throttleDisabledForDebugging) { this._update(); return; } @@ -410,7 +446,10 @@ export class Section { this._updateClientInfo( clientLabelText, /** @type {!Protocol.Target.TargetInfo} */ (this._clientInfoCache.get(client))); } - this._manager.target().targetAgent().getTargetInfo(client).then(this._onClientInfo.bind(this, clientLabelText)); + this._manager.target() + .targetAgent() + .invoke_getTargetInfo({targetId: client}) + .then(this._onClientInfo.bind(this, clientLabelText)); } } @@ -421,7 +460,8 @@ export class Section { this._sourceField.removeChildren(); const fileName = Common.ParsedURL.ParsedURL.extractName(version.scriptURL); const name = this._sourceField.createChild('div', 'report-field-value-filename'); - const link = Components.Linkifier.Linkifier.linkifyURL(version.scriptURL, {text: fileName}); + const link = Components.Linkifier.Linkifier.linkifyURL( + version.scriptURL, /** @type {!Components.Linkifier.LinkifyURLOptions} */ ({text: fileName})); link.tabIndex = 0; name.appendChild(link); if (this._registration.errors.length) { @@ -432,12 +472,14 @@ export class Section { self.onInvokeElement(errorsLabel, () => Common.Console.Console.instance().show()); name.appendChild(errorsLabel); } - this._sourceField.createChild('div', 'report-field-value-subtitle').textContent = - Common.UIString.UIString('Received %s', new Date(version.scriptResponseTime * 1000).toLocaleString()); + if (version.scriptResponseTime !== undefined) { + this._sourceField.createChild('div', 'report-field-value-subtitle').textContent = + Common.UIString.UIString('Received %s', new Date(version.scriptResponseTime * 1000).toLocaleString()); + } } /** - * @return {!Promise} + * @return {!Promise} */ _update() { const fingerprint = this._registration.fingerprint(); @@ -490,8 +532,10 @@ export class Section { versionsStack, 'service-worker-waiting-circle', Common.UIString.UIString('#%s waiting to activate', waiting.id)); this._createLink(waitingEntry, Common.UIString.UIString('skipWaiting'), this._skipButtonClicked.bind(this)); - waitingEntry.createChild('div', 'service-worker-subtitle').textContent = - Common.UIString.UIString('Received %s', new Date(waiting.scriptResponseTime * 1000).toLocaleString()); + if (waiting.scriptResponseTime !== undefined) { + waitingEntry.createChild('div', 'service-worker-subtitle').textContent = + Common.UIString.UIString('Received %s', new Date(waiting.scriptResponseTime * 1000).toLocaleString()); + } if (!this._targetForVersionId(waiting.id) && (waiting.isRunning() || waiting.isStarting())) { this._createLink( waitingEntry, Common.UIString.UIString('inspect'), this._inspectButtonClicked.bind(this, waiting.id)); @@ -501,8 +545,10 @@ export class Section { const installingEntry = this._addVersion( versionsStack, 'service-worker-installing-circle', Common.UIString.UIString('#%s trying to install', installing.id)); - installingEntry.createChild('div', 'service-worker-subtitle').textContent = - Common.UIString.UIString('Received %s', new Date(installing.scriptResponseTime * 1000).toLocaleString()); + if (installing.scriptResponseTime !== undefined) { + installingEntry.createChild('div', 'service-worker-subtitle').textContent = + Common.UIString.UIString('Received %s', new Date(installing.scriptResponseTime * 1000).toLocaleString()); + } if (!this._targetForVersionId(installing.id) && (installing.isRunning() || installing.isStarting())) { this._createLink( installingEntry, Common.UIString.UIString('inspect'), this._inspectButtonClicked.bind(this, installing.id)); @@ -514,17 +560,21 @@ export class Section { /** * @param {!Element} parent * @param {string} title - * @param {function()} listener + * @param {function():void} listener * @param {string=} className * @param {boolean=} useCapture * @return {!Element} */ _createLink(parent, title, listener, className, useCapture) { - const button = parent.createChild('button', className); + const button = /** @type {!HTMLElement} */ (document.createElement('button')); + if (className) { + button.className = className; + } button.classList.add('link', 'devtools-link'); button.textContent = title; button.tabIndex = 0; button.addEventListener('click', listener, useCapture); + parent.appendChild(button); return button; } @@ -542,6 +592,42 @@ export class Section { this._manager.updateRegistration(this._registration.id); } + /** + * @param {!Common.EventTarget.EventTargetEvent} event + */ + _networkRequestsClicked(event) { + const applicationTabLocation = UI.ViewManager.ViewManager.instance().locationNameForViewId('resources'); + const networkTabLocation = applicationTabLocation === 'drawer-view' ? 'panel' : 'drawer-view'; + UI.ViewManager.ViewManager.instance().showViewInLocation('network', networkTabLocation); + + Network.NetworkPanel.NetworkPanel.revealAndFilter([ + { + filterType: Network.NetworkLogView.FilterType.Is, + filterValue: Network.NetworkLogView.IsFilterType.ServiceWorkerIntercepted, + }, + ]); + + const requests = SDK.NetworkLog.NetworkLog.instance().requests(); + let lastRequest = null; + if (Array.isArray(requests)) { + for (const request of requests) { + if (!lastRequest && request.fetchedViaServiceWorker) { + lastRequest = request; + } + if (request.fetchedViaServiceWorker && lastRequest && + lastRequest.responseReceivedTime < request.responseReceivedTime) { + lastRequest = request; + } + } + } + if (lastRequest) { + Network.NetworkPanel.NetworkPanel.selectAndShowRequest( + lastRequest, Network.NetworkItemView.Tabs.Timing, {clearFilter: false}); + } + + this._manager.serviceWorkerNetworkRequestsPanelOpen = true; + } + /** * @param {string} data */ @@ -568,9 +654,10 @@ export class Section { /** * @param {!Element} element - * @param {?Protocol.Target.TargetInfo} targetInfo + * @param {!Protocol.Target.GetTargetInfoResponse} targetInfoResponse */ - _onClientInfo(element, targetInfo) { + _onClientInfo(element, targetInfoResponse) { + const targetInfo = targetInfoResponse.targetInfo; if (!targetInfo) { return; } @@ -599,7 +686,7 @@ export class Section { * @param {string} targetId */ _activateTarget(targetId) { - this._manager.target().targetAgent().activateTarget(targetId); + this._manager.target().targetAgent().invoke_activateTarget({targetId}); } _startButtonClicked() { @@ -631,7 +718,7 @@ export class Section { _wrapWidget(container) { const shadowRoot = UI.Utils.createShadowRootWithCoreStyles(container); UI.Utils.appendStyle(shadowRoot, 'resources/serviceWorkersView.css'); - const contentElement = createElement('div'); + const contentElement = document.createElement('div'); shadowRoot.appendChild(contentElement); return contentElement; } diff --git a/front_end/resources/resources-legacy.js b/front_end/resources/resources-legacy.js index b1b635401e7..a4facd60654 100644 --- a/front_end/resources/resources-legacy.js +++ b/front_end/resources/resources-legacy.js @@ -109,3 +109,13 @@ Resources.ServiceWorkerCacheView = ResourcesModule.ServiceWorkerCacheViews.Servi /** @constructor */ Resources.ServiceWorkersView = ResourcesModule.ServiceWorkersView.ServiceWorkersView; + +/** + * @type {function(boolean):void} + */ +Resources.ServiceWorkersView.setThrottleDisabledForDebugging = + ResourcesModule.ServiceWorkersView.setThrottleDisabledForDebugging; + +Object.defineProperty(Resources.ServiceWorkersView, '_noThrottle', { + set: ResourcesModule.ServiceWorkersView.setThrottleDisabledForDebugging, +}); diff --git a/front_end/resources/resources_strings.grdp b/front_end/resources/resources_strings.grdp index 8dbeb556951..81dfa9958dd 100644 --- a/front_end/resources/resources_strings.grdp +++ b/front_end/resources/resources_strings.grdp @@ -516,6 +516,9 @@ as used by Chrome Primary key + + Icon URL '$1sfoo/icon.png' failed to parse + Actual width ($1s100px) of icon $2shttps://example.com/icon.png does not match specified width ($3s100px) @@ -555,6 +558,9 @@ as used by Chrome Show events from other domains + + Network requests + Query: $1s"SELECT * FROM LOGS" diff --git a/front_end/sdk/ContentSecurityPolicyIssue.js b/front_end/sdk/ContentSecurityPolicyIssue.js index da31374a7b3..18d38b27038 100644 --- a/front_end/sdk/ContentSecurityPolicyIssue.js +++ b/front_end/sdk/ContentSecurityPolicyIssue.js @@ -95,6 +95,18 @@ const cspEvalViolation = { }], }; +const cspTrustedTypesSinkViolation = { + file: 'issues/descriptions/cspTrustedTypesSinkViolation.md', + issueKind: IssueKind.BreakingChange, + links: [{link: 'https://web.dev/trusted-types/#fix-the-violations', linkTitle: ls`Trusted Types - Fix violations`}], +}; + +const cspTrustedTypesPolicyViolation = { + file: 'issues/descriptions/cspTrustedTypesPolicyViolation.md', + issueKind: IssueKind.BreakingChange, + links: [{link: 'https://web.dev/trusted-types/', linkTitle: ls`Trusted Types - Policy violation`}], +}; + /** @type {string} */ export const urlViolationCode = [ Protocol.Audits.InspectorIssueCode.ContentSecurityPolicyIssue, @@ -113,10 +125,24 @@ export const evalViolationCode = [ Protocol.Audits.ContentSecurityPolicyViolationType.KEvalViolation ].join('::'); +/** @type {string} */ +export const trustedTypesSinkViolationCode = [ + Protocol.Audits.InspectorIssueCode.ContentSecurityPolicyIssue, + Protocol.Audits.ContentSecurityPolicyViolationType.KTrustedTypesSinkViolation +].join('::'); + +/** @type {string} */ +export const trustedTypesPolicyViolationCode = [ + Protocol.Audits.InspectorIssueCode.ContentSecurityPolicyIssue, + Protocol.Audits.ContentSecurityPolicyViolationType.KTrustedTypesPolicyViolation +].join('::'); + // TODO(crbug.com/1082628): Add handling of other CSP violation types later as they'll need more work. /** @type {!Map} */ const issueDescriptions = new Map([ [Protocol.Audits.ContentSecurityPolicyViolationType.KURLViolation, cspURLViolation], [Protocol.Audits.ContentSecurityPolicyViolationType.KInlineViolation, cspInlineViolation], [Protocol.Audits.ContentSecurityPolicyViolationType.KEvalViolation, cspEvalViolation], + [Protocol.Audits.ContentSecurityPolicyViolationType.KTrustedTypesSinkViolation, cspTrustedTypesSinkViolation], + [Protocol.Audits.ContentSecurityPolicyViolationType.KTrustedTypesPolicyViolation, cspTrustedTypesPolicyViolation], ]); diff --git a/front_end/sdk/DOMModel.js b/front_end/sdk/DOMModel.js index d3f13e5213e..8566eeaeafc 100644 --- a/front_end/sdk/DOMModel.js +++ b/front_end/sdk/DOMModel.js @@ -29,13 +29,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Host from '../host/host.js'; import * as Platform from '../platform/platform.js'; -import * as ProtocolClient from '../protocol_client/protocol_client.js'; +import * as ProtocolClient from '../protocol_client/protocol_client.js'; // eslint-disable-line no-unused-vars import * as Root from '../root/root.js'; import {CSSModel} from './CSSModel.js'; @@ -54,12 +51,63 @@ export class DOMNode { */ constructor(domModel) { this._domModel = domModel; - - /** - * Node ID is always set by this._init. - * @type {number} - */ + this._agent = this._domModel._agent; + /** @type {?DOMDocument} */ + this.ownerDocument; + /** @type {boolean} */ + this._isInShadowTree; + /** @type {number} */ this.id; + /** @type {number|undefined} */ + this.index = undefined; + /** @type {number} */ + this._backendNodeId; + /** @type {number} */ + this._nodeType; + /** @type {string} */ + this._nodeName; + /** @type {string} */ + this._localName; + /** @type {string} */ + this._nodeValue; + /** @type {!Protocol.DOM.PseudoType|undefined} */ + this._pseudoType; + /** @type {!Protocol.DOM.ShadowRootType|undefined} */ + this._shadowRootType; + /** @type {?string} */ + this._frameOwnerFrameId; + /** @type {string|undefined} */ + this._xmlVersion; + /** @type {boolean} */ + this._isSVGNode; + /** @type {?Promise} */ + this._creationStackTrace = null; + /** @type {!Map} */ + this._pseudoElements = new Map(); + /** @type {!Array.} */ + this._distributedNodes = []; + /** @type {!Array.} */ + this._shadowRoots = []; + /** @type {!Map} */ + this._attributes = new Map(); + /** @type {!Map} */ + this._markers = new Map(); + /** @type {number} */ + this._subtreeMarkerCount = 0; + /** @type {number} */ + this._childNodeCount; + /** @type {?Array.} */ + this._children = null; + /** @type {!DOMNode|null} */ + this.nextSibling = null; + /** @type {!DOMNode|null} */ + this.previousSibling = null; + /** @type {!DOMNode|null} */ + this.firstChild = null; + /** @type {!DOMNode|null} */ + this.lastChild = null; + /** @type {!DOMNode|null} */ + this.parentNode = null; } /** @@ -76,10 +124,10 @@ export class DOMNode { } /** - * @param {?DOMDocument} doc - * @param {boolean} isInShadowTree - * @param {!Protocol.DOM.Node} payload - */ + * @param {?DOMDocument} doc + * @param {boolean} isInShadowTree + * @param {!Protocol.DOM.Node} payload + */ _init(doc, isInShadowTree, payload) { this._agent = this._domModel._agent; this.ownerDocument = doc; @@ -97,29 +145,13 @@ export class DOMNode { this._frameOwnerFrameId = payload.frameId || null; this._xmlVersion = payload.xmlVersion; this._isSVGNode = !!payload.isSVG; - this._creationStackTrace = null; - - this._shadowRoots = []; - /** @type {!Map} */ - this._attributes = new Map(); if (payload.attributes) { this._setAttributesPayload(payload.attributes); } - /** @type {!Map} */ - this._markers = new Map(); - this._subtreeMarkerCount = 0; this._childNodeCount = payload.childNodeCount || 0; - this._children = null; - - this.nextSibling = null; - this.previousSibling = null; - this.firstChild = null; - this.lastChild = null; - this.parentNode = null; - if (payload.shadowRoots) { for (let i = 0; i < payload.shadowRoots.length; ++i) { const root = payload.shadowRoots[i]; @@ -212,7 +244,7 @@ export class DOMNode { } const stackTracesPromise = this._agent.invoke_getNodeStackTraces({nodeId: this.id}); - this._creationStackTrace = stackTracesPromise.then(res => res.creation); + this._creationStackTrace = stackTracesPromise.then(res => res.creation || null); return this._creationStackTrace; } @@ -342,7 +374,7 @@ export class DOMNode { if (!this._pseudoElements) { return null; } - return this._pseudoElements.get(DOMNode.PseudoElementNames.Before); + return this._pseudoElements.get(DOMNode.PseudoElementNames.Before) || null; } /** @@ -352,7 +384,7 @@ export class DOMNode { if (!this._pseudoElements) { return null; } - return this._pseudoElements.get(DOMNode.PseudoElementNames.After); + return this._pseudoElements.get(DOMNode.PseudoElementNames.After) || null; } /** @@ -362,7 +394,7 @@ export class DOMNode { if (!this._pseudoElements) { return null; } - return this._pseudoElements.get(DOMNode.PseudoElementNames.Marker); + return this._pseudoElements.get(DOMNode.PseudoElementNames.Marker) || null; } /** @@ -377,7 +409,7 @@ export class DOMNode { * @return {!Array.} */ distributedNodes() { - return this._distributedNodes || []; + return this._distributedNodes; } /** @@ -403,7 +435,7 @@ export class DOMNode { return null; } - let current = this; + let current = /** @type {?DOMNode} */ (this); while (current && !current.isShadowRoot()) { current = current.parentNode; } @@ -464,12 +496,11 @@ export class DOMNode { */ setNodeName(name, callback) { this._agent.invoke_setNodeName({nodeId: this.id, name}).then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback( - response[ProtocolClient.InspectorBackend.ProtocolError] || null, this._domModel.nodeForId(response.nodeId)); + callback(response.getError() || null, this._domModel.nodeForId(response.nodeId)); } }); } @@ -494,11 +525,11 @@ export class DOMNode { */ setNodeValue(value, callback) { this._agent.invoke_setNodeValue({nodeId: this.id, value}).then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] || null); + callback(response.getError() || null); } }); } @@ -519,11 +550,11 @@ export class DOMNode { */ setAttribute(name, text, callback) { this._agent.invoke_setAttributesAsText({nodeId: this.id, text, name}).then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] || null); + callback(response.getError() || null); } }); } @@ -535,11 +566,11 @@ export class DOMNode { */ setAttributeValue(name, value, callback) { this._agent.invoke_setAttributeValue({nodeId: this.id, name, value}).then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] || null); + callback(response.getError() || null); } }); } @@ -566,7 +597,7 @@ export class DOMNode { */ async removeAttribute(name) { const response = await this._agent.invoke_removeAttribute({nodeId: this.id, name}); - if (response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (response.getError()) { return; } this._attributes.delete(name); @@ -582,7 +613,7 @@ export class DOMNode { return; } this._agent.invoke_requestChildNodes({nodeId: this.id}).then(response => { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] ? null : this.children()); + callback(response.getError() ? null : this.children()); }); } @@ -593,14 +624,15 @@ export class DOMNode { */ async getSubtree(depth, pierce) { const response = await this._agent.invoke_requestChildNodes({nodeId: this.id, depth: depth, pierce: pierce}); - return response[ProtocolClient.InspectorBackend.ProtocolError] ? null : this._children; + return response.getError() ? null : this._children; } /** * @return {!Promise} */ - getOuterHTML() { - return this._agent.getOuterHTML(this.id); + async getOuterHTML() { + const {outerHTML} = await this._agent.invoke_getOuterHTML({nodeId: this.id}); + return outerHTML; } /** @@ -609,11 +641,11 @@ export class DOMNode { */ setOuterHTML(html, callback) { this._agent.invoke_setOuterHTML({nodeId: this.id, outerHTML: html}).then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] || null); + callback(response.getError() || null); } }); } @@ -623,11 +655,11 @@ export class DOMNode { */ removeNode(callback) { this._agent.invoke_removeNode({nodeId: this.id}).then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] || null); + callback(response.getError() || null); } }); } @@ -636,11 +668,11 @@ export class DOMNode { * @return {!Promise} */ async copyNode() { - const text = await this._agent.getOuterHTML(this.id); - if (text !== null) { - Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(text); + const {outerHTML} = await this._agent.invoke_getOuterHTML({nodeId: this.id}); + if (outerHTML !== null) { + Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(outerHTML); } - return text; + return outerHTML; } /** @@ -648,15 +680,15 @@ export class DOMNode { */ path() { /** - * @param {?DOMNode} node + * @param {!DOMNode} node */ function canPush(node) { - return node && ('index' in node || (node.isShadowRoot() && node.parentNode)) && node._nodeName.length; + return (node.index !== undefined || (node.isShadowRoot() && node.parentNode)) && node._nodeName.length; } const path = []; - let node = this; - while (canPush(node)) { + let node = /** @type {?DOMNode} */ (this); + while (node && canPush(node)) { const index = typeof node.index === 'number' ? node.index : (node.shadowRootType() === DOMNode.ShadowRootTypes.UserAgent ? 'u' : 'a'); @@ -724,7 +756,8 @@ export class DOMNode { continue; } - if (!oldAttributesMap.has(name) || oldAttributesMap.get(name).value !== value) { + const oldAttribute = oldAttributesMap.get(name); + if (!oldAttribute || oldAttribute.value !== value) { attributesChanged = true; } } @@ -737,6 +770,9 @@ export class DOMNode { * @return {!DOMNode} */ _insertChild(prev, payload) { + if (!this._children) { + throw new Error('DOMNode._children is expected to not be null.'); + } const node = DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payload); this._children.splice(this._children.indexOf(prev) + 1, 0, node); this._renumber(); @@ -747,14 +783,20 @@ export class DOMNode { * @param {!DOMNode} node */ _removeChild(node) { - if (node.pseudoType()) { - this._pseudoElements.delete(node.pseudoType()); + const pseudoType = node.pseudoType(); + if (pseudoType) { + this._pseudoElements.delete(pseudoType); } else { const shadowRootIndex = this._shadowRoots.indexOf(node); if (shadowRootIndex !== -1) { this._shadowRoots.splice(shadowRootIndex, 1); } else { - console.assert(this._children.indexOf(node) !== -1); + if (!this._children) { + throw new Error('DOMNode._children is expected to not be null.'); + } + if (this._children.indexOf(node) === -1) { + throw new Error('DOMNode._children is expected to contain the node to be removed.'); + } this._children.splice(this._children.indexOf(node), 1); } } @@ -783,7 +825,6 @@ export class DOMNode { * @param {!Array.|undefined} payloads */ _setPseudoElements(payloads) { - this._pseudoElements = new Map(); if (!payloads) { return; } @@ -791,7 +832,11 @@ export class DOMNode { for (let i = 0; i < payloads.length; ++i) { const node = DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payloads[i]); node.parentNode = this; - this._pseudoElements.set(node.pseudoType(), node); + const pseudoType = node.pseudoType(); + if (!pseudoType) { + throw new Error('DOMNode.pseudoType() is expected to be defined.'); + } + this._pseudoElements.set(pseudoType, node); } } @@ -807,6 +852,9 @@ export class DOMNode { } _renumber() { + if (!this._children) { + throw new Error('DOMNode._children is expected to not be null.'); + } this._childNodeCount = this._children.length; if (this._childNodeCount === 0) { this.firstChild = null; @@ -863,11 +911,11 @@ export class DOMNode { .invoke_copyTo( {nodeId: this.id, targetNodeId: targetNode.id, insertBeforeNodeId: anchorNode ? anchorNode.id : undefined}) .then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback(response[ProtocolClient.InspectorBackend.ProtocolError] || null, response.nodeId); + callback(response.getError() || null, response.nodeId); } }); } @@ -875,20 +923,18 @@ export class DOMNode { /** * @param {!DOMNode} targetNode * @param {?DOMNode} anchorNode - * @param {function(?ProtocolClient.InspectorBackend.ProtocolError, ?SDK.DOMNode)=} callback + * @param {function(?ProtocolClient.InspectorBackend.ProtocolError, ?DOMNode)=} callback */ moveTo(targetNode, anchorNode, callback) { this._agent .invoke_moveTo( {nodeId: this.id, targetNodeId: targetNode.id, insertBeforeNodeId: anchorNode ? anchorNode.id : undefined}) .then(response => { - if (!response[ProtocolClient.InspectorBackend.ProtocolError]) { + if (!response.getError()) { this._domModel.markUndoableState(); } if (callback) { - callback( - response[ProtocolClient.InspectorBackend.ProtocolError] || null, - this._domModel.nodeForId(response.nodeId)); + callback(response.getError() || null, this._domModel.nodeForId(response.nodeId)); } }); } @@ -911,22 +957,22 @@ export class DOMNode { } this._markers.delete(name); - for (let node = this; node; node = node.parentNode) { + for (let node = /** @type {?DOMNode} */ (this); node; node = node.parentNode) { --node._subtreeMarkerCount; } - for (let node = this; node; node = node.parentNode) { + for (let node = /** @type {?DOMNode} */ (this); node; node = node.parentNode) { this._domModel.dispatchEventToListeners(Events.MarkersChanged, node); } return; } if (this.parentNode && !this._markers.has(name)) { - for (let node = this; node; node = node.parentNode) { + for (let node = /** @type {?DOMNode} */ (this); node; node = node.parentNode) { ++node._subtreeMarkerCount; } } this._markers.set(name, value); - for (let node = this; node; node = node.parentNode) { + for (let node = /** @type {?DOMNode} */ (this); node; node = node.parentNode) { this._domModel.dispatchEventToListeners(Events.MarkersChanged, node); } } @@ -972,8 +1018,9 @@ export class DOMNode { if (!url) { return url; } - for (let frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { - if (frameOwnerCandidate.baseURL) { + for (let frameOwnerCandidate = /** @type {?DOMNode} */ (this); frameOwnerCandidate; + frameOwnerCandidate = frameOwnerCandidate.parentNode) { + if (frameOwnerCandidate instanceof DOMDocument && frameOwnerCandidate.baseURL) { return Common.ParsedURL.ParsedURL.completeURL(frameOwnerCandidate.baseURL, url); } } @@ -984,11 +1031,11 @@ export class DOMNode { * @param {string=} mode */ highlight(mode) { - this._domModel.overlayModel().highlightInOverlay({node: this}, mode); + this._domModel.overlayModel().highlightInOverlay({node: this, selectorList: undefined}, mode); } highlightForTwoSeconds() { - this._domModel.overlayModel().highlightInOverlayForTwoSeconds({node: this}); + this._domModel.overlayModel().highlightInOverlayForTwoSeconds({node: this, selectorList: undefined}); } /** @@ -996,23 +1043,24 @@ export class DOMNode { * @return {!Promise} */ async resolveToObject(objectGroup) { - const object = await this._agent.resolveNode(this.id, undefined, objectGroup); - return object && this._domModel._runtimeModel.createRemoteObject(object); + const {object} = await this._agent.invoke_resolveNode({nodeId: this.id, backendNodeId: undefined, objectGroup}); + return object && this._domModel._runtimeModel.createRemoteObject(object) || null; } /** * @return {!Promise} */ - boxModel() { - return this._agent.getBoxModel(this.id); + async boxModel() { + const {model} = await this._agent.invoke_getBoxModel({nodeId: this.id}); + return model; } - setAsInspectedNode() { - let node = this; - if (node.pseudoType()) { + async setAsInspectedNode() { + let node = /** @type {?DOMNode} */ (this); + if (node && node.pseudoType()) { node = node.parentNode; } - while (true) { + while (node) { let ancestor = node.ancestorUserAgentShadowRoot(); if (!ancestor) { break; @@ -1024,14 +1072,17 @@ export class DOMNode { // User agent shadow root, keep climbing up. node = ancestor; } - this._agent.setInspectedNode(node.id); + if (!node) { + throw new Error('In DOMNode.setAsInspectedNode: node is expected to not be null.'); + } + await this._agent.invoke_setInspectedNode({nodeId: node.id}); } /** * @return {?DOMNode} */ enclosingElementOrSelf() { - let node = this; + let node = /** @type {?DOMNode} */ (this); if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) { node = node.parentNode; } @@ -1066,6 +1117,9 @@ export class DOMNode { async focus() { const node = this.enclosingElementOrSelf(); + if (!node) { + throw new Error('DOMNode.focus expects node to not be null.'); + } const object = await node.resolveToObject(); if (!object) { return; @@ -1073,11 +1127,11 @@ export class DOMNode { await object.callFunction(focusInPage); object.release(); node.highlightForTwoSeconds(); - this._domModel.target().pageAgent().bringToFront(); + await this._domModel.target().pageAgent().invoke_bringToFront(); /** * @suppressReceiverCheck - * @this {!Element} + * @this {!HTMLElement} */ function focusInPage() { this.focus(); @@ -1169,7 +1223,7 @@ export class DeferredDOMNode { } highlight() { - this._domModel.overlayModel().highlightInOverlay({deferredNode: this}); + this._domModel.overlayModel().highlightInOverlay({deferredNode: this, selectorList: undefined}); } } @@ -1198,7 +1252,9 @@ export class DOMDocument extends DOMNode { */ constructor(domModel, payload) { super(domModel); + /** @type {?DOMNode} */ this.body = null; + /** @type {?DOMNode} */ this.documentElement = null; this._init(this, false, payload); this.documentURL = payload.documentURL || ''; @@ -1231,10 +1287,10 @@ export class DOMModel extends SDKModel { this._lastMutationId; /** @type {?Promise} */ - this._pendingDocumentRequestPromise; + this._pendingDocumentRequestPromise = null; if (!target.suspended()) { - this._agent.invoke_enable({}); + this._agent.invoke_enable(); } if (Root.Runtime.experiments.isEnabled('captureNodeCreationStacks')) { @@ -1324,8 +1380,8 @@ export class DOMModel extends SDKModel { * @return {!Promise} */ async _requestDocument() { - const {root: documentPayload} = await this._agent.invoke_getDocument(); - delete this._pendingDocumentRequestPromise; + const {root: documentPayload} = await this._agent.invoke_getDocument({}); + this._pendingDocumentRequestPromise = null; if (documentPayload) { this._setDocument(documentPayload); @@ -1480,11 +1536,11 @@ export class DOMModel extends SDKModel { } /** - * @param {!Protocol.DOM.NodeId} nodeId + * @param {?Protocol.DOM.NodeId} nodeId * @return {?DOMNode} */ nodeForId(nodeId) { - return this._idToDOMNode[nodeId] || null; + return nodeId ? this._idToDOMNode[nodeId] || null : null; } _documentUpdated() { @@ -1625,8 +1681,15 @@ export class DOMModel extends SDKModel { const node = DOMNode.create(this, parent.ownerDocument, false, pseudoElement); node.parentNode = parent; this._idToDOMNode[node.id] = node; - console.assert(!parent._pseudoElements.get(node.pseudoType())); - parent._pseudoElements.set(node.pseudoType(), node); + const pseudoType = node.pseudoType(); + if (!pseudoType) { + throw new Error('DOMModel._pseudoElementAdded expects pseudoType to be defined.'); + } + const previousPseudoType = parent._pseudoElements.get(pseudoType); + if (previousPseudoType) { + throw new Error('DOMModel._pseudoElementAdded expects parent to not already have this pseudo type added.'); + } + parent._pseudoElements.set(pseudoType, node); this.dispatchEventToListeners(Events.NodeInserted, node); this._scheduleMutationEvent(node); } @@ -1691,6 +1754,9 @@ export class DOMModel extends SDKModel { */ async getNodesByStyle(computedStyles, pierce = false) { await this.requestDocument(); + if (!this._document) { + throw new Error('DOMModel.getNodesByStyle expects to have a document.'); + } const response = await this._agent.invoke_getNodesForSubtreeByStyle({nodeId: this._document.id, computedStyles, pierce}); if (response.getError()) { @@ -1988,7 +2054,7 @@ export class DOMModelUndoStack { * @param {!DOMModel} model * @param {boolean} minorChange */ - _markUndoableState(model, minorChange) { + async _markUndoableState(model, minorChange) { // Both minor and major changes get into the stack, but minor updates are coalesced. // Commit major undoable state in the old model upon model switch. if (this._lastModelWithMinorChange && model !== this._lastModelWithMinorChange) { @@ -2010,7 +2076,7 @@ export class DOMModelUndoStack { if (minorChange) { this._lastModelWithMinorChange = model; } else { - model._agent.markUndoableState(); + await model._agent.invoke_markUndoableState(); this._lastModelWithMinorChange = null; } } @@ -2018,25 +2084,25 @@ export class DOMModelUndoStack { /** * @return {!Promise} */ - undo() { + async undo() { if (this._index === 0) { return Promise.resolve(); } --this._index; this._lastModelWithMinorChange = null; - return this._stack[this._index]._agent.undo(); + await this._stack[this._index]._agent.invoke_undo(); } /** * @return {!Promise} */ - redo() { + async redo() { if (this._index >= this._stack.length) { return Promise.resolve(); } ++this._index; this._lastModelWithMinorChange = null; - return this._stack[this._index - 1]._agent.redo(); + await this._stack[this._index - 1]._agent.invoke_redo(); } /** @@ -2060,4 +2126,5 @@ export class DOMModelUndoStack { SDKModel.register(DOMModel, Capability.DOM, true); /** @typedef {{name: string, value: string, _node: DOMNode}} */ +// @ts-ignore typedef export let Attribute; diff --git a/front_end/sdk/DebuggerModel.js b/front_end/sdk/DebuggerModel.js index ace16a100e0..42884889dc0 100644 --- a/front_end/sdk/DebuggerModel.js +++ b/front_end/sdk/DebuggerModel.js @@ -752,6 +752,8 @@ export class DebuggerModel extends SDKModel { } else { this.stepInto(); } + } else { + Common.EventTarget.fireEvent('DevTools.DebuggerPaused'); } _scheduledPauseOnAsyncCall = null; diff --git a/front_end/sdk/EmulationModel.js b/front_end/sdk/EmulationModel.js index ad27afb3d7e..026314c1e30 100644 --- a/front_end/sdk/EmulationModel.js +++ b/front_end/sdk/EmulationModel.js @@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import {CSSModel} from './CSSModel.js'; +import {MultitargetNetworkManager} from './NetworkManager.js'; import {Events, OverlayModel} from './OverlayModel.js'; import {Capability, SDKModel, Target} from './SDKModel.js'; // eslint-disable-line no-unused-vars @@ -23,14 +21,17 @@ export class EmulationModel extends SDKModel { this._cssModel = target.model(CSSModel); this._overlayModel = target.model(OverlayModel); if (this._overlayModel) { - this._overlayModel.addEventListener(Events.InspectModeWillBeToggled, this._updateTouch, this); + this._overlayModel.addEventListener(Events.InspectModeWillBeToggled, () => { + this._updateTouch(); + }, this); } const disableJavascriptSetting = Common.Settings.Settings.instance().moduleSetting('javaScriptDisabled'); disableJavascriptSetting.addChangeListener( - () => this._emulationAgent.setScriptExecutionDisabled(disableJavascriptSetting.get())); + async () => + await this._emulationAgent.invoke_setScriptExecutionDisabled({value: disableJavascriptSetting.get()})); if (disableJavascriptSetting.get()) { - this._emulationAgent.setScriptExecutionDisabled(true); + this._emulationAgent.invoke_setScriptExecutionDisabled({value: true}); } const touchSetting = Common.Settings.Settings.instance().moduleSetting('emulation.touch'); @@ -100,13 +101,33 @@ export class EmulationModel extends SDKModel { this._setLocalFontsDisabled(localFontsDisabledSetting.get()); } + const avifFormatDisabledSetting = Common.Settings.Settings.instance().moduleSetting('avifFormatDisabled'); + const webpFormatDisabledSetting = Common.Settings.Settings.instance().moduleSetting('webpFormatDisabled'); + + const updateDisabledImageFormats = () => { + const types = []; + if (avifFormatDisabledSetting.get()) { + types.push(Protocol.Emulation.DisabledImageType.Avif); + } + if (webpFormatDisabledSetting.get()) { + types.push(Protocol.Emulation.DisabledImageType.Webp); + } + this._setDisabledImageTypes(types); + }; + + avifFormatDisabledSetting.addChangeListener(updateDisabledImageFormats); + webpFormatDisabledSetting.addChangeListener(updateDisabledImageFormats); + + if (webpFormatDisabledSetting.get() || avifFormatDisabledSetting.get()) { + updateDisabledImageFormats(); + } + this._touchEnabled = false; this._touchMobile = false; this._customTouchEnabled = false; this._touchConfiguration = { enabled: false, configuration: Protocol.Emulation.SetEmitTouchEventsForMouseRequestConfiguration.Mobile, - scriptId: '' }; } @@ -118,21 +139,22 @@ export class EmulationModel extends SDKModel { } /** - * @return {!Promise} + * @return {!Promise} */ - resetPageScaleFactor() { - return this._emulationAgent.resetPageScaleFactor(); + async resetPageScaleFactor() { + await this._emulationAgent.invoke_resetPageScaleFactor(); } /** * @param {?Protocol.Page.SetDeviceMetricsOverrideRequest} metrics * @return {!Promise} */ - emulateDevice(metrics) { + async emulateDevice(metrics) { if (metrics) { - return this._emulationAgent.invoke_setDeviceMetricsOverride(metrics); + await this._emulationAgent.invoke_setDeviceMetricsOverride(metrics); + } else { + await this._emulationAgent.invoke_clearDeviceMetricsOverride(); } - return this._emulationAgent.clearDeviceMetricsOverride(); } /** @@ -146,20 +168,20 @@ export class EmulationModel extends SDKModel { * @param {?Location} location */ async emulateLocation(location) { - if (!location) { - this._emulationAgent.clearGeolocationOverride(); - this._emulationAgent.setTimezoneOverride(''); - this._emulationAgent.setLocaleOverride(''); - this._emulationAgent.setUserAgentOverride(SDK.multitargetNetworkManager.currentUserAgent()); - } - - if (location.error) { - this._emulationAgent.setGeolocationOverride(); - this._emulationAgent.setTimezoneOverride(''); - this._emulationAgent.setLocaleOverride(''); - this._emulationAgent.setUserAgentOverride(SDK.multitargetNetworkManager.currentUserAgent()); + if (!location || location.error) { + await Promise.all([ + this._emulationAgent.invoke_clearGeolocationOverride(), + this._emulationAgent.invoke_setTimezoneOverride({timezoneId: ''}), + this._emulationAgent.invoke_setLocaleOverride({locale: ''}), + this._emulationAgent.invoke_setUserAgentOverride( + {userAgent: MultitargetNetworkManager.instance().currentUserAgent()}), + ]); } else { - const processEmulationResult = (errorType, result) => { + /** + * @param {string} errorType + * @param {*} result + */ + function processEmulationResult(errorType, result) { const errorMessage = result.getError(); if (errorMessage) { return Promise.reject({ @@ -167,10 +189,10 @@ export class EmulationModel extends SDKModel { message: errorMessage, }); } - return Promise.resolve(result); - }; + return Promise.resolve(); + } - return Promise.all([ + await Promise.all([ this._emulationAgent .invoke_setGeolocationOverride({ latitude: location.latitude, @@ -190,7 +212,7 @@ export class EmulationModel extends SDKModel { .then(result => processEmulationResult('emulation-set-locale', result)), this._emulationAgent .invoke_setUserAgentOverride({ - userAgent: SDK.multitargetNetworkManager.currentUserAgent(), + userAgent: MultitargetNetworkManager.instance().currentUserAgent(), acceptLanguage: location.locale, }) .then(result => processEmulationResult('emulation-set-user-agent', result)), @@ -200,13 +222,14 @@ export class EmulationModel extends SDKModel { /** * @param {?DeviceOrientation} deviceOrientation + * @returns {!Promise} */ - emulateDeviceOrientation(deviceOrientation) { + async emulateDeviceOrientation(deviceOrientation) { if (deviceOrientation) { - this._deviceOrientationAgent.setDeviceOrientationOverride( - deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma); + await this._deviceOrientationAgent.invoke_setDeviceOrientationOverride( + {alpha: deviceOrientation.alpha, beta: deviceOrientation.beta, gamma: deviceOrientation.gamma}); } else { - this._deviceOrientationAgent.clearDeviceOrientationOverride(); + await this._deviceOrientationAgent.invoke_clearDeviceOrientationOverride(); } } @@ -224,9 +247,10 @@ export class EmulationModel extends SDKModel { /** * @param {string} type * @param {!Array<{name: string, value: string}>} features + * @returns {!Promise} */ - _emulateCSSMedia(type, features) { - this._emulationAgent.setEmulatedMedia(type, features); + async _emulateCSSMedia(type, features) { + await this._emulationAgent.invoke_setEmulatedMedia({media: type, features}); if (this._cssModel) { this._cssModel.mediaQueryResultChanged(); } @@ -234,41 +258,59 @@ export class EmulationModel extends SDKModel { /** * @param {!Protocol.Emulation.SetEmulatedVisionDeficiencyRequestType} type + * @returns {!Promise} */ - _emulateVisionDeficiency(type) { - this._emulationAgent.setEmulatedVisionDeficiency(type); + async _emulateVisionDeficiency(type) { + await this._emulationAgent.invoke_setEmulatedVisionDeficiency({type}); } + /** + * + * @param {boolean} disabled + */ _setLocalFontsDisabled(disabled) { + if (!this._cssModel) { + return; + } this._cssModel.setLocalFontsEnabled(!disabled); } + /** + * @param {!Array} imageTypes + */ + _setDisabledImageTypes(imageTypes) { + this._emulationAgent.invoke_setDisabledImageTypes({imageTypes}); + } + /** * @param {number} rate + * @returns {!Promise} */ - setCPUThrottlingRate(rate) { - this._emulationAgent.setCPUThrottlingRate(rate); + async setCPUThrottlingRate(rate) { + await this._emulationAgent.invoke_setCPUThrottlingRate({rate}); } /** * @param {boolean} enabled * @param {boolean} mobile + * @returns {!Promise} */ - emulateTouch(enabled, mobile) { + async emulateTouch(enabled, mobile) { this._touchEnabled = enabled; this._touchMobile = mobile; - this._updateTouch(); + await this._updateTouch(); } /** * @param {boolean} enabled + * @returns {!Promise} */ - overrideEmulateTouch(enabled) { + async overrideEmulateTouch(enabled) { this._customTouchEnabled = enabled; - this._updateTouch(); + await this._updateTouch(); } - _updateTouch() { + async _updateTouch() { let configuration = { enabled: this._touchEnabled, configuration: this._touchMobile ? Protocol.Emulation.SetEmitTouchEventsForMouseRequestConfiguration.Mobile : @@ -277,14 +319,14 @@ export class EmulationModel extends SDKModel { if (this._customTouchEnabled) { configuration = { enabled: true, - configuration: Protocol.Emulation.SetEmitTouchEventsForMouseRequestConfiguration.Mobile + configuration: Protocol.Emulation.SetEmitTouchEventsForMouseRequestConfiguration.Mobile, }; } if (this._overlayModel && this._overlayModel.inspectModeEnabled()) { configuration = { enabled: false, - configuration: Protocol.Emulation.SetEmitTouchEventsForMouseRequestConfiguration.Mobile + configuration: Protocol.Emulation.SetEmitTouchEventsForMouseRequestConfiguration.Mobile, }; } @@ -297,8 +339,9 @@ export class EmulationModel extends SDKModel { } this._touchConfiguration = configuration; - this._emulationAgent.setTouchEmulationEnabled(configuration.enabled, 1); - this._emulationAgent.setEmitTouchEventsForMouse(configuration.enabled, configuration.configuration); + await this._emulationAgent.invoke_setTouchEmulationEnabled({enabled: configuration.enabled, maxTouchPoints: 1}); + await this._emulationAgent.invoke_setEmitTouchEventsForMouse( + {enabled: configuration.enabled, configuration: configuration.configuration}); } _updateCssMedia() { @@ -339,6 +382,7 @@ export class Location { } /** + * @param {string} value * @return {!Location} */ static parseSetting(value) { @@ -354,6 +398,7 @@ export class Location { * @param {string} latitudeString * @param {string} longitudeString * @param {string} timezoneId + * @param {string} locale * @return {?Location} */ static parseUserInput(latitudeString, longitudeString, timezoneId, locale) { @@ -380,7 +425,7 @@ export class Location { static latitudeValidator(value) { const numValue = parseFloat(value); const valid = /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value) && numValue >= -90 && numValue <= 90; - return {valid}; + return {valid, errorMessage: undefined}; } /** @@ -390,7 +435,7 @@ export class Location { static longitudeValidator(value) { const numValue = parseFloat(value); const valid = /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value) && numValue >= -180 && numValue <= 180; - return {valid}; + return {valid, errorMessage: undefined}; } /** @@ -405,7 +450,7 @@ export class Location { // the input other than checking if it contains at least one alphabet. // The empty string resets the override, and is accepted as well. const valid = value === '' || /[a-zA-Z]/.test(value); - return {valid}; + return {valid, errorMessage: undefined}; } /** @@ -420,7 +465,7 @@ export class Location { // The empty string resets the override, and is accepted as // well. const valid = value === '' || /[a-zA-Z]{2}/.test(value); - return {valid}; + return {valid, errorMessage: undefined}; } /** @@ -446,6 +491,7 @@ export class DeviceOrientation { } /** + * @param {string} value * @return {!DeviceOrientation} */ static parseSetting(value) { @@ -457,6 +503,9 @@ export class DeviceOrientation { } /** + * @param {string} alphaString + * @param {string} betaString + * @param {string} gammaString * @return {?DeviceOrientation} */ static parseUserInput(alphaString, betaString, gammaString) { @@ -485,7 +534,7 @@ export class DeviceOrientation { */ static validator(value) { const valid = /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value); - return {valid}; + return {valid, errorMessage: undefined}; } /** diff --git a/front_end/sdk/NetworkManager.js b/front_end/sdk/NetworkManager.js index bd537694899..6bdd027978e 100644 --- a/front_end/sdk/NetworkManager.js +++ b/front_end/sdk/NetworkManager.js @@ -277,16 +277,16 @@ export const OfflineConditions = { /** @type {!Conditions} */ export const Slow3GConditions = { title: Common.UIString.UIString('Slow 3G'), - download: 500 * 1024 / 8 * .8, - upload: 500 * 1024 / 8 * .8, + download: 500 * 1000 / 8 * .8, + upload: 500 * 1000 / 8 * .8, latency: 400 * 5, }; /** @type {!Conditions} */ export const Fast3GConditions = { title: Common.UIString.UIString('Fast 3G'), - download: 1.6 * 1024 * 1024 / 8 * .9, - upload: 750 * 1024 / 8 * .9, + download: 1.6 * 1000 * 1000 / 8 * .9, + upload: 750 * 1000 / 8 * .9, latency: 150 * 3.75, }; @@ -642,8 +642,15 @@ export class NetworkDispatcher { * @override * @param {!Protocol.Network.LoadingFailedEvent} request */ - loadingFailed( - {requestId, timestamp: time, type: resourceType, errorText: localizedDescription, canceled, blockedReason}) { + loadingFailed({ + requestId, + timestamp: time, + type: resourceType, + errorText: localizedDescription, + canceled, + blockedReason, + corsErrorStatus + }) { const networkRequest = this._inflightRequestsById.get(requestId); if (!networkRequest) { return; @@ -660,6 +667,9 @@ export class NetworkDispatcher { Events.MessageGenerated, {message: message, requestId: requestId, warning: true}); } } + if (corsErrorStatus) { + networkRequest.setCorsErrorStatus(corsErrorStatus); + } networkRequest.localizedFailDescription = localizedDescription; this._getExtraInfoBuilder(requestId).finished(); this._finishNetworkRequest(networkRequest, time, -1); diff --git a/front_end/sdk/NetworkRequest.js b/front_end/sdk/NetworkRequest.js index feed61f6107..69c9d0d0de3 100644 --- a/front_end/sdk/NetworkRequest.js +++ b/front_end/sdk/NetworkRequest.js @@ -99,6 +99,8 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper { this._endTime = -1; /** @type {!Protocol.Network.BlockedReason|undefined} */ this._blockedReason = undefined; + /** @type {!Protocol.Network.CorsErrorStatus|undefined} */ + this._corsErrorStatus = undefined; this.statusCode = 0; this.statusText = ''; @@ -579,6 +581,20 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper { this._blockedReason = reason; } + /** + * @return {!Protocol.Network.CorsErrorStatus|undefined} + */ + corsErrorStatus() { + return this._corsErrorStatus; + } + + /** + * @param {!Protocol.Network.CorsErrorStatus} corsErrorStatus + */ + setCorsErrorStatus(corsErrorStatus) { + this._corsErrorStatus = corsErrorStatus; + } + /** * @return {boolean} */ diff --git a/front_end/sdk/RemoteObject.js b/front_end/sdk/RemoteObject.js index 8e1c176e894..4980d3d7818 100644 --- a/front_end/sdk/RemoteObject.js +++ b/front_end/sdk/RemoteObject.js @@ -29,7 +29,7 @@ */ import {DebuggerModel, FunctionDetails} from './DebuggerModel.js'; // eslint-disable-line no-unused-vars -import {RuntimeModel} from './RuntimeModel.js'; // eslint-disable-line no-unused-vars +import {RuntimeModel} from './RuntimeModel.js'; // eslint-disable-line no-unused-vars export class RemoteObject { /** @@ -232,6 +232,11 @@ export class RemoteObject { throw 'Not implemented'; } + /** @param {string|undefined} description*/ + set description(description) { + throw 'Not implemented'; + } + /** @return {boolean} */ get hasChildren() { throw 'Not implemented'; @@ -452,6 +457,14 @@ export class RemoteObjectImpl extends RemoteObject { return this._description; } + /** + * @override + * @param {string|undefined} description + */ + set description(description) { + this._description = description; + } + /** * @override * @return {boolean} @@ -495,6 +508,13 @@ export class RemoteObjectImpl extends RemoteObject { return this.doGetProperties(false, accessorPropertiesOnly, generatePreview); } + /** + * @param {!Protocol.Runtime.RemoteObject} object + */ + _createRemoteObject(object) { + return Promise.resolve(this._runtimeModel.createRemoteObject(object)); + } + /** * @param {boolean} ownProperties * @param {boolean} accessorPropertiesOnly @@ -518,7 +538,7 @@ export class RemoteObjectImpl extends RemoteObject { const {result: properties = [], internalProperties = [], privateProperties = []} = response; const result = []; for (const property of properties) { - const propertyValue = property.value ? this._runtimeModel.createRemoteObject(property.value) : null; + const propertyValue = property.value ? await this._createRemoteObject(property.value) : null; const propertySymbol = property.symbol ? this._runtimeModel.createRemoteObject(property.symbol) : null; const remoteProperty = new RemoteObjectProperty( property.name, propertyValue, !!property.enumerable, !!property.writable, !!property.isOwn, diff --git a/front_end/sdk/ServiceWorkerManager.js b/front_end/sdk/ServiceWorkerManager.js index 8d1dd06c63c..7453748eebd 100644 --- a/front_end/sdk/ServiceWorkerManager.js +++ b/front_end/sdk/ServiceWorkerManager.js @@ -56,6 +56,9 @@ export class ServiceWorkerManager extends SDKModel { } this._forceUpdateSetting.addChangeListener(this._forceUpdateSettingChanged, this); new ServiceWorkerContextNamer(target, this); + + /** Status of service worker network requests panel */ + this.serviceWorkerNetworkRequestsPanelOpen = false; } async enable() { diff --git a/front_end/sdk/module.json b/front_end/sdk/module.json index 51f77d08af6..c5f1a6070c8 100644 --- a/front_end/sdk/module.json +++ b/front_end/sdk/module.json @@ -577,6 +577,42 @@ ], "defaultValue": false }, + { + "type": "setting", + "category": "Rendering", + "settingName": "avifFormatDisabled", + "settingType": "boolean", + "storageType": "session", + "options": [ + { + "value": true, + "title": "Disable AVIF format" + }, + { + "value": false, + "title": "Enable AVIF format" + } + ], + "defaultValue": false + }, + { + "type": "setting", + "category": "Rendering", + "settingName": "webpFormatDisabled", + "settingType": "boolean", + "storageType": "session", + "options": [ + { + "value": true, + "title": "Disable WebP format" + }, + { + "value": false, + "title": "Enable WebP format" + } + ], + "defaultValue": false + }, { "type": "setting", "category": "Console", diff --git a/front_end/sdk/sdk_strings.grdp b/front_end/sdk/sdk_strings.grdp index 8a30d05a02b..42a0285fb3f 100644 --- a/front_end/sdk/sdk_strings.grdp +++ b/front_end/sdk/sdk_strings.grdp @@ -105,6 +105,9 @@ Indicate whether a cookie is intended to be set in cross-site context by specifying its SameSite attribute + + Enable WebP format + No value found for parameter "$1shttps". @@ -129,6 +132,9 @@ This Set-Cookie was blocked because it had the "SameSite=Strict" attribute but came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site. + + Disable AVIF format + Set-Cookie header is ignored in response from url: $1shttps://example.com. Cookie length should be less than or equal to 4096 characters. @@ -194,6 +200,9 @@ Show grid named areas + + Trusted Types - Fix violations + Show line numbers @@ -221,6 +230,9 @@ Do not emulate CSS prefers-reduced-data + + Enable AVIF format + This Set-Cookie didn't specify a "SameSite" attribute, was defaulted to "SameSite=Lax", and was blocked because it came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site. @@ -241,6 +253,9 @@ Migrate entirely to HTTPS to allow cookies to be set by same-site subresources + + Trusted Types - Policy violation + This cookie was blocked because it had the "SameSite=Strict" attribute but the request was cross-site. This includes top-level navigation requests initiated by other sites. This request is considered cross-site because the URL has a different scheme than the current site. @@ -535,6 +550,9 @@ Disable network request blocking + + Disable WebP format + Hide layout shift regions diff --git a/front_end/settings/KeybindsSettingsTab.js b/front_end/settings/KeybindsSettingsTab.js index 99045c3c75c..478549a8147 100644 --- a/front_end/settings/KeybindsSettingsTab.js +++ b/front_end/settings/KeybindsSettingsTab.js @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks import * as Common from '../common/common.js'; import * as Host from '../host/host.js'; import * as i18n from '../i18n/i18n.js'; +import * as Root from '../root/root.js'; import * as UI from '../ui/ui.js'; export const UIStrings = { @@ -92,8 +91,10 @@ export class KeybindsSettingsTab extends UI.Widget.VBox { keybindsSetSetting.addChangeListener(this.update, this); const keybindsSetSelect = UI.SettingsUI.createControlForSetting(keybindsSetSetting, i18nString(UIStrings.matchShortcutsFromPreset)); - keybindsSetSelect.classList.add('keybinds-set-select'); - this.contentElement.appendChild(keybindsSetSelect); + if (keybindsSetSelect) { + keybindsSetSelect.classList.add('keybinds-set-select'); + this.contentElement.appendChild(keybindsSetSelect); + } /** @type {!UI.ListModel.ListModel} */ this._items = new UI.ListModel.ListModel(); @@ -162,7 +163,7 @@ export class KeybindsSettingsTab extends UI.Widget.VBox { } if (newDescriptors) { UI.ShortcutRegistry.ShortcutRegistry.instance().registerUserShortcut( - originalShortcut.changeKeys(/** @type !Array. */ (newDescriptors)) + originalShortcut.changeKeys(/** @type {!Array.} */ (newDescriptors)) .changeType(UI.KeyboardShortcut.Type.UserShortcut)); if (originalShortcut.type === UI.KeyboardShortcut.Type.UnsetShortcut) { Host.userMetrics.actionTaken(Host.UserMetrics.Action.UserShortcutAdded); @@ -198,14 +199,14 @@ export class KeybindsSettingsTab extends UI.Widget.VBox { * @override * @param {?KeybindsItem} from * @param {?KeybindsItem} to - * @param {?Element} fromElement - * @param {?Element} toElement + * @param {?HTMLElement} fromElement + * @param {?HTMLElement} toElement */ selectedItemChanged(from, to, fromElement, toElement) { if (fromElement) { fromElement.tabIndex = -1; } - if (toElement) { + if (toElement && this._editingRow) { if (to === this._editingItem) { this._editingRow.focus(); } else { @@ -271,7 +272,10 @@ export class KeybindsSettingsTab extends UI.Widget.VBox { return 0; }); + /** @type {!Array.} */ const items = []; + + /** @type {string} */ let currentCategory; actions.forEach(action => { if (currentCategory !== action.category()) { @@ -287,7 +291,8 @@ export class KeybindsSettingsTab extends UI.Widget.VBox { * @param {!Event} event */ onEscapeKeyPressed(event) { - if (this._editingRow && document.deepActiveElement().nodeName === 'INPUT') { + const deepActiveElement = document.deepActiveElement(); + if (this._editingRow && deepActiveElement && deepActiveElement.nodeName === 'INPUT') { this._editingRow.onEscapeKeyPressed(event); } } @@ -329,9 +334,9 @@ export class ShortcutListItem { this._shortcutInputs = new Map(); /** @type {!Array.} */ this._shortcuts = UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction(item.id()); - /** @type {?Element} */ + /** @type {?HTMLElement} */ this._elementToFocus = null; - /** @type {?Element} */ + /** @type {?HTMLButtonElement} */ this._confirmButton = null; /** @type {?Element} */ this._addShortcutLinkContainer = null; @@ -380,7 +385,8 @@ export class ShortcutListItem { _setupEditor() { this._addShortcutLinkContainer = this.element.createChild('div', 'keybinds-shortcut devtools-link'); - const addShortcutLink = this._addShortcutLinkContainer.createChild('span', 'devtools-link'); + const addShortcutLink = + /** @type {!HTMLDivElement} */ (this._addShortcutLinkContainer.createChild('span', 'devtools-link')); addShortcutLink.textContent = i18nString(UIStrings.addAShortcut); addShortcutLink.tabIndex = 0; UI.ARIAUtils.markAsLink(addShortcutLink); @@ -414,7 +420,10 @@ export class ShortcutListItem { new UI.KeyboardShortcut.KeyboardShortcut([], this._item.id(), UI.KeyboardShortcut.Type.UnsetShortcut); this._shortcuts.push(shortcut); this._update(); - this._shortcutInputs.get(shortcut).focus(); + const shortcutInput = /** @type {!HTMLElement} */ (this._shortcutInputs.get(shortcut)); + if (shortcutInput) { + shortcutInput.focus(); + } } /** @@ -425,6 +434,7 @@ export class ShortcutListItem { if (this._editedShortcuts.has(shortcut) && !this._editedShortcuts.get(shortcut)) { return; } + /** @type {!UI.Icon.Icon} */ let icon; if (shortcut.type !== UI.KeyboardShortcut.Type.UnsetShortcut && !shortcut.isDefault()) { icon = UI.Icon.Icon.create('largeicon-shortcut-changed', 'keybinds-modified'); @@ -433,7 +443,7 @@ export class ShortcutListItem { } const shortcutElement = this.element.createChild('div', 'keybinds-shortcut keybinds-list-text'); if (this._isEditing) { - const shortcutInput = shortcutElement.createChild('input', 'harmony-input'); + const shortcutInput = /** @type {!HTMLInputElement} */ (shortcutElement.createChild('input', 'harmony-input')); shortcutInput.spellcheck = false; this._shortcutInputs.set(shortcut, shortcutInput); if (!this._elementToFocus) { @@ -480,11 +490,11 @@ export class ShortcutListItem { * @param {string} label * @param {string} iconName * @param {string} className - * @param {!Function} listener - * @return {!Element} + * @param {function():void} listener + * @return {!HTMLButtonElement} */ _createIconButton(label, iconName, className, listener) { - const button = document.createElement('button'); + const button = /** @type {!HTMLButtonElement}*/ (document.createElement('button')); button.appendChild(UI.Icon.Icon.create(iconName)); button.addEventListener('click', listener); UI.ARIAUtils.setAccessibleName(button, label); @@ -496,15 +506,15 @@ export class ShortcutListItem { /** * @param {!UI.KeyboardShortcut.KeyboardShortcut} shortcut - * @param {!Element} shortcutInput + * @param {!HTMLInputElement} shortcutInput * @param {!Event} event */ _onShortcutInputKeyDown(shortcut, shortcutInput, event) { - if (event.key !== 'Tab') { + if (/** @type {!KeyboardEvent} */ (event).key !== 'Tab') { const userKey = UI.KeyboardShortcut.KeyboardShortcut.makeKeyFromEvent(/** @type {!KeyboardEvent} */ (event)); const codeAndModifiers = UI.KeyboardShortcut.KeyboardShortcut.keyCodeAndModifiersFromKey(userKey); const userDescriptor = UI.KeyboardShortcut.KeyboardShortcut.makeDescriptor( - {code: userKey, name: event.key}, codeAndModifiers.modifiers); + {code: userKey, name: /** @type {!KeyboardEvent} */ (event).key}, codeAndModifiers.modifiers); shortcutInput.value = this._shortcutInputTextForDescriptor(userDescriptor); this._editedShortcuts.set(shortcut, [userDescriptor]); this._validateInputs(); @@ -551,37 +561,46 @@ export class ShortcutListItem { if (activeElement === shortcutInput) { this._onShortcutInputKeyDown( /** @type {!UI.KeyboardShortcut.KeyboardShortcut} */ (shortcut), - /** @type {!HTMLInputElement} */ (shortcutInput), event); + /** @type {!HTMLInputElement} */ (shortcutInput), /** @type {!KeyboardEvent} */ (event)); } } } _validateInputs() { - this._confirmButton.disabled = false; - this._errorMessageElement.classList.add('hidden'); + const confirmButton = this._confirmButton; + const errorMessageElement = this._errorMessageElement; + if (!confirmButton || !errorMessageElement) { + return; + } + + confirmButton.disabled = false; + errorMessageElement.classList.add('hidden'); this._shortcutInputs.forEach((shortcutInput, shortcut) => { const userDescriptors = this._editedShortcuts.get(shortcut); if (!userDescriptors) { return; } if (UI.KeyboardShortcut.KeyboardShortcut.isModifier(userDescriptors[0].key)) { - this._confirmButton.disabled = true; + confirmButton.disabled = true; shortcutInput.classList.add('error-input'); UI.ARIAUtils.setInvalid(shortcutInput, true); - this._errorMessageElement.classList.remove('hidden'); - this._errorMessageElement.textContent = i18nString(UIStrings.shortcutsCannotContainOnly); + errorMessageElement.classList.remove('hidden'); + errorMessageElement.textContent = i18nString(UIStrings.shortcutsCannotContainOnly); return; } const conflicts = UI.ShortcutRegistry.ShortcutRegistry.instance() .actionsForDescriptors(userDescriptors) .filter(actionId => actionId !== this._item.id()); if (conflicts.length) { - this._confirmButton.disabled = true; + confirmButton.disabled = true; shortcutInput.classList.add('error-input'); UI.ARIAUtils.setInvalid(shortcutInput, true); - this._errorMessageElement.classList.remove('hidden'); + errorMessageElement.classList.remove('hidden'); const action = UI.ActionRegistry.ActionRegistry.instance().action(conflicts[0]); - this._errorMessageElement.textContent = i18nString(UIStrings.thisShortcutIsInUseByS, {PH1: action.title()}); + if (!action) { + return; + } + errorMessageElement.textContent = i18nString(UIStrings.thisShortcutIsInUseByS, {PH1: action.title()}); return; } shortcutInput.classList.remove('error-input'); @@ -591,4 +610,5 @@ export class ShortcutListItem { } /** @typedef {string|!UI.Action.Action} */ +// @ts-ignore typedef export let KeybindsItem; diff --git a/front_end/settings/settingsScreen.css b/front_end/settings/settingsScreen.css index c56eca55923..33d386ff5bb 100644 --- a/front_end/settings/settingsScreen.css +++ b/front_end/settings/settingsScreen.css @@ -175,6 +175,7 @@ fieldset { font-weight: normal; margin: 0; padding-bottom: 3px; + white-space: nowrap; } .settings-tab .settings-section-title { diff --git a/front_end/source_frame/BinaryResourceViewFactory.js b/front_end/source_frame/BinaryResourceViewFactory.js index ed1540cd5d2..d417cc5707f 100644 --- a/front_end/source_frame/BinaryResourceViewFactory.js +++ b/front_end/source_frame/BinaryResourceViewFactory.js @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks import * as Common from '../common/common.js'; // eslint-disable-line no-unused-vars import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars +import * as UI from '../ui/ui.js'; // eslint-disable-line no-unused-vars import {ResourceSourceFrame} from './ResourceSourceFrame.js'; @@ -22,7 +21,7 @@ export class BinaryResourceViewFactory { this._resourceType = resourceType; /** @type {?Promise} */ this._arrayPromise = null; - /** @type {?Promise} */ + /** @type {?Promise} */ this._hexPromise = null; /** @type {?Promise} */ this._utf8Promise = null; @@ -43,11 +42,9 @@ export class BinaryResourceViewFactory { */ async hex() { if (!this._hexPromise) { - this._hexPromise = new Promise(async resolve => { const content = await this._fetchContentAsArray(); const hexString = BinaryResourceViewFactory.uint8ArrayToHexString(content); - resolve({content: hexString, isEncoded: false}); - }); + return {content: hexString, isEncoded: false}; } return this._hexPromise; @@ -82,7 +79,7 @@ export class BinaryResourceViewFactory { return new ResourceSourceFrame( TextUtils.StaticContentProvider.StaticContentProvider.fromString( this._contentUrl, this._resourceType, this._base64content), - /* autoPrettyPrint */ false, {lineNumbers: false, lineWrapping: true}); + /* autoPrettyPrint */ false, /** @type {!UI.TextEditor.Options} */ ({lineNumbers: false, lineWrapping: true})); } /** @@ -97,7 +94,7 @@ export class BinaryResourceViewFactory { }); return new ResourceSourceFrame( hexViewerContentProvider, - /* autoPrettyPrint */ false, {lineNumbers: false, lineWrapping: false}); + /* autoPrettyPrint */ false, /** @type {!UI.TextEditor.Options} */ ({lineNumbers: false, lineWrapping: false})); } /** @@ -109,7 +106,7 @@ export class BinaryResourceViewFactory { new TextUtils.StaticContentProvider.StaticContentProvider(this._contentUrl, this._resourceType, utf8fn); return new ResourceSourceFrame( utf8ContentProvider, - /* autoPrettyPrint */ false, {lineNumbers: true, lineWrapping: true}); + /* autoPrettyPrint */ false, /** @type {!UI.TextEditor.Options} */ ({lineNumbers: true, lineWrapping: true})); } /** diff --git a/front_end/source_frame/ImageView.js b/front_end/source_frame/ImageView.js index 2990becdc36..50028cc39cf 100644 --- a/front_end/source_frame/ImageView.js +++ b/front_end/source_frame/ImageView.js @@ -26,9 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Host from '../host/host.js'; import * as Platform from '../platform/platform.js'; @@ -67,7 +64,9 @@ export class ImageView extends UI.View.SimpleView { this._dimensionsLabel = new UI.Toolbar.ToolbarText(); this._mimeTypeLabel = new UI.Toolbar.ToolbarText(mimeType); this._container = this.element.createChild('div', 'image'); - this._imagePreviewElement = this._container.createChild('img', 'resource-image-view'); + /** @type {!HTMLImageElement} */ + this._imagePreviewElement = + /** @type {!HTMLImageElement} */ (this._container.createChild('img', 'resource-image-view')); this._imagePreviewElement.addEventListener('contextmenu', this._contextMenu.bind(this), true); } @@ -110,6 +109,7 @@ export class ImageView extends UI.View.SimpleView { } const contentEncoded = await this._contentProvider.contentEncoded(); + /** @type {?string} */ this._cachedContent = content; let imageSrc = TextUtils.ContentProvider.contentAsDataURL(content, this._mimeType, contentEncoded); if (content === null) { @@ -118,7 +118,9 @@ export class ImageView extends UI.View.SimpleView { const loadPromise = new Promise(x => { this._imagePreviewElement.onload = x; }); - this._imagePreviewElement.src = imageSrc; + if (imageSrc) { + this._imagePreviewElement.src = imageSrc; + } this._imagePreviewElement.alt = ls`Image from ${this._url}`; const size = content && !contentEncoded ? content.length : base64ToSize(content); this._sizeLabel.setText(Platform.NumberUtilities.bytesToString(size)); @@ -127,6 +129,9 @@ export class ImageView extends UI.View.SimpleView { '%d × %d', this._imagePreviewElement.naturalWidth, this._imagePreviewElement.naturalHeight)); } + /** + * @param {!Event} event + */ _contextMenu(event) { const contextMenu = new UI.ContextMenu.ContextMenu(event); if (!this._parsedURL.isDataURL()) { @@ -153,7 +158,7 @@ export class ImageView extends UI.View.SimpleView { } _saveImage() { - const link = createElement('a'); + const link = document.createElement('a'); link.download = this._parsedURL.displayName; link.href = this._url; link.click(); @@ -174,7 +179,10 @@ export class ImageView extends UI.View.SimpleView { const entry = items[0].webkitGetAsEntry(); const encoded = !entry.name.endsWith('.svg'); - entry.file(file => { + /** + * @param {!Blob} file + */ + const fileCallback = file => { const reader = new FileReader(); reader.onloadend = () => { let result; @@ -184,7 +192,7 @@ export class ImageView extends UI.View.SimpleView { result = null; console.error('Can\'t read file: ' + e); } - if (typeof result !== 'string') { + if (typeof result !== 'string' || !this._uiSourceCode) { return; } this._uiSourceCode.setContent(encoded ? btoa(result) : result, encoded); @@ -194,6 +202,7 @@ export class ImageView extends UI.View.SimpleView { } else { reader.readAsText(file); } - }); + }; + entry.file(fileCallback); } } diff --git a/front_end/source_frame/ResourceSourceFrame.js b/front_end/source_frame/ResourceSourceFrame.js index 37c657071f0..98f442ddfee 100644 --- a/front_end/source_frame/ResourceSourceFrame.js +++ b/front_end/source_frame/ResourceSourceFrame.js @@ -27,8 +27,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars import * as UI from '../ui/ui.js'; @@ -75,7 +73,7 @@ export class ResourceSourceFrame extends SourceFrameImpl { * @param {!UI.ContextMenu.ContextMenu} contextMenu * @param {number} lineNumber * @param {number} columnNumber - * @return {!Promise} + * @return {!Promise} */ populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) { contextMenu.appendApplicableItems(this._resource); @@ -88,7 +86,6 @@ export class SearchableContainer extends UI.Widget.VBox { * @param {!TextUtils.ContentProvider.ContentProvider} resource * @param {string} highlighterType * @param {boolean=} autoPrettyPrint - * @return {!UI.Widget.Widget} */ constructor(resource, highlighterType, autoPrettyPrint) { super(true); diff --git a/front_end/source_frame/SourcesTextEditor.js b/front_end/source_frame/SourcesTextEditor.js index 6d674e6516b..465e42667c1 100644 --- a/front_end/source_frame/SourcesTextEditor.js +++ b/front_end/source_frame/SourcesTextEditor.js @@ -228,7 +228,7 @@ export class SourcesTextEditor extends TextEditor.CodeMirrorTextEditor.CodeMirro /** * @param {!TextUtils.TextRange.TextRange} range * @param {string} cssClass - * @return {!Object} + * @return {!CodeMirror.TextMarker} */ highlightRange(range, cssClass) { cssClass = 'CodeMirror-persist-highlight ' + cssClass; @@ -1065,5 +1065,5 @@ const LinesToScanForIndentationGuessing = 1000; const MaximumNumberOfWhitespacesPerSingleSpan = 16; export const lineNumbersGutterType = 'CodeMirror-linenumbers'; -/** @typedef {{gutterType: string, lineNumber: number, event: !Event}} */ +/** @typedef {{gutterType: string, lineNumber: number, event: !MouseEvent}} */ export let GutterClickEventData; diff --git a/front_end/source_frame/XMLView.js b/front_end/source_frame/XMLView.js index 084c5b1b365..801fa17ca79 100644 --- a/front_end/source_frame/XMLView.js +++ b/front_end/source_frame/XMLView.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Platform from '../platform/platform.js'; import * as TextUtils from '../text_utils/text_utils.js'; @@ -30,13 +27,16 @@ export class XMLView extends UI.Widget.Widget { this._searchableView; /** @type {number} */ this._currentSearchFocusIndex = 0; - /** @type {!Array.} */ + /** @type {!Array.} */ this._currentSearchTreeElements = []; /** @type {?UI.SearchableView.SearchConfig} */ this._searchConfig; XMLViewNode.populate(this._treeOutline, parsedXML, this); - this._treeOutline.firstChild().select(true /* omitFocus */, false /* selectedByUser */); + const firstChild = this._treeOutline.firstChild(); + if (firstChild) { + firstChild.select(true /* omitFocus */, false /* selectedByUser */); + } } /** @@ -60,11 +60,18 @@ export class XMLView extends UI.Widget.Widget { static parseXML(text, mimeType) { let parsedXML; try { - parsedXML = (new DOMParser()).parseFromString(text, mimeType); + switch (mimeType) { + case 'application/xhtml+xml': + case 'application/xml': + case 'image/svg+xml': + case 'text/html': + case 'text/xml': + parsedXML = (new DOMParser()).parseFromString(text, mimeType); + } } catch (e) { return null; } - if (parsedXML.body) { + if (!parsedXML || parsedXML.body) { return null; } return parsedXML; @@ -131,7 +138,8 @@ export class XMLView extends UI.Widget.Widget { this._currentSearchTreeElements = []; const regex = this._searchConfig.toSearchRegex(true); - for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) { + for (let element = /** @type {?UI.TreeOutline.TreeElement} */ (this._treeOutline.rootElement()); element; + element = element.traverseNextTreeElement(false)) { if (!(element instanceof XMLViewNode)) { continue; } @@ -160,7 +168,8 @@ export class XMLView extends UI.Widget.Widget { } _innerSearchCanceled() { - for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) { + for (let element = /** @type {?UI.TreeOutline.TreeElement} */ (this._treeOutline.rootElement()); element; + element = element.traverseNextTreeElement(false)) { if (!(element instanceof XMLViewNode)) { continue; } @@ -239,16 +248,16 @@ export class XMLView extends UI.Widget.Widget { */ export class XMLViewNode extends UI.TreeOutline.TreeElement { /** - * @param {!Node} node + * @param {!Node|!ParentNode} node * @param {boolean} closeTag * @param {!XMLView} xmlView */ constructor(node, closeTag, xmlView) { - super('', !closeTag && !!node.childElementCount); + super('', !closeTag && 'childElementCount' in node && !!node.childElementCount); this._node = node; this._closeTag = closeTag; this.selectable = true; - /** @type {!Array.} */ + /** @type {!Array.} */ this._highlightChanges = []; this._xmlView = xmlView; this._updateTitle(); @@ -256,17 +265,20 @@ export class XMLViewNode extends UI.TreeOutline.TreeElement { /** * @param {!UI.TreeOutline.TreeOutline|!UI.TreeOutline.TreeElement} root - * @param {!Node} xmlNode + * @param {!Node|!ParentNode} xmlNode * @param {!XMLView} xmlView */ static populate(root, xmlNode, xmlView) { + if (!(xmlNode instanceof Node)) { + return; + } let node = xmlNode.firstChild; while (node) { const currentNode = node; node = node.nextSibling; const nodeType = currentNode.nodeType; // ignore empty TEXT - if (nodeType === 3 && currentNode.nodeValue.match(/\s+/)) { + if (nodeType === 3 && currentNode.nodeValue && currentNode.nodeValue.match(/\s+/)) { continue; } // ignore ATTRIBUTE, ENTITY_REFERENCE, ENTITY, DOCUMENT, DOCUMENT_TYPE, DOCUMENT_FRAGMENT, NOTATION @@ -295,6 +307,9 @@ export class XMLViewNode extends UI.TreeOutline.TreeElement { if (additionalCssClassName) { cssClasses += ' ' + additionalCssClassName; } + if (!this.listItemElement.textContent) { + return false; + } const content = this.listItemElement.textContent.replace(/\xA0/g, ' '); let match = regex.exec(content); const ranges = []; @@ -315,50 +330,66 @@ export class XMLViewNode extends UI.TreeOutline.TreeElement { _updateTitle() { const node = this._node; + if (!('nodeType' in node)) { + return; + } switch (node.nodeType) { case 1: { // ELEMENT - const tag = node.tagName; - if (this._closeTag) { - this._setTitle(['', 'shadow-xml-view-tag']); - return; - } - const titleItems = ['<' + tag, 'shadow-xml-view-tag']; - const attributes = node.attributes; - for (let i = 0; i < attributes.length; ++i) { - const attributeNode = attributes.item(i); - titleItems.push( - '\xA0', 'shadow-xml-view-tag', attributeNode.name, 'shadow-xml-view-attribute-name', '="', - 'shadow-xml-view-tag', attributeNode.value, 'shadow-xml-view-attribute-value', '"', - 'shadow-xml-view-tag'); - } - if (!this.expanded) { - if (node.childElementCount) { - titleItems.push( - '>', 'shadow-xml-view-tag', '…', 'shadow-xml-view-comment', '', 'shadow-xml-view-tag']); + return; + } + const titleItems = ['<' + tag, 'shadow-xml-view-tag']; + const attributes = node.attributes; + for (let i = 0; i < attributes.length; ++i) { + const attributeNode = attributes.item(i); + if (!attributeNode) { + return; + } titleItems.push( - '>', 'shadow-xml-view-tag', node.textContent, 'shadow-xml-view-text', '', 'shadow-xml-view-tag', '…', 'shadow-xml-view-comment', '', 'shadow-xml-view-tag', node.textContent, 'shadow-xml-view-text', '', 'shadow-xml-view-tag'); + this._setTitle(titleItems); + return; } - titleItems.push('>', 'shadow-xml-view-tag'); - this._setTitle(titleItems); return; } case 3: { // TEXT - this._setTitle([node.nodeValue, 'shadow-xml-view-text']); + if (node.nodeValue) { + this._setTitle([node.nodeValue, 'shadow-xml-view-text']); + } return; } case 4: { // CDATA - this._setTitle([ - '', 'shadow-xml-view-cdata' - ]); + if (node.nodeValue) { + this._setTitle([ + '', 'shadow-xml-view-cdata' + ]); + } return; } case 7: { // PROCESSING_INSTRUCTION - this._setTitle(['', 'shadow-xml-view-processing-instruction']); + if (node.nodeValue) { + this._setTitle( + ['', 'shadow-xml-view-processing-instruction']); + } return; } case 8: { // COMMENT @@ -372,7 +403,7 @@ export class XMLViewNode extends UI.TreeOutline.TreeElement { * @param {!Array.} items */ _setTitle(items) { - const titleFragment = createDocumentFragment(); + const titleFragment = document.createDocumentFragment(); for (let i = 0; i < items.length; i += 2) { titleFragment.createChild('span', items[i + 1]).textContent = items[i]; } @@ -403,7 +434,7 @@ export class XMLViewNode extends UI.TreeOutline.TreeElement { /** * @override - * @returns {!Promise} + * @returns {!Promise} */ async onpopulate() { XMLViewNode.populate(this, this._node, this._xmlView); diff --git a/front_end/sources/BUILD.gn b/front_end/sources/BUILD.gn index 26f6ecaa2a2..e02c8e8f563 100644 --- a/front_end/sources/BUILD.gn +++ b/front_end/sources/BUILD.gn @@ -30,7 +30,6 @@ devtools_module("sources") { "ScriptFormatterEditorAction.js", "ScriptOriginPlugin.js", "SearchSourcesView.js", - "SimpleHistoryManager.js", "SnippetsPlugin.js", "SourceMapNamesResolver.js", "SourcesNavigator.js", diff --git a/front_end/sources/DebuggerPlugin.js b/front_end/sources/DebuggerPlugin.js index 692bb4c407a..d3391a67540 100644 --- a/front_end/sources/DebuggerPlugin.js +++ b/front_end/sources/DebuggerPlugin.js @@ -28,9 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Bindings from '../bindings/bindings.js'; import * as Common from '../common/common.js'; import * as Host from '../host/host.js'; @@ -46,8 +43,19 @@ import * as Workspace from '../workspace/workspace.js'; import {AddSourceMapURLDialog} from './AddSourceMapURLDialog.js'; import {BreakpointEditDialog, LogpointPrefix} from './BreakpointEditDialog.js'; import {Plugin} from './Plugin.js'; +import {ScriptFormatterEditorAction} from './ScriptFormatterEditorAction.js'; import {resolveExpression, resolveScopeInObject} from './SourceMapNamesResolver.js'; import {SourcesPanel} from './SourcesPanel.js'; +import {EditorAction} from './SourcesView.js'; + +// eslint-disable-next-line no-unused-vars +class DecoratorWidget extends HTMLDivElement { + constructor() { + super(); + /** @type {!Map} */ + this.__nameToToken; + } +} export class DebuggerPlugin extends Plugin { /** @@ -64,6 +72,7 @@ export class DebuggerPlugin extends Plugin { /** @type {?Workspace.UISourceCode.UILocation} */ this._executionLocation = null; this._controlDown = false; + /** @type {?number} */ this._asyncStepInHoveredLine = 0; this._asyncStepInHovered = false; /** @type {?number} */ @@ -112,7 +121,7 @@ export class DebuggerPlugin extends Plugin { const breakpoints = this._lineBreakpointDecorations(selection.startLine) .map(decoration => decoration.breakpoint) .filter(breakpoint => !!breakpoint); - let breakpoint; + let breakpoint = null; if (breakpoints.length) { breakpoint = breakpoints[0]; } @@ -122,24 +131,23 @@ export class DebuggerPlugin extends Plugin { } }; UI.ShortcutRegistry.ShortcutRegistry.instance().addShortcutListener(this._textEditor.element, shortcutHandlers); - this._boundKeyDown = /** @type {function(!Event)} */ (this._onKeyDown.bind(this)); + this._boundKeyDown = /** @type {function(!Event): void} */ (this._onKeyDown.bind(this)); this._textEditor.element.addEventListener('keydown', this._boundKeyDown, true); - this._boundKeyUp = /** @type {function(!Event)} */ (this._onKeyUp.bind(this)); + this._boundKeyUp = /** @type {function(!Event): void} */ (this._onKeyUp.bind(this)); this._textEditor.element.addEventListener('keyup', this._boundKeyUp, true); - this._boundMouseMove = /** @type {function(!Event)} */ (this._onMouseMove.bind(this)); + this._boundMouseMove = /** @type {function(!Event): void} */ (this._onMouseMove.bind(this)); this._textEditor.element.addEventListener('mousemove', this._boundMouseMove, false); - this._boundMouseDown = /** @type {function(!Event)} */ (this._onMouseDown.bind(this)); + this._boundMouseDown = /** @type {function(!Event): void} */ (this._onMouseDown.bind(this)); this._textEditor.element.addEventListener('mousedown', this._boundMouseDown, true); - this._boundBlur = this._onBlur.bind(this); + this._boundBlur = /** @type {function(!Event): void} */ (this._onBlur.bind(this)); this._textEditor.element.addEventListener('focusout', this._boundBlur, false); - this._boundWheel = event => { - if (this._executionLocation && UI.KeyboardShortcut.KeyboardShortcut.eventHasCtrlOrMeta(event)) { - event.preventDefault(); - } - }; + this._boundWheel = /** @type {function(!Event): void} */ (this._onWheel.bind(this)); this._textEditor.element.addEventListener('wheel', this._boundWheel, true); - this._boundGutterClick = /** @type {function({data: *})} */ (this._handleGutterClick.bind(this)); + this._boundGutterClick = + /** @type {function(!Common.EventTarget.EventTargetEvent): void} */ (e => { + this._handleGutterClick(e); + }); this._textEditor.addEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, this._boundGutterClick, this); this._breakpointManager.addEventListener( @@ -169,9 +177,9 @@ export class DebuggerPlugin extends Plugin { .moduleSetting('skipContentScripts') .addChangeListener(this._showBlackboxInfobarIfNeeded, this); - /** @type {!Map.} */ + /** @type {!Map.} */ this._valueWidgets = new Map(); - /** @type {?Map} */ + /** @type {?Map} */ this._continueToLocationDecorations = null; UI.Context.Context.instance().addFlavorChangeListener(SDK.DebuggerModel.CallFrame, this._callFrameChanged, this); @@ -296,9 +304,10 @@ export class DebuggerPlugin extends Plugin { async populateLineGutterContextMenu(contextMenu, editorLineNumber) { const uiLocation = new Workspace.UISourceCode.UILocation(this._uiSourceCode, editorLineNumber, 0); this._scriptsPanel.appendUILocationItems(contextMenu, uiLocation); - const breakpoints = this._lineBreakpointDecorations(editorLineNumber) - .map(decoration => decoration.breakpoint) - .filter(breakpoint => !!breakpoint); + const breakpoints = + /** @type {!Array} */ (this._lineBreakpointDecorations(editorLineNumber) + .map(decoration => decoration.breakpoint) + .filter(breakpoint => !!breakpoint)); const hasOnlyJavaScript = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance() .scriptsForUISourceCode(this._uiSourceCode) .every(script => script.isJavaScript()); @@ -310,10 +319,10 @@ export class DebuggerPlugin extends Plugin { if (hasOnlyJavaScript) { contextMenu.debugSection().appendItem( Common.UIString.UIString('Add conditional breakpoint…'), - this._editBreakpointCondition.bind(this, editorLineNumber, null, null)); + () => this._editBreakpointCondition.bind(this, editorLineNumber, null, null, false /* preferLogpoint */)); contextMenu.debugSection().appendItem( ls`Add logpoint…`, - this._editBreakpointCondition.bind(this, editorLineNumber, null, null, true /* preferLogpoint */)); + () => this._editBreakpointCondition.bind(this, editorLineNumber, null, null, true /* preferLogpoint */)); contextMenu.debugSection().appendItem( Common.UIString.UIString('Never pause here'), this._createNewBreakpoint.bind(this, editorLineNumber, 'false', true)); @@ -322,14 +331,15 @@ export class DebuggerPlugin extends Plugin { const hasOneBreakpoint = breakpoints.length === 1; const removeTitle = hasOneBreakpoint ? Common.UIString.UIString('Remove breakpoint') : Common.UIString.UIString('Remove all breakpoints in line'); - contextMenu.debugSection().appendItem(removeTitle, () => breakpoints.map(breakpoint => breakpoint.remove())); + contextMenu.debugSection().appendItem(removeTitle, () => breakpoints.map(breakpoint => breakpoint.remove(false))); if (hasOneBreakpoint && hasOnlyJavaScript) { // Editing breakpoints only make sense for conditional breakpoints // and logpoints and both are currently only available for JavaScript // debugging. contextMenu.debugSection().appendItem( Common.UIString.UIString('Edit breakpoint…'), - this._editBreakpointCondition.bind(this, editorLineNumber, breakpoints[0], null)); + this._editBreakpointCondition.bind( + this, editorLineNumber, breakpoints[0], null, false /* preferLogpoint */)); } const hasEnabled = breakpoints.some(breakpoint => breakpoint.enabled()); if (hasEnabled) { @@ -351,7 +361,7 @@ export class DebuggerPlugin extends Plugin { * @param {!UI.ContextMenu.ContextMenu} contextMenu * @param {number} editorLineNumber * @param {number} editorColumnNumber - * @return {!Promise} + * @return {!Promise} */ populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber) { /** @@ -457,7 +467,7 @@ export class DebuggerPlugin extends Plugin { continue; } const enabled = decoration.enabled; - decoration.breakpoint.remove(); + decoration.breakpoint.remove(false); const location = decoration.handle.resolve(); if (location) { await this._setBreakpoint(location.lineNumber, location.columnNumber, decoration.condition, enabled); @@ -497,9 +507,9 @@ export class DebuggerPlugin extends Plugin { const mouseColumn = textPosition.startColumn; const textSelection = this._textEditor.selection().normalize(); let anchorBox; - let editorLineNumber; - let startHighlight; - let endHighlight; + let editorLineNumber = -1; + let startHighlight = -1; + let endHighlight = -1; const selectedCallFrame = /** @type {!SDK.DebuggerModel.CallFrame} */ (UI.Context.Context.instance().flavor(SDK.DebuggerModel.CallFrame)); @@ -517,6 +527,12 @@ export class DebuggerPlugin extends Plugin { const leftCorner = this._textEditor.cursorPositionToCoordinates(textSelection.startLine, textSelection.startColumn); const rightCorner = this._textEditor.cursorPositionToCoordinates(textSelection.endLine, textSelection.endColumn); + if (!leftCorner) { + throw new Error('Expected leftCorner to not be null.'); + } + if (!rightCorner) { + throw new Error('Expected rightCorner to not be null.'); + } anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); editorLineNumber = textSelection.startLine; startHighlight = textSelection.startColumn; @@ -528,6 +544,12 @@ export class DebuggerPlugin extends Plugin { } const leftCorner = this._textEditor.cursorPositionToCoordinates(textPosition.startLine, token.startColumn); const rightCorner = this._textEditor.cursorPositionToCoordinates(textPosition.startLine, token.endColumn - 1); + if (!leftCorner) { + throw new Error('Expected leftCorner to not be null.'); + } + if (!rightCorner) { + throw new Error('Expected rightCorner to not be null.'); + } anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); editorLineNumber = textPosition.startLine; startHighlight = token.startColumn; @@ -548,6 +570,12 @@ export class DebuggerPlugin extends Plugin { const leftCorner = this._textEditor.cursorPositionToCoordinates(editorLineNumber, token.startColumn); const rightCorner = this._textEditor.cursorPositionToCoordinates(editorLineNumber, token.endColumn - 1); + if (!leftCorner) { + throw new Error('Expected leftCorner to not be null.'); + } + if (!rightCorner) { + throw new Error('Expected rightCorner to not be null.'); + } anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); startHighlight = token.startColumn; @@ -579,13 +607,15 @@ export class DebuggerPlugin extends Plugin { } } + /** @type {?ObjectUI.ObjectPopoverHelper.ObjectPopoverHelper} */ let objectPopoverHelper; + /** @type {?Object} */ let highlightDescriptor; - /* + /** + * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode * @param {string} evaluationText - * @param {!Workspace.UISourceCode.UISourceCode} - * @return {!Promise} + * @return {!Promise} */ async function evaluate(uiSourceCode, evaluationText) { if (selectedCallFrame.script.isWasm()) { @@ -595,7 +625,7 @@ export class DebuggerPlugin extends Plugin { const object = await /** @type {!Bindings.DebuggerLanguagePlugins.SourceScope}*/ (scopeChain) .getVariableValue(evaluationText); if (object) { - return {object}; + return {object, exceptionDetails: undefined}; } } return null; @@ -610,7 +640,12 @@ export class DebuggerPlugin extends Plugin { includeCommandLineAPI: false, silent: true, returnByValue: false, - generatePreview: false + generatePreview: false, + throwOnSideEffect: undefined, + timeout: undefined, + disableBreaks: undefined, + replMode: undefined, + allowUnsafeEvalBlockedByCSP: undefined }); } @@ -620,7 +655,8 @@ export class DebuggerPlugin extends Plugin { const evaluationText = this._textEditor.line(editorLineNumber).substring(startHighlight, endHighlight + 1); const result = await evaluate(this._uiSourceCode, evaluationText); - if (!result || !result.object || (result.object.type === 'object' && result.object.subtype === 'error')) { + if (!result || 'error' in result || !result.object || + (result.object.type === 'object' && result.object.subtype === 'error')) { return false; } objectPopoverHelper = @@ -639,17 +675,30 @@ export class DebuggerPlugin extends Plugin { return true; }, hide: () => { - objectPopoverHelper.dispose(); + if (objectPopoverHelper) { + objectPopoverHelper.dispose(); + } debuggerModel.runtimeModel().releaseObjectGroup('popover'); - this._textEditor.removeHighlight(highlightDescriptor); + if (highlightDescriptor) { + this._textEditor.removeHighlight(highlightDescriptor); + } } }; } + /** + * @param {!WheelEvent} event + */ + _onWheel(event) { + if (this._executionLocation && UI.KeyboardShortcut.KeyboardShortcut.eventHasCtrlOrMeta(event)) { + event.preventDefault(); + } + } + /** * @param {!KeyboardEvent} event */ - async _onKeyDown(event) { + _onKeyDown(event) { if (!event.ctrlKey || (!event.metaKey && Host.Platform.isMac())) { this._clearControlDown(); } @@ -665,7 +714,7 @@ export class DebuggerPlugin extends Plugin { if (UI.KeyboardShortcut.KeyboardShortcut.eventHasCtrlOrMeta(event) && this._executionLocation) { this._controlDown = true; if (event.key === (Host.Platform.isMac() ? 'Meta' : 'Control')) { - this._controlTimeout = setTimeout(() => { + this._controlTimeout = window.setTimeout(() => { if (this._executionLocation && this._controlDown) { this._showContinueToLocations(); } @@ -685,8 +734,9 @@ export class DebuggerPlugin extends Plugin { } } if (this._continueToLocationDecorations) { + const target = /** @type {!Element} */ (event.target); const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y); - const hovering = !!event.target.enclosingNodeOrSelfWithClass('source-frame-async-step-in'); + const hovering = !!target.enclosingNodeOrSelfWithClass('source-frame-async-step-in'); this._setAsyncStepInHoveredLine(textPosition ? textPosition.startLine : null, hovering); } } @@ -730,7 +780,11 @@ export class DebuggerPlugin extends Plugin { continue; } if (range.from.ch <= textPosition.startColumn && textPosition.startColumn <= range.to.ch) { - this._continueToLocationDecorations.get(decoration)(); + const callback = this._continueToLocationDecorations.get(decoration); + if (!callback) { + throw new Error('Expected a function'); + } + callback(); break; } } @@ -753,7 +807,9 @@ export class DebuggerPlugin extends Plugin { _clearControlDown() { this._controlDown = false; this._clearContinueToLocations(); - clearTimeout(this._controlTimeout); + if (this._controlTimeout) { + clearTimeout(this._controlTimeout); + } } /** @@ -764,7 +820,7 @@ export class DebuggerPlugin extends Plugin { */ async _editBreakpointCondition(editorLineNumber, breakpoint, location, preferLogpoint) { const oldCondition = breakpoint ? breakpoint.condition() : ''; - const decorationElement = createElement('div'); + const decorationElement = document.createElement('div'); const dialog = new BreakpointEditDialog(editorLineNumber, oldCondition, !!preferLogpoint, async result => { dialog.detach(); this._textEditor.removeDecoration(decorationElement, editorLineNumber); @@ -859,14 +915,21 @@ export class DebuggerPlugin extends Plugin { let previousCallLine = -1; for (const location of locations) { const editorLocation = this._transformer.uiLocationToEditorLocation(location.lineNumber, location.columnNumber); - let token = this._textEditor.tokenAtTextPosition(editorLocation.lineNumber, editorLocation.columnNumber); - if (!token) { + const tokenThatIsPossiblyNull = + this._textEditor.tokenAtTextPosition(editorLocation.lineNumber, editorLocation.columnNumber); + if (!tokenThatIsPossiblyNull) { continue; } + let token = /** @type {!TextEditor.CodeMirrorTextEditor.Token} */ (tokenThatIsPossiblyNull); + const line = this._textEditor.line(editorLocation.lineNumber); let tokenContent = line.substring(token.startColumn, token.endColumn); if (!token.type && tokenContent === '.') { - token = this._textEditor.tokenAtTextPosition(editorLocation.lineNumber, token.endColumn + 1); + const nextToken = this._textEditor.tokenAtTextPosition(editorLocation.lineNumber, token.endColumn + 1); + if (!nextToken) { + throw new Error('nextToken should not be null.'); + } + token = nextToken; tokenContent = line.substring(token.startColumn, token.endColumn); } if (!token.type) { @@ -894,7 +957,11 @@ export class DebuggerPlugin extends Plugin { let isAsyncCall = (line[token.startColumn - 1] === '.' && tokenContent === 'then') || tokenContent === 'setTimeout' || tokenContent === 'setInterval' || tokenContent === 'postMessage'; if (tokenContent === 'new') { - token = this._textEditor.tokenAtTextPosition(editorLocation.lineNumber, token.endColumn + 1); + const nextToken = this._textEditor.tokenAtTextPosition(editorLocation.lineNumber, token.endColumn + 1); + if (!nextToken) { + throw new Error('nextToken should not be null.'); + } + token = nextToken; tokenContent = line.substring(token.startColumn, token.endColumn); isAsyncCall = tokenContent === 'Worker'; } @@ -929,7 +996,8 @@ export class DebuggerPlugin extends Plugin { * @return {?{from: number, to: number}} */ _findAsyncStepInRange(textEditor, editorLineNumber, line, column) { - let token; + /** @type {?TextEditor.CodeMirrorTextEditor.Token} */ + let token = null; let tokenText; let from = column; let to = line.length; @@ -946,7 +1014,7 @@ export class DebuggerPlugin extends Plugin { return null; } - nextToken(); + token = nextToken(); if (!token) { return null; } @@ -957,7 +1025,7 @@ export class DebuggerPlugin extends Plugin { if (position >= line.length) { return {from: from, to: to}; } - nextToken(); + token = nextToken(); if (!token) { return {from: from, to: to}; } @@ -991,6 +1059,8 @@ export class DebuggerPlugin extends Plugin { to = token.endColumn; tokenText = line.substring(token.startColumn, token.endColumn); } + + return token; } function skipWhitespace() { @@ -1000,6 +1070,9 @@ export class DebuggerPlugin extends Plugin { continue; } const token = textEditor.tokenAtTextPosition(editorLineNumber, position); + if (!token) { + throw new Error('expected token to not be null'); + } if (token.type === 'js-comment') { position = token.endColumn; continue; @@ -1142,10 +1215,16 @@ export class DebuggerPlugin extends Plugin { continue; } - const widget = document.createElement('div'); + const widget = /** @type {!DecoratorWidget} */ (document.createElement('div')); widget.classList.add('text-editor-value-decoration'); const base = this._textEditor.cursorPositionToCoordinates(i, 0); + if (!base) { + throw new Error('base is expected to not be null'); + } const offset = this._textEditor.cursorPositionToCoordinates(i, this._textEditor.line(i).length); + if (!offset) { + throw new Error('offset is expected to not be null'); + } const codeMirrorLinesLeftPadding = 4; const left = offset.x - base.x + codeMirrorLinesLeftPadding; widget.style.left = left + 'px'; @@ -1162,11 +1241,14 @@ export class DebuggerPlugin extends Plugin { if (renderedNameCount) { UI.UIUtils.createTextChild(widget, ', '); } - const nameValuePair = widget.createChild('span'); + const nameValuePair = /** @type {!HTMLElement} */ (widget.createChild('span')); widget.__nameToToken.set(infoId, nameValuePair); const info = infoMap.get(infoId); UI.UIUtils.createTextChild(nameValuePair, info.name + ' = '); const value = info.value; + if (!value) { + throw new Error('value is expected to be null'); + } const propertyCount = value.preview ? value.preview.properties.length : 0; const entryCount = value.preview && value.preview.entries ? value.preview.entries.length : 0; if (diracAngel.toggles.hasInlineCFs && value.customPreview()) { @@ -1186,8 +1268,10 @@ export class DebuggerPlugin extends Plugin { if (oldWidget) { widgetChanged = false; for (const name of widget.__nameToToken.keys()) { - const oldText = oldWidget.__nameToToken.get(name) ? oldWidget.__nameToToken.get(name).textContent : ''; - const newText = widget.__nameToToken.get(name) ? widget.__nameToToken.get(name).textContent : ''; + const oldTextElement = oldWidget.__nameToToken.get(name); + const newTextElement = widget.__nameToToken.get(name); + const oldText = oldTextElement ? oldTextElement.textContent : ''; + const newText = newTextElement ? newTextElement.textContent : ''; if (newText !== oldText) { widgetChanged = true; // value has changed, update it. @@ -1217,28 +1301,34 @@ export class DebuggerPlugin extends Plugin { clearTimeout(this._clearValueWidgetsTimer); this._clearValueWidgetsTimer = null; } - this._clearValueWidgetsTimer = setTimeout(this._clearValueWidgets.bind(this), 1000); + this._clearValueWidgetsTimer = window.setTimeout(this._clearValueWidgets.bind(this), 1000); this._clearContinueToLocationsNoRestore(); }); } _clearValueWidgets() { - clearTimeout(this._clearValueWidgetsTimer); + if (this._clearValueWidgetsTimer) { + clearTimeout(this._clearValueWidgetsTimer); + } this._clearValueWidgetsTimer = null; this._textEditor.operation(() => { for (const line of this._valueWidgets.keys()) { - this._textEditor.removeDecoration(this._valueWidgets.get(line), line); + const valueWidget = this._valueWidgets.get(line); + if (valueWidget) { + this._textEditor.removeDecoration(valueWidget, line); + } } this._valueWidgets.clear(); }); } _clearContinueToLocationsNoRestore() { - if (!this._continueToLocationDecorations) { + const continueToLocationDecorations = this._continueToLocationDecorations; + if (!continueToLocationDecorations) { return; } this._textEditor.operation(() => { - for (const decoration of this._continueToLocationDecorations.keys()) { + for (const decoration of continueToLocationDecorations.keys()) { this._textEditor.removeHighlight(decoration); } this._continueToLocationDecorations = null; @@ -1394,7 +1484,7 @@ export class DebuggerPlugin extends Plugin { /** * @param {!BreakpointDecoration} decoration - * @param {!Event} event + * @param {!MouseEvent} event */ async _inlineBreakpointClick(decoration, event) { event.consume(true); @@ -1402,7 +1492,7 @@ export class DebuggerPlugin extends Plugin { if (event.shiftKey) { decoration.breakpoint.setEnabled(!decoration.breakpoint.enabled()); } else { - decoration.breakpoint.remove(); + decoration.breakpoint.remove(false); } } else { const editorLocation = decoration.handle.resolve(); @@ -1442,11 +1532,13 @@ export class DebuggerPlugin extends Plugin { if (decoration.breakpoint) { contextMenu.debugSection().appendItem( Common.UIString.UIString('Edit breakpoint…'), - this._editBreakpointCondition.bind(this, editorLocation.lineNumber, decoration.breakpoint, null)); + this._editBreakpointCondition.bind( + this, editorLocation.lineNumber, decoration.breakpoint, null, false /* preferLogpoint */)); } else { contextMenu.debugSection().appendItem( Common.UIString.UIString('Add conditional breakpoint…'), - this._editBreakpointCondition.bind(this, editorLocation.lineNumber, null, editorLocation)); + this._editBreakpointCondition.bind( + this, editorLocation.lineNumber, null, editorLocation, false /* preferLogpoint */)); contextMenu.debugSection().appendItem( ls`Add logpoint…`, this._editBreakpointCondition.bind( @@ -1695,15 +1787,16 @@ export class DebuggerPlugin extends Plugin { return; } - const editorActions = await Root.Runtime.Runtime.instance().allInstances(Sources.SourcesView.EditorAction); + const editorActions = await Root.Runtime.Runtime.instance().allInstances(EditorAction); + /** @type {(function(): void) | null} */ let formatterCallback = null; for (const editorAction of editorActions) { - if (editorAction instanceof Sources.ScriptFormatterEditorAction) { + if (editorAction instanceof ScriptFormatterEditorAction) { // Check if the source code is formattable the same way the pretty print button does if (!editorAction.isCurrentUISourceCodeFormatable()) { return; } - formatterCallback = editorAction.toggleFormatScriptSource.bind(editorAction); + formatterCallback = () => editorAction.toggleFormatScriptSource.bind(editorAction); break; } } @@ -1768,12 +1861,13 @@ export class DebuggerPlugin extends Plugin { return; } const hasDisabled = this._textEditor.hasLineClass(editorLineNumber, 'cm-breakpoint-disabled'); - const breakpoints = decorations.map(decoration => decoration.breakpoint).filter(breakpoint => !!breakpoint); + const breakpoints = /** @type {!Array} */ ( + decorations.map(decoration => decoration.breakpoint).filter(breakpoint => !!breakpoint)); for (const breakpoint of breakpoints) { if (onlyDisable) { breakpoint.setEnabled(hasDisabled); } else { - breakpoint.remove(); + breakpoint.remove(false); } } } @@ -1897,7 +1991,7 @@ export class DebuggerPlugin extends Plugin { */ export class BreakpointDecoration { /** - * @param {!TextEditor.CodeMirrorTextEditor.CodeMirrorTextEditor} textEditor + * @param {!SourceFrame.SourcesTextEditor.SourcesTextEditor} textEditor * @param {!TextEditor.CodeMirrorTextEditor.TextEditorPositionHandle} handle * @param {string} condition * @param {boolean} enabled @@ -1954,6 +2048,7 @@ export class BreakpointDecoration { } this.bookmark = this._textEditor.addBookmark( editorLocation.lineNumber, editorLocation.columnNumber, this.element, BreakpointDecoration.bookmarkSymbol); + // @ts-ignore Only used for layout tests this.bookmark[BreakpointDecoration._elementSymbolForTest] = this.element; } diff --git a/front_end/sources/EditingLocationHistoryManager.js b/front_end/sources/EditingLocationHistoryManager.js index eb0cc432f0b..8bf4e0e0aa0 100644 --- a/front_end/sources/EditingLocationHistoryManager.js +++ b/front_end/sources/EditingLocationHistoryManager.js @@ -33,7 +33,6 @@ import * as SourceFrame from '../source_frame/source_frame.js'; import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars import * as Workspace from '../workspace/workspace.js'; // eslint-disable-line no-unused-vars -import {HistoryEntry, SimpleHistoryManager} from './SimpleHistoryManager.js'; // eslint-disable-line no-unused-vars import {SourcesView} from './SourcesView.js'; // eslint-disable-line no-unused-vars import {UISourceCodeFrame} from './UISourceCodeFrame.js'; // eslint-disable-line no-unused-vars @@ -47,7 +46,7 @@ export class EditingLocationHistoryManager { */ constructor(sourcesView, currentSourceFrameCallback) { this._sourcesView = sourcesView; - this._historyManager = new SimpleHistoryManager(HistoryDepth); + this._historyManager = new Common.SimpleHistoryManager.SimpleHistoryManager(HistoryDepth); this._currentSourceFrameCallback = currentSourceFrameCallback; } @@ -137,7 +136,7 @@ export class EditingLocationHistoryManager { export const HistoryDepth = 20; /** - * @implements {HistoryEntry} + * @implements {Common.SimpleHistoryManager.HistoryEntry} * @unrestricted */ export class EditingLocationHistoryEntry { diff --git a/front_end/sources/FilteredUISourceCodeListProvider.js b/front_end/sources/FilteredUISourceCodeListProvider.js index 2fb9ab7e35d..08c94716434 100644 --- a/front_end/sources/FilteredUISourceCodeListProvider.js +++ b/front_end/sources/FilteredUISourceCodeListProvider.js @@ -18,8 +18,10 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg this._defaultScores = null; this._scorer = new FilePathScoreFunction(''); - /** @type {!Array.} */ + /** @type {!Array} */ this._uiSourceCodes = []; + /** @type {!Set} */ + this._uiSourceCodeUrls = new Set(); /** @type {string} */ this._query; @@ -39,13 +41,16 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg */ _populate(skipProject) { this._uiSourceCodes = []; - const projects = Workspace.Workspace.WorkspaceImpl.instance().projects().filter(this.filterProject.bind(this)); - for (let i = 0; i < projects.length; ++i) { - if (skipProject && projects[i] === skipProject) { - continue; + this._uiSourceCodeUrls.clear(); + for (const project of Workspace.Workspace.WorkspaceImpl.instance().projects()) { + if (project !== skipProject && this.filterProject(project)) { + for (const uiSourceCode of project.uiSourceCodes()) { + if (this._filterUISourceCode(uiSourceCode)) { + this._uiSourceCodes.push(uiSourceCode); + this._uiSourceCodeUrls.add(uiSourceCode.url()); + } + } } - const uiSourceCodes = projects[i].uiSourceCodes().filter(this._filterUISourceCode.bind(this)); - this._uiSourceCodes = this._uiSourceCodes.concat(uiSourceCodes); } } @@ -54,6 +59,9 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg * @return {boolean} */ _filterUISourceCode(uiSourceCode) { + if (this._uiSourceCodeUrls.has(uiSourceCode.url())) { + return false; + } const binding = Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode); return !binding || binding.fileSystem === uiSourceCode; } @@ -229,6 +237,7 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg return; } this._uiSourceCodes.push(uiSourceCode); + this._uiSourceCodeUrls.add(uiSourceCode.url()); this.refresh(); } diff --git a/front_end/sources/GutterDiffPlugin.js b/front_end/sources/GutterDiffPlugin.js index 321c61272ac..b44f59491b9 100644 --- a/front_end/sources/GutterDiffPlugin.js +++ b/front_end/sources/GutterDiffPlugin.js @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Diff from '../diff/diff.js'; // eslint-disable-line no-unused-vars import * as Persistence from '../persistence/persistence.js'; @@ -18,7 +15,7 @@ import {Plugin} from './Plugin.js'; export class GutterDiffPlugin extends Plugin { /** - * @param {!TextEditor.CodeMirrorTextEditor.CodeMirrorTextEditor} textEditor + * @param {!SourceFrame.SourcesTextEditor.SourcesTextEditor} textEditor * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode */ constructor(textEditor, uiSourceCode) { @@ -132,6 +129,12 @@ export class GutterDiffPlugin extends Plugin { const rightKey = rightKeys[rightIndex]; const left = oldDecorations.get(leftKey); const right = decorations.get(rightKey); + if (!left) { + throw new Error(`No decoration with key ${leftKey}`); + } + if (!right) { + throw new Error(`No decoration with key ${rightKey}`); + } if (leftKey === rightKey && left.type === right.type) { equal.push(left); ++leftIndex; @@ -146,11 +149,19 @@ export class GutterDiffPlugin extends Plugin { } while (leftIndex < leftKeys.length) { const leftKey = leftKeys[leftIndex++]; - removed.push(oldDecorations.get(leftKey)); + const left = oldDecorations.get(leftKey); + if (!left) { + throw new Error(`No decoration with key ${leftKey}`); + } + removed.push(left); } while (rightIndex < rightKeys.length) { const rightKey = rightKeys[rightIndex++]; - added.push(decorations.get(rightKey)); + const right = decorations.get(rightKey); + if (!right) { + throw new Error(`No decoration with key ${rightKey}`); + } + added.push(right); } return {added: added, removed: removed, equal: equal}; } @@ -165,7 +176,7 @@ export class GutterDiffPlugin extends Plugin { * @override * @param {!UI.ContextMenu.ContextMenu} contextMenu * @param {number} lineNumber - * @return {!Promise} + * @return {!Promise} */ async populateLineGutterContextMenu(contextMenu, lineNumber) { GutterDiffPlugin._appendRevealDiffContextMenu(contextMenu, this._uiSourceCode); @@ -176,12 +187,16 @@ export class GutterDiffPlugin extends Plugin { * @param {!UI.ContextMenu.ContextMenu} contextMenu * @param {number} lineNumber * @param {number} columnNumber - * @return {!Promise} + * @return {!Promise} */ async populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) { GutterDiffPlugin._appendRevealDiffContextMenu(contextMenu, this._uiSourceCode); } + /** + * @param {!UI.ContextMenu.ContextMenu} contextMenu + * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode + */ static _appendRevealDiffContextMenu(contextMenu, uiSourceCode) { if (!WorkspaceDiff.WorkspaceDiff.workspaceDiff().isUISourceCodeModified(uiSourceCode)) { return; @@ -204,7 +219,7 @@ export class GutterDiffPlugin extends Plugin { export class GutterDecoration { /** - * @param {!TextEditor.CodeMirrorTextEditor.CodeMirrorTextEditor} textEditor + * @param {!SourceFrame.SourcesTextEditor.SourcesTextEditor} textEditor * @param {number} lineNumber * @param {!SourceFrame.SourceCodeDiff.EditType} type */ diff --git a/front_end/sources/SourceMapNamesResolver.js b/front_end/sources/SourceMapNamesResolver.js index a39b422abe1..31774933566 100644 --- a/front_end/sources/SourceMapNamesResolver.js +++ b/front_end/sources/SourceMapNamesResolver.js @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Bindings from '../bindings/bindings.js'; import * as Formatter from '../formatter/formatter.js'; +import * as Platform from '../platform/platform.js'; import * as SDK from '../sdk/sdk.js'; import * as TextUtils from '../text_utils/text_utils.js'; import * as Workspace from '../workspace/workspace.js'; // eslint-disable-line no-unused-vars -export const cachedMapSymbol = Symbol('cache'); -export const cachedIdentifiersSymbol = Symbol('cachedIdentifiers'); +/** @type {!WeakMap>>} */ +const scopeToCachedIdentifiersMap = new WeakMap(); +/** @type {!WeakMap>} */ +const cachedMapBycallFrame = new WeakMap(); /** * @unrestricted */ @@ -65,22 +65,20 @@ export class Mapping extends Array { export const scopeIdentifiers = function(scope) { const startLocation = scope.startLocation(); const endLocation = scope.endLocation(); - - if (scope.type() === Protocol.Debugger.ScopeType.Global || !startLocation || !endLocation || - !startLocation.script() || !startLocation.script().sourceMapURL || - (startLocation.script() !== endLocation.script())) { + const startLocationScript = startLocation ? startLocation.script() : null; + if (scope.type() === Protocol.Debugger.ScopeType.Global || !startLocationScript || !endLocation || + !startLocationScript.sourceMapURL || (startLocationScript !== endLocation.script())) { return Promise.resolve(/** @type {!Array}*/ ([])); } - const script = startLocation.script(); - return script.requestContent().then(onContent); + return startLocationScript.requestContent().then(onContent); /** * @param {!TextUtils.ContentProvider.DeferredContent} deferredContent * @return {!Promise>} */ function onContent(deferredContent) { - if (!deferredContent.content) { + if (!deferredContent.content || !startLocation || !endLocation) { return Promise.resolve(/** @type {!Array}*/ ([])); } @@ -124,7 +122,7 @@ export const scopeIdentifiers = function(scope) { * @return {!Promise} */ export const resolveScope = function(scope) { - let identifiersPromise = scope[cachedIdentifiersSymbol]; + let identifiersPromise = scopeToCachedIdentifiersMap.get(scope); if (identifiersPromise) { return identifiersPromise; } @@ -138,7 +136,7 @@ export const resolveScope = function(scope) { /** @type {!Map} */ const textCache = new Map(); identifiersPromise = scopeIdentifiers(scope).then(onIdentifiers); - scope[cachedIdentifiersSymbol] = identifiersPromise; + scopeToCachedIdentifiersMap.set(scope, identifiersPromise); return identifiersPromise; /** @@ -151,6 +149,9 @@ export const resolveScope = function(scope) { // Extract as much as possible from SourceMap. for (let i = 0; i < identifiers.length; ++i) { const id = identifiers[i]; + if (!sourceMap) { + continue; + } const entry = sourceMap.findEntry(id.lineNumber, id.columnNumber); if (entry && entry.name) { const compiled = new NameDescriptor(id.name, id.lineNumber, id.columnNumber); @@ -188,8 +189,8 @@ export const resolveScope = function(scope) { * @return {!Promise} */ function resolveSourceName(id) { - const startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber); - const endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.name.length); + const startEntry = sourceMap ? sourceMap.findEntry(id.lineNumber, id.columnNumber) : null; + const endEntry = sourceMap ? sourceMap.findEntry(id.lineNumber, id.columnNumber + id.name.length) : null; if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sourceURL !== endEntry.sourceURL || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber) { @@ -240,7 +241,7 @@ export const resolveScope = function(scope) { * @return {!Promise} */ export const allVariablesInCallFrame = function(callFrame) { - const cached = callFrame[cachedMapSymbol]; + const cached = cachedMapBycallFrame.get(callFrame); if (cached) { return Promise.resolve(cached); } @@ -428,14 +429,14 @@ export const resolveThisObject = function(callFrame) { const compiledName = thisRecords[0].compiledNameDescriptor.name; return callFrame - .evaluate({ + .evaluate(/** @type {!SDK.RuntimeModel.EvaluationOptions} */ ({ expression: compiledName, objectGroup: 'backtrace', includeCommandLineAPI: false, silent: true, returnByValue: false, generatePreview: true - }) + })) .then(onEvaluated); } @@ -444,7 +445,10 @@ export const resolveThisObject = function(callFrame) { * @return {?SDK.RemoteObject.RemoteObject} */ function onEvaluated(result) { - return !result.exceptionDetails && result.object ? result.object : callFrame.thisObject(); + if ('exceptionDetails' in result && callFrame) { + return !result.exceptionDetails && result.object ? result.object : callFrame.thisObject(); + } + return null; } }; @@ -455,10 +459,10 @@ export const resolveThisObject = function(callFrame) { export const resolveScopeInObject = function(scope) { const startLocation = scope.startLocation(); const endLocation = scope.endLocation(); + const startLocationScript = startLocation ? startLocation.script() : null; - if (scope.type() === Protocol.Debugger.ScopeType.Global || !startLocation || !endLocation || - !startLocation.script() || !startLocation.script().sourceMapURL || - startLocation.script() !== endLocation.script()) { + if (scope.type() === Protocol.Debugger.ScopeType.Global || !startLocationScript || !endLocation || + !startLocationScript.sourceMapURL || startLocationScript !== endLocation.script()) { return scope.object(); } @@ -632,9 +636,10 @@ export class RemoteObject extends SDK.RemoteObject.RemoteObject { /** * @override - * @param {function(this:Object, ...)} functionDeclaration + * @param {function(this:Object, ...?):T} functionDeclaration * @param {!Array=} args * @return {!Promise} + * @template T */ callFunction(functionDeclaration, args) { return this._object.callFunction(functionDeclaration, args); @@ -643,7 +648,7 @@ export class RemoteObject extends SDK.RemoteObject.RemoteObject { /** * @override - * @param {function(this:Object, ...):T} functionDeclaration + * @param {function(this:Object, ...?):T} functionDeclaration * @param {!Array|undefined} args * @return {!Promise} * @template T @@ -683,3 +688,23 @@ export class RemoteObject extends SDK.RemoteObject.RemoteObject { return this._object.isNode(); } } + +/** + * @type {function(...*):*} scope + */ +let _scopeResolvedForTest = function() {}; + + +/** + * @return {function(...*):*} scope + */ +export const getScopeResolvedForTest = () => { + return _scopeResolvedForTest; +}; + +/** + * @param {function(...*):*} scope + */ +export const setScopeResolvedForTest = scope => { + _scopeResolvedForTest = scope; +}; diff --git a/front_end/sources/module.json b/front_end/sources/module.json index 458e6231ab3..bba9a36199f 100644 --- a/front_end/sources/module.json +++ b/front_end/sources/module.json @@ -1145,7 +1145,6 @@ "BreakpointEditDialog.js", "CallStackSidebarPane.js", "DebuggerPausedMessage.js", - "SimpleHistoryManager.js", "EditingLocationHistoryManager.js", "FilePathScoreFunction.js", "FilteredUISourceCodeListProvider.js", diff --git a/front_end/sources/sources-legacy.js b/front_end/sources/sources-legacy.js index 3ee26d580d2..b03d5fc8f0d 100644 --- a/front_end/sources/sources-legacy.js +++ b/front_end/sources/sources-legacy.js @@ -150,22 +150,19 @@ Sources.SearchSourcesView = SourcesModule.SearchSourcesView.SearchSourcesView; /** @constructor */ Sources.SearchSourcesView.ActionDelegate = SourcesModule.SearchSourcesView.ActionDelegate; -/** @constructor */ -Sources.SimpleHistoryManager = SourcesModule.SimpleHistoryManager.SimpleHistoryManager; - -/** @interface */ -Sources.HistoryEntry = SourcesModule.SimpleHistoryManager.HistoryEntry; - /** @constructor */ Sources.SnippetsPlugin = SourcesModule.SnippetsPlugin.SnippetsPlugin; Sources.SourceMapNamesResolver = {}; +Sources.SourceMapNamesResolver.setScopeResolvedForTest = SourcesModule.SourceMapNamesResolver.setScopeResolvedForTest; + // Tests can override this global symbol and therefore can't be exported -Sources.SourceMapNamesResolver._scopeResolvedForTest = function() {}; +Object.defineProperty(Sources.SourceMapNamesResolver, '_scopeResolvedForTest', { + get: SourcesModule.SourceMapNamesResolver.getScopeResolvedForTest, + set: SourcesModule.SourceMapNamesResolver.setScopeResolvedForTest, +}); -Sources.SourceMapNamesResolver._cachedMapSymbol = SourcesModule.SourceMapNamesResolver.cachedMapSymbol; -Sources.SourceMapNamesResolver._cachedIdentifiersSymbol = SourcesModule.SourceMapNamesResolver.cachedIdentifiersSymbol; Sources.SourceMapNamesResolver._scopeIdentifiers = SourcesModule.SourceMapNamesResolver.scopeIdentifiers; Sources.SourceMapNamesResolver._resolveScope = SourcesModule.SourceMapNamesResolver.resolveScope; Sources.SourceMapNamesResolver._allVariablesInCallFrame = SourcesModule.SourceMapNamesResolver.allVariablesInCallFrame; diff --git a/front_end/sources/sources.js b/front_end/sources/sources.js index 73a4db102ab..add4dba771d 100644 --- a/front_end/sources/sources.js +++ b/front_end/sources/sources.js @@ -25,7 +25,6 @@ import * as ScopeChainSidebarPane from './ScopeChainSidebarPane.js'; import * as ScriptFormatterEditorAction from './ScriptFormatterEditorAction.js'; import * as ScriptOriginPlugin from './ScriptOriginPlugin.js'; import * as SearchSourcesView from './SearchSourcesView.js'; -import * as SimpleHistoryManager from './SimpleHistoryManager.js'; import * as SnippetsPlugin from './SnippetsPlugin.js'; import * as SourceMapNamesResolver from './SourceMapNamesResolver.js'; import * as SourcesNavigator from './SourcesNavigator.js'; @@ -61,7 +60,6 @@ export { ScriptFormatterEditorAction, ScriptOriginPlugin, SearchSourcesView, - SimpleHistoryManager, SnippetsPlugin, SourceMapNamesResolver, SourcesNavigator, diff --git a/front_end/sources_test_runner/SourcesTestRunner.js b/front_end/sources_test_runner/SourcesTestRunner.js index 6c8316abcbf..0139708b902 100644 --- a/front_end/sources_test_runner/SourcesTestRunner.js +++ b/front_end/sources_test_runner/SourcesTestRunner.js @@ -164,7 +164,11 @@ SourcesTestRunner.dumpSwatchPositions = function(sourceFrame, bookmarkType) { for (let i = 0; i < markers.length; i++) { const position = markers[i].position(); - const text = markers[i]._marker.widgetNode.firstChild.textContent; + const swatch = markers[i]._marker.widgetNode.firstChild; + let text = swatch.textContent; + if (swatch.localName === 'devtools-color-swatch') { + text = swatch.color.asString(swatch.format); + } TestRunner.addResult('Line ' + position.startLine + ', Column ' + position.startColumn + ': ' + text); } }; diff --git a/front_end/text_editor/CodeMirrorTextEditor.js b/front_end/text_editor/CodeMirrorTextEditor.js index ad21946e4ef..3550c19ba21 100644 --- a/front_end/text_editor/CodeMirrorTextEditor.js +++ b/front_end/text_editor/CodeMirrorTextEditor.js @@ -40,6 +40,22 @@ import * as UI from '../ui/ui.js'; import {changeObjectToEditOperation, toPos, toRange} from './CodeMirrorUtils.js'; import {TextEditorAutocompleteController} from './TextEditorAutocompleteController.js'; +/** + * @typedef {{ +* startColumn: number, +* endColumn: number, +* type: string +* }} +*/ +// @ts-ignore typedef +export let Token; + +/** + * @typedef {{x: number, y: number, height: number}} + */ +// @ts-ignore typedef +export let Coordinates; + /** * @implements {UI.TextEditor.TextEditor} * @unrestricted @@ -661,7 +677,7 @@ export class CodeMirrorTextEditor extends UI.Widget.VBox { /** * @param {number} lineNumber * @param {number} column - * @return {?{x: number, y: number, height: number}} + * @return {?Coordinates} */ cursorPositionToCoordinates(lineNumber, column) { if (lineNumber >= this._codeMirror.lineCount() || lineNumber < 0 || column < 0 || @@ -706,7 +722,7 @@ export class CodeMirrorTextEditor extends UI.Widget.VBox { * @override * @param {number} lineNumber * @param {number} columnNumber - * @return {?{startColumn: number, endColumn: number, type: string}} + * @return {?Token} */ tokenAtTextPosition(lineNumber, columnNumber) { if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount()) { diff --git a/front_end/theme_support/theme_support_impl.js b/front_end/theme_support/theme_support_impl.js index 0e34d5917a1..372810874a6 100644 --- a/front_end/theme_support/theme_support_impl.js +++ b/front_end/theme_support/theme_support_impl.js @@ -29,9 +29,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @ts-nocheck -// TODO(crbug.com/1011811): Enable TypeScript compiler checks - import * as Common from '../common/common.js'; import * as Platform from '../platform/platform.js'; import * as Root from '../root/root.js'; @@ -137,13 +134,13 @@ export class ThemeSupport { if (!content) { console.error(cssFile + ' not preloaded. Check module.json'); } - let styleElement = createElement('style'); + let styleElement = document.createElement('style'); styleElement.textContent = content; node.appendChild(styleElement); const themeStyleSheet = ThemeSupport.instance().themeStyleSheet(cssFile, content); if (themeStyleSheet) { - styleElement = createElement('style'); + styleElement = document.createElement('style'); styleElement.textContent = themeStyleSheet + '\n' + Root.Runtime.Runtime.resolveSourceURL(cssFile + '.theme'); node.appendChild(styleElement); } @@ -193,7 +190,7 @@ export class ThemeSupport { if (!href) { continue; } - result.push(this._patchForTheme(href, styleSheets[i])); + result.push(this._patchForTheme(href, /** @type {!CSSStyleSheet} */ (styleSheets[i]))); } result.push('/*# sourceURL=inspector.css.theme */'); @@ -231,7 +228,7 @@ export class ThemeSupport { /** * @param {string} id - * @param {!StyleSheet} styleSheet + * @param {!CSSStyleSheet} styleSheet * @return {string} */ _patchForTheme(id, styleSheet) { @@ -244,19 +241,25 @@ export class ThemeSupport { const rules = styleSheet.cssRules; const result = []; for (let j = 0; j < rules.length; ++j) { - if (rules[j] instanceof CSSImportRule) { - result.push(this._patchForTheme(rules[j].styleSheet.href, rules[j].styleSheet)); + const rule = rules[j]; + if (rule instanceof CSSImportRule) { + result.push(this._patchForTheme(rule.styleSheet.href || '', rule.styleSheet)); continue; } + + if (!(rule instanceof CSSStyleRule)) { + continue; + } + /** @type {!Array} */ const output = []; - const style = rules[j].style; - const selectorText = rules[j].selectorText; + const style = rule.style; + const selectorText = rule.selectorText; for (let i = 0; style && i < style.length; ++i) { this._patchProperty(selectorText, style, style[i], output); } if (output.length) { - result.push(rules[j].selectorText + '{' + output.join('') + '}'); + result.push(rule.selectorText + '{' + output.join('') + '}'); } } diff --git a/front_end/third_party/puppeteer/BUILD.gn b/front_end/third_party/puppeteer/BUILD.gn index d62e1dd413c..a843eacf486 100644 --- a/front_end/third_party/puppeteer/BUILD.gn +++ b/front_end/third_party/puppeteer/BUILD.gn @@ -13,9 +13,18 @@ devtools_pre_built("puppeteer") { "package/lib/esm/puppeteer/common/Accessibility.d.ts", "package/lib/esm/puppeteer/common/Accessibility.d.ts.map", "package/lib/esm/puppeteer/common/Accessibility.js", + "package/lib/esm/puppeteer/common/AriaQueryHandler.d.ts", + "package/lib/esm/puppeteer/common/AriaQueryHandler.d.ts.map", + "package/lib/esm/puppeteer/common/AriaQueryHandler.js", "package/lib/esm/puppeteer/common/Browser.d.ts", "package/lib/esm/puppeteer/common/Browser.d.ts.map", "package/lib/esm/puppeteer/common/Browser.js", + "package/lib/esm/puppeteer/common/BrowserConnector.d.ts", + "package/lib/esm/puppeteer/common/BrowserConnector.d.ts.map", + "package/lib/esm/puppeteer/common/BrowserConnector.js", + "package/lib/esm/puppeteer/common/BrowserWebSocketTransport.d.ts", + "package/lib/esm/puppeteer/common/BrowserWebSocketTransport.d.ts.map", + "package/lib/esm/puppeteer/common/BrowserWebSocketTransport.js", "package/lib/esm/puppeteer/common/Connection.d.ts", "package/lib/esm/puppeteer/common/Connection.d.ts.map", "package/lib/esm/puppeteer/common/Connection.js", @@ -88,6 +97,9 @@ devtools_pre_built("puppeteer") { "package/lib/esm/puppeteer/common/Page.d.ts", "package/lib/esm/puppeteer/common/Page.d.ts.map", "package/lib/esm/puppeteer/common/Page.js", + "package/lib/esm/puppeteer/common/Product.d.ts", + "package/lib/esm/puppeteer/common/Product.d.ts.map", + "package/lib/esm/puppeteer/common/Product.js", "package/lib/esm/puppeteer/common/Puppeteer.d.ts", "package/lib/esm/puppeteer/common/Puppeteer.d.ts.map", "package/lib/esm/puppeteer/common/Puppeteer.js", @@ -112,30 +124,33 @@ devtools_pre_built("puppeteer") { "package/lib/esm/puppeteer/common/USKeyboardLayout.d.ts", "package/lib/esm/puppeteer/common/USKeyboardLayout.d.ts.map", "package/lib/esm/puppeteer/common/USKeyboardLayout.js", - "package/lib/esm/puppeteer/common/WebSocketTransport.d.ts", - "package/lib/esm/puppeteer/common/WebSocketTransport.d.ts.map", - "package/lib/esm/puppeteer/common/WebSocketTransport.js", "package/lib/esm/puppeteer/common/WebWorker.d.ts", "package/lib/esm/puppeteer/common/WebWorker.d.ts.map", "package/lib/esm/puppeteer/common/WebWorker.js", "package/lib/esm/puppeteer/common/assert.d.ts", "package/lib/esm/puppeteer/common/assert.d.ts.map", "package/lib/esm/puppeteer/common/assert.js", + "package/lib/esm/puppeteer/common/fetch.d.ts", + "package/lib/esm/puppeteer/common/fetch.d.ts.map", + "package/lib/esm/puppeteer/common/fetch.js", "package/lib/esm/puppeteer/common/helper.d.ts", "package/lib/esm/puppeteer/common/helper.d.ts.map", "package/lib/esm/puppeteer/common/helper.js", "package/lib/esm/puppeteer/environment.d.ts", "package/lib/esm/puppeteer/environment.d.ts.map", "package/lib/esm/puppeteer/environment.js", - "package/lib/esm/puppeteer/index-core.d.ts", - "package/lib/esm/puppeteer/index-core.d.ts.map", - "package/lib/esm/puppeteer/index-core.js", - "package/lib/esm/puppeteer/index.d.ts", - "package/lib/esm/puppeteer/index.d.ts.map", - "package/lib/esm/puppeteer/index.js", - "package/lib/esm/puppeteer/initialize.d.ts", - "package/lib/esm/puppeteer/initialize.d.ts.map", - "package/lib/esm/puppeteer/initialize.js", + "package/lib/esm/puppeteer/initialize-node.d.ts", + "package/lib/esm/puppeteer/initialize-node.d.ts.map", + "package/lib/esm/puppeteer/initialize-node.js", + "package/lib/esm/puppeteer/initialize-web.d.ts", + "package/lib/esm/puppeteer/initialize-web.d.ts.map", + "package/lib/esm/puppeteer/initialize-web.js", + "package/lib/esm/puppeteer/node-puppeteer-core.d.ts", + "package/lib/esm/puppeteer/node-puppeteer-core.d.ts.map", + "package/lib/esm/puppeteer/node-puppeteer-core.js", + "package/lib/esm/puppeteer/node.d.ts", + "package/lib/esm/puppeteer/node.d.ts.map", + "package/lib/esm/puppeteer/node.js", "package/lib/esm/puppeteer/node/BrowserFetcher.d.ts", "package/lib/esm/puppeteer/node/BrowserFetcher.d.ts.map", "package/lib/esm/puppeteer/node/BrowserFetcher.js", @@ -148,12 +163,24 @@ devtools_pre_built("puppeteer") { "package/lib/esm/puppeteer/node/Launcher.d.ts", "package/lib/esm/puppeteer/node/Launcher.d.ts.map", "package/lib/esm/puppeteer/node/Launcher.js", + "package/lib/esm/puppeteer/node/NodeWebSocketTransport.d.ts", + "package/lib/esm/puppeteer/node/NodeWebSocketTransport.d.ts.map", + "package/lib/esm/puppeteer/node/NodeWebSocketTransport.js", "package/lib/esm/puppeteer/node/PipeTransport.d.ts", "package/lib/esm/puppeteer/node/PipeTransport.d.ts.map", "package/lib/esm/puppeteer/node/PipeTransport.js", + "package/lib/esm/puppeteer/node/Puppeteer.d.ts", + "package/lib/esm/puppeteer/node/Puppeteer.d.ts.map", + "package/lib/esm/puppeteer/node/Puppeteer.js", + "package/lib/esm/puppeteer/node/install.d.ts", + "package/lib/esm/puppeteer/node/install.d.ts.map", + "package/lib/esm/puppeteer/node/install.js", "package/lib/esm/puppeteer/revisions.d.ts", "package/lib/esm/puppeteer/revisions.d.ts.map", "package/lib/esm/puppeteer/revisions.js", + "package/lib/esm/puppeteer/web.d.ts", + "package/lib/esm/puppeteer/web.d.ts.map", + "package/lib/esm/puppeteer/web.js", "package/lib/esm/vendor/mitt/src/index.d.ts", "package/lib/esm/vendor/mitt/src/index.d.ts.map", "package/lib/esm/vendor/mitt/src/index.js", diff --git a/front_end/third_party/puppeteer/package/LICENSE b/front_end/third_party/puppeteer/package/LICENSE index afdfe50e72e..d2c171df74e 100644 --- a/front_end/third_party/puppeteer/package/LICENSE +++ b/front_end/third_party/puppeteer/package/LICENSE @@ -1,7 +1,7 @@ Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -193,7 +193,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/front_end/third_party/puppeteer/package/README.md b/front_end/third_party/puppeteer/package/README.md index a7e87358942..82467c0ee3c 100644 --- a/front_end/third_party/puppeteer/package/README.md +++ b/front_end/third_party/puppeteer/package/README.md @@ -6,7 +6,7 @@ -###### [API](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) +###### [API](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) > Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium. @@ -37,7 +37,7 @@ npm i puppeteer # or "yarn add puppeteer" ``` -Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#environment-variables). +Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#environment-variables). ### puppeteer-core @@ -63,7 +63,7 @@ Note: Prior to v1.18.1, Puppeteer required at least Node v6.4.0. Versions from v Node 8.9.0+. Starting from v3.0.0 Puppeteer starts to rely on Node 10.18.1+. All examples below use async/await which is only supported in Node v7.6.0 or greater. Puppeteer will be familiar to people using other browser testing frameworks. You create an instance -of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#). +of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#). **Example** - navigating to https://example.com and saving a screenshot as *example.png*: @@ -88,7 +88,7 @@ Execute script on the command line node example.js ``` -Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#pagesetviewportviewport). +Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#pagesetviewportviewport). **Example** - create a PDF. @@ -113,7 +113,7 @@ Execute script on the command line node hn.js ``` -See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#pagepdfoptions) for more information about creating pdfs. +See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#pagepdfoptions) for more information about creating pdfs. **Example** - evaluate script in the context of the page @@ -148,7 +148,7 @@ Execute script on the command line node get-dimensions.js ``` -See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. +See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. @@ -157,7 +157,7 @@ See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/ **1. Uses Headless mode** -Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#puppeteerlaunchoptions) when launching a browser: +Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#puppeteerlaunchoptions) when launching a browser: ```js const browser = await puppeteer.launch({headless: false}); // default is true @@ -173,7 +173,7 @@ pass in the executable's path when creating a `Browser` instance: const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'}); ``` -You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#puppeteerlaunchoptions) for more information. +You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#puppeteerlaunchoptions) for more information. See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. @@ -185,7 +185,7 @@ Puppeteer creates its own browser user profile which it **cleans up on every run ## Resources -- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md) +- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md) - [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples/) - [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer) @@ -328,7 +328,7 @@ See [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING Official Firefox support is currently experimental. The ongoing collaboration with Mozilla aims to support common end-to-end testing use cases, for which developers expect cross-browser coverage. The Puppeteer team needs input from users to stabilize Firefox support and to bring missing APIs to our attention. -From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. +From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari. This effort includes exploration of a standard for executing cross-browser commands (instead of relying on the non-standard DevTools Protocol used by Chrome). @@ -424,7 +424,7 @@ await page.evaluate(() => { You may find that Puppeteer does not behave as expected when controlling pages that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this: -* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) +* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) * Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming). #### Q: I am having trouble installing / running Puppeteer in my test environment. Where should I look for help? diff --git a/front_end/third_party/puppeteer/package/cjs-entry-core.js b/front_end/third_party/puppeteer/package/cjs-entry-core.js index 70e9b88040f..446726fafa3 100644 --- a/front_end/third_party/puppeteer/package/cjs-entry-core.js +++ b/front_end/third_party/puppeteer/package/cjs-entry-core.js @@ -25,5 +25,5 @@ * This means that we can publish to CJS and ESM whilst maintaining the expected * import behaviour for CJS and ESM users. */ -const puppeteerExport = require('./lib/cjs/puppeteer/index-core'); +const puppeteerExport = require('./lib/cjs/puppeteer/node-puppeteer-core'); module.exports = puppeteerExport.default; diff --git a/front_end/third_party/puppeteer/package/cjs-entry.js b/front_end/third_party/puppeteer/package/cjs-entry.js index 1bcec7d85af..d1840a9bea1 100644 --- a/front_end/third_party/puppeteer/package/cjs-entry.js +++ b/front_end/third_party/puppeteer/package/cjs-entry.js @@ -25,5 +25,5 @@ * This means that we can publish to CJS and ESM whilst maintaining the expected * import behaviour for CJS and ESM users. */ -const puppeteerExport = require('./lib/cjs/puppeteer/index'); +const puppeteerExport = require('./lib/cjs/puppeteer/node'); module.exports = puppeteerExport.default; diff --git a/front_end/third_party/puppeteer/package/install.js b/front_end/third_party/puppeteer/package/install.js index 5fe1314e4a6..11518a595f5 100644 --- a/front_end/third_party/puppeteer/package/install.js +++ b/front_end/third_party/puppeteer/package/install.js @@ -32,7 +32,7 @@ async function download() { const { downloadBrowser, logPolitely, - } = require('./lib/cjs/puppeteer/install'); + } = require('./lib/cjs/puppeteer/node/install'); if (process.env.PUPPETEER_SKIP_DOWNLOAD) { logPolitely( diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.d.ts deleted file mode 100644 index 4fca5db7228..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export * from './common/Accessibility.js'; -export * from './common/Browser.js'; -export * from './node/BrowserFetcher.js'; -export * from './common/Connection.js'; -export * from './common/ConsoleMessage.js'; -export * from './common/Coverage.js'; -export * from './common/DeviceDescriptors.js'; -export * from './common/Dialog.js'; -export * from './common/DOMWorld.js'; -export * from './common/JSHandle.js'; -export * from './common/ExecutionContext.js'; -export * from './common/EventEmitter.js'; -export * from './common/FileChooser.js'; -export * from './common/FrameManager.js'; -export * from './common/Input.js'; -export * from './common/Page.js'; -export * from './common/Puppeteer.js'; -export * from './node/LaunchOptions.js'; -export * from './node/Launcher.js'; -export * from './common/HTTPRequest.js'; -export * from './common/HTTPResponse.js'; -export * from './common/SecurityDetails.js'; -export * from './common/Target.js'; -export * from './common/Errors.js'; -export * from './common/Tracing.js'; -export * from './common/NetworkManager.js'; -export * from './common/WebWorker.js'; -export * from './common/USKeyboardLayout.js'; -export * from './common/EvalTypes.js'; -export * from './common/PDFOptions.js'; -export * from './common/TimeoutSettings.js'; -export * from './common/LifecycleWatcher.js'; -export * from 'devtools-protocol/types/protocol'; -//# sourceMappingURL=api-docs-entry.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.d.ts.map deleted file mode 100644 index 1e462ec6c80..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"api-docs-entry.d.ts","sourceRoot":"","sources":["../../../src/api-docs-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.js deleted file mode 100644 index c98190a29e7..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api-docs-entry.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -/* - * This file re-exports any APIs that we want to have documentation generated - * for. It is used by API Extractor to determine what parts of the system to - * document. - * - * We also have src/api.ts. This is used in `index.js` and by the legacy DocLint - * system. src/api-docs-entry.ts is ONLY used by API Extractor. - * - * Once we have migrated to API Extractor and removed DocLint we can remove the - * duplication and use this file. - */ -__exportStar(require("./common/Accessibility.js"), exports); -__exportStar(require("./common/Browser.js"), exports); -__exportStar(require("./node/BrowserFetcher.js"), exports); -__exportStar(require("./common/Connection.js"), exports); -__exportStar(require("./common/ConsoleMessage.js"), exports); -__exportStar(require("./common/Coverage.js"), exports); -__exportStar(require("./common/DeviceDescriptors.js"), exports); -__exportStar(require("./common/Dialog.js"), exports); -__exportStar(require("./common/DOMWorld.js"), exports); -__exportStar(require("./common/JSHandle.js"), exports); -__exportStar(require("./common/ExecutionContext.js"), exports); -__exportStar(require("./common/EventEmitter.js"), exports); -__exportStar(require("./common/FileChooser.js"), exports); -__exportStar(require("./common/FrameManager.js"), exports); -__exportStar(require("./common/Input.js"), exports); -__exportStar(require("./common/Page.js"), exports); -__exportStar(require("./common/Puppeteer.js"), exports); -__exportStar(require("./node/LaunchOptions.js"), exports); -__exportStar(require("./node/Launcher.js"), exports); -__exportStar(require("./common/HTTPRequest.js"), exports); -__exportStar(require("./common/HTTPResponse.js"), exports); -__exportStar(require("./common/SecurityDetails.js"), exports); -__exportStar(require("./common/Target.js"), exports); -__exportStar(require("./common/Errors.js"), exports); -__exportStar(require("./common/Tracing.js"), exports); -__exportStar(require("./common/NetworkManager.js"), exports); -__exportStar(require("./common/WebWorker.js"), exports); -__exportStar(require("./common/USKeyboardLayout.js"), exports); -__exportStar(require("./common/EvalTypes.js"), exports); -__exportStar(require("./common/PDFOptions.js"), exports); -__exportStar(require("./common/TimeoutSettings.js"), exports); -__exportStar(require("./common/LifecycleWatcher.js"), exports); -__exportStar(require("devtools-protocol/types/protocol"), exports); diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.d.ts deleted file mode 100644 index 736b3b54394..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.d.ts +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Copyright 2018 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { CDPSession } from './Connection.js'; -import { ElementHandle } from './JSHandle.js'; -/** - * Represents a Node and the properties of it that are relevant to Accessibility. - * @public - */ -export interface SerializedAXNode { - /** - * The {@link https://www.w3.org/TR/wai-aria/#usage_intro | role} of the node. - */ - role: string; - /** - * A human readable name for the node. - */ - name?: string; - /** - * The current value of the node. - */ - value?: string | number; - /** - * An additional human readable description of the node. - */ - description?: string; - /** - * Any keyboard shortcuts associated with this node. - */ - keyshortcuts?: string; - /** - * A human readable alternative to the role. - */ - roledescription?: string; - /** - * A description of the current value. - */ - valuetext?: string; - disabled?: boolean; - expanded?: boolean; - focused?: boolean; - modal?: boolean; - multiline?: boolean; - /** - * Whether more than one child can be selected. - */ - multiselectable?: boolean; - readonly?: boolean; - required?: boolean; - selected?: boolean; - /** - * Whether the checkbox is checked, or in a - * {@link https://www.w3.org/TR/wai-aria-practices/examples/checkbox/checkbox-2/checkbox-2.html | mixed state}. - */ - checked?: boolean | 'mixed'; - /** - * Whether the node is checked or in a mixed state. - */ - pressed?: boolean | 'mixed'; - /** - * The level of a heading. - */ - level?: number; - valuemin?: number; - valuemax?: number; - autocomplete?: string; - haspopup?: string; - /** - * Whether and in what way this node's value is invalid. - */ - invalid?: string; - orientation?: string; - /** - * Children of this node, if there are any. - */ - children?: SerializedAXNode[]; -} -/** - * @public - */ -export interface SnapshotOptions { - /** - * Prune unintersting nodes from the tree. - * @defaultValue true - */ - interestingOnly?: boolean; - /** - * Prune unintersting nodes from the tree. - * @defaultValue The root node of the entire page. - */ - root?: ElementHandle; -} -/** - * The Accessibility class provides methods for inspecting Chromium's - * accessibility tree. The accessibility tree is used by assistive technology - * such as {@link https://en.wikipedia.org/wiki/Screen_reader | screen readers} or - * {@link https://en.wikipedia.org/wiki/Switch_access | switches}. - * - * @remarks - * - * Accessibility is a very platform-specific thing. On different platforms, - * there are different screen readers that might have wildly different output. - * - * Blink - Chrome's rendering engine - has a concept of "accessibility tree", - * which is then translated into different platform-specific APIs. Accessibility - * namespace gives users access to the Blink Accessibility Tree. - * - * Most of the accessibility tree gets filtered out when converting from Blink - * AX Tree to Platform-specific AX-Tree or by assistive technologies themselves. - * By default, Puppeteer tries to approximate this filtering, exposing only - * the "interesting" nodes of the tree. - * - * @public - */ -export declare class Accessibility { - private _client; - /** - * @internal - */ - constructor(client: CDPSession); - /** - * Captures the current state of the accessibility tree. - * The returned object represents the root accessible node of the page. - * - * @remarks - * - * **NOTE** The Chromium accessibility tree contains nodes that go unused on - * most platforms and by most screen readers. Puppeteer will discard them as - * well for an easier to process tree, unless `interestingOnly` is set to - * `false`. - * - * @example - * An example of dumping the entire accessibility tree: - * ```js - * const snapshot = await page.accessibility.snapshot(); - * console.log(snapshot); - * ``` - * - * @example - * An example of logging the focused node's name: - * ```js - * const snapshot = await page.accessibility.snapshot(); - * const node = findFocusedNode(snapshot); - * console.log(node && node.name); - * - * function findFocusedNode(node) { - * if (node.focused) - * return node; - * for (const child of node.children || []) { - * const foundNode = findFocusedNode(child); - * return foundNode; - * } - * return null; - * } - * ``` - * - * @returns An AXNode object representing the snapshot. - * - */ - snapshot(options?: SnapshotOptions): Promise; - private serializeTree; - private collectInterestingNodes; -} -//# sourceMappingURL=Accessibility.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.d.ts.map deleted file mode 100644 index 09e4537815d..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Accessibility.d.ts","sourceRoot":"","sources":["../../../../src/common/Accessibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAa;IAE5B;;OAEG;gBACS,MAAM,EAAE,UAAU;IAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACU,QAAQ,CACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IA0B5B,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,uBAAuB;CAWhC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.js deleted file mode 100644 index 03dff902668..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Accessibility.js +++ /dev/null @@ -1,360 +0,0 @@ -"use strict"; -/** - * Copyright 2018 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Accessibility = void 0; -/** - * The Accessibility class provides methods for inspecting Chromium's - * accessibility tree. The accessibility tree is used by assistive technology - * such as {@link https://en.wikipedia.org/wiki/Screen_reader | screen readers} or - * {@link https://en.wikipedia.org/wiki/Switch_access | switches}. - * - * @remarks - * - * Accessibility is a very platform-specific thing. On different platforms, - * there are different screen readers that might have wildly different output. - * - * Blink - Chrome's rendering engine - has a concept of "accessibility tree", - * which is then translated into different platform-specific APIs. Accessibility - * namespace gives users access to the Blink Accessibility Tree. - * - * Most of the accessibility tree gets filtered out when converting from Blink - * AX Tree to Platform-specific AX-Tree or by assistive technologies themselves. - * By default, Puppeteer tries to approximate this filtering, exposing only - * the "interesting" nodes of the tree. - * - * @public - */ -class Accessibility { - /** - * @internal - */ - constructor(client) { - this._client = client; - } - /** - * Captures the current state of the accessibility tree. - * The returned object represents the root accessible node of the page. - * - * @remarks - * - * **NOTE** The Chromium accessibility tree contains nodes that go unused on - * most platforms and by most screen readers. Puppeteer will discard them as - * well for an easier to process tree, unless `interestingOnly` is set to - * `false`. - * - * @example - * An example of dumping the entire accessibility tree: - * ```js - * const snapshot = await page.accessibility.snapshot(); - * console.log(snapshot); - * ``` - * - * @example - * An example of logging the focused node's name: - * ```js - * const snapshot = await page.accessibility.snapshot(); - * const node = findFocusedNode(snapshot); - * console.log(node && node.name); - * - * function findFocusedNode(node) { - * if (node.focused) - * return node; - * for (const child of node.children || []) { - * const foundNode = findFocusedNode(child); - * return foundNode; - * } - * return null; - * } - * ``` - * - * @returns An AXNode object representing the snapshot. - * - */ - async snapshot(options = {}) { - const { interestingOnly = true, root = null } = options; - const { nodes } = await this._client.send('Accessibility.getFullAXTree'); - let backendNodeId = null; - if (root) { - const { node } = await this._client.send('DOM.describeNode', { - objectId: root._remoteObject.objectId, - }); - backendNodeId = node.backendNodeId; - } - const defaultRoot = AXNode.createTree(nodes); - let needle = defaultRoot; - if (backendNodeId) { - needle = defaultRoot.find((node) => node.payload.backendDOMNodeId === backendNodeId); - if (!needle) - return null; - } - if (!interestingOnly) - return this.serializeTree(needle)[0]; - const interestingNodes = new Set(); - this.collectInterestingNodes(interestingNodes, defaultRoot, false); - if (!interestingNodes.has(needle)) - return null; - return this.serializeTree(needle, interestingNodes)[0]; - } - serializeTree(node, whitelistedNodes) { - const children = []; - for (const child of node.children) - children.push(...this.serializeTree(child, whitelistedNodes)); - if (whitelistedNodes && !whitelistedNodes.has(node)) - return children; - const serializedNode = node.serialize(); - if (children.length) - serializedNode.children = children; - return [serializedNode]; - } - collectInterestingNodes(collection, node, insideControl) { - if (node.isInteresting(insideControl)) - collection.add(node); - if (node.isLeafNode()) - return; - insideControl = insideControl || node.isControl(); - for (const child of node.children) - this.collectInterestingNodes(collection, child, insideControl); - } -} -exports.Accessibility = Accessibility; -class AXNode { - constructor(payload) { - this.children = []; - this._richlyEditable = false; - this._editable = false; - this._focusable = false; - this._hidden = false; - this.payload = payload; - this._name = this.payload.name ? this.payload.name.value : ''; - this._role = this.payload.role ? this.payload.role.value : 'Unknown'; - for (const property of this.payload.properties || []) { - if (property.name === 'editable') { - this._richlyEditable = property.value.value === 'richtext'; - this._editable = true; - } - if (property.name === 'focusable') - this._focusable = property.value.value; - if (property.name === 'hidden') - this._hidden = property.value.value; - } - } - _isPlainTextField() { - if (this._richlyEditable) - return false; - if (this._editable) - return true; - return (this._role === 'textbox' || - this._role === 'ComboBox' || - this._role === 'searchbox'); - } - _isTextOnlyObject() { - const role = this._role; - return role === 'LineBreak' || role === 'text' || role === 'InlineTextBox'; - } - _hasFocusableChild() { - if (this._cachedHasFocusableChild === undefined) { - this._cachedHasFocusableChild = false; - for (const child of this.children) { - if (child._focusable || child._hasFocusableChild()) { - this._cachedHasFocusableChild = true; - break; - } - } - } - return this._cachedHasFocusableChild; - } - find(predicate) { - if (predicate(this)) - return this; - for (const child of this.children) { - const result = child.find(predicate); - if (result) - return result; - } - return null; - } - isLeafNode() { - if (!this.children.length) - return true; - // These types of objects may have children that we use as internal - // implementation details, but we want to expose them as leaves to platform - // accessibility APIs because screen readers might be confused if they find - // any children. - if (this._isPlainTextField() || this._isTextOnlyObject()) - return true; - // Roles whose children are only presentational according to the ARIA and - // HTML5 Specs should be hidden from screen readers. - // (Note that whilst ARIA buttons can have only presentational children, HTML5 - // buttons are allowed to have content.) - switch (this._role) { - case 'doc-cover': - case 'graphics-symbol': - case 'img': - case 'Meter': - case 'scrollbar': - case 'slider': - case 'separator': - case 'progressbar': - return true; - default: - break; - } - // Here and below: Android heuristics - if (this._hasFocusableChild()) - return false; - if (this._focusable && this._name) - return true; - if (this._role === 'heading' && this._name) - return true; - return false; - } - isControl() { - switch (this._role) { - case 'button': - case 'checkbox': - case 'ColorWell': - case 'combobox': - case 'DisclosureTriangle': - case 'listbox': - case 'menu': - case 'menubar': - case 'menuitem': - case 'menuitemcheckbox': - case 'menuitemradio': - case 'radio': - case 'scrollbar': - case 'searchbox': - case 'slider': - case 'spinbutton': - case 'switch': - case 'tab': - case 'textbox': - case 'tree': - return true; - default: - return false; - } - } - isInteresting(insideControl) { - const role = this._role; - if (role === 'Ignored' || this._hidden) - return false; - if (this._focusable || this._richlyEditable) - return true; - // If it's not focusable but has a control role, then it's interesting. - if (this.isControl()) - return true; - // A non focusable child of a control is not interesting - if (insideControl) - return false; - return this.isLeafNode() && !!this._name; - } - serialize() { - const properties = new Map(); - for (const property of this.payload.properties || []) - properties.set(property.name.toLowerCase(), property.value.value); - if (this.payload.name) - properties.set('name', this.payload.name.value); - if (this.payload.value) - properties.set('value', this.payload.value.value); - if (this.payload.description) - properties.set('description', this.payload.description.value); - const node = { - role: this._role, - }; - const userStringProperties = [ - 'name', - 'value', - 'description', - 'keyshortcuts', - 'roledescription', - 'valuetext', - ]; - const getUserStringPropertyValue = (key) => properties.get(key); - for (const userStringProperty of userStringProperties) { - if (!properties.has(userStringProperty)) - continue; - node[userStringProperty] = getUserStringPropertyValue(userStringProperty); - } - const booleanProperties = [ - 'disabled', - 'expanded', - 'focused', - 'modal', - 'multiline', - 'multiselectable', - 'readonly', - 'required', - 'selected', - ]; - const getBooleanPropertyValue = (key) => properties.get(key); - for (const booleanProperty of booleanProperties) { - // WebArea's treat focus differently than other nodes. They report whether - // their frame has focus, not whether focus is specifically on the root - // node. - if (booleanProperty === 'focused' && this._role === 'WebArea') - continue; - const value = getBooleanPropertyValue(booleanProperty); - if (!value) - continue; - node[booleanProperty] = getBooleanPropertyValue(booleanProperty); - } - const tristateProperties = ['checked', 'pressed']; - for (const tristateProperty of tristateProperties) { - if (!properties.has(tristateProperty)) - continue; - const value = properties.get(tristateProperty); - node[tristateProperty] = - value === 'mixed' ? 'mixed' : value === 'true' ? true : false; - } - const numericalProperties = [ - 'level', - 'valuemax', - 'valuemin', - ]; - const getNumericalPropertyValue = (key) => properties.get(key); - for (const numericalProperty of numericalProperties) { - if (!properties.has(numericalProperty)) - continue; - node[numericalProperty] = getNumericalPropertyValue(numericalProperty); - } - const tokenProperties = [ - 'autocomplete', - 'haspopup', - 'invalid', - 'orientation', - ]; - const getTokenPropertyValue = (key) => properties.get(key); - for (const tokenProperty of tokenProperties) { - const value = getTokenPropertyValue(tokenProperty); - if (!value || value === 'false') - continue; - node[tokenProperty] = getTokenPropertyValue(tokenProperty); - } - return node; - } - static createTree(payloads) { - const nodeById = new Map(); - for (const payload of payloads) - nodeById.set(payload.nodeId, new AXNode(payload)); - for (const node of nodeById.values()) { - for (const childId of node.payload.childIds || []) - node.children.push(nodeById.get(childId)); - } - return nodeById.values().next().value; - } -} diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.d.ts deleted file mode 100644 index 43df72baf69..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.d.ts +++ /dev/null @@ -1,424 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/// -import { ChildProcess } from 'child_process'; -import { Protocol } from 'devtools-protocol'; - -import { Connection } from './Connection.js'; -import { EventEmitter } from './EventEmitter.js'; -import { Page } from './Page.js'; -import { Viewport } from './PuppeteerViewport.js'; -import { Target } from './Target.js'; - -declare type BrowserCloseCallback = () => Promise | void; -/** - * @public - */ -export interface WaitForTargetOptions { - /** - * Maximum wait time in milliseconds. Pass `0` to disable the timeout. - * @defaultValue 30 seconds. - */ - timeout?: number; -} -/** - * All the events a {@link Browser | browser instance} may emit. - * - * @public - */ -export declare const enum BrowserEmittedEvents { - /** - * Emitted when Puppeteer gets disconnected from the Chromium instance. This - * might happen because of one of the following: - * - * - Chromium is closed or crashed - * - * - The {@link Browser.disconnect | browser.disconnect } method was called. - */ - Disconnected = "disconnected", - /** - * Emitted when the url of a target changes. Contains a {@link Target} instance. - * - * @remarks - * - * Note that this includes target changes in incognito browser contexts. - */ - TargetChanged = "targetchanged", - /** - * Emitted when a target is created, for example when a new page is opened by - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open | window.open} - * or by {@link Browser.newPage | browser.newPage} - * - * Contains a {@link Target} instance. - * - * @remarks - * - * Note that this includes target creations in incognito browser contexts. - */ - TargetCreated = "targetcreated", - /** - * Emitted when a target is destroyed, for example when a page is closed. - * Contains a {@link Target} instance. - * - * @remarks - * - * Note that this includes target destructions in incognito browser contexts. - */ - TargetDestroyed = "targetdestroyed" -} -/** - * A Browser is created when Puppeteer connects to a Chromium instance, either through - * {@link Puppeteer.launch} or {@link Puppeteer.connect}. - * - * @remarks - * - * The Browser class extends from Puppeteer's {@link EventEmitter} class and will - * emit various events which are documented in the {@link BrowserEmittedEvents} enum. - * - * @example - * - * An example of using a {@link Browser} to create a {@link Page}: - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * await page.goto('https://example.com'); - * await browser.close(); - * })(); - * ``` - * - * @example - * - * An example of disconnecting from and reconnecting to a {@link Browser}: - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * // Store the endpoint to be able to reconnect to Chromium - * const browserWSEndpoint = browser.wsEndpoint(); - * // Disconnect puppeteer from Chromium - * browser.disconnect(); - * - * // Use the endpoint to reestablish a connection - * const browser2 = await puppeteer.connect({browserWSEndpoint}); - * // Close Chromium - * await browser2.close(); - * })(); - * ``` - * - * @public - */ -export declare class Browser extends EventEmitter { - /** - * @internal - */ - static create(connection: Connection, contextIds: string[], ignoreHTTPSErrors: boolean, defaultViewport?: Viewport, process?: ChildProcess, closeCallback?: BrowserCloseCallback): Promise; - private _ignoreHTTPSErrors; - private _defaultViewport?; - private _process?; - private _connection; - private _closeCallback; - private _defaultContext; - private _contexts; - /** - * @internal - * Used in Target.ts directly so cannot be marked private. - */ - _targets: Map; - /** - * @internal - */ - constructor(connection: Connection, contextIds: string[], ignoreHTTPSErrors: boolean, defaultViewport?: Viewport, process?: ChildProcess, closeCallback?: BrowserCloseCallback); - /** - * The spawned browser process. Returns `null` if the browser instance was created with - * {@link Puppeteer.connect}. - */ - process(): ChildProcess | null; - /** - * Creates a new incognito browser context. This won't share cookies/cache with other - * browser contexts. - * - * @example - * ```js - * (async () => { - * const browser = await puppeteer.launch(); - * // Create a new incognito browser context. - * const context = await browser.createIncognitoBrowserContext(); - * // Create a new page in a pristine context. - * const page = await context.newPage(); - * // Do stuff - * await page.goto('https://example.com'); - * })(); - * ``` - */ - createIncognitoBrowserContext(): Promise; - /** - * Returns an array of all open browser contexts. In a newly created browser, this will - * return a single instance of {@link BrowserContext}. - */ - browserContexts(): BrowserContext[]; - /** - * Returns the default browser context. The default browser context cannot be closed. - */ - defaultBrowserContext(): BrowserContext; - /** - * @internal - * Used by BrowserContext directly so cannot be marked private. - */ - _disposeContext(contextId?: string): Promise; - private _targetCreated; - private _targetDestroyed; - private _targetInfoChanged; - /** - * The browser websocket endpoint which can be used as an argument to - * {@link Puppeteer.connect}. - * - * @returns The Browser websocket url. - * - * @remarks - * - * The format is `ws://${host}:${port}/devtools/browser/`. - * - * You can find the `webSocketDebuggerUrl` from `http://${host}:${port}/json/version`. - * Learn more about the - * {@link https://chromedevtools.github.io/devtools-protocol | devtools protocol} and - * the {@link - * https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target - * | browser endpoint}. - */ - wsEndpoint(): string; - /** - * Creates a {@link Page} in the default browser context. - */ - newPage(): Promise; - /** - * @internal - * Used by BrowserContext directly so cannot be marked private. - */ - _createPageInContext(contextId?: string): Promise; - /** - * All active targets inside the Browser. In case of multiple browser contexts, returns - * an array with all the targets in all browser contexts. - */ - targets(): Target[]; - /** - * The target associated with the browser. - */ - target(): Target; - /** - * Searches for a target in all browser contexts. - * - * @param predicate - A function to be run for every target. - * @returns The first target found that matches the `predicate` function. - * - * @example - * - * An example of finding a target for a page opened via `window.open`: - * ```js - * await page.evaluate(() => window.open('https://www.example.com/')); - * const newWindowTarget = await browser.waitForTarget(target => target.url() === 'https://www.example.com/'); - * ``` - */ - waitForTarget(predicate: (x: Target) => boolean, options?: WaitForTargetOptions): Promise; - /** - * An array of all open pages inside the Browser. - * - * @remarks - * - * In case of multiple browser contexts, returns an array with all the pages in all - * browser contexts. Non-visible pages, such as `"background_page"`, will not be listed - * here. You can find them using {@link Target.page}. - */ - pages(): Promise; - /** - * A string representing the browser name and version. - * - * @remarks - * - * For headless Chromium, this is similar to `HeadlessChrome/61.0.3153.0`. For - * non-headless, this is similar to `Chrome/61.0.3153.0`. - * - * The format of browser.version() might change with future releases of Chromium. - */ - version(): Promise; - /** - * The browser's original user agent. Pages can override the browser user agent with - * {@link Page.setUserAgent}. - */ - userAgent(): Promise; - /** - * Closes Chromium and all of its pages (if any were opened). The {@link Browser} object - * itself is considered to be disposed and cannot be used anymore. - */ - close(): Promise; - /** - * Disconnects Puppeteer from the browser, but leaves the Chromium process running. - * After calling `disconnect`, the {@link Browser} object is considered disposed and - * cannot be used anymore. - */ - disconnect(): void; - /** - * Indicates that the browser is connected. - */ - isConnected(): boolean; - private _getVersion; -} -export declare const enum BrowserContextEmittedEvents { - /** - * Emitted when the url of a target inside the browser context changes. - * Contains a {@link Target} instance. - */ - TargetChanged = "targetchanged", - /** - * Emitted when a target is created within the browser context, for example - * when a new page is opened by - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open | window.open} - * or by {@link BrowserContext.newPage | browserContext.newPage} - * - * Contains a {@link Target} instance. - */ - TargetCreated = "targetcreated", - /** - * Emitted when a target is destroyed within the browser context, for example - * when a page is closed. Contains a {@link Target} instance. - */ - TargetDestroyed = "targetdestroyed" -} -/** - * BrowserContexts provide a way to operate multiple independent browser - * sessions. When a browser is launched, it has a single BrowserContext used by - * default. The method {@link Browser.newPage | Browser.newPage} creates a page - * in the default browser context. - * - * @remarks - * - * The Browser class extends from Puppeteer's {@link EventEmitter} class and - * will emit various events which are documented in the - * {@link BrowserContextEmittedEvents} enum. - * - * If a page opens another page, e.g. with a `window.open` call, the popup will - * belong to the parent page's browser context. - * - * Puppeteer allows creation of "incognito" browser contexts with - * {@link Browser.createIncognitoBrowserContext | Browser.createIncognitoBrowserContext} - * method. "Incognito" browser contexts don't write any browsing data to disk. - * - * @example - * ```js - * // Create a new incognito browser context - * const context = await browser.createIncognitoBrowserContext(); - * // Create a new page inside context. - * const page = await context.newPage(); - * // ... do stuff with page ... - * await page.goto('https://example.com'); - * // Dispose context once it's no longer needed. - * await context.close(); - * ``` - */ -export declare class BrowserContext extends EventEmitter { - private _connection; - private _browser; - private _id?; - /** - * @internal - */ - constructor(connection: Connection, browser: Browser, contextId?: string); - /** - * An array of all active targets inside the browser context. - */ - targets(): Target[]; - /** - * This searches for a target in this specific browser context. - * - * @example - * An example of finding a target for a page opened via `window.open`: - * ```js - * await page.evaluate(() => window.open('https://www.example.com/')); - * const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/'); - * ``` - * - * @param predicate - A function to be run for every target - * @param options - An object of options. Accepts a timout, - * which is the maximum wait time in milliseconds. - * Pass `0` to disable the timeout. Defaults to 30 seconds. - * @returns Promise which resolves to the first target found - * that matches the `predicate` function. - */ - waitForTarget(predicate: (x: Target) => boolean, options?: { - timeout?: number; - }): Promise; - /** - * An array of all pages inside the browser context. - * - * @returns Promise which resolves to an array of all open pages. - * Non visible pages, such as `"background_page"`, will not be listed here. - * You can find them using {@link Target.page | the target page}. - */ - pages(): Promise; - /** - * Returns whether BrowserContext is incognito. - * The default browser context is the only non-incognito browser context. - * - * @remarks - * The default browser context cannot be closed. - */ - isIncognito(): boolean; - /** - * @example - * ```js - * const context = browser.defaultBrowserContext(); - * await context.overridePermissions('https://html5demos.com', ['geolocation']); - * ``` - * - * @param origin - The origin to grant permissions to, e.g. "https://example.com". - * @param permissions - An array of permissions to grant. - * All permissions that are not listed here will be automatically denied. - */ - overridePermissions(origin: string, permissions: Protocol.Browser.PermissionType[]): Promise; - /** - * Clears all permission overrides for the browser context. - * - * @example - * ```js - * const context = browser.defaultBrowserContext(); - * context.overridePermissions('https://example.com', ['clipboard-read']); - * // do stuff .. - * context.clearPermissionOverrides(); - * ``` - */ - clearPermissionOverrides(): Promise; - /** - * Creates a new page in the browser context. - */ - newPage(): Promise; - /** - * The browser this browser context belongs to. - */ - browser(): Browser; - /** - * Closes the browser context. All the targets that belong to the browser context - * will be closed. - * - * @remarks - * Only incognito browser contexts can be closed. - */ - close(): Promise; -} -export {}; -//# sourceMappingURL=Browser.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.d.ts.map deleted file mode 100644 index 2e1d5273b1e..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../../../../src/common/Browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAA2B,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,aAAK,oBAAoB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,0BAAkB,oBAAoB;IACpC;;;;;;;OAOG;IACH,YAAY,iBAAiB;IAE7B;;;;;;OAMG;IACH,aAAa,kBAAkB;IAE/B;;;;;;;;;;OAUG;IACH,aAAa,kBAAkB;IAC/B;;;;;;;OAOG;IACH,eAAe,oBAAoB;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBAAa,OAAQ,SAAQ,YAAY;IACvC;;OAEG;WACU,MAAM,CACjB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,MAAM,EAAE,EACpB,iBAAiB,EAAE,OAAO,EAC1B,eAAe,CAAC,EAAE,QAAQ,EAC1B,OAAO,CAAC,EAAE,YAAY,EACtB,aAAa,CAAC,EAAE,oBAAoB,GACnC,OAAO,CAAC,OAAO,CAAC;IAYnB,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,gBAAgB,CAAC,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,SAAS,CAA8B;IAC/C;;;OAGG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B;;OAEG;gBAED,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,MAAM,EAAE,EACpB,iBAAiB,EAAE,OAAO,EAC1B,eAAe,CAAC,EAAE,QAAQ,EAC1B,OAAO,CAAC,EAAE,YAAY,EACtB,aAAa,CAAC,EAAE,oBAAoB;IAgCtC;;;OAGG;IACH,OAAO,IAAI,YAAY,GAAG,IAAI;IAI9B;;;;;;;;;;;;;;;;OAgBG;IACG,6BAA6B,IAAI,OAAO,CAAC,cAAc,CAAC;IAa9D;;;OAGG;IACH,eAAe,IAAI,cAAc,EAAE;IAInC;;OAEG;IACH,qBAAqB,IAAI,cAAc;IAIvC;;;OAGG;IACG,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAO1C,cAAc;YA6Bd,gBAAgB;IAa9B,OAAO,CAAC,kBAAkB;IAgB1B;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,IAAI,MAAM;IAIpB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;OAGG;IACG,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7D;;;OAGG;IACH,OAAO,IAAI,MAAM,EAAE;IAMnB;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;;;;;;;;;;;;OAaG;IACG,aAAa,CACjB,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,EACjC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC;IAyBlB;;;;;;;;OAQG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAQ9B;;;;;;;;;OASG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAKhC;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAKlC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;;;OAIG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,WAAW;CAGpB;AAED,0BAAkB,2BAA2B;IAC3C;;;OAGG;IACH,aAAa,kBAAkB;IAE/B;;;;;;;OAOG;IACH,aAAa,kBAAkB;IAC/B;;;OAGG;IACH,eAAe,oBAAoB;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,GAAG,CAAC,CAAS;IAErB;;OAEG;gBACS,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM;IAOxE;;OAEG;IACH,OAAO,IAAI,MAAM,EAAE;IAMnB;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,CACX,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,EACjC,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GACjC,OAAO,CAAC,MAAM,CAAC;IAOlB;;;;;;OAMG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAS9B;;;;;;OAMG;IACH,WAAW,IAAI,OAAO;IAItB;;;;;;;;;;OAUG;IACG,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,GAC7C,OAAO,CAAC,IAAI,CAAC;IAqChB;;;;;;;;;;OAUG;IACG,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IAM/C;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;;;;;OAMG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.js deleted file mode 100644 index 31d98a7e675..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Browser.js +++ /dev/null @@ -1,519 +0,0 @@ -"use strict"; -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.BrowserContext = exports.Browser = void 0; -const assert_js_1 = require("./assert.js"); -const helper_js_1 = require("./helper.js"); -const Target_js_1 = require("./Target.js"); -const EventEmitter_js_1 = require("./EventEmitter.js"); -const Connection_js_1 = require("./Connection.js"); -/** - * A Browser is created when Puppeteer connects to a Chromium instance, either through - * {@link Puppeteer.launch} or {@link Puppeteer.connect}. - * - * @remarks - * - * The Browser class extends from Puppeteer's {@link EventEmitter} class and will - * emit various events which are documented in the {@link BrowserEmittedEvents} enum. - * - * @example - * - * An example of using a {@link Browser} to create a {@link Page}: - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * await page.goto('https://example.com'); - * await browser.close(); - * })(); - * ``` - * - * @example - * - * An example of disconnecting from and reconnecting to a {@link Browser}: - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * // Store the endpoint to be able to reconnect to Chromium - * const browserWSEndpoint = browser.wsEndpoint(); - * // Disconnect puppeteer from Chromium - * browser.disconnect(); - * - * // Use the endpoint to reestablish a connection - * const browser2 = await puppeteer.connect({browserWSEndpoint}); - * // Close Chromium - * await browser2.close(); - * })(); - * ``` - * - * @public - */ -class Browser extends EventEmitter_js_1.EventEmitter { - /** - * @internal - */ - constructor(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) { - super(); - this._ignoreHTTPSErrors = ignoreHTTPSErrors; - this._defaultViewport = defaultViewport; - this._process = process; - this._connection = connection; - this._closeCallback = closeCallback || function () { }; - this._defaultContext = new BrowserContext(this._connection, this, null); - this._contexts = new Map(); - for (const contextId of contextIds) - this._contexts.set(contextId, new BrowserContext(this._connection, this, contextId)); - this._targets = new Map(); - this._connection.on(Connection_js_1.ConnectionEmittedEvents.Disconnected, () => this.emit("disconnected" /* Disconnected */)); - this._connection.on('Target.targetCreated', this._targetCreated.bind(this)); - this._connection.on('Target.targetDestroyed', this._targetDestroyed.bind(this)); - this._connection.on('Target.targetInfoChanged', this._targetInfoChanged.bind(this)); - } - /** - * @internal - */ - static async create(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) { - const browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback); - await connection.send('Target.setDiscoverTargets', { discover: true }); - return browser; - } - /** - * The spawned browser process. Returns `null` if the browser instance was created with - * {@link Puppeteer.connect}. - */ - process() { - return this._process; - } - /** - * Creates a new incognito browser context. This won't share cookies/cache with other - * browser contexts. - * - * @example - * ```js - * (async () => { - * const browser = await puppeteer.launch(); - * // Create a new incognito browser context. - * const context = await browser.createIncognitoBrowserContext(); - * // Create a new page in a pristine context. - * const page = await context.newPage(); - * // Do stuff - * await page.goto('https://example.com'); - * })(); - * ``` - */ - async createIncognitoBrowserContext() { - const { browserContextId } = await this._connection.send('Target.createBrowserContext'); - const context = new BrowserContext(this._connection, this, browserContextId); - this._contexts.set(browserContextId, context); - return context; - } - /** - * Returns an array of all open browser contexts. In a newly created browser, this will - * return a single instance of {@link BrowserContext}. - */ - browserContexts() { - return [this._defaultContext, ...Array.from(this._contexts.values())]; - } - /** - * Returns the default browser context. The default browser context cannot be closed. - */ - defaultBrowserContext() { - return this._defaultContext; - } - /** - * @internal - * Used by BrowserContext directly so cannot be marked private. - */ - async _disposeContext(contextId) { - await this._connection.send('Target.disposeBrowserContext', { - browserContextId: contextId || undefined, - }); - this._contexts.delete(contextId); - } - async _targetCreated(event) { - const targetInfo = event.targetInfo; - const { browserContextId } = targetInfo; - const context = browserContextId && this._contexts.has(browserContextId) - ? this._contexts.get(browserContextId) - : this._defaultContext; - const target = new Target_js_1.Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport); - assert_js_1.assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated'); - this._targets.set(event.targetInfo.targetId, target); - if (await target._initializedPromise) { - this.emit("targetcreated" /* TargetCreated */, target); - context.emit("targetcreated" /* TargetCreated */, target); - } - } - async _targetDestroyed(event) { - const target = this._targets.get(event.targetId); - target._initializedCallback(false); - this._targets.delete(event.targetId); - target._closedCallback(); - if (await target._initializedPromise) { - this.emit("targetdestroyed" /* TargetDestroyed */, target); - target - .browserContext() - .emit("targetdestroyed" /* TargetDestroyed */, target); - } - } - _targetInfoChanged(event) { - const target = this._targets.get(event.targetInfo.targetId); - assert_js_1.assert(target, 'target should exist before targetInfoChanged'); - const previousURL = target.url(); - const wasInitialized = target._isInitialized; - target._targetInfoChanged(event.targetInfo); - if (wasInitialized && previousURL !== target.url()) { - this.emit("targetchanged" /* TargetChanged */, target); - target - .browserContext() - .emit("targetchanged" /* TargetChanged */, target); - } - } - /** - * The browser websocket endpoint which can be used as an argument to - * {@link Puppeteer.connect}. - * - * @returns The Browser websocket url. - * - * @remarks - * - * The format is `ws://${host}:${port}/devtools/browser/`. - * - * You can find the `webSocketDebuggerUrl` from `http://${host}:${port}/json/version`. - * Learn more about the - * {@link https://chromedevtools.github.io/devtools-protocol | devtools protocol} and - * the {@link - * https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target - * | browser endpoint}. - */ - wsEndpoint() { - return this._connection.url(); - } - /** - * Creates a {@link Page} in the default browser context. - */ - async newPage() { - return this._defaultContext.newPage(); - } - /** - * @internal - * Used by BrowserContext directly so cannot be marked private. - */ - async _createPageInContext(contextId) { - const { targetId } = await this._connection.send('Target.createTarget', { - url: 'about:blank', - browserContextId: contextId || undefined, - }); - const target = await this._targets.get(targetId); - assert_js_1.assert(await target._initializedPromise, 'Failed to create target for page'); - const page = await target.page(); - return page; - } - /** - * All active targets inside the Browser. In case of multiple browser contexts, returns - * an array with all the targets in all browser contexts. - */ - targets() { - return Array.from(this._targets.values()).filter((target) => target._isInitialized); - } - /** - * The target associated with the browser. - */ - target() { - return this.targets().find((target) => target.type() === 'browser'); - } - /** - * Searches for a target in all browser contexts. - * - * @param predicate - A function to be run for every target. - * @returns The first target found that matches the `predicate` function. - * - * @example - * - * An example of finding a target for a page opened via `window.open`: - * ```js - * await page.evaluate(() => window.open('https://www.example.com/')); - * const newWindowTarget = await browser.waitForTarget(target => target.url() === 'https://www.example.com/'); - * ``` - */ - async waitForTarget(predicate, options = {}) { - const { timeout = 30000 } = options; - const existingTarget = this.targets().find(predicate); - if (existingTarget) - return existingTarget; - let resolve; - const targetPromise = new Promise((x) => (resolve = x)); - this.on("targetcreated" /* TargetCreated */, check); - this.on("targetchanged" /* TargetChanged */, check); - try { - if (!timeout) - return await targetPromise; - return await helper_js_1.helper.waitWithTimeout(targetPromise, 'target', timeout); - } - finally { - this.removeListener("targetcreated" /* TargetCreated */, check); - this.removeListener("targetchanged" /* TargetChanged */, check); - } - function check(target) { - if (predicate(target)) - resolve(target); - } - } - /** - * An array of all open pages inside the Browser. - * - * @remarks - * - * In case of multiple browser contexts, returns an array with all the pages in all - * browser contexts. Non-visible pages, such as `"background_page"`, will not be listed - * here. You can find them using {@link Target.page}. - */ - async pages() { - const contextPages = await Promise.all(this.browserContexts().map((context) => context.pages())); - // Flatten array. - return contextPages.reduce((acc, x) => acc.concat(x), []); - } - /** - * A string representing the browser name and version. - * - * @remarks - * - * For headless Chromium, this is similar to `HeadlessChrome/61.0.3153.0`. For - * non-headless, this is similar to `Chrome/61.0.3153.0`. - * - * The format of browser.version() might change with future releases of Chromium. - */ - async version() { - const version = await this._getVersion(); - return version.product; - } - /** - * The browser's original user agent. Pages can override the browser user agent with - * {@link Page.setUserAgent}. - */ - async userAgent() { - const version = await this._getVersion(); - return version.userAgent; - } - /** - * Closes Chromium and all of its pages (if any were opened). The {@link Browser} object - * itself is considered to be disposed and cannot be used anymore. - */ - async close() { - await this._closeCallback.call(null); - this.disconnect(); - } - /** - * Disconnects Puppeteer from the browser, but leaves the Chromium process running. - * After calling `disconnect`, the {@link Browser} object is considered disposed and - * cannot be used anymore. - */ - disconnect() { - this._connection.dispose(); - } - /** - * Indicates that the browser is connected. - */ - isConnected() { - return !this._connection._closed; - } - _getVersion() { - return this._connection.send('Browser.getVersion'); - } -} -exports.Browser = Browser; -/** - * BrowserContexts provide a way to operate multiple independent browser - * sessions. When a browser is launched, it has a single BrowserContext used by - * default. The method {@link Browser.newPage | Browser.newPage} creates a page - * in the default browser context. - * - * @remarks - * - * The Browser class extends from Puppeteer's {@link EventEmitter} class and - * will emit various events which are documented in the - * {@link BrowserContextEmittedEvents} enum. - * - * If a page opens another page, e.g. with a `window.open` call, the popup will - * belong to the parent page's browser context. - * - * Puppeteer allows creation of "incognito" browser contexts with - * {@link Browser.createIncognitoBrowserContext | Browser.createIncognitoBrowserContext} - * method. "Incognito" browser contexts don't write any browsing data to disk. - * - * @example - * ```js - * // Create a new incognito browser context - * const context = await browser.createIncognitoBrowserContext(); - * // Create a new page inside context. - * const page = await context.newPage(); - * // ... do stuff with page ... - * await page.goto('https://example.com'); - * // Dispose context once it's no longer needed. - * await context.close(); - * ``` - */ -class BrowserContext extends EventEmitter_js_1.EventEmitter { - /** - * @internal - */ - constructor(connection, browser, contextId) { - super(); - this._connection = connection; - this._browser = browser; - this._id = contextId; - } - /** - * An array of all active targets inside the browser context. - */ - targets() { - return this._browser - .targets() - .filter((target) => target.browserContext() === this); - } - /** - * This searches for a target in this specific browser context. - * - * @example - * An example of finding a target for a page opened via `window.open`: - * ```js - * await page.evaluate(() => window.open('https://www.example.com/')); - * const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/'); - * ``` - * - * @param predicate - A function to be run for every target - * @param options - An object of options. Accepts a timout, - * which is the maximum wait time in milliseconds. - * Pass `0` to disable the timeout. Defaults to 30 seconds. - * @returns Promise which resolves to the first target found - * that matches the `predicate` function. - */ - waitForTarget(predicate, options = {}) { - return this._browser.waitForTarget((target) => target.browserContext() === this && predicate(target), options); - } - /** - * An array of all pages inside the browser context. - * - * @returns Promise which resolves to an array of all open pages. - * Non visible pages, such as `"background_page"`, will not be listed here. - * You can find them using {@link Target.page | the target page}. - */ - async pages() { - const pages = await Promise.all(this.targets() - .filter((target) => target.type() === 'page') - .map((target) => target.page())); - return pages.filter((page) => !!page); - } - /** - * Returns whether BrowserContext is incognito. - * The default browser context is the only non-incognito browser context. - * - * @remarks - * The default browser context cannot be closed. - */ - isIncognito() { - return !!this._id; - } - /** - * @example - * ```js - * const context = browser.defaultBrowserContext(); - * await context.overridePermissions('https://html5demos.com', ['geolocation']); - * ``` - * - * @param origin - The origin to grant permissions to, e.g. "https://example.com". - * @param permissions - An array of permissions to grant. - * All permissions that are not listed here will be automatically denied. - */ - async overridePermissions(origin, permissions) { - const webPermissionToProtocol = new Map([ - ['geolocation', 'geolocation'], - ['midi', 'midi'], - ['notifications', 'notifications'], - // TODO: push isn't a valid type? - // ['push', 'push'], - ['camera', 'videoCapture'], - ['microphone', 'audioCapture'], - ['background-sync', 'backgroundSync'], - ['ambient-light-sensor', 'sensors'], - ['accelerometer', 'sensors'], - ['gyroscope', 'sensors'], - ['magnetometer', 'sensors'], - ['accessibility-events', 'accessibilityEvents'], - ['clipboard-read', 'clipboardReadWrite'], - ['clipboard-write', 'clipboardReadWrite'], - ['payment-handler', 'paymentHandler'], - // chrome-specific permissions we have. - ['midi-sysex', 'midiSysex'], - ]); - permissions = permissions.map((permission) => { - const protocolPermission = webPermissionToProtocol.get(permission); - if (!protocolPermission) - throw new Error('Unknown permission: ' + permission); - return protocolPermission; - }); - await this._connection.send('Browser.grantPermissions', { - origin, - browserContextId: this._id || undefined, - permissions, - }); - } - /** - * Clears all permission overrides for the browser context. - * - * @example - * ```js - * const context = browser.defaultBrowserContext(); - * context.overridePermissions('https://example.com', ['clipboard-read']); - * // do stuff .. - * context.clearPermissionOverrides(); - * ``` - */ - async clearPermissionOverrides() { - await this._connection.send('Browser.resetPermissions', { - browserContextId: this._id || undefined, - }); - } - /** - * Creates a new page in the browser context. - */ - newPage() { - return this._browser._createPageInContext(this._id); - } - /** - * The browser this browser context belongs to. - */ - browser() { - return this._browser; - } - /** - * Closes the browser context. All the targets that belong to the browser context - * will be closed. - * - * @remarks - * Only incognito browser contexts can be closed. - */ - async close() { - assert_js_1.assert(this._id, 'Non-incognito profiles cannot be closed!'); - await this._browser._disposeContext(this._id); - } -} -exports.BrowserContext = BrowserContext; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.d.ts deleted file mode 100644 index 0756d87f1b7..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.d.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { Protocol } from 'devtools-protocol'; -import { ProtocolMapping } from 'devtools-protocol/types/protocol-mapping.js'; -import { ConnectionTransport } from './ConnectionTransport.js'; -import { EventEmitter } from './EventEmitter.js'; -interface ConnectionCallback { - resolve: Function; - reject: Function; - error: Error; - method: string; -} -/** - * Internal events that the Connection class emits. - * - * @internal - */ -export declare const ConnectionEmittedEvents: { - readonly Disconnected: symbol; -}; -/** - * @internal - */ -export declare class Connection extends EventEmitter { - _url: string; - _transport: ConnectionTransport; - _delay: number; - _lastId: number; - _sessions: Map; - _closed: boolean; - _callbacks: Map; - constructor(url: string, transport: ConnectionTransport, delay?: number); - static fromSession(session: CDPSession): Connection; - /** - * @param {string} sessionId - * @returns {?CDPSession} - */ - session(sessionId: string): CDPSession | null; - url(): string; - send(method: T, ...paramArgs: ProtocolMapping.Commands[T]['paramsType']): Promise; - _rawSend(message: {}): number; - _onMessage(message: string): Promise; - _onClose(): void; - dispose(): void; - /** - * @param {Protocol.Target.TargetInfo} targetInfo - * @returns {!Promise} - */ - createSession(targetInfo: Protocol.Target.TargetInfo): Promise; -} -interface CDPSessionOnMessageObject { - id?: number; - method: string; - params: {}; - error: { - message: string; - data: any; - }; - result?: any; -} -/** - * Internal events that the CDPSession class emits. - * - * @internal - */ -export declare const CDPSessionEmittedEvents: { - readonly Disconnected: symbol; -}; -/** - * The `CDPSession` instances are used to talk raw Chrome Devtools Protocol. - * - * @remarks - * - * Protocol methods can be called with {@link CDPSession.send} method and protocol - * events can be subscribed to with `CDPSession.on` method. - * - * Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer} - * and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md | Getting Started with DevTools Protocol}. - * - * @example - * ```js - * const client = await page.target().createCDPSession(); - * await client.send('Animation.enable'); - * client.on('Animation.animationCreated', () => console.log('Animation created!')); - * const response = await client.send('Animation.getPlaybackRate'); - * console.log('playback rate is ' + response.playbackRate); - * await client.send('Animation.setPlaybackRate', { - * playbackRate: response.playbackRate / 2 - * }); - * ``` - * - * @public - */ -export declare class CDPSession extends EventEmitter { - /** - * @internal - */ - _connection: Connection; - private _sessionId; - private _targetType; - private _callbacks; - /** - * @internal - */ - constructor(connection: Connection, targetType: string, sessionId: string); - send(method: T, ...paramArgs: ProtocolMapping.Commands[T]['paramsType']): Promise; - /** - * @internal - */ - _onMessage(object: CDPSessionOnMessageObject): void; - /** - * Detaches the cdpSession from the target. Once detached, the cdpSession object - * won't emit any events and can't be used to send messages. - */ - detach(): Promise; - /** - * @internal - */ - _onClosed(): void; -} -export {}; -//# sourceMappingURL=Connection.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.d.ts.map deleted file mode 100644 index dff726e837a..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Connection.d.ts","sourceRoot":"","sources":["../../../../src/common/Connection.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,UAAU,kBAAkB;IAC1B,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;CAE1B,CAAC;AAEX;;GAEG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,mBAAmB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,SAAK;IACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAa;IAC/C,OAAO,UAAS;IAEhB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAa;gBAE5C,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,KAAK,SAAI;IAUlE,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU;IAInD;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAI7C,GAAG,IAAI,MAAM;IAIb,IAAI,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,QAAQ,EAC3C,MAAM,EAAE,CAAC,EACT,GAAG,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GACtD,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAcrD,QAAQ,CAAC,OAAO,EAAE,EAAE,GAAG,MAAM;IAQvB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsChD,QAAQ,IAAI,IAAI;IAkBhB,OAAO,IAAI,IAAI;IAKf;;;OAGG;IACG,aAAa,CACjB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,GACrC,OAAO,CAAC,UAAU,CAAC;CAOvB;AAED,UAAU,yBAAyB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,EAAE,CAAC;IACX,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,CAAC;IACtC,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;CAE1B,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C;;OAEG;IACH,WAAW,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAA8C;IAEhE;;OAEG;gBACS,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAOzE,IAAI,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,QAAQ,EAC3C,MAAM,EAAE,CAAC,EACT,GAAG,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GACtD,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IA0BrD;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI;IAenD;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAU7B;;OAEG;IACH,SAAS,IAAI,IAAI;CAYlB"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.js deleted file mode 100644 index 8ca18019a1f..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Connection.js +++ /dev/null @@ -1,271 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.CDPSession = exports.CDPSessionEmittedEvents = exports.Connection = exports.ConnectionEmittedEvents = void 0; -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const assert_js_1 = require("./assert.js"); -const Debug_js_1 = require("./Debug.js"); -const debugProtocolSend = Debug_js_1.debug('puppeteer:protocol:SEND ►'); -const debugProtocolReceive = Debug_js_1.debug('puppeteer:protocol:RECV ◀'); -const EventEmitter_js_1 = require("./EventEmitter.js"); -/** - * Internal events that the Connection class emits. - * - * @internal - */ -exports.ConnectionEmittedEvents = { - Disconnected: Symbol('Connection.Disconnected'), -}; -/** - * @internal - */ -class Connection extends EventEmitter_js_1.EventEmitter { - constructor(url, transport, delay = 0) { - super(); - this._lastId = 0; - this._sessions = new Map(); - this._closed = false; - this._callbacks = new Map(); - this._url = url; - this._delay = delay; - this._transport = transport; - this._transport.onmessage = this._onMessage.bind(this); - this._transport.onclose = this._onClose.bind(this); - } - static fromSession(session) { - return session._connection; - } - /** - * @param {string} sessionId - * @returns {?CDPSession} - */ - session(sessionId) { - return this._sessions.get(sessionId) || null; - } - url() { - return this._url; - } - send(method, ...paramArgs) { - // There is only ever 1 param arg passed, but the Protocol defines it as an - // array of 0 or 1 items See this comment: - // https://github.com/ChromeDevTools/devtools-protocol/pull/113#issuecomment-412603285 - // which explains why the protocol defines the params this way for better - // type-inference. - // So now we check if there are any params or not and deal with them accordingly. - const params = paramArgs.length ? paramArgs[0] : undefined; - const id = this._rawSend({ method, params }); - return new Promise((resolve, reject) => { - this._callbacks.set(id, { resolve, reject, error: new Error(), method }); - }); - } - _rawSend(message) { - const id = ++this._lastId; - message = JSON.stringify(Object.assign({}, message, { id })); - debugProtocolSend(message); - this._transport.send(message); - return id; - } - async _onMessage(message) { - if (this._delay) - await new Promise((f) => setTimeout(f, this._delay)); - debugProtocolReceive(message); - const object = JSON.parse(message); - if (object.method === 'Target.attachedToTarget') { - const sessionId = object.params.sessionId; - const session = new CDPSession(this, object.params.targetInfo.type, sessionId); - this._sessions.set(sessionId, session); - } - else if (object.method === 'Target.detachedFromTarget') { - const session = this._sessions.get(object.params.sessionId); - if (session) { - session._onClosed(); - this._sessions.delete(object.params.sessionId); - } - } - if (object.sessionId) { - const session = this._sessions.get(object.sessionId); - if (session) - session._onMessage(object); - } - else if (object.id) { - const callback = this._callbacks.get(object.id); - // Callbacks could be all rejected if someone has called `.dispose()`. - if (callback) { - this._callbacks.delete(object.id); - if (object.error) - callback.reject(createProtocolError(callback.error, callback.method, object)); - else - callback.resolve(object.result); - } - } - else { - this.emit(object.method, object.params); - } - } - _onClose() { - if (this._closed) - return; - this._closed = true; - this._transport.onmessage = null; - this._transport.onclose = null; - for (const callback of this._callbacks.values()) - callback.reject(rewriteError(callback.error, `Protocol error (${callback.method}): Target closed.`)); - this._callbacks.clear(); - for (const session of this._sessions.values()) - session._onClosed(); - this._sessions.clear(); - this.emit(exports.ConnectionEmittedEvents.Disconnected); - } - dispose() { - this._onClose(); - this._transport.close(); - } - /** - * @param {Protocol.Target.TargetInfo} targetInfo - * @returns {!Promise} - */ - async createSession(targetInfo) { - const { sessionId } = await this.send('Target.attachToTarget', { - targetId: targetInfo.targetId, - flatten: true, - }); - return this._sessions.get(sessionId); - } -} -exports.Connection = Connection; -/** - * Internal events that the CDPSession class emits. - * - * @internal - */ -exports.CDPSessionEmittedEvents = { - Disconnected: Symbol('CDPSession.Disconnected'), -}; -/** - * The `CDPSession` instances are used to talk raw Chrome Devtools Protocol. - * - * @remarks - * - * Protocol methods can be called with {@link CDPSession.send} method and protocol - * events can be subscribed to with `CDPSession.on` method. - * - * Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer} - * and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md | Getting Started with DevTools Protocol}. - * - * @example - * ```js - * const client = await page.target().createCDPSession(); - * await client.send('Animation.enable'); - * client.on('Animation.animationCreated', () => console.log('Animation created!')); - * const response = await client.send('Animation.getPlaybackRate'); - * console.log('playback rate is ' + response.playbackRate); - * await client.send('Animation.setPlaybackRate', { - * playbackRate: response.playbackRate / 2 - * }); - * ``` - * - * @public - */ -class CDPSession extends EventEmitter_js_1.EventEmitter { - /** - * @internal - */ - constructor(connection, targetType, sessionId) { - super(); - this._callbacks = new Map(); - this._connection = connection; - this._targetType = targetType; - this._sessionId = sessionId; - } - send(method, ...paramArgs) { - if (!this._connection) - return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the ${this._targetType} has been closed.`)); - // See the comment in Connection#send explaining why we do this. - const params = paramArgs.length ? paramArgs[0] : undefined; - const id = this._connection._rawSend({ - sessionId: this._sessionId, - method, - /* TODO(jacktfranklin@): once this Firefox bug is solved - * we no longer need the `|| {}` check - * https://bugzilla.mozilla.org/show_bug.cgi?id=1631570 - */ - params: params || {}, - }); - return new Promise((resolve, reject) => { - this._callbacks.set(id, { resolve, reject, error: new Error(), method }); - }); - } - /** - * @internal - */ - _onMessage(object) { - if (object.id && this._callbacks.has(object.id)) { - const callback = this._callbacks.get(object.id); - this._callbacks.delete(object.id); - if (object.error) - callback.reject(createProtocolError(callback.error, callback.method, object)); - else - callback.resolve(object.result); - } - else { - assert_js_1.assert(!object.id); - this.emit(object.method, object.params); - } - } - /** - * Detaches the cdpSession from the target. Once detached, the cdpSession object - * won't emit any events and can't be used to send messages. - */ - async detach() { - if (!this._connection) - throw new Error(`Session already detached. Most likely the ${this._targetType} has been closed.`); - await this._connection.send('Target.detachFromTarget', { - sessionId: this._sessionId, - }); - } - /** - * @internal - */ - _onClosed() { - for (const callback of this._callbacks.values()) - callback.reject(rewriteError(callback.error, `Protocol error (${callback.method}): Target closed.`)); - this._callbacks.clear(); - this._connection = null; - this.emit(exports.CDPSessionEmittedEvents.Disconnected); - } -} -exports.CDPSession = CDPSession; -/** - * @param {!Error} error - * @param {string} method - * @param {{error: {message: string, data: any}}} object - * @returns {!Error} - */ -function createProtocolError(error, method, object) { - let message = `Protocol error (${method}): ${object.error.message}`; - if ('data' in object.error) - message += ` ${object.error.data}`; - return rewriteError(error, message); -} -/** - * @param {!Error} error - * @param {string} message - * @returns {!Error} - */ -function rewriteError(error, message) { - error.message = message; - return error; -} diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectionTransport.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectionTransport.d.ts.map deleted file mode 100644 index 7b55f821811..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectionTransport.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ConnectionTransport.d.ts","sourceRoot":"","sources":["../../../../src/common/ConnectionTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,MAAM,KAAA,OAAE;IACb,KAAK,QAAG;IACR,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts deleted file mode 100644 index 0ca5f94dd3f..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { JSHandle } from './JSHandle.js'; -/** - * @public - */ -export interface ConsoleMessageLocation { - /** - * URL of the resource if known or `undefined` otherwise. - */ - url?: string; - /** - * 0-based line number in the resource if known or `undefined` otherwise. - */ - lineNumber?: number; - /** - * 0-based column number in the resource if known or `undefined` otherwise. - */ - columnNumber?: number; -} -/** - * The supported types for console messages. - */ -export declare type ConsoleMessageType = 'log' | 'debug' | 'info' | 'error' | 'warning' | 'dir' | 'dirxml' | 'table' | 'trace' | 'clear' | 'startGroup' | 'startGroupCollapsed' | 'endGroup' | 'assert' | 'profile' | 'profileEnd' | 'count' | 'timeEnd' | 'verbose'; -/** - * ConsoleMessage objects are dispatched by page via the 'console' event. - * @public - */ -export declare class ConsoleMessage { - private _type; - private _text; - private _args; - private _location; - /** - * @public - */ - constructor(type: ConsoleMessageType, text: string, args: JSHandle[], location?: ConsoleMessageLocation); - /** - * @returns The type of the console message. - */ - type(): ConsoleMessageType; - /** - * @returns The text of the console message. - */ - text(): string; - /** - * @returns An array of arguments passed to the console. - */ - args(): JSHandle[]; - /** - * @returns The location of the console message. - */ - location(): ConsoleMessageLocation; -} -//# sourceMappingURL=ConsoleMessage.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts.map deleted file mode 100644 index b241d856c42..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ConsoleMessage.d.ts","sourceRoot":"","sources":["../../../../src/common/ConsoleMessage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,oBAAY,kBAAkB,GAC1B,KAAK,GACL,OAAO,GACP,MAAM,GACN,OAAO,GACP,SAAS,GACT,KAAK,GACL,QAAQ,GACR,OAAO,GACP,OAAO,GACP,OAAO,GACP,YAAY,GACZ,qBAAqB,GACrB,UAAU,GACV,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,OAAO,GACP,SAAS,GACT,SAAS,CAAC;AAEd;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,SAAS,CAAyB;IAE1C;;OAEG;gBAED,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,EAAE,EAChB,QAAQ,GAAE,sBAA2B;IAQvC;;OAEG;IACH,IAAI,IAAI,kBAAkB;IAI1B;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;OAEG;IACH,IAAI,IAAI,QAAQ,EAAE;IAIlB;;OAEG;IACH,QAAQ,IAAI,sBAAsB;CAGnC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.js deleted file mode 100644 index 7f2edb39cf0..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ConsoleMessage = void 0; -/** - * ConsoleMessage objects are dispatched by page via the 'console' event. - * @public - */ -class ConsoleMessage { - /** - * @public - */ - constructor(type, text, args, location = {}) { - this._type = type; - this._text = text; - this._args = args; - this._location = location; - } - /** - * @returns The type of the console message. - */ - type() { - return this._type; - } - /** - * @returns The text of the console message. - */ - text() { - return this._text; - } - /** - * @returns An array of arguments passed to the console. - */ - args() { - return this._args; - } - /** - * @returns The location of the console message. - */ - location() { - return this._location; - } -} -exports.ConsoleMessage = ConsoleMessage; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.d.ts deleted file mode 100644 index 0233eaac1fc..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.d.ts +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Protocol } from 'devtools-protocol'; - -import { CDPSession } from './Connection.js'; -import { PuppeteerEventListener } from './helper.js'; - -/** - * The CoverageEntry class represents one entry of the coverage report. - * @public - */ -export interface CoverageEntry { - /** - * The URL of the style sheet or script. - */ - url: string; - /** - * The content of the style sheet or script. - */ - text: string; - /** - * The covered range as start and end positions. - */ - ranges: Array<{ - start: number; - end: number; - }>; -} -/** - * Set of configurable options for JS coverage. - * @public - */ -export interface JSCoverageOptions { - /** - * Whether to reset coverage on every navigation. - */ - resetOnNavigation?: boolean; - /** - * Whether anonymous scripts generated by the page should be reported. - */ - reportAnonymousScripts?: boolean; -} -/** - * Set of configurable options for CSS coverage. - * @public - */ -export interface CSSCoverageOptions { - /** - * Whether to reset coverage on every navigation. - */ - resetOnNavigation?: boolean; -} -/** - * The Coverage class provides methods to gathers information about parts of - * JavaScript and CSS that were used by the page. - * - * @remarks - * To output coverage in a form consumable by {@link https://github.com/istanbuljs | Istanbul}, - * see {@link https://github.com/istanbuljs/puppeteer-to-istanbul | puppeteer-to-istanbul}. - * - * @example - * An example of using JavaScript and CSS coverage to get percentage of initially - * executed code: - * ```js - * // Enable both JavaScript and CSS coverage - * await Promise.all([ - * page.coverage.startJSCoverage(), - * page.coverage.startCSSCoverage() - * ]); - * // Navigate to page - * await page.goto('https://example.com'); - * // Disable both JavaScript and CSS coverage - * const [jsCoverage, cssCoverage] = await Promise.all([ - * page.coverage.stopJSCoverage(), - * page.coverage.stopCSSCoverage(), - * ]); - * let totalBytes = 0; - * let usedBytes = 0; - * const coverage = [...jsCoverage, ...cssCoverage]; - * for (const entry of coverage) { - * totalBytes += entry.text.length; - * for (const range of entry.ranges) - * usedBytes += range.end - range.start - 1; - * } - * console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`); - * ``` - * @public - */ -export declare class Coverage { - /** - * @internal - */ - _jsCoverage: JSCoverage; - /** - * @internal - */ - _cssCoverage: CSSCoverage; - constructor(client: CDPSession); - /** - * @param options - defaults to - * `{ resetOnNavigation : true, reportAnonymousScripts : false }` - * @returns Promise that resolves when coverage is started. - * - * @remarks - * Anonymous scripts are ones that don't have an associated url. These are - * scripts that are dynamically created on the page using `eval` or - * `new Function`. If `reportAnonymousScripts` is set to `true`, anonymous - * scripts will have `__puppeteer_evaluation_script__` as their URL. - */ - startJSCoverage(options?: JSCoverageOptions): Promise; - /** - * @returns Promise that resolves to the array of coverage reports for - * all scripts. - * - * @remarks - * JavaScript Coverage doesn't include anonymous scripts by default. - * However, scripts with sourceURLs are reported. - */ - stopJSCoverage(): Promise; - /** - * @param options - defaults to `{ resetOnNavigation : true }` - * @returns Promise that resolves when coverage is started. - */ - startCSSCoverage(options?: CSSCoverageOptions): Promise; - /** - * @returns Promise that resolves to the array of coverage reports - * for all stylesheets. - * @remarks - * CSS Coverage doesn't include dynamically injected style tags - * without sourceURLs. - */ - stopCSSCoverage(): Promise; -} -declare class JSCoverage { - _client: CDPSession; - _enabled: boolean; - _scriptURLs: Map; - _scriptSources: Map; - _eventListeners: PuppeteerEventListener[]; - _resetOnNavigation: boolean; - _reportAnonymousScripts: boolean; - constructor(client: CDPSession); - start(options?: { - resetOnNavigation?: boolean; - reportAnonymousScripts?: boolean; - }): Promise; - _onExecutionContextsCleared(): void; - _onScriptParsed(event: Protocol.Debugger.ScriptParsedEvent): Promise; - stop(): Promise; -} -declare class CSSCoverage { - _client: CDPSession; - _enabled: boolean; - _stylesheetURLs: Map; - _stylesheetSources: Map; - _eventListeners: PuppeteerEventListener[]; - _resetOnNavigation: boolean; - _reportAnonymousScripts: boolean; - constructor(client: CDPSession); - start(options?: { - resetOnNavigation?: boolean; - }): Promise; - _onExecutionContextsCleared(): void; - _onStyleSheet(event: Protocol.CSS.StyleSheetAddedEvent): Promise; - stop(): Promise; -} -export {}; -//# sourceMappingURL=Coverage.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.d.ts.map deleted file mode 100644 index cb4f25d4194..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Coverage.d.ts","sourceRoot":"","sources":["../../../../src/common/Coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAsB,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,QAAQ;IACnB;;OAEG;IACH,WAAW,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,YAAY,EAAE,WAAW,CAAC;gBAEd,MAAM,EAAE,UAAU;IAK9B;;;;;;;;;;OAUG;IACG,eAAe,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrE;;;;;;;OAOG;IACG,cAAc,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAIhD;;;OAGG;IACG,gBAAgB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE;;;;;;OAMG;IACG,eAAe,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAGlD;AAED,cAAM,UAAU;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,UAAS;IACjB,WAAW,sBAA6B;IACxC,cAAc,sBAA6B;IAC3C,eAAe,EAAE,sBAAsB,EAAE,CAAM;IAC/C,kBAAkB,UAAS;IAC3B,uBAAuB,UAAS;gBAEpB,MAAM,EAAE,UAAU;IAIxB,KAAK,CACT,OAAO,GAAE;QACP,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,sBAAsB,CAAC,EAAE,OAAO,CAAC;KAC7B,GACL,OAAO,CAAC,IAAI,CAAC;IAkChB,2BAA2B,IAAI,IAAI;IAM7B,eAAe,CACnB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,GACzC,OAAO,CAAC,IAAI,CAAC;IAiBV,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAkCvC;AAED,cAAM,WAAW;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,UAAS;IACjB,eAAe,sBAA6B;IAC5C,kBAAkB,sBAA6B;IAC/C,eAAe,EAAE,sBAAsB,EAAE,CAAM;IAC/C,kBAAkB,UAAS;IAC3B,uBAAuB,UAAS;gBAEpB,MAAM,EAAE,UAAU;IAIxB,KAAK,CAAC,OAAO,GAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BzE,2BAA2B,IAAI,IAAI;IAM7B,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBtE,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAuCvC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.js deleted file mode 100644 index 9bb4d3ed7e0..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Coverage.js +++ /dev/null @@ -1,319 +0,0 @@ -"use strict"; -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Coverage = void 0; -const assert_js_1 = require("./assert.js"); -const helper_js_1 = require("./helper.js"); -const ExecutionContext_js_1 = require("./ExecutionContext.js"); -/** - * The Coverage class provides methods to gathers information about parts of - * JavaScript and CSS that were used by the page. - * - * @remarks - * To output coverage in a form consumable by {@link https://github.com/istanbuljs | Istanbul}, - * see {@link https://github.com/istanbuljs/puppeteer-to-istanbul | puppeteer-to-istanbul}. - * - * @example - * An example of using JavaScript and CSS coverage to get percentage of initially - * executed code: - * ```js - * // Enable both JavaScript and CSS coverage - * await Promise.all([ - * page.coverage.startJSCoverage(), - * page.coverage.startCSSCoverage() - * ]); - * // Navigate to page - * await page.goto('https://example.com'); - * // Disable both JavaScript and CSS coverage - * const [jsCoverage, cssCoverage] = await Promise.all([ - * page.coverage.stopJSCoverage(), - * page.coverage.stopCSSCoverage(), - * ]); - * let totalBytes = 0; - * let usedBytes = 0; - * const coverage = [...jsCoverage, ...cssCoverage]; - * for (const entry of coverage) { - * totalBytes += entry.text.length; - * for (const range of entry.ranges) - * usedBytes += range.end - range.start - 1; - * } - * console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`); - * ``` - * @public - */ -class Coverage { - constructor(client) { - this._jsCoverage = new JSCoverage(client); - this._cssCoverage = new CSSCoverage(client); - } - /** - * @param options - defaults to - * `{ resetOnNavigation : true, reportAnonymousScripts : false }` - * @returns Promise that resolves when coverage is started. - * - * @remarks - * Anonymous scripts are ones that don't have an associated url. These are - * scripts that are dynamically created on the page using `eval` or - * `new Function`. If `reportAnonymousScripts` is set to `true`, anonymous - * scripts will have `__puppeteer_evaluation_script__` as their URL. - */ - async startJSCoverage(options = {}) { - return await this._jsCoverage.start(options); - } - /** - * @returns Promise that resolves to the array of coverage reports for - * all scripts. - * - * @remarks - * JavaScript Coverage doesn't include anonymous scripts by default. - * However, scripts with sourceURLs are reported. - */ - async stopJSCoverage() { - return await this._jsCoverage.stop(); - } - /** - * @param options - defaults to `{ resetOnNavigation : true }` - * @returns Promise that resolves when coverage is started. - */ - async startCSSCoverage(options = {}) { - return await this._cssCoverage.start(options); - } - /** - * @returns Promise that resolves to the array of coverage reports - * for all stylesheets. - * @remarks - * CSS Coverage doesn't include dynamically injected style tags - * without sourceURLs. - */ - async stopCSSCoverage() { - return await this._cssCoverage.stop(); - } -} -exports.Coverage = Coverage; -class JSCoverage { - constructor(client) { - this._enabled = false; - this._scriptURLs = new Map(); - this._scriptSources = new Map(); - this._eventListeners = []; - this._resetOnNavigation = false; - this._reportAnonymousScripts = false; - this._client = client; - } - async start(options = {}) { - assert_js_1.assert(!this._enabled, 'JSCoverage is already enabled'); - const { resetOnNavigation = true, reportAnonymousScripts = false, } = options; - this._resetOnNavigation = resetOnNavigation; - this._reportAnonymousScripts = reportAnonymousScripts; - this._enabled = true; - this._scriptURLs.clear(); - this._scriptSources.clear(); - this._eventListeners = [ - helper_js_1.helper.addEventListener(this._client, 'Debugger.scriptParsed', this._onScriptParsed.bind(this)), - helper_js_1.helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)), - ]; - await Promise.all([ - this._client.send('Profiler.enable'), - this._client.send('Profiler.startPreciseCoverage', { - callCount: false, - detailed: true, - }), - this._client.send('Debugger.enable'), - this._client.send('Debugger.setSkipAllPauses', { skip: true }), - ]); - } - _onExecutionContextsCleared() { - if (!this._resetOnNavigation) - return; - this._scriptURLs.clear(); - this._scriptSources.clear(); - } - async _onScriptParsed(event) { - // Ignore puppeteer-injected scripts - if (event.url === ExecutionContext_js_1.EVALUATION_SCRIPT_URL) - return; - // Ignore other anonymous scripts unless the reportAnonymousScripts option is true. - if (!event.url && !this._reportAnonymousScripts) - return; - try { - const response = await this._client.send('Debugger.getScriptSource', { - scriptId: event.scriptId, - }); - this._scriptURLs.set(event.scriptId, event.url); - this._scriptSources.set(event.scriptId, response.scriptSource); - } - catch (error) { - // This might happen if the page has already navigated away. - helper_js_1.debugError(error); - } - } - async stop() { - assert_js_1.assert(this._enabled, 'JSCoverage is not enabled'); - this._enabled = false; - const result = await Promise.all([ - this._client.send('Profiler.takePreciseCoverage'), - this._client.send('Profiler.stopPreciseCoverage'), - this._client.send('Profiler.disable'), - this._client.send('Debugger.disable'), - ]); - helper_js_1.helper.removeEventListeners(this._eventListeners); - const coverage = []; - const profileResponse = result[0]; - for (const entry of profileResponse.result) { - let url = this._scriptURLs.get(entry.scriptId); - if (!url && this._reportAnonymousScripts) - url = 'debugger://VM' + entry.scriptId; - const text = this._scriptSources.get(entry.scriptId); - if (text === undefined || url === undefined) - continue; - const flattenRanges = []; - for (const func of entry.functions) - flattenRanges.push(...func.ranges); - const ranges = convertToDisjointRanges(flattenRanges); - coverage.push({ url, ranges, text }); - } - return coverage; - } -} -class CSSCoverage { - constructor(client) { - this._enabled = false; - this._stylesheetURLs = new Map(); - this._stylesheetSources = new Map(); - this._eventListeners = []; - this._resetOnNavigation = false; - this._reportAnonymousScripts = false; - this._client = client; - } - async start(options = {}) { - assert_js_1.assert(!this._enabled, 'CSSCoverage is already enabled'); - const { resetOnNavigation = true } = options; - this._resetOnNavigation = resetOnNavigation; - this._enabled = true; - this._stylesheetURLs.clear(); - this._stylesheetSources.clear(); - this._eventListeners = [ - helper_js_1.helper.addEventListener(this._client, 'CSS.styleSheetAdded', this._onStyleSheet.bind(this)), - helper_js_1.helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)), - ]; - await Promise.all([ - this._client.send('DOM.enable'), - this._client.send('CSS.enable'), - this._client.send('CSS.startRuleUsageTracking'), - ]); - } - _onExecutionContextsCleared() { - if (!this._resetOnNavigation) - return; - this._stylesheetURLs.clear(); - this._stylesheetSources.clear(); - } - async _onStyleSheet(event) { - const header = event.header; - // Ignore anonymous scripts - if (!header.sourceURL) - return; - try { - const response = await this._client.send('CSS.getStyleSheetText', { - styleSheetId: header.styleSheetId, - }); - this._stylesheetURLs.set(header.styleSheetId, header.sourceURL); - this._stylesheetSources.set(header.styleSheetId, response.text); - } - catch (error) { - // This might happen if the page has already navigated away. - helper_js_1.debugError(error); - } - } - async stop() { - assert_js_1.assert(this._enabled, 'CSSCoverage is not enabled'); - this._enabled = false; - const ruleTrackingResponse = await this._client.send('CSS.stopRuleUsageTracking'); - await Promise.all([ - this._client.send('CSS.disable'), - this._client.send('DOM.disable'), - ]); - helper_js_1.helper.removeEventListeners(this._eventListeners); - // aggregate by styleSheetId - const styleSheetIdToCoverage = new Map(); - for (const entry of ruleTrackingResponse.ruleUsage) { - let ranges = styleSheetIdToCoverage.get(entry.styleSheetId); - if (!ranges) { - ranges = []; - styleSheetIdToCoverage.set(entry.styleSheetId, ranges); - } - ranges.push({ - startOffset: entry.startOffset, - endOffset: entry.endOffset, - count: entry.used ? 1 : 0, - }); - } - const coverage = []; - for (const styleSheetId of this._stylesheetURLs.keys()) { - const url = this._stylesheetURLs.get(styleSheetId); - const text = this._stylesheetSources.get(styleSheetId); - const ranges = convertToDisjointRanges(styleSheetIdToCoverage.get(styleSheetId) || []); - coverage.push({ url, ranges, text }); - } - return coverage; - } -} -function convertToDisjointRanges(nestedRanges) { - const points = []; - for (const range of nestedRanges) { - points.push({ offset: range.startOffset, type: 0, range }); - points.push({ offset: range.endOffset, type: 1, range }); - } - // Sort points to form a valid parenthesis sequence. - points.sort((a, b) => { - // Sort with increasing offsets. - if (a.offset !== b.offset) - return a.offset - b.offset; - // All "end" points should go before "start" points. - if (a.type !== b.type) - return b.type - a.type; - const aLength = a.range.endOffset - a.range.startOffset; - const bLength = b.range.endOffset - b.range.startOffset; - // For two "start" points, the one with longer range goes first. - if (a.type === 0) - return bLength - aLength; - // For two "end" points, the one with shorter range goes first. - return aLength - bLength; - }); - const hitCountStack = []; - const results = []; - let lastOffset = 0; - // Run scanning line to intersect all ranges. - for (const point of points) { - if (hitCountStack.length && - lastOffset < point.offset && - hitCountStack[hitCountStack.length - 1] > 0) { - const lastResult = results.length ? results[results.length - 1] : null; - if (lastResult && lastResult.end === lastOffset) - lastResult.end = point.offset; - else - results.push({ start: lastOffset, end: point.offset }); - } - lastOffset = point.offset; - if (point.type === 0) - hitCountStack.push(point.range.count); - else - hitCountStack.pop(); - } - // Filter out empty ranges. - return results.filter((range) => range.end - range.start > 1); -} diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.d.ts deleted file mode 100644 index a2276edb037..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.d.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright 2019 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/// -import { EvaluateFn, EvaluateFnReturnType, EvaluateHandleFn, SerializableOrJSHandle, UnwrapPromiseLike , WrapElementHandle} from './EvalTypes.js'; -import { ExecutionContext } from './ExecutionContext.js'; -import { Frame , FrameManager} from './FrameManager.js'; -import { MouseButton } from './Input.js'; -import { ElementHandle , JSHandle} from './JSHandle.js'; -import { PuppeteerLifeCycleEvent } from './LifecycleWatcher.js'; -import { TimeoutSettings } from './TimeoutSettings.js'; - -/** - * @public - */ -export interface WaitForSelectorOptions { - visible?: boolean; - hidden?: boolean; - timeout?: number; -} -/** - * @internal - */ -export declare class DOMWorld { - private _frameManager; - private _frame; - private _timeoutSettings; - private _documentPromise?; - private _contextPromise?; - private _contextResolveCallback?; - private _detached; - /** - * internal - */ - _waitTasks: Set; - constructor(frameManager: FrameManager, frame: Frame, timeoutSettings: TimeoutSettings); - frame(): Frame; - _setContext(context?: ExecutionContext): void; - _hasContext(): boolean; - _detach(): void; - executionContext(): Promise; - evaluateHandle(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise; - evaluate(pageFunction: T, ...args: SerializableOrJSHandle[]): Promise>>; - $(selector: string): Promise; - _document(): Promise; - $x(expression: string): Promise; - $eval(selector: string, pageFunction: (element: Element, ...args: unknown[]) => ReturnType | Promise, ...args: SerializableOrJSHandle[]): Promise>; - $$eval(selector: string, pageFunction: (elements: Element[], ...args: unknown[]) => ReturnType | Promise, ...args: SerializableOrJSHandle[]): Promise>; - $$(selector: string): Promise; - content(): Promise; - setContent(html: string, options?: { - timeout?: number; - waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]; - }): Promise; - /** - * Adds a script tag into the current context. - * - * @remarks - * - * You can pass a URL, filepath or string of contents. Note that when running Puppeteer - * in a browser environment you cannot pass a filepath and should use either - * `url` or `content`. - */ - addScriptTag(options: { - url?: string; - path?: string; - content?: string; - type?: string; - }): Promise; - /** - * Adds a style tag into the current context. - * - * @remarks - * - * You can pass a URL, filepath or string of contents. Note that when running Puppeteer - * in a browser environment you cannot pass a filepath and should use either - * `url` or `content`. - * - */ - addStyleTag(options: { - url?: string; - path?: string; - content?: string; - }): Promise; - click(selector: string, options: { - delay?: number; - button?: MouseButton; - clickCount?: number; - }): Promise; - focus(selector: string): Promise; - hover(selector: string): Promise; - select(selector: string, ...values: string[]): Promise; - tap(selector: string): Promise; - type(selector: string, text: string, options?: { - delay: number; - }): Promise; - waitForSelector(selector: string, options: WaitForSelectorOptions): Promise; - waitForXPath(xpath: string, options: WaitForSelectorOptions): Promise; - waitForFunction(pageFunction: Function | string, options?: { - polling?: string | number; - timeout?: number; - }, ...args: SerializableOrJSHandle[]): Promise; - title(): Promise; - private _waitForSelectorOrXPath; -} -declare class WaitTask { - _domWorld: DOMWorld; - _polling: string | number; - _timeout: number; - _predicateBody: string; - _args: SerializableOrJSHandle[]; - _runCount: number; - promise: Promise; - _resolve: (x: JSHandle) => void; - _reject: (x: Error) => void; - _timeoutTimer?: NodeJS.Timeout; - _terminated: boolean; - constructor(domWorld: DOMWorld, predicateBody: Function | string, predicateQueryHandlerBody: Function | string | undefined, title: string, polling: string | number, timeout: number, ...args: SerializableOrJSHandle[]); - terminate(error: Error): void; - rerun(): Promise; - _cleanup(): void; -} -export {}; -//# sourceMappingURL=DOMWorld.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.d.ts.map deleted file mode 100644 index cc6a070e792..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"DOMWorld.d.ts","sourceRoot":"","sources":["../../../../src/common/DOMWorld.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;;AAIH,OAAO,EAEL,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAUxB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,gBAAgB,CAAC,CAAgC;IACzD,OAAO,CAAC,eAAe,CAAC,CAAmC;IAE3D,OAAO,CAAC,uBAAuB,CAAC,CAAwC;IAExE,OAAO,CAAC,SAAS,CAAS;IAC1B;;OAEG;IACH,UAAU,gBAAuB;gBAG/B,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,eAAe;IAQlC,KAAK,IAAI,KAAK;IAId,WAAW,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAa7C,WAAW,IAAI,OAAO;IAItB,OAAO,IAAI,IAAI;IAQf,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAQvC,cAAc,CAAC,WAAW,SAAS,QAAQ,GAAG,QAAQ,EAC1D,YAAY,EAAE,gBAAgB,EAC9B,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,WAAW,CAAC;IAKjB,QAAQ,CAAC,CAAC,SAAS,UAAU,EACjC,YAAY,EAAE,CAAC,EACf,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;IAQhD,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAMlD,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;IASnC,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAMhD,KAAK,CAAC,UAAU,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,CACZ,OAAO,EAAE,OAAO,EAChB,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,EACrC,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAKnC,MAAM,CAAC,UAAU,EACrB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,CACZ,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,EACrC,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAUnC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAM9C,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAW1B,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,uBAAuB,GAAG,uBAAuB,EAAE,CAAC;KAC5D,GACL,OAAO,CAAC,IAAI,CAAC;IA0BhB;;;;;;;;OAQG;IACG,YAAY,CAAC,OAAO,EAAE;QAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,aAAa,CAAC;IA0E1B;;;;;;;;;OASG;IACG,WAAW,CAAC,OAAO,EAAE;QACzB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,aAAa,CAAC;IAoEpB,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GACrE,OAAO,CAAC,IAAI,CAAC;IAOV,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQhE,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpC,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAC1B,OAAO,CAAC,IAAI,CAAC;IAOhB,eAAe,CACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIhC,YAAY,CACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIhC,eAAe,CACb,YAAY,EAAE,QAAQ,GAAG,MAAM,EAC/B,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,EAC7D,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,QAAQ,CAAC;IAgBd,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;YAIhB,uBAAuB;CAyEtC;AAED,cAAM,QAAQ;IACZ,SAAS,EAAE,QAAQ,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,SAAS,SAAK;IACd,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3B,QAAQ,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAC/B,WAAW,UAAS;gBAGlB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,QAAQ,GAAG,MAAM,EAChC,yBAAyB,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,EACxD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,EAAE,MAAM,EACf,GAAG,IAAI,EAAE,sBAAsB,EAAE;IAsDnC,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD5B,QAAQ,IAAI,IAAI;CAIjB"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.js deleted file mode 100644 index d0a17eae3c0..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DOMWorld.js +++ /dev/null @@ -1,520 +0,0 @@ -"use strict"; -/** - * Copyright 2019 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.DOMWorld = void 0; -const assert_js_1 = require("./assert.js"); -const helper_js_1 = require("./helper.js"); -const LifecycleWatcher_js_1 = require("./LifecycleWatcher.js"); -const Errors_js_1 = require("./Errors.js"); -const QueryHandler_js_1 = require("./QueryHandler.js"); -const environment_js_1 = require("../environment.js"); -/** - * @internal - */ -class DOMWorld { - constructor(frameManager, frame, timeoutSettings) { - this._documentPromise = null; - this._contextPromise = null; - this._contextResolveCallback = null; - this._detached = false; - /** - * internal - */ - this._waitTasks = new Set(); - this._frameManager = frameManager; - this._frame = frame; - this._timeoutSettings = timeoutSettings; - this._setContext(null); - } - frame() { - return this._frame; - } - _setContext(context) { - if (context) { - this._contextResolveCallback.call(null, context); - this._contextResolveCallback = null; - for (const waitTask of this._waitTasks) - waitTask.rerun(); - } - else { - this._documentPromise = null; - this._contextPromise = new Promise((fulfill) => { - this._contextResolveCallback = fulfill; - }); - } - } - _hasContext() { - return !this._contextResolveCallback; - } - _detach() { - this._detached = true; - for (const waitTask of this._waitTasks) - waitTask.terminate(new Error('waitForFunction failed: frame got detached.')); - } - executionContext() { - if (this._detached) - throw new Error(`Execution Context is not available in detached frame "${this._frame.url()}" (are you trying to evaluate?)`); - return this._contextPromise; - } - async evaluateHandle(pageFunction, ...args) { - const context = await this.executionContext(); - return context.evaluateHandle(pageFunction, ...args); - } - async evaluate(pageFunction, ...args) { - const context = await this.executionContext(); - return context.evaluate(pageFunction, ...args); - } - async $(selector) { - const document = await this._document(); - const value = await document.$(selector); - return value; - } - async _document() { - if (this._documentPromise) - return this._documentPromise; - this._documentPromise = this.executionContext().then(async (context) => { - const document = await context.evaluateHandle('document'); - return document.asElement(); - }); - return this._documentPromise; - } - async $x(expression) { - const document = await this._document(); - const value = await document.$x(expression); - return value; - } - async $eval(selector, pageFunction, ...args) { - const document = await this._document(); - return document.$eval(selector, pageFunction, ...args); - } - async $$eval(selector, pageFunction, ...args) { - const document = await this._document(); - const value = await document.$$eval(selector, pageFunction, ...args); - return value; - } - async $$(selector) { - const document = await this._document(); - const value = await document.$$(selector); - return value; - } - async content() { - return await this.evaluate(() => { - let retVal = ''; - if (document.doctype) - retVal = new XMLSerializer().serializeToString(document.doctype); - if (document.documentElement) - retVal += document.documentElement.outerHTML; - return retVal; - }); - } - async setContent(html, options = {}) { - const { waitUntil = ['load'], timeout = this._timeoutSettings.navigationTimeout(), } = options; - // We rely upon the fact that document.open() will reset frame lifecycle with "init" - // lifecycle event. @see https://crrev.com/608658 - await this.evaluate((html) => { - document.open(); - document.write(html); - document.close(); - }, html); - const watcher = new LifecycleWatcher_js_1.LifecycleWatcher(this._frameManager, this._frame, waitUntil, timeout); - const error = await Promise.race([ - watcher.timeoutOrTerminationPromise(), - watcher.lifecyclePromise(), - ]); - watcher.dispose(); - if (error) - throw error; - } - /** - * Adds a script tag into the current context. - * - * @remarks - * - * You can pass a URL, filepath or string of contents. Note that when running Puppeteer - * in a browser environment you cannot pass a filepath and should use either - * `url` or `content`. - */ - async addScriptTag(options) { - const { url = null, path = null, content = null, type = '' } = options; - if (url !== null) { - try { - const context = await this.executionContext(); - return (await context.evaluateHandle(addScriptUrl, url, type)).asElement(); - } - catch (error) { - throw new Error(`Loading script from ${url} failed`); - } - } - if (path !== null) { - if (!environment_js_1.isNode) { - throw new Error('Cannot pass a filepath to addScriptTag in the browser environment.'); - } - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require('fs'); - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { promisify } = require('util'); - const readFileAsync = promisify(fs.readFile); - let contents = await readFileAsync(path, 'utf8'); - contents += '//# sourceURL=' + path.replace(/\n/g, ''); - const context = await this.executionContext(); - return (await context.evaluateHandle(addScriptContent, contents, type)).asElement(); - } - if (content !== null) { - const context = await this.executionContext(); - return (await context.evaluateHandle(addScriptContent, content, type)).asElement(); - } - throw new Error('Provide an object with a `url`, `path` or `content` property'); - async function addScriptUrl(url, type) { - const script = document.createElement('script'); - script.src = url; - if (type) - script.type = type; - const promise = new Promise((res, rej) => { - script.onload = res; - script.onerror = rej; - }); - document.head.appendChild(script); - await promise; - return script; - } - function addScriptContent(content, type = 'text/javascript') { - const script = document.createElement('script'); - script.type = type; - script.text = content; - let error = null; - script.onerror = (e) => (error = e); - document.head.appendChild(script); - if (error) - throw error; - return script; - } - } - /** - * Adds a style tag into the current context. - * - * @remarks - * - * You can pass a URL, filepath or string of contents. Note that when running Puppeteer - * in a browser environment you cannot pass a filepath and should use either - * `url` or `content`. - * - */ - async addStyleTag(options) { - const { url = null, path = null, content = null } = options; - if (url !== null) { - try { - const context = await this.executionContext(); - return (await context.evaluateHandle(addStyleUrl, url)).asElement(); - } - catch (error) { - throw new Error(`Loading style from ${url} failed`); - } - } - if (path !== null) { - if (!environment_js_1.isNode) { - throw new Error('Cannot pass a filepath to addStyleTag in the browser environment.'); - } - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require('fs'); - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { promisify } = require('util'); - const readFileAsync = promisify(fs.readFile); - let contents = await readFileAsync(path, 'utf8'); - contents += '/*# sourceURL=' + path.replace(/\n/g, '') + '*/'; - const context = await this.executionContext(); - return (await context.evaluateHandle(addStyleContent, contents)).asElement(); - } - if (content !== null) { - const context = await this.executionContext(); - return (await context.evaluateHandle(addStyleContent, content)).asElement(); - } - throw new Error('Provide an object with a `url`, `path` or `content` property'); - async function addStyleUrl(url) { - const link = document.createElement('link'); - link.rel = 'stylesheet'; - link.href = url; - const promise = new Promise((res, rej) => { - link.onload = res; - link.onerror = rej; - }); - document.head.appendChild(link); - await promise; - return link; - } - async function addStyleContent(content) { - const style = document.createElement('style'); - style.type = 'text/css'; - style.appendChild(document.createTextNode(content)); - const promise = new Promise((res, rej) => { - style.onload = res; - style.onerror = rej; - }); - document.head.appendChild(style); - await promise; - return style; - } - } - async click(selector, options) { - const handle = await this.$(selector); - assert_js_1.assert(handle, 'No node found for selector: ' + selector); - await handle.click(options); - await handle.dispose(); - } - async focus(selector) { - const handle = await this.$(selector); - assert_js_1.assert(handle, 'No node found for selector: ' + selector); - await handle.focus(); - await handle.dispose(); - } - async hover(selector) { - const handle = await this.$(selector); - assert_js_1.assert(handle, 'No node found for selector: ' + selector); - await handle.hover(); - await handle.dispose(); - } - async select(selector, ...values) { - const handle = await this.$(selector); - assert_js_1.assert(handle, 'No node found for selector: ' + selector); - const result = await handle.select(...values); - await handle.dispose(); - return result; - } - async tap(selector) { - const handle = await this.$(selector); - assert_js_1.assert(handle, 'No node found for selector: ' + selector); - await handle.tap(); - await handle.dispose(); - } - async type(selector, text, options) { - const handle = await this.$(selector); - assert_js_1.assert(handle, 'No node found for selector: ' + selector); - await handle.type(text, options); - await handle.dispose(); - } - waitForSelector(selector, options) { - return this._waitForSelectorOrXPath(selector, false, options); - } - waitForXPath(xpath, options) { - return this._waitForSelectorOrXPath(xpath, true, options); - } - waitForFunction(pageFunction, options = {}, ...args) { - const { polling = 'raf', timeout = this._timeoutSettings.timeout(), } = options; - return new WaitTask(this, pageFunction, undefined, 'function', polling, timeout, ...args).promise; - } - async title() { - return this.evaluate(() => document.title); - } - async _waitForSelectorOrXPath(selectorOrXPath, isXPath, options = {}) { - const { visible: waitForVisible = false, hidden: waitForHidden = false, timeout = this._timeoutSettings.timeout(), } = options; - const polling = waitForVisible || waitForHidden ? 'raf' : 'mutation'; - const title = `${isXPath ? 'XPath' : 'selector'} "${selectorOrXPath}"${waitForHidden ? ' to be hidden' : ''}`; - const { updatedSelector, queryHandler } = QueryHandler_js_1.getQueryHandlerAndSelector(selectorOrXPath); - const waitTask = new WaitTask(this, predicate, queryHandler.queryOne, title, polling, timeout, updatedSelector, isXPath, waitForVisible, waitForHidden); - const handle = await waitTask.promise; - if (!handle.asElement()) { - await handle.dispose(); - return null; - } - return handle.asElement(); - function predicate(selectorOrXPath, isXPath, waitForVisible, waitForHidden) { - const node = isXPath - ? document.evaluate(selectorOrXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue - : predicateQueryHandler - ? predicateQueryHandler(document, selectorOrXPath) - : document.querySelector(selectorOrXPath); - if (!node) - return waitForHidden; - if (!waitForVisible && !waitForHidden) - return node; - const element = node.nodeType === Node.TEXT_NODE - ? node.parentElement - : node; - const style = window.getComputedStyle(element); - const isVisible = style && style.visibility !== 'hidden' && hasVisibleBoundingBox(); - const success = waitForVisible === isVisible || waitForHidden === !isVisible; - return success ? node : null; - function hasVisibleBoundingBox() { - const rect = element.getBoundingClientRect(); - return !!(rect.top || rect.bottom || rect.width || rect.height); - } - } - } -} -exports.DOMWorld = DOMWorld; -class WaitTask { - constructor(domWorld, predicateBody, predicateQueryHandlerBody, title, polling, timeout, ...args) { - this._runCount = 0; - this._terminated = false; - if (helper_js_1.helper.isString(polling)) - assert_js_1.assert(polling === 'raf' || polling === 'mutation', 'Unknown polling option: ' + polling); - else if (helper_js_1.helper.isNumber(polling)) - assert_js_1.assert(polling > 0, 'Cannot poll with non-positive interval: ' + polling); - else - throw new Error('Unknown polling options: ' + polling); - function getPredicateBody(predicateBody, predicateQueryHandlerBody) { - if (helper_js_1.helper.isString(predicateBody)) - return `return (${predicateBody});`; - if (predicateQueryHandlerBody) { - return ` - return (function wrapper(args) { - const predicateQueryHandler = ${predicateQueryHandlerBody}; - return (${predicateBody})(...args); - })(args);`; - } - return `return (${predicateBody})(...args);`; - } - this._domWorld = domWorld; - this._polling = polling; - this._timeout = timeout; - this._predicateBody = getPredicateBody(predicateBody, predicateQueryHandlerBody); - this._args = args; - this._runCount = 0; - domWorld._waitTasks.add(this); - this.promise = new Promise((resolve, reject) => { - this._resolve = resolve; - this._reject = reject; - }); - // Since page navigation requires us to re-install the pageScript, we should track - // timeout on our end. - if (timeout) { - const timeoutError = new Errors_js_1.TimeoutError(`waiting for ${title} failed: timeout ${timeout}ms exceeded`); - this._timeoutTimer = setTimeout(() => this.terminate(timeoutError), timeout); - } - this.rerun(); - } - terminate(error) { - this._terminated = true; - this._reject(error); - this._cleanup(); - } - async rerun() { - const runCount = ++this._runCount; - /** @type {?JSHandle} */ - let success = null; - let error = null; - try { - success = await (await this._domWorld.executionContext()).evaluateHandle(waitForPredicatePageFunction, this._predicateBody, this._polling, this._timeout, ...this._args); - } - catch (error_) { - error = error_; - } - if (this._terminated || runCount !== this._runCount) { - if (success) - await success.dispose(); - return; - } - // Ignore timeouts in pageScript - we track timeouts ourselves. - // If the frame's execution context has already changed, `frame.evaluate` will - // throw an error - ignore this predicate run altogether. - if (!error && - (await this._domWorld.evaluate((s) => !s, success).catch(() => true))) { - await success.dispose(); - return; - } - // When the page is navigated, the promise is rejected. - // We will try again in the new execution context. - if (error && error.message.includes('Execution context was destroyed')) - return; - // We could have tried to evaluate in a context which was already - // destroyed. - if (error && - error.message.includes('Cannot find context with specified id')) - return; - if (error) - this._reject(error); - else - this._resolve(success); - this._cleanup(); - } - _cleanup() { - clearTimeout(this._timeoutTimer); - this._domWorld._waitTasks.delete(this); - } -} -async function waitForPredicatePageFunction(predicateBody, polling, timeout, ...args) { - const predicate = new Function('...args', predicateBody); - let timedOut = false; - if (timeout) - setTimeout(() => (timedOut = true), timeout); - if (polling === 'raf') - return await pollRaf(); - if (polling === 'mutation') - return await pollMutation(); - if (typeof polling === 'number') - return await pollInterval(polling); - /** - * @returns {!Promise<*>} - */ - async function pollMutation() { - const success = await predicate(...args); - if (success) - return Promise.resolve(success); - let fulfill; - const result = new Promise((x) => (fulfill = x)); - const observer = new MutationObserver(async () => { - if (timedOut) { - observer.disconnect(); - fulfill(); - } - const success = await predicate(...args); - if (success) { - observer.disconnect(); - fulfill(success); - } - }); - observer.observe(document, { - childList: true, - subtree: true, - attributes: true, - }); - return result; - } - async function pollRaf() { - let fulfill; - const result = new Promise((x) => (fulfill = x)); - await onRaf(); - return result; - async function onRaf() { - if (timedOut) { - fulfill(); - return; - } - const success = await predicate(...args); - if (success) - fulfill(success); - else - requestAnimationFrame(onRaf); - } - } - async function pollInterval(pollInterval) { - let fulfill; - const result = new Promise((x) => (fulfill = x)); - await onTimeout(); - return result; - async function onTimeout() { - if (timedOut) { - fulfill(); - return; - } - const success = await predicate(...args); - if (success) - fulfill(success); - else - setTimeout(onTimeout, pollInterval); - } - } -} diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.d.ts deleted file mode 100644 index 77b2e5bcd6f..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * A debug function that can be used in any environment. - * - * @remarks - * - * If used in Node, it falls back to the - * {@link https://www.npmjs.com/package/debug | debug module}. In the browser it - * uses `console.log`. - * - * @param prefix - this will be prefixed to each log. - * @returns a function that can be called to log to that debug channel. - * - * In Node, use the `DEBUG` environment variable to control logging: - * - * ``` - * DEBUG=* // logs all channels - * DEBUG=foo // logs the `foo` channel - * DEBUG=foo* // logs any channels starting with `foo` - * ``` - * - * In the browser, set `window.__PUPPETEER_DEBUG` to a string: - * - * ``` - * window.__PUPPETEER_DEBUG='*'; // logs all channels - * window.__PUPPETEER_DEBUG='foo'; // logs the `foo` channel - * window.__PUPPETEER_DEBUG='foo*'; // logs any channels starting with `foo` - * ``` - * - * @example - * ``` - * const log = debug('Page'); - * - * log('new page created') - * // logs "Page: new page created" - * ``` - */ -export declare const debug: (prefix: string) => (...args: unknown[]) => void; -//# sourceMappingURL=Debug.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.d.ts.map deleted file mode 100644 index 2f3bd79bec9..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Debug.d.ts","sourceRoot":"","sources":["../../../../src/common/Debug.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,KAAK,WAAY,MAAM,eAAc,OAAO,EAAE,KAAK,IA4B/D,CAAC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.js deleted file mode 100644 index 6a01693c17d..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Debug.js +++ /dev/null @@ -1,80 +0,0 @@ -"use strict"; -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.debug = void 0; -const environment_js_1 = require("../environment.js"); -/** - * A debug function that can be used in any environment. - * - * @remarks - * - * If used in Node, it falls back to the - * {@link https://www.npmjs.com/package/debug | debug module}. In the browser it - * uses `console.log`. - * - * @param prefix - this will be prefixed to each log. - * @returns a function that can be called to log to that debug channel. - * - * In Node, use the `DEBUG` environment variable to control logging: - * - * ``` - * DEBUG=* // logs all channels - * DEBUG=foo // logs the `foo` channel - * DEBUG=foo* // logs any channels starting with `foo` - * ``` - * - * In the browser, set `window.__PUPPETEER_DEBUG` to a string: - * - * ``` - * window.__PUPPETEER_DEBUG='*'; // logs all channels - * window.__PUPPETEER_DEBUG='foo'; // logs the `foo` channel - * window.__PUPPETEER_DEBUG='foo*'; // logs any channels starting with `foo` - * ``` - * - * @example - * ``` - * const log = debug('Page'); - * - * log('new page created') - * // logs "Page: new page created" - * ``` - */ -exports.debug = (prefix) => { - if (environment_js_1.isNode) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - return require('debug')(prefix); - } - return (...logArgs) => { - const debugLevel = globalThis.__PUPPETEER_DEBUG; - if (!debugLevel) - return; - const everythingShouldBeLogged = debugLevel === '*'; - const prefixMatchesDebugLevel = everythingShouldBeLogged || - /** - * If the debug level is `foo*`, that means we match any prefix that - * starts with `foo`. If the level is `foo`, we match only the prefix - * `foo`. - */ - (debugLevel.endsWith('*') - ? prefix.startsWith(debugLevel) - : prefix === debugLevel); - if (!prefixMatchesDebugLevel) - return; - // eslint-disable-next-line no-console - console.log(`${prefix}:`, ...logArgs); - }; -}; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.d.ts deleted file mode 100644 index f74e0171162..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -interface Device { - name: string; - userAgent: string; - viewport: { - width: number; - height: number; - deviceScaleFactor: number; - isMobile: boolean; - hasTouch: boolean; - isLandscape: boolean; - }; -} -export declare type DevicesMap = { - [name: string]: Device; -}; -declare const devicesMap: DevicesMap; -export { devicesMap }; -//# sourceMappingURL=DeviceDescriptors.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.d.ts.map deleted file mode 100644 index 6215766fb6e..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"DeviceDescriptors.d.ts","sourceRoot":"","sources":["../../../../src/common/DeviceDescriptors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;CACH;AAg6BD,oBAAY,UAAU,GAAG;IACvB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,UAAU,EAAE,UAAe,CAAC;AAIlC,OAAO,EAAE,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.js deleted file mode 100644 index 60e7af7c142..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DeviceDescriptors.js +++ /dev/null @@ -1,876 +0,0 @@ -"use strict"; -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.devicesMap = void 0; -const devices = [ - { - name: 'Blackberry PlayBook', - userAgent: 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+', - viewport: { - width: 600, - height: 1024, - deviceScaleFactor: 1, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Blackberry PlayBook landscape', - userAgent: 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+', - viewport: { - width: 1024, - height: 600, - deviceScaleFactor: 1, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'BlackBerry Z30', - userAgent: 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'BlackBerry Z30 landscape', - userAgent: 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Galaxy Note 3', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Galaxy Note 3 landscape', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Galaxy Note II', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Galaxy Note II landscape', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Galaxy S III', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Galaxy S III landscape', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Galaxy S5', - userAgent: 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Galaxy S5 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPad', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', - viewport: { - width: 768, - height: 1024, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPad landscape', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', - viewport: { - width: 1024, - height: 768, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPad Mini', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', - viewport: { - width: 768, - height: 1024, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPad Mini landscape', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', - viewport: { - width: 1024, - height: 768, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPad Pro', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', - viewport: { - width: 1024, - height: 1366, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPad Pro landscape', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', - viewport: { - width: 1366, - height: 1024, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 4', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53', - viewport: { - width: 320, - height: 480, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 4 landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53', - viewport: { - width: 480, - height: 320, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 5', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', - viewport: { - width: 320, - height: 568, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 5 landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', - viewport: { - width: 568, - height: 320, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 6', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 375, - height: 667, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 6 landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 667, - height: 375, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 6 Plus', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 414, - height: 736, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 6 Plus landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 736, - height: 414, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 7', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 375, - height: 667, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 7 landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 667, - height: 375, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 7 Plus', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 414, - height: 736, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 7 Plus landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 736, - height: 414, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 8', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 375, - height: 667, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 8 landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 667, - height: 375, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone 8 Plus', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 414, - height: 736, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone 8 Plus landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 736, - height: 414, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone SE', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', - viewport: { - width: 320, - height: 568, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone SE landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', - viewport: { - width: 568, - height: 320, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone X', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 375, - height: 812, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone X landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', - viewport: { - width: 812, - height: 375, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'iPhone XR', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - viewport: { - width: 414, - height: 896, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'iPhone XR landscape', - userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - viewport: { - width: 896, - height: 414, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'JioPhone 2', - userAgent: 'Mozilla/5.0 (Mobile; LYF/F300B/LYF-F300B-001-01-15-130718-i;Android; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5', - viewport: { - width: 240, - height: 320, - deviceScaleFactor: 1, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'JioPhone 2 landscape', - userAgent: 'Mozilla/5.0 (Mobile; LYF/F300B/LYF-F300B-001-01-15-130718-i;Android; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5', - viewport: { - width: 320, - height: 240, - deviceScaleFactor: 1, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Kindle Fire HDX', - userAgent: 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true', - viewport: { - width: 800, - height: 1280, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Kindle Fire HDX landscape', - userAgent: 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true', - viewport: { - width: 1280, - height: 800, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'LG Optimus L70', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 384, - height: 640, - deviceScaleFactor: 1.25, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'LG Optimus L70 landscape', - userAgent: 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 640, - height: 384, - deviceScaleFactor: 1.25, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Microsoft Lumia 550', - userAgent: 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Microsoft Lumia 950', - userAgent: 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 4, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Microsoft Lumia 950 landscape', - userAgent: 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 4, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 10', - userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', - viewport: { - width: 800, - height: 1280, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 10 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', - viewport: { - width: 1280, - height: 800, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 4', - userAgent: 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 384, - height: 640, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 4 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 640, - height: 384, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 5', - userAgent: 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 360, - height: 640, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 5 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 640, - height: 360, - deviceScaleFactor: 3, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 5X', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 412, - height: 732, - deviceScaleFactor: 2.625, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 5X landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 732, - height: 412, - deviceScaleFactor: 2.625, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 6', - userAgent: 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 412, - height: 732, - deviceScaleFactor: 3.5, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 6 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 732, - height: 412, - deviceScaleFactor: 3.5, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 6P', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 412, - height: 732, - deviceScaleFactor: 3.5, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 6P landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 732, - height: 412, - deviceScaleFactor: 3.5, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nexus 7', - userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', - viewport: { - width: 600, - height: 960, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nexus 7 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', - viewport: { - width: 960, - height: 600, - deviceScaleFactor: 2, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nokia Lumia 520', - userAgent: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)', - viewport: { - width: 320, - height: 533, - deviceScaleFactor: 1.5, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nokia Lumia 520 landscape', - userAgent: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)', - viewport: { - width: 533, - height: 320, - deviceScaleFactor: 1.5, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Nokia N9', - userAgent: 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13', - viewport: { - width: 480, - height: 854, - deviceScaleFactor: 1, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Nokia N9 landscape', - userAgent: 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13', - viewport: { - width: 854, - height: 480, - deviceScaleFactor: 1, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Pixel 2', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 411, - height: 731, - deviceScaleFactor: 2.625, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Pixel 2 landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 731, - height: 411, - deviceScaleFactor: 2.625, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, - { - name: 'Pixel 2 XL', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 411, - height: 823, - deviceScaleFactor: 3.5, - isMobile: true, - hasTouch: true, - isLandscape: false, - }, - }, - { - name: 'Pixel 2 XL landscape', - userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', - viewport: { - width: 823, - height: 411, - deviceScaleFactor: 3.5, - isMobile: true, - hasTouch: true, - isLandscape: true, - }, - }, -]; -const devicesMap = {}; -exports.devicesMap = devicesMap; -for (const device of devices) - devicesMap[device.name] = device; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.d.ts deleted file mode 100644 index 660e1d946b8..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.d.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Protocol } from 'devtools-protocol'; - -import { CDPSession } from './Connection.js'; - -/** - * Dialog instances are dispatched by the {@link Page} via the `dialog` event. - * - * @remarks - * - * @example - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * page.on('dialog', async dialog => { - * console.log(dialog.message()); - * await dialog.dismiss(); - * await browser.close(); - * }); - * page.evaluate(() => alert('1')); - * })(); - * ``` - */ -export declare class Dialog { - private _client; - private _type; - private _message; - private _defaultValue; - private _handled; - /** - * @internal - */ - constructor(client: CDPSession, type: Protocol.Page.DialogType, message: string, defaultValue?: string); - /** - * @returns The type of the dialog. - */ - type(): Protocol.Page.DialogType; - /** - * @returns The message displayed in the dialog. - */ - message(): string; - /** - * @returns The default value of the prompt, or an empty string if the dialog - * is not a `prompt`. - */ - defaultValue(): string; - /** - * @param promptText - optional text that will be entered in the dialog - * prompt. Has no effect if the dialog's type is not `prompt`. - * - * @returns A promise that resolves when the dialog has been accepted. - */ - accept(promptText?: string): Promise; - /** - * @returns A promise which will resolve once the dialog has been dismissed - */ - dismiss(): Promise; -} -//# sourceMappingURL=Dialog.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.d.ts.map deleted file mode 100644 index d2fee6a7328..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../../src/common/Dialog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAS;IAEzB;;OAEG;gBAED,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,EAC9B,OAAO,EAAE,MAAM,EACf,YAAY,SAAK;IAQnB;;OAEG;IACH,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU;IAIhC;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;;OAGG;IACH,YAAY,IAAI,MAAM;IAItB;;;;;OAKG;IACG,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAO/B"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.js deleted file mode 100644 index 0013a0d1016..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Dialog.js +++ /dev/null @@ -1,96 +0,0 @@ -"use strict"; -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Dialog = void 0; -const assert_js_1 = require("./assert.js"); -/** - * Dialog instances are dispatched by the {@link Page} via the `dialog` event. - * - * @remarks - * - * @example - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * page.on('dialog', async dialog => { - * console.log(dialog.message()); - * await dialog.dismiss(); - * await browser.close(); - * }); - * page.evaluate(() => alert('1')); - * })(); - * ``` - */ -class Dialog { - /** - * @internal - */ - constructor(client, type, message, defaultValue = '') { - this._handled = false; - this._client = client; - this._type = type; - this._message = message; - this._defaultValue = defaultValue; - } - /** - * @returns The type of the dialog. - */ - type() { - return this._type; - } - /** - * @returns The message displayed in the dialog. - */ - message() { - return this._message; - } - /** - * @returns The default value of the prompt, or an empty string if the dialog - * is not a `prompt`. - */ - defaultValue() { - return this._defaultValue; - } - /** - * @param promptText - optional text that will be entered in the dialog - * prompt. Has no effect if the dialog's type is not `prompt`. - * - * @returns A promise that resolves when the dialog has been accepted. - */ - async accept(promptText) { - assert_js_1.assert(!this._handled, 'Cannot accept dialog which is already handled!'); - this._handled = true; - await this._client.send('Page.handleJavaScriptDialog', { - accept: true, - promptText: promptText, - }); - } - /** - * @returns A promise which will resolve once the dialog has been dismissed - */ - async dismiss() { - assert_js_1.assert(!this._handled, 'Cannot dismiss dialog which is already handled!'); - this._handled = true; - await this._client.send('Page.handleJavaScriptDialog', { - accept: false, - }); - } -} -exports.Dialog = Dialog; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.d.ts deleted file mode 100644 index c9abdc158a4..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { CDPSession } from './Connection.js'; -import { Viewport } from './PuppeteerViewport.js'; -export declare class EmulationManager { - _client: CDPSession; - _emulatingMobile: boolean; - _hasTouch: boolean; - constructor(client: CDPSession); - emulateViewport(viewport: Viewport): Promise; -} -//# sourceMappingURL=EmulationManager.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.d.ts.map deleted file mode 100644 index 0cfbf8e6a60..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"EmulationManager.d.ts","sourceRoot":"","sources":["../../../../src/common/EmulationManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,qBAAa,gBAAgB;IAC3B,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,UAAS;IACzB,SAAS,UAAS;gBAEN,MAAM,EAAE,UAAU;IAIxB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;CA6B5D"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.js deleted file mode 100644 index c0914dbea0c..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EmulationManager.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.EmulationManager = void 0; -class EmulationManager { - constructor(client) { - this._emulatingMobile = false; - this._hasTouch = false; - this._client = client; - } - async emulateViewport(viewport) { - const mobile = viewport.isMobile || false; - const width = viewport.width; - const height = viewport.height; - const deviceScaleFactor = viewport.deviceScaleFactor || 1; - const screenOrientation = viewport.isLandscape - ? { angle: 90, type: 'landscapePrimary' } - : { angle: 0, type: 'portraitPrimary' }; - const hasTouch = viewport.hasTouch || false; - await Promise.all([ - this._client.send('Emulation.setDeviceMetricsOverride', { - mobile, - width, - height, - deviceScaleFactor, - screenOrientation, - }), - this._client.send('Emulation.setTouchEmulationEnabled', { - enabled: hasTouch, - }), - ]); - const reloadNeeded = this._emulatingMobile !== mobile || this._hasTouch !== hasTouch; - this._emulatingMobile = mobile; - this._hasTouch = hasTouch; - return reloadNeeded; - } -} -exports.EmulationManager = EmulationManager; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.d.ts deleted file mode 100644 index a0b094b522a..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright 2018 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -declare class CustomError extends Error { - constructor(message: string); -} -/** - * TimeoutError is emitted whenever certain operations are terminated due to timeout. - * - * @remarks - * - * Example operations are {@link Page.waitForSelector | page.waitForSelector} - * or {@link Puppeteer.launch | puppeteer.launch}. - * - * @public - */ -export declare class TimeoutError extends CustomError { -} -export declare type PuppeteerErrors = Record; -export declare const puppeteerErrors: PuppeteerErrors; -export {}; -//# sourceMappingURL=Errors.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.d.ts.map deleted file mode 100644 index 442a102c159..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../../../../src/common/Errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAM,WAAY,SAAQ,KAAK;gBACjB,OAAO,EAAE,MAAM;CAK5B;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAa,SAAQ,WAAW;CAAG;AAEhD,oBAAY,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,WAAW,CAAC,CAAC;AAEjE,eAAO,MAAM,eAAe,EAAE,eAE7B,CAAC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.js deleted file mode 100644 index 1ce3eb058e4..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Errors.js +++ /dev/null @@ -1,41 +0,0 @@ -"use strict"; -/** - * Copyright 2018 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.puppeteerErrors = exports.TimeoutError = void 0; -class CustomError extends Error { - constructor(message) { - super(message); - this.name = this.constructor.name; - Error.captureStackTrace(this, this.constructor); - } -} -/** - * TimeoutError is emitted whenever certain operations are terminated due to timeout. - * - * @remarks - * - * Example operations are {@link Page.waitForSelector | page.waitForSelector} - * or {@link Puppeteer.launch | puppeteer.launch}. - * - * @public - */ -class TimeoutError extends CustomError { -} -exports.TimeoutError = TimeoutError; -exports.puppeteerErrors = { - TimeoutError, -}; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EvalTypes.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EvalTypes.d.ts deleted file mode 100644 index 46fbd894f6e..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EvalTypes.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ElementHandle , JSHandle} from './JSHandle.js'; - -/** - * @public - */ -export declare type EvaluateFn = string | ((arg1: T, ...args: unknown[]) => unknown); -export declare type UnwrapPromiseLike = T extends PromiseLike ? U : T; -/** - * @public - */ -export declare type EvaluateFnReturnType = T extends (...args: unknown[]) => infer R ? R : unknown; -/** - * @public - */ -export declare type EvaluateHandleFn = string | ((...args: unknown[]) => unknown); -/** - * @public - */ -export declare type Serializable = number | string | boolean | null | BigInt | JSONArray | JSONObject; -/** - * @public - */ -export declare type JSONArray = Serializable[]; -/** - * @public - */ -export interface JSONObject { - [key: string]: Serializable; -} -/** - * @public - */ -export declare type SerializableOrJSHandle = Serializable | JSHandle; -/** - * Wraps a DOM element into an ElementHandle instance - * @public - **/ -export declare type WrapElementHandle = X extends Element ? ElementHandle : X; -/** - * Unwraps a DOM element out of an ElementHandle instance - * @public - **/ -export declare type UnwrapElementHandle = X extends ElementHandle ? E : X; -//# sourceMappingURL=EvalTypes.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EvalTypes.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EvalTypes.d.ts.map deleted file mode 100644 index cb2b74fe21d..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EvalTypes.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"EvalTypes.d.ts","sourceRoot":"","sources":["../../../../src/common/EvalTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAExD;;GAEG;AACH,oBAAY,UAAU,CAAC,CAAC,GAAG,OAAO,IAC9B,MAAM,GACN,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC;AAE/C,oBAAY,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAE1E;;GAEG;AACH,oBAAY,oBAAoB,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,CACjE,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,MAAM,CAAC,GACR,CAAC,GACD,OAAO,CAAC;AAEZ;;GAEG;AACH,oBAAY,gBAAgB,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC;AAE1E;;GAEG;AACH,oBAAY,YAAY,GACpB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,MAAM,GACN,SAAS,GACT,UAAU,CAAC;AAEf;;GAEG;AACH,oBAAY,SAAS,GAAG,YAAY,EAAE,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;CAC7B;AAED;;GAEG;AACH,oBAAY,sBAAsB,GAAG,YAAY,GAAG,QAAQ,CAAC;AAE7D;;;IAGI;AACJ,oBAAY,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAE5E;;;IAGI;AACJ,oBAAY,mBAAmB,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts deleted file mode 100644 index fa24ddd3818..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { EventType, Handler } from '../../vendor/mitt/src/index.js'; -/** - * @internal - */ -export interface CommonEventEmitter { - on(event: EventType, handler: Handler): CommonEventEmitter; - off(event: EventType, handler: Handler): CommonEventEmitter; - addListener(event: EventType, handler: Handler): CommonEventEmitter; - removeListener(event: EventType, handler: Handler): CommonEventEmitter; - emit(event: EventType, eventData?: any): boolean; - once(event: EventType, handler: Handler): CommonEventEmitter; - listenerCount(event: string): number; - removeAllListeners(event?: EventType): CommonEventEmitter; -} -/** - * The EventEmitter class that many Puppeteer classes extend. - * - * @remarks - * - * This allows you to listen to events that Puppeteer classes fire and act - * accordingly. Therefore you'll mostly use {@link EventEmitter.on | on} and - * {@link EventEmitter.off | off} to bind - * and unbind to event listeners. - * - * @public - */ -export declare class EventEmitter implements CommonEventEmitter { - private emitter; - private eventsMap; - /** - * @internal - */ - constructor(); - /** - * Bind an event listener to fire when an event occurs. - * @param event - the event type you'd like to listen to. Can be a string or symbol. - * @param handler - the function to be called when the event occurs. - * @returns `this` to enable you to chain calls. - */ - on(event: EventType, handler: Handler): EventEmitter; - /** - * Remove an event listener from firing. - * @param event - the event type you'd like to stop listening to. - * @param handler - the function that should be removed. - * @returns `this` to enable you to chain calls. - */ - off(event: EventType, handler: Handler): EventEmitter; - /** - * Remove an event listener. - * @deprecated please use `off` instead. - */ - removeListener(event: EventType, handler: Handler): EventEmitter; - /** - * Add an event listener. - * @deprecated please use `on` instead. - */ - addListener(event: EventType, handler: Handler): EventEmitter; - /** - * Emit an event and call any associated listeners. - * - * @param event - the event you'd like to emit - * @param eventData - any data you'd like to emit with the event - * @returns `true` if there are any listeners, `false` if there are not. - */ - emit(event: EventType, eventData?: any): boolean; - /** - * Like `on` but the listener will only be fired once and then it will be removed. - * @param event - the event you'd like to listen to - * @param handler - the handler function to run when the event occurs - * @returns `this` to enable you to chain calls. - */ - once(event: EventType, handler: Handler): EventEmitter; - /** - * Gets the number of listeners for a given event. - * - * @param event - the event to get the listener count for - * @returns the number of listeners bound to the given event - */ - listenerCount(event: EventType): number; - /** - * Removes all listeners. If given an event argument, it will remove only - * listeners for that event. - * @param event - the event to remove listeners for. - * @returns `this` to enable you to chain calls. - */ - removeAllListeners(event?: EventType): EventEmitter; - private eventListenersCount; -} -//# sourceMappingURL=EventEmitter.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts.map deleted file mode 100644 index fa7686c64c2..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../../../../src/common/EventEmitter.ts"],"names":[],"mappings":"AAAA,OAAa,EAEX,SAAS,EACT,OAAO,EACR,MAAM,gCAAgC,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,CAAC;IAC3D,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,CAAC;IAK5D,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,CAAC;IACpE,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,CAAC;IACvE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC;IACjD,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,CAAC;IAC7D,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAErC,kBAAkB,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,kBAAkB,CAAC;CAC3D;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,YAAa,YAAW,kBAAkB;IACrD,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,SAAS,CAAmC;IAEpD;;OAEG;;IAKH;;;;;OAKG;IACH,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY;IAKpD;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY;IAKrD;;;OAGG;IACH,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY;IAKhE;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY;IAK7D;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,GAAG,GAAG,OAAO;IAKhD;;;;;OAKG;IACH,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY;IAStD;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM;IAIvC;;;;;OAKG;IACH,kBAAkB,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,YAAY;IASnD,OAAO,CAAC,mBAAmB;CAG5B"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.js deleted file mode 100644 index 1e6d5345d5f..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.js +++ /dev/null @@ -1,116 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.EventEmitter = void 0; -const index_js_1 = __importDefault(require("../../vendor/mitt/src/index.js")); -/** - * The EventEmitter class that many Puppeteer classes extend. - * - * @remarks - * - * This allows you to listen to events that Puppeteer classes fire and act - * accordingly. Therefore you'll mostly use {@link EventEmitter.on | on} and - * {@link EventEmitter.off | off} to bind - * and unbind to event listeners. - * - * @public - */ -class EventEmitter { - /** - * @internal - */ - constructor() { - this.eventsMap = new Map(); - this.emitter = index_js_1.default(this.eventsMap); - } - /** - * Bind an event listener to fire when an event occurs. - * @param event - the event type you'd like to listen to. Can be a string or symbol. - * @param handler - the function to be called when the event occurs. - * @returns `this` to enable you to chain calls. - */ - on(event, handler) { - this.emitter.on(event, handler); - return this; - } - /** - * Remove an event listener from firing. - * @param event - the event type you'd like to stop listening to. - * @param handler - the function that should be removed. - * @returns `this` to enable you to chain calls. - */ - off(event, handler) { - this.emitter.off(event, handler); - return this; - } - /** - * Remove an event listener. - * @deprecated please use `off` instead. - */ - removeListener(event, handler) { - this.off(event, handler); - return this; - } - /** - * Add an event listener. - * @deprecated please use `on` instead. - */ - addListener(event, handler) { - this.on(event, handler); - return this; - } - /** - * Emit an event and call any associated listeners. - * - * @param event - the event you'd like to emit - * @param eventData - any data you'd like to emit with the event - * @returns `true` if there are any listeners, `false` if there are not. - */ - emit(event, eventData) { - this.emitter.emit(event, eventData); - return this.eventListenersCount(event) > 0; - } - /** - * Like `on` but the listener will only be fired once and then it will be removed. - * @param event - the event you'd like to listen to - * @param handler - the handler function to run when the event occurs - * @returns `this` to enable you to chain calls. - */ - once(event, handler) { - const onceHandler = (eventData) => { - handler(eventData); - this.off(event, onceHandler); - }; - return this.on(event, onceHandler); - } - /** - * Gets the number of listeners for a given event. - * - * @param event - the event to get the listener count for - * @returns the number of listeners bound to the given event - */ - listenerCount(event) { - return this.eventListenersCount(event); - } - /** - * Removes all listeners. If given an event argument, it will remove only - * listeners for that event. - * @param event - the event to remove listeners for. - * @returns `this` to enable you to chain calls. - */ - removeAllListeners(event) { - if (event) { - this.eventsMap.delete(event); - } - else { - this.eventsMap.clear(); - } - return this; - } - eventListenersCount(event) { - return this.eventsMap.has(event) ? this.eventsMap.get(event).length : 0; - } -} -exports.EventEmitter = EventEmitter; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.d.ts deleted file mode 100644 index d717c7464f9..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.d.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright 2019 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * IMPORTANT: we are mid-way through migrating away from this Events.ts file - * in favour of defining events next to the class that emits them. - * - * However we need to maintain this file for now because the legacy DocLint - * system relies on them. Be aware in the mean time if you make a change here - * you probably need to replicate it in the relevant class. For example if you - * add a new Page event, you should update the PageEmittedEvents enum in - * src/common/Page.ts. - * - * Chat to @jackfranklin if you're unsure. - */ -export declare const Events: { - readonly Page: { - readonly Close: "close"; - readonly Console: "console"; - readonly Dialog: "dialog"; - readonly DOMContentLoaded: "domcontentloaded"; - readonly Error: "error"; - readonly PageError: "pageerror"; - readonly Request: "request"; - readonly Response: "response"; - readonly RequestFailed: "requestfailed"; - readonly RequestFinished: "requestfinished"; - readonly FrameAttached: "frameattached"; - readonly FrameDetached: "framedetached"; - readonly FrameNavigated: "framenavigated"; - readonly Load: "load"; - readonly Metrics: "metrics"; - readonly Popup: "popup"; - readonly WorkerCreated: "workercreated"; - readonly WorkerDestroyed: "workerdestroyed"; - }; - readonly Browser: { - readonly TargetCreated: "targetcreated"; - readonly TargetDestroyed: "targetdestroyed"; - readonly TargetChanged: "targetchanged"; - readonly Disconnected: "disconnected"; - }; - readonly BrowserContext: { - readonly TargetCreated: "targetcreated"; - readonly TargetDestroyed: "targetdestroyed"; - readonly TargetChanged: "targetchanged"; - }; - readonly NetworkManager: { - readonly Request: symbol; - readonly Response: symbol; - readonly RequestFailed: symbol; - readonly RequestFinished: symbol; - }; - readonly FrameManager: { - readonly FrameAttached: symbol; - readonly FrameNavigated: symbol; - readonly FrameDetached: symbol; - readonly LifecycleEvent: symbol; - readonly FrameNavigatedWithinDocument: symbol; - readonly ExecutionContextCreated: symbol; - readonly ExecutionContextDestroyed: symbol; - }; - readonly Connection: { - readonly Disconnected: symbol; - }; - readonly CDPSession: { - readonly Disconnected: symbol; - }; -}; -//# sourceMappingURL=Events.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.d.ts.map deleted file mode 100644 index 0ef025a148a..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Events.d.ts","sourceRoot":"","sources":["../../../../src/common/Events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmET,CAAC"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.js deleted file mode 100644 index 106a3d5609a..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/Events.js +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; -/** - * Copyright 2019 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Events = void 0; -/** - * IMPORTANT: we are mid-way through migrating away from this Events.ts file - * in favour of defining events next to the class that emits them. - * - * However we need to maintain this file for now because the legacy DocLint - * system relies on them. Be aware in the mean time if you make a change here - * you probably need to replicate it in the relevant class. For example if you - * add a new Page event, you should update the PageEmittedEvents enum in - * src/common/Page.ts. - * - * Chat to @jackfranklin if you're unsure. - */ -exports.Events = { - Page: { - Close: 'close', - Console: 'console', - Dialog: 'dialog', - DOMContentLoaded: 'domcontentloaded', - Error: 'error', - // Can't use just 'error' due to node.js special treatment of error events. - // @see https://nodejs.org/api/events.html#events_error_events - PageError: 'pageerror', - Request: 'request', - Response: 'response', - RequestFailed: 'requestfailed', - RequestFinished: 'requestfinished', - FrameAttached: 'frameattached', - FrameDetached: 'framedetached', - FrameNavigated: 'framenavigated', - Load: 'load', - Metrics: 'metrics', - Popup: 'popup', - WorkerCreated: 'workercreated', - WorkerDestroyed: 'workerdestroyed', - }, - Browser: { - TargetCreated: 'targetcreated', - TargetDestroyed: 'targetdestroyed', - TargetChanged: 'targetchanged', - Disconnected: 'disconnected', - }, - BrowserContext: { - TargetCreated: 'targetcreated', - TargetDestroyed: 'targetdestroyed', - TargetChanged: 'targetchanged', - }, - NetworkManager: { - Request: Symbol('Events.NetworkManager.Request'), - Response: Symbol('Events.NetworkManager.Response'), - RequestFailed: Symbol('Events.NetworkManager.RequestFailed'), - RequestFinished: Symbol('Events.NetworkManager.RequestFinished'), - }, - FrameManager: { - FrameAttached: Symbol('Events.FrameManager.FrameAttached'), - FrameNavigated: Symbol('Events.FrameManager.FrameNavigated'), - FrameDetached: Symbol('Events.FrameManager.FrameDetached'), - LifecycleEvent: Symbol('Events.FrameManager.LifecycleEvent'), - FrameNavigatedWithinDocument: Symbol('Events.FrameManager.FrameNavigatedWithinDocument'), - ExecutionContextCreated: Symbol('Events.FrameManager.ExecutionContextCreated'), - ExecutionContextDestroyed: Symbol('Events.FrameManager.ExecutionContextDestroyed'), - }, - Connection: { - Disconnected: Symbol('Events.Connection.Disconnected'), - }, - CDPSession: { - Disconnected: Symbol('Events.CDPSession.Disconnected'), - }, -}; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.d.ts deleted file mode 100644 index fa4e0be9562..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.d.ts +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Protocol } from 'devtools-protocol'; - -import { CDPSession } from './Connection.js'; -import { DOMWorld } from './DOMWorld.js'; -import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes.js'; -import { Frame } from './FrameManager.js'; -import { ElementHandle , JSHandle} from './JSHandle.js'; - -export declare const EVALUATION_SCRIPT_URL = "__puppeteer_evaluation_script__"; -/** - * This class represents a context for JavaScript execution. A [Page] might have - * many execution contexts: - * - each - * {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe | - * frame } has "default" execution context that is always created after frame is - * attached to DOM. This context is returned by the - * {@link frame.executionContext()} method. - * - {@link https://developer.chrome.com/extensions | Extension}'s content scripts - * create additional execution contexts. - * - * Besides pages, execution contexts can be found in - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | - * workers }. - * - * @public - */ -export declare class ExecutionContext { - /** - * @internal - */ - _client: CDPSession; - /** - * @internal - */ - _world: DOMWorld; - private _contextId; - /** - * @internal - */ - constructor(client: CDPSession, contextPayload: Protocol.Runtime.ExecutionContextDescription, world: DOMWorld); - /** - * @remarks - * - * Not every execution context is associated with a frame. For - * example, workers and extensions have execution contexts that are not - * associated with frames. - * - * @returns The frame associated with this execution context. - */ - frame(): Frame | null; - /** - * @remarks - * If the function passed to the `executionContext.evaluate` returns a - * Promise, then `executionContext.evaluate` would wait for the promise to - * resolve and return its value. If the function passed to the - * `executionContext.evaluate` returns a non-serializable value, then - * `executionContext.evaluate` resolves to `undefined`. DevTools Protocol also - * supports transferring some additional values that are not serializable by - * `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals. - * - * - * @example - * ```js - * const executionContext = await page.mainFrame().executionContext(); - * const result = await executionContext.evaluate(() => Promise.resolve(8 * 7))* ; - * console.log(result); // prints "56" - * ``` - * - * @example - * A string can also be passed in instead of a function. - * - * ```js - * console.log(await executionContext.evaluate('1 + 2')); // prints "3" - * ``` - * - * @example - * {@link JSHandle} instances can be passed as arguments to the - * `executionContext.* evaluate`: - * ```js - * const oneHandle = await executionContext.evaluateHandle(() => 1); - * const twoHandle = await executionContext.evaluateHandle(() => 2); - * const result = await executionContext.evaluate( - * (a, b) => a + b, oneHandle, * twoHandle - * ); - * await oneHandle.dispose(); - * await twoHandle.dispose(); - * console.log(result); // prints '3'. - * ``` - * @param pageFunction a function to be evaluated in the `executionContext` - * @param args argument to pass to the page function - * - * @returns A promise that resolves to the return value of the given function. - */ - evaluate(pageFunction: Function | string, ...args: unknown[]): Promise; - /** - * @remarks - * The only difference between `executionContext.evaluate` and - * `executionContext.evaluateHandle` is that `executionContext.evaluateHandle` - * returns an in-page object (a {@link JSHandle}). - * If the function passed to the `executionContext.evaluateHandle` returns a - * Promise, then `executionContext.evaluateHandle` would wait for the - * promise to resolve and return its value. - * - * @example - * ```js - * const context = await page.mainFrame().executionContext(); - * const aHandle = await context.evaluateHandle(() => Promise.resolve(self)); - * aHandle; // Handle for the global object. - * ``` - * - * @example - * A string can also be passed in instead of a function. - * - * ```js - * // Handle for the '3' * object. - * const aHandle = await context.evaluateHandle('1 + 2'); - * ``` - * - * @example - * JSHandle instances can be passed as arguments - * to the `executionContext.* evaluateHandle`: - * - * ```js - * const aHandle = await context.evaluateHandle(() => document.body); - * const resultHandle = await context.evaluateHandle(body => body.innerHTML, * aHandle); - * console.log(await resultHandle.jsonValue()); // prints body's innerHTML - * await aHandle.dispose(); - * await resultHandle.dispose(); - * ``` - * - * @param pageFunction a function to be evaluated in the `executionContext` - * @param args argument to pass to the page function - * - * @returns A promise that resolves to the return value of the given function - * as an in-page object (a {@link JSHandle}). - */ - evaluateHandle(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise; - private _evaluateInternal; - /** - * This method iterates the JavaScript heap and finds all the objects with the - * given prototype. - * @remarks - * @example - * ```js - * // Create a Map object - * await page.evaluate(() => window.map = new Map()); - * // Get a handle to the Map object prototype - * const mapPrototype = await page.evaluateHandle(() => Map.prototype); - * // Query all map instances into an array - * const mapInstances = await page.queryObjects(mapPrototype); - * // Count amount of map objects in heap - * const count = await page.evaluate(maps => maps.length, mapInstances); - * await mapInstances.dispose(); - * await mapPrototype.dispose(); - * ``` - * - * @param prototypeHandle a handle to the object prototype - * - * @returns A handle to an array of objects with the given prototype. - */ - queryObjects(prototypeHandle: JSHandle): Promise; - /** - * @internal - */ - _adoptBackendNodeId(backendNodeId: Protocol.DOM.BackendNodeId): Promise; - /** - * @internal - */ - _adoptElementHandle(elementHandle: ElementHandle): Promise; -} -//# sourceMappingURL=ExecutionContext.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.d.ts.map deleted file mode 100644 index e53af2b64ec..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ExecutionContext.d.ts","sourceRoot":"","sources":["../../../../src/common/ExecutionContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAkB,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE1E,eAAO,MAAM,qBAAqB,oCAAoC,CAAC;AAGvE;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,OAAO,EAAE,UAAU,CAAC;IACpB;;OAEG;IACH,MAAM,EAAE,QAAQ,CAAC;IACjB,OAAO,CAAC,UAAU,CAAS;IAE3B;;OAEG;gBAED,MAAM,EAAE,UAAU,EAClB,cAAc,EAAE,QAAQ,CAAC,OAAO,CAAC,2BAA2B,EAC5D,KAAK,EAAE,QAAQ;IAOjB;;;;;;;;OAQG;IACH,KAAK,IAAI,KAAK,GAAG,IAAI;IAIrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACG,QAAQ,CAAC,UAAU,SAAS,GAAG,EACnC,YAAY,EAAE,QAAQ,GAAG,MAAM,EAC/B,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,UAAU,CAAC;IAQtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACG,cAAc,CAAC,UAAU,SAAS,QAAQ,GAAG,aAAa,GAAG,QAAQ,EACzE,YAAY,EAAE,gBAAgB,EAC9B,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,UAAU,CAAC;YAIR,iBAAiB;IAuI/B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,YAAY,CAAC,eAAe,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAYhE;;OAEG;IACG,mBAAmB,CACvB,aAAa,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,GACxC,OAAO,CAAC,aAAa,CAAC;IAQzB;;OAEG;IACG,mBAAmB,CACvB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,aAAa,CAAC;CAW1B"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.js deleted file mode 100644 index d8195474667..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ExecutionContext.js +++ /dev/null @@ -1,317 +0,0 @@ -"use strict"; -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ExecutionContext = exports.EVALUATION_SCRIPT_URL = void 0; -const assert_js_1 = require("./assert.js"); -const helper_js_1 = require("./helper.js"); -const JSHandle_js_1 = require("./JSHandle.js"); -exports.EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__'; -const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m; -/** - * This class represents a context for JavaScript execution. A [Page] might have - * many execution contexts: - * - each - * {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe | - * frame } has "default" execution context that is always created after frame is - * attached to DOM. This context is returned by the - * {@link frame.executionContext()} method. - * - {@link https://developer.chrome.com/extensions | Extension}'s content scripts - * create additional execution contexts. - * - * Besides pages, execution contexts can be found in - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | - * workers }. - * - * @public - */ -class ExecutionContext { - /** - * @internal - */ - constructor(client, contextPayload, world) { - this._client = client; - this._world = world; - this._contextId = contextPayload.id; - } - /** - * @remarks - * - * Not every execution context is associated with a frame. For - * example, workers and extensions have execution contexts that are not - * associated with frames. - * - * @returns The frame associated with this execution context. - */ - frame() { - return this._world ? this._world.frame() : null; - } - /** - * @remarks - * If the function passed to the `executionContext.evaluate` returns a - * Promise, then `executionContext.evaluate` would wait for the promise to - * resolve and return its value. If the function passed to the - * `executionContext.evaluate` returns a non-serializable value, then - * `executionContext.evaluate` resolves to `undefined`. DevTools Protocol also - * supports transferring some additional values that are not serializable by - * `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals. - * - * - * @example - * ```js - * const executionContext = await page.mainFrame().executionContext(); - * const result = await executionContext.evaluate(() => Promise.resolve(8 * 7))* ; - * console.log(result); // prints "56" - * ``` - * - * @example - * A string can also be passed in instead of a function. - * - * ```js - * console.log(await executionContext.evaluate('1 + 2')); // prints "3" - * ``` - * - * @example - * {@link JSHandle} instances can be passed as arguments to the - * `executionContext.* evaluate`: - * ```js - * const oneHandle = await executionContext.evaluateHandle(() => 1); - * const twoHandle = await executionContext.evaluateHandle(() => 2); - * const result = await executionContext.evaluate( - * (a, b) => a + b, oneHandle, * twoHandle - * ); - * await oneHandle.dispose(); - * await twoHandle.dispose(); - * console.log(result); // prints '3'. - * ``` - * @param pageFunction a function to be evaluated in the `executionContext` - * @param args argument to pass to the page function - * - * @returns A promise that resolves to the return value of the given function. - */ - async evaluate(pageFunction, ...args) { - return await this._evaluateInternal(true, pageFunction, ...args); - } - /** - * @remarks - * The only difference between `executionContext.evaluate` and - * `executionContext.evaluateHandle` is that `executionContext.evaluateHandle` - * returns an in-page object (a {@link JSHandle}). - * If the function passed to the `executionContext.evaluateHandle` returns a - * Promise, then `executionContext.evaluateHandle` would wait for the - * promise to resolve and return its value. - * - * @example - * ```js - * const context = await page.mainFrame().executionContext(); - * const aHandle = await context.evaluateHandle(() => Promise.resolve(self)); - * aHandle; // Handle for the global object. - * ``` - * - * @example - * A string can also be passed in instead of a function. - * - * ```js - * // Handle for the '3' * object. - * const aHandle = await context.evaluateHandle('1 + 2'); - * ``` - * - * @example - * JSHandle instances can be passed as arguments - * to the `executionContext.* evaluateHandle`: - * - * ```js - * const aHandle = await context.evaluateHandle(() => document.body); - * const resultHandle = await context.evaluateHandle(body => body.innerHTML, * aHandle); - * console.log(await resultHandle.jsonValue()); // prints body's innerHTML - * await aHandle.dispose(); - * await resultHandle.dispose(); - * ``` - * - * @param pageFunction a function to be evaluated in the `executionContext` - * @param args argument to pass to the page function - * - * @returns A promise that resolves to the return value of the given function - * as an in-page object (a {@link JSHandle}). - */ - async evaluateHandle(pageFunction, ...args) { - return this._evaluateInternal(false, pageFunction, ...args); - } - async _evaluateInternal(returnByValue, pageFunction, ...args) { - const suffix = `//# sourceURL=${exports.EVALUATION_SCRIPT_URL}`; - if (helper_js_1.helper.isString(pageFunction)) { - const contextId = this._contextId; - const expression = pageFunction; - const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression) - ? expression - : expression + '\n' + suffix; - const { exceptionDetails, result: remoteObject } = await this._client - .send('Runtime.evaluate', { - expression: expressionWithSourceUrl, - contextId, - returnByValue, - awaitPromise: true, - userGesture: true, - }) - .catch(rewriteError); - if (exceptionDetails) - throw new Error('Evaluation failed: ' + helper_js_1.helper.getExceptionMessage(exceptionDetails)); - return returnByValue - ? helper_js_1.helper.valueFromRemoteObject(remoteObject) - : JSHandle_js_1.createJSHandle(this, remoteObject); - } - if (typeof pageFunction !== 'function') - throw new Error(`Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.`); - let functionText = pageFunction.toString(); - try { - new Function('(' + functionText + ')'); - } - catch (error) { - // This means we might have a function shorthand. Try another - // time prefixing 'function '. - if (functionText.startsWith('async ')) - functionText = - 'async function ' + functionText.substring('async '.length); - else - functionText = 'function ' + functionText; - try { - new Function('(' + functionText + ')'); - } - catch (error) { - // We tried hard to serialize, but there's a weird beast here. - throw new Error('Passed function is not well-serializable!'); - } - } - let callFunctionOnPromise; - try { - callFunctionOnPromise = this._client.send('Runtime.callFunctionOn', { - functionDeclaration: functionText + '\n' + suffix + '\n', - executionContextId: this._contextId, - arguments: args.map(convertArgument.bind(this)), - returnByValue, - awaitPromise: true, - userGesture: true, - }); - } - catch (error) { - if (error instanceof TypeError && - error.message.startsWith('Converting circular structure to JSON')) - error.message += ' Are you passing a nested JSHandle?'; - throw error; - } - const { exceptionDetails, result: remoteObject, } = await callFunctionOnPromise.catch(rewriteError); - if (exceptionDetails) - throw new Error('Evaluation failed: ' + helper_js_1.helper.getExceptionMessage(exceptionDetails)); - return returnByValue - ? helper_js_1.helper.valueFromRemoteObject(remoteObject) - : JSHandle_js_1.createJSHandle(this, remoteObject); - /** - * @param {*} arg - * @returns {*} - * @this {ExecutionContext} - */ - function convertArgument(arg) { - if (typeof arg === 'bigint') - // eslint-disable-line valid-typeof - return { unserializableValue: `${arg.toString()}n` }; - if (Object.is(arg, -0)) - return { unserializableValue: '-0' }; - if (Object.is(arg, Infinity)) - return { unserializableValue: 'Infinity' }; - if (Object.is(arg, -Infinity)) - return { unserializableValue: '-Infinity' }; - if (Object.is(arg, NaN)) - return { unserializableValue: 'NaN' }; - const objectHandle = arg && arg instanceof JSHandle_js_1.JSHandle ? arg : null; - if (objectHandle) { - if (objectHandle._context !== this) - throw new Error('JSHandles can be evaluated only in the context they were created!'); - if (objectHandle._disposed) - throw new Error('JSHandle is disposed!'); - if (objectHandle._remoteObject.unserializableValue) - return { - unserializableValue: objectHandle._remoteObject.unserializableValue, - }; - if (!objectHandle._remoteObject.objectId) - return { value: objectHandle._remoteObject.value }; - return { objectId: objectHandle._remoteObject.objectId }; - } - return { value: arg }; - } - function rewriteError(error) { - if (error.message.includes('Object reference chain is too long')) - return { result: { type: 'undefined' } }; - if (error.message.includes("Object couldn't be returned by value")) - return { result: { type: 'undefined' } }; - if (error.message.endsWith('Cannot find context with specified id') || - error.message.endsWith('Inspected target navigated or closed')) - throw new Error('Execution context was destroyed, most likely because of a navigation.'); - throw error; - } - } - /** - * This method iterates the JavaScript heap and finds all the objects with the - * given prototype. - * @remarks - * @example - * ```js - * // Create a Map object - * await page.evaluate(() => window.map = new Map()); - * // Get a handle to the Map object prototype - * const mapPrototype = await page.evaluateHandle(() => Map.prototype); - * // Query all map instances into an array - * const mapInstances = await page.queryObjects(mapPrototype); - * // Count amount of map objects in heap - * const count = await page.evaluate(maps => maps.length, mapInstances); - * await mapInstances.dispose(); - * await mapPrototype.dispose(); - * ``` - * - * @param prototypeHandle a handle to the object prototype - * - * @returns A handle to an array of objects with the given prototype. - */ - async queryObjects(prototypeHandle) { - assert_js_1.assert(!prototypeHandle._disposed, 'Prototype JSHandle is disposed!'); - assert_js_1.assert(prototypeHandle._remoteObject.objectId, 'Prototype JSHandle must not be referencing primitive value'); - const response = await this._client.send('Runtime.queryObjects', { - prototypeObjectId: prototypeHandle._remoteObject.objectId, - }); - return JSHandle_js_1.createJSHandle(this, response.objects); - } - /** - * @internal - */ - async _adoptBackendNodeId(backendNodeId) { - const { object } = await this._client.send('DOM.resolveNode', { - backendNodeId: backendNodeId, - executionContextId: this._contextId, - }); - return JSHandle_js_1.createJSHandle(this, object); - } - /** - * @internal - */ - async _adoptElementHandle(elementHandle) { - assert_js_1.assert(elementHandle.executionContext() !== this, 'Cannot adopt handle that already belongs to this execution context'); - assert_js_1.assert(this._world, 'Cannot adopt handle without DOMWorld'); - const nodeInfo = await this._client.send('DOM.describeNode', { - objectId: elementHandle._remoteObject.objectId, - }); - return this._adoptBackendNodeId(nodeInfo.node.backendNodeId); - } -} -exports.ExecutionContext = ExecutionContext; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.d.ts deleted file mode 100644 index 1f9fd3b13d8..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.d.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Protocol } from 'devtools-protocol'; - -import { ElementHandle } from './JSHandle.js'; - -/** - * File choosers let you react to the page requesting for a file. - * @remarks - * `FileChooser` objects are returned via the `page.waitForFileChooser` method. - * @example - * An example of using `FileChooser`: - * ```js - * const [fileChooser] = await Promise.all([ - * page.waitForFileChooser(), - * page.click('#upload-file-button'), // some button that triggers file selection - * ]); - * await fileChooser.accept(['/tmp/myfile.pdf']); - * ``` - * **NOTE** In browsers, only one file chooser can be opened at a time. - * All file choosers must be accepted or canceled. Not doing so will prevent - * subsequent file choosers from appearing. - */ -export declare class FileChooser { - private _element; - private _multiple; - private _handled; - /** - * @internal - */ - constructor(element: ElementHandle, event: Protocol.Page.FileChooserOpenedEvent); - /** - * Whether file chooser allow for {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#attr-multiple | multiple} file selection. - */ - isMultiple(): boolean; - /** - * Accept the file chooser request with given paths. - * @param filePaths - If some of the `filePaths` are relative paths, - * then they are resolved relative to the {@link https://nodejs.org/api/process.html#process_process_cwd | current working directory}. - */ - accept(filePaths: string[]): Promise; - /** - * Closes the file chooser without selecting any files. - */ - cancel(): Promise; -} -//# sourceMappingURL=FileChooser.d.ts.map \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.d.ts.map b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.d.ts.map deleted file mode 100644 index 3305117b8d2..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"FileChooser.d.ts","sourceRoot":"","sources":["../../../../src/common/FileChooser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,QAAQ,CAAS;IAEzB;;OAEG;gBAED,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,sBAAsB;IAM7C;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;;;OAIG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAO9B"} \ No newline at end of file diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.js b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.js deleted file mode 100644 index 50b913f09c0..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FileChooser.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FileChooser = void 0; -const assert_js_1 = require("./assert.js"); -/** - * File choosers let you react to the page requesting for a file. - * @remarks - * `FileChooser` objects are returned via the `page.waitForFileChooser` method. - * @example - * An example of using `FileChooser`: - * ```js - * const [fileChooser] = await Promise.all([ - * page.waitForFileChooser(), - * page.click('#upload-file-button'), // some button that triggers file selection - * ]); - * await fileChooser.accept(['/tmp/myfile.pdf']); - * ``` - * **NOTE** In browsers, only one file chooser can be opened at a time. - * All file choosers must be accepted or canceled. Not doing so will prevent - * subsequent file choosers from appearing. - */ -class FileChooser { - /** - * @internal - */ - constructor(element, event) { - this._handled = false; - this._element = element; - this._multiple = event.mode !== 'selectSingle'; - } - /** - * Whether file chooser allow for {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#attr-multiple | multiple} file selection. - */ - isMultiple() { - return this._multiple; - } - /** - * Accept the file chooser request with given paths. - * @param filePaths - If some of the `filePaths` are relative paths, - * then they are resolved relative to the {@link https://nodejs.org/api/process.html#process_process_cwd | current working directory}. - */ - async accept(filePaths) { - assert_js_1.assert(!this._handled, 'Cannot accept FileChooser which is already handled!'); - this._handled = true; - await this._element.uploadFile(...filePaths); - } - /** - * Closes the file chooser without selecting any files. - */ - async cancel() { - assert_js_1.assert(!this._handled, 'Cannot cancel FileChooser which is already handled!'); - this._handled = true; - } -} -exports.FileChooser = FileChooser; diff --git a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FrameManager.d.ts b/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FrameManager.d.ts deleted file mode 100644 index c108ae26d0a..00000000000 --- a/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/FrameManager.d.ts +++ /dev/null @@ -1,710 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Protocol } from 'devtools-protocol'; - -import { CDPSession } from './Connection.js'; -import { DOMWorld, WaitForSelectorOptions } from './DOMWorld.js'; -import { EvaluateFn, EvaluateFnReturnType, EvaluateHandleFn, SerializableOrJSHandle, UnwrapPromiseLike , WrapElementHandle} from './EvalTypes.js'; -import { EventEmitter } from './EventEmitter.js'; -import { ExecutionContext } from './ExecutionContext.js'; -import { HTTPResponse } from './HTTPResponse.js'; -import { MouseButton } from './Input.js'; -import { ElementHandle , JSHandle} from './JSHandle.js'; -import { PuppeteerLifeCycleEvent } from './LifecycleWatcher.js'; -import { NetworkManager } from './NetworkManager.js'; -import { Page } from './Page.js'; -import { TimeoutSettings } from './TimeoutSettings.js'; - -/** - * We use symbols to prevent external parties listening to these events. - * They are internal to Puppeteer. - * - * @internal - */ -export declare const FrameManagerEmittedEvents: { - FrameAttached: symbol; - FrameNavigated: symbol; - FrameDetached: symbol; - LifecycleEvent: symbol; - FrameNavigatedWithinDocument: symbol; - ExecutionContextCreated: symbol; - ExecutionContextDestroyed: symbol; -}; -/** - * @internal - */ -export declare class FrameManager extends EventEmitter { - _client: CDPSession; - private _page; - private _networkManager; - _timeoutSettings: TimeoutSettings; - private _frames; - private _contextIdToContext; - private _isolatedWorlds; - private _mainFrame; - constructor(client: CDPSession, page: Page, ignoreHTTPSErrors: boolean, timeoutSettings: TimeoutSettings); - initialize(): Promise; - networkManager(): NetworkManager; - navigateFrame(frame: Frame, url: string, options?: { - referer?: string; - timeout?: number; - waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]; - }): Promise; - waitForFrameNavigation(frame: Frame, options?: { - timeout?: number; - waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]; - }): Promise; - _onLifecycleEvent(event: Protocol.Page.LifecycleEventEvent): void; - _onFrameStoppedLoading(frameId: string): void; - _handleFrameTree(frameTree: Protocol.Page.FrameTree): void; - page(): Page; - mainFrame(): Frame; - frames(): Frame[]; - frame(frameId: string): Frame | null; - _onFrameAttached(frameId: string, parentFrameId?: string): void; - _onFrameNavigated(framePayload: Protocol.Page.Frame): void; - _ensureIsolatedWorld(name: string): Promise; - _onFrameNavigatedWithinDocument(frameId: string, url: string): void; - _onFrameDetached(frameId: string): void; - _onExecutionContextCreated(contextPayload: Protocol.Runtime.ExecutionContextDescription): void; - private _onExecutionContextDestroyed; - private _onExecutionContextsCleared; - executionContextById(contextId: number): ExecutionContext; - private _removeFramesRecursively; -} -/** - * @public - */ -export interface FrameWaitForFunctionOptions { - /** - * An interval at which the `pageFunction` is executed, defaults to `raf`. If - * `polling` is a number, then it is treated as an interval in milliseconds at - * which the function would be executed. If `polling` is a string, then it can - * be one of the following values: - * - * - `raf` - to constantly execute `pageFunction` in `requestAnimationFrame` - * callback. This is the tightest polling mode which is suitable to observe - * styling changes. - * - * - `mutation` - to execute `pageFunction` on every DOM mutation. - */ - polling?: string | number; - /** - * Maximum time to wait in milliseconds. Defaults to `30000` (30 seconds). - * Pass `0` to disable the timeout. Puppeteer's default timeout can be changed - * using {@link Page.setDefaultTimeout}. - */ - timeout?: number; -} -/** - * @public - */ -export interface FrameAddScriptTagOptions { - /** - * the URL of the script to be added. - */ - url?: string; - /** - * The path to a JavaScript file to be injected into the frame. - * @remarks - * If `path` is a relative path, it is resolved relative to the current - * working directory (`process.cwd()` in Node.js). - */ - path?: string; - /** - * Raw JavaScript content to be injected into the frame. - */ - content?: string; - /** - * Set the script's `type`. Use `module` in order to load an ES2015 module. - */ - type?: string; -} -/** - * @public - */ -export interface FrameAddStyleTagOptions { - /** - * the URL of the CSS file to be added. - */ - url?: string; - /** - * The path to a CSS file to be injected into the frame. - * @remarks - * If `path` is a relative path, it is resolved relative to the current - * working directory (`process.cwd()` in Node.js). - */ - path?: string; - /** - * Raw CSS content to be injected into the frame. - */ - content?: string; -} -/** - * At every point of time, page exposes its current frame tree via the - * {@link Page.mainFrame | page.mainFrame} and - * {@link Frame.childFrames | frame.childFrames} methods. - * - * @remarks - * - * `Frame` object lifecycles are controlled by three events that are all - * dispatched on the page object: - * - * - {@link PageEmittedEvents.FrameAttached} - * - * - {@link PageEmittedEvents.FrameNavigated} - * - * - {@link PageEmittedEvents.FrameDetached} - * - * @Example - * An example of dumping frame tree: - * - * ```js - * const puppeteer = require('puppeteer'); - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * await page.goto('https://www.google.com/chrome/browser/canary.html'); - * dumpFrameTree(page.mainFrame(), ''); - * await browser.close(); - * - * function dumpFrameTree(frame, indent) { - * console.log(indent + frame.url()); - * for (const child of frame.childFrames()) { - * dumpFrameTree(child, indent + ' '); - * } - * } - * })(); - * ``` - * - * @Example - * An example of getting text from an iframe element: - * - * ```js - * const frame = page.frames().find(frame => frame.name() === 'myframe'); - * const text = await frame.$eval('.selector', element => element.textContent); - * console.log(text); - * ``` - * - * @public - */ -export declare class Frame { - /** - * @internal - */ - _frameManager: FrameManager; - private _parentFrame?; - /** - * @internal - */ - _id: string; - private _url; - private _detached; - /** - * @internal - */ - _loaderId: string; - /** - * @internal - */ - _name?: string; - /** - * @internal - */ - _lifecycleEvents: Set; - /** - * @internal - */ - _mainWorld: DOMWorld; - /** - * @internal - */ - _secondaryWorld: DOMWorld; - /** - * @internal - */ - _childFrames: Set; - /** - * @internal - */ - constructor(frameManager: FrameManager, parentFrame: Frame | null, frameId: string); - /** - * @remarks - * - * `frame.goto` will throw an error if: - * - there's an SSL error (e.g. in case of self-signed certificates). - * - * - target URL is invalid. - * - * - the `timeout` is exceeded during navigation. - * - * - the remote server does not respond or is unreachable. - * - * - the main resource failed to load. - * - * `frame.goto` will not throw an error when any valid HTTP status code is - * returned by the remote server, including 404 "Not Found" and 500 "Internal - * Server Error". The status code for such responses can be retrieved by - * calling {@link HTTPResponse.status}. - * - * NOTE: `frame.goto` either throws an error or returns a main resource - * response. The only exceptions are navigation to `about:blank` or - * navigation to the same URL with a different hash, which would succeed and - * return `null`. - * - * NOTE: Headless mode doesn't support navigation to a PDF document. See - * the {@link https://bugs.chromium.org/p/chromium/issues/detail?id=761295 | upstream - * issue}. - * - * @param url - the URL to navigate the frame to. This should include the - * scheme, e.g. `https://`. - * @param options - navigation options. `waitUntil` is useful to define when - * the navigation should be considered successful - see the docs for - * {@link PuppeteerLifeCycleEvent} for more details. - * - * @returns A promise which resolves to the main resource response. In case of - * multiple redirects, the navigation will resolve with the response of the - * last redirect. - */ - goto(url: string, options?: { - referer?: string; - timeout?: number; - waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]; - }): Promise; - /** - * @remarks - * - * This resolves when the frame navigates to a new URL. It is useful for when - * you run code which will indirectly cause the frame to navigate. Consider - * this example: - * - * ```js - * const [response] = await Promise.all([ - * // The navigation promise resolves after navigation has finished - * frame.waitForNavigation(), - * // Clicking the link will indirectly cause a navigation - * frame.click('a.my-link'), - * ]); - * ``` - * - * Usage of the {@link https://developer.mozilla.org/en-US/docs/Web/API/History_API | History API} to change the URL is considered a navigation. - * - * @param options - options to configure when the navigation is consided finished. - * @returns a promise that resolves when the frame navigates to a new URL. - */ - waitForNavigation(options?: { - timeout?: number; - waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]; - }): Promise; - /** - * @returns a promise that resolves to the frame's default execution context. - */ - executionContext(): Promise; - /** - * @remarks - * - * The only difference between {@link Frame.evaluate} and - * `frame.evaluateHandle` is that `evaluateHandle` will return the value - * wrapped in an in-page object. - * - * This method behaves identically to {@link Page.evaluateHandle} except it's - * run within the context of the `frame`, rather than the entire page. - * - * @param pageFunction - a function that is run within the frame - * @param args - arguments to be passed to the pageFunction - */ - evaluateHandle(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise; - /** - * @remarks - * - * This method behaves identically to {@link Page.evaluate} except it's run - * within the context of the `frame`, rather than the entire page. - * - * @param pageFunction - a function that is run within the frame - * @param args - arguments to be passed to the pageFunction - */ - evaluate(pageFunction: T, ...args: SerializableOrJSHandle[]): Promise>>; - /** - * This method queries the frame for the given selector. - * - * @param selector - a selector to query for. - * @returns A promise which resolves to an `ElementHandle` pointing at the - * element, or `null` if it was not found. - */ - $(selector: string): Promise; - /** - * This method evaluates the given XPath expression and returns the results. - * - * @param expression - the XPath expression to evaluate. - */ - $x(expression: string): Promise; - /** - * @remarks - * - * This method runs `document.querySelector` within - * the frame and passes it as the first argument to `pageFunction`. - * - * If `pageFunction` returns a Promise, then `frame.$eval` would wait for - * the promise to resolve and return its value. - * - * @example - * - * ```js - * const searchValue = await frame.$eval('#search', el => el.value); - * ``` - * - * @param selector - the selector to query for - * @param pageFunction - the function to be evaluated in the frame's context - * @param args - additional arguments to pass to `pageFuncton` - */ - $eval(selector: string, pageFunction: (element: Element, ...args: unknown[]) => ReturnType | Promise, ...args: SerializableOrJSHandle[]): Promise>; - /** - * @remarks - * - * This method runs `Array.from(document.querySelectorAll(selector))` within - * the frame and passes it as the first argument to `pageFunction`. - * - * If `pageFunction` returns a Promise, then `frame.$$eval` would wait for - * the promise to resolve and return its value. - * - * @example - * - * ```js - * const divsCounts = await frame.$$eval('div', divs => divs.length); - * ``` - * - * @param selector - the selector to query for - * @param pageFunction - the function to be evaluated in the frame's context - * @param args - additional arguments to pass to `pageFuncton` - */ - $$eval(selector: string, pageFunction: (elements: Element[], ...args: unknown[]) => ReturnType | Promise, ...args: SerializableOrJSHandle[]): Promise>; - /** - * This runs `document.querySelectorAll` in the frame and returns the result. - * - * @param selector - a selector to search for - * @returns An array of element handles pointing to the found frame elements. - */ - $$(selector: string): Promise; - /** - * @returns the full HTML contents of the frame, including the doctype. - */ - content(): Promise; - /** - * Set the content of the frame. - * - * @param html - HTML markup to assign to the page. - * @param options - options to configure how long before timing out and at - * what point to consider the content setting successful. - */ - setContent(html: string, options?: { - timeout?: number; - waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[]; - }): Promise; - /** - * @remarks - * - * If the name is empty, it returns the `id` attribute instead. - * - * Note: This value is calculated once when the frame is created, and will not - * update if the attribute is changed later. - * - * @returns the frame's `name` attribute as specified in the tag. - */ - name(): string; - /** - * @returns the frame's URL. - */ - url(): string; - /** - * @returns the parent `Frame`, if any. Detached and main frames return `null`. - */ - parentFrame(): Frame | null; - /** - * @returns an array of child frames. - */ - childFrames(): Frame[]; - /** - * @returns `true` if the frame has been detached, or `false` otherwise. - */ - isDetached(): boolean; - /** - * Adds a ` diff --git a/test/e2e/resources/application/service-worker.js b/test/e2e/resources/application/service-worker.js new file mode 100644 index 00000000000..1ee35a4b8f3 --- /dev/null +++ b/test/e2e/resources/application/service-worker.js @@ -0,0 +1,26 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// @ts-nocheck +const CACHE_NAME = 'cache-v1'; + +const urlsToCache = [ + '/test/e2e/resources/application/main.css', +]; + + +self.addEventListener('install', (event) => { + event.waitUntil(caches.open(CACHE_NAME).then(function(cache) { + return cache.addAll(urlsToCache); + })); +}); + +self.addEventListener('fetch', (event) => { + event.respondWith(caches.match(event.request).then(function(response) { + if (response) { + return response; + } + return fetch(event.request); + })); +}); diff --git a/test/e2e/resources/inline_editor/BUILD.gn b/test/e2e/resources/inline_editor/BUILD.gn new file mode 100644 index 00000000000..ac0e9c47b1e --- /dev/null +++ b/test/e2e/resources/inline_editor/BUILD.gn @@ -0,0 +1,12 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../../../scripts/build/ninja/copy.gni") + +copy_to_gen("inline_editor") { + sources = [ + "default.html", + "var-chain.html", + ] +} diff --git a/test/e2e/resources/inline_editor/default.html b/test/e2e/resources/inline_editor/default.html new file mode 100644 index 00000000000..6b10991f334 --- /dev/null +++ b/test/e2e/resources/inline_editor/default.html @@ -0,0 +1,15 @@ + + + +
Inspected div
diff --git a/test/e2e/resources/inline_editor/var-chain.html b/test/e2e/resources/inline_editor/var-chain.html new file mode 100644 index 00000000000..8b5401c3908 --- /dev/null +++ b/test/e2e/resources/inline_editor/var-chain.html @@ -0,0 +1,10 @@ + + + +
Inspected div
diff --git a/test/e2e/settings/BUILD.gn b/test/e2e/settings/BUILD.gn new file mode 100644 index 00000000000..99c39174d0e --- /dev/null +++ b/test/e2e/settings/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../../third_party/typescript/typescript.gni") + +node_ts_library("settings") { + sources = [ "shortcut_settings_test.ts" ] + + deps = [ + "../../shared", + "../helpers", + ] +} diff --git a/test/e2e/settings/shortcut_settings_test.ts b/test/e2e/settings/shortcut_settings_test.ts new file mode 100644 index 00000000000..da4d72f2f09 --- /dev/null +++ b/test/e2e/settings/shortcut_settings_test.ts @@ -0,0 +1,151 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chai'; + +import {enableExperiment, getBrowserAndPages, waitFor, waitForElementWithTextContent, waitForFunction, waitForNoElementsWithTextContent} from '../../shared/helper.js'; +import {describe, it} from '../../shared/mocha-extensions.js'; +import {getSelectedItemText, QUICK_OPEN_SELECTOR} from '../helpers/quick_open-helpers.js'; +import {openSettingsTab} from '../helpers/settings-helpers.js'; +import {ADD_SHORTCUT_LINK_TEXT, clickAddShortcutLink, clickShortcutCancelButton, clickShortcutConfirmButton, clickShortcutDeleteButton, clickShortcutResetButton, editShortcutListItem, selectKeyboardShortcutPreset, shortcutInputValues, shortcutsForAction, waitForEmptyShortcutInput} from '../helpers/settings-shortcuts-helpers.js'; + +describe('Shortcuts Settings tab', async () => { + it('should update when the shortcuts preset is changed ', async () => { + await openSettingsTab('Shortcuts'); + await selectKeyboardShortcutPreset('vsCode'); + + // wait for a shortcut that vsCode has but the default preset does not + await waitForElementWithTextContent('CtrlKCtrlS'); + + const shortcutsShortcuts = await shortcutsForAction('Shortcuts'); + const settingsShortcuts = await shortcutsForAction('Settings'); + const pauseShortcuts = await shortcutsForAction('Pause script execution'); + assert.deepStrictEqual(shortcutsShortcuts, ['CtrlKCtrlS']); + assert.deepStrictEqual(settingsShortcuts, ['Shift?', 'Ctrl,']); + assert.deepStrictEqual(pauseShortcuts, ['Ctrl\\', 'F5', 'ShiftF5']); + }); + + it('should apply new shortcuts when the preset is changed', async () => { + const {frontend} = getBrowserAndPages(); + await openSettingsTab('Shortcuts'); + await selectKeyboardShortcutPreset('vsCode'); + + // wait for a shortcut that vsCode has but the default preset does not + await waitForElementWithTextContent('CtrlKCtrlS'); + + // close the settings dialog + await frontend.keyboard.press('Escape'); + + // use a newly-enabled shortcut to open the command menu + await frontend.keyboard.press('F1'); + await waitFor(QUICK_OPEN_SELECTOR); + + // make sure the command menu reflects the new shortcuts + await frontend.keyboard.type('Shortcuts'); + const shortcutsItemText = await getSelectedItemText(); + + assert.strictEqual(shortcutsItemText, 'SettingsShortcutsCtrl + K Ctrl + S'); + }); + + it('should allow users to open the shortcut editor and view the current shortcut', async () => { + await enableExperiment('keyboardShortcutEditor'); + + await openSettingsTab('Shortcuts'); + await editShortcutListItem('Show Console'); + + const shortcutInputsText = await shortcutInputValues(); + assert.deepStrictEqual(shortcutInputsText, ['Ctrl + `']); + }); + + it('should allow users to open the shortcut editor and change and add shortcuts', async () => { + const {frontend} = getBrowserAndPages(); + await enableExperiment('keyboardShortcutEditor'); + + await openSettingsTab('Shortcuts'); + await editShortcutListItem('Show Console'); + + await frontend.keyboard.down('Control'); + await frontend.keyboard.press('1'); + await frontend.keyboard.up('Control'); + + await clickAddShortcutLink(); + await waitForEmptyShortcutInput(); + await frontend.keyboard.down('Control'); + await frontend.keyboard.press('2'); + await frontend.keyboard.up('Control'); + + const shortcutInputsText = await shortcutInputValues(); + assert.deepStrictEqual(shortcutInputsText, ['Ctrl + 1', 'Ctrl + 2']); + await clickShortcutConfirmButton(); + await waitForNoElementsWithTextContent(ADD_SHORTCUT_LINK_TEXT); + + const shortcuts = await shortcutsForAction('Show Console'); + assert.deepStrictEqual(shortcuts, ['Ctrl1', 'Ctrl2']); + }); + + it('should allow users to open the shortcut editor and delete and reset shortcuts', async () => { + const {frontend} = getBrowserAndPages(); + await enableExperiment('keyboardShortcutEditor'); + + await openSettingsTab('Shortcuts'); + await editShortcutListItem('Show Console'); + + await frontend.keyboard.down('Control'); + await frontend.keyboard.press('1'); + await frontend.keyboard.up('Control'); + + await clickAddShortcutLink(); + await waitForEmptyShortcutInput(); + await frontend.keyboard.down('Control'); + await frontend.keyboard.press('2'); + await frontend.keyboard.up('Control'); + + const shortcutInputsText = await shortcutInputValues(); + assert.deepStrictEqual(shortcutInputsText, ['Ctrl + 1', 'Ctrl + 2']); + + await clickShortcutDeleteButton(0); + let shortcutInputTextAfterDeletion; + await waitForFunction(async () => { + shortcutInputTextAfterDeletion = await shortcutInputValues(); + return shortcutInputTextAfterDeletion.length === 1; + }); + assert.deepStrictEqual(shortcutInputTextAfterDeletion, ['Ctrl + 2']); + + await clickShortcutResetButton(); + const shortcutInputTextAfterReset = await shortcutInputValues(); + assert.deepStrictEqual(shortcutInputTextAfterReset, ['Ctrl + `']); + + await clickShortcutConfirmButton(); + await waitForNoElementsWithTextContent(ADD_SHORTCUT_LINK_TEXT); + + const shortcuts = await shortcutsForAction('Show Console'); + assert.deepStrictEqual(shortcuts, ['Ctrl`']); + }); + + it('should allow users to cancel an edit and discard their changes to shortcuts', async () => { + const {frontend} = getBrowserAndPages(); + await enableExperiment('keyboardShortcutEditor'); + + await openSettingsTab('Shortcuts'); + await editShortcutListItem('Show Console'); + + await frontend.keyboard.down('Control'); + await frontend.keyboard.press('1'); + await frontend.keyboard.up('Control'); + + await clickAddShortcutLink(); + await waitForEmptyShortcutInput(); + await frontend.keyboard.down('Control'); + await frontend.keyboard.press('2'); + await frontend.keyboard.up('Control'); + + const shortcutInputsText = await shortcutInputValues(); + assert.deepStrictEqual(shortcutInputsText, ['Ctrl + 1', 'Ctrl + 2']); + await clickShortcutCancelButton(); + await waitForNoElementsWithTextContent(ADD_SHORTCUT_LINK_TEXT); + + const shortcuts = await shortcutsForAction('Show Console'); + assert.deepStrictEqual(shortcuts, ['Ctrl`']); + }); +}); diff --git a/test/e2e/sources/debugger-language-plugins_test.ts b/test/e2e/sources/debugger-language-plugins_test.ts index 482db513a18..1bffb6821e1 100644 --- a/test/e2e/sources/debugger-language-plugins_test.ts +++ b/test/e2e/sources/debugger-language-plugins_test.ts @@ -578,6 +578,16 @@ describe('The Debugger Language Plugins', async () => { canExpand: false, hasValue: true, }, + { + typeNames: ['int'], + typeId: 'int', + members: [], + alignment: 0, + arraySize: 0, + size: 4, + canExpand: false, + hasValue: true, + }, ]; const base = {rootType: typeInfos[0], payload: 28}; @@ -589,18 +599,44 @@ describe('The Debugger Language Plugins', async () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars async getFormatter(expressionOrField: string|{base: EvalBase, field: FieldInfo[]}, context: RawLocation): Promise<{js: string}|null> { + function format() { + const sym = Symbol('sym'); + + class $tag { + [sym]: EvalBase; + constructor() { + const rootType = { + typeNames: ['int'], + typeId: 'int', + members: [], + alignment: 0, + arraySize: 0, + size: 4, + canExpand: false, + hasValue: true, + }; + this[sym] = {payload: {value: 19}, rootType}; + } + } + + const value = {value: 26, recurse: new $tag()}; + return {tag: {className: '$tag', symbol: sym}, value}; + } + if (typeof expressionOrField === 'string') { return null; } const {base, field} = expressionOrField; - if (typeof base.payload !== 'number' || base.payload !== 28 || field.length !== 2 || - field[0].name !== 'member' || field[0].offset !== 1 || field[0].typeId !== 'TestTypeMember' || - field[1].name !== 'member2' || field[1].offset !== 1 || field[1].typeId !== 'TestTypeMember2') { - return null; + if (base.payload === 28 && field.length === 2 && field[0].name === 'member' && field[0].offset === 1 && + field[0].typeId === 'TestTypeMember' && field[1].name === 'member2' && field[1].offset === 1 && + field[1].typeId === 'TestTypeMember2') { + return {js: `${format.toString()} format()`}; } - - return {js: '26'}; + if ((base.payload as {value: number}).value === 19 && field.length === 0) { + return {js: '27'}; + } + return null; } } @@ -615,9 +651,15 @@ describe('The Debugger Language Plugins', async () => { await goToResource('sources/wasm/unreachable.html'); await waitFor(RESUME_BUTTON); - - const locals = await getValuesForScope('LOCAL', 2, 3); - assert.deepEqual(locals, ['local: TestType', 'member: TestTypeMember', 'member2: 26']); + const locals = await getValuesForScope('LOCAL', 3, 5); + assert.deepEqual(locals, [ + 'local: TestType', + 'member: TestTypeMember', + 'member2: TestTypeMember2', + 'recurse: 27', + 'value: 26', + '__proto__: Object', + ]); }); it('shows variable value in popover', async () => { diff --git a/test/shared/helper.ts b/test/shared/helper.ts index 5c6b6f4c54f..b117349c1a3 100644 --- a/test/shared/helper.ts +++ b/test/shared/helper.ts @@ -10,6 +10,12 @@ import {reloadDevTools} from '../conductor/hooks.js'; import {getBrowserAndPages, getHostedModeServerPort} from '../conductor/puppeteer-state.js'; import {AsyncScope} from './mocha-extensions.js'; +declare global { + interface Window { + __pendingEvents: Map; + } +} + export let platform: string; switch (os.platform()) { case 'darwin': @@ -229,6 +235,18 @@ export const waitForElementsWithTextContent = }, asyncScope)); }; +export const waitForNoElementsWithTextContent = + (textContent: string, root?: puppeteer.JSHandle, asyncScope = new AsyncScope()) => { + return asyncScope.exec(() => waitForFunction(async () => { + const elems = await $$textContent(textContent, root); + if (elems && elems.length === 0) { + return true; + } + + return false; + }, asyncScope)); + }; + export const waitForFunction = async(fn: () => Promise, asyncScope = new AsyncScope()): Promise => { return await asyncScope.exec(async () => { while (true) { @@ -450,4 +468,31 @@ export const scrollElementIntoView = async (selector: string, root?: puppeteer.J }); }; +export const installEventListener = function(frontend: puppeteer.Page, eventType: string) { + return frontend.evaluate(eventType => { + if (!('__pendingEvents' in window)) { + window.__pendingEvents = new Map(); + } + window.addEventListener(eventType, (e: Event) => { + let events = window.__pendingEvents.get(eventType); + if (!events) { + events = []; + window.__pendingEvents.set(eventType, events); + } + events.push(e); + }); + }, eventType); +}; + +export const getPendingEvents = function(frontend: puppeteer.Page, eventType: string) { + return frontend.evaluate(eventType => { + if (!('__pendingEvents' in window)) { + return []; + } + const pendingEvents = window.__pendingEvents.get(eventType); + window.__pendingEvents.set(eventType, []); + return pendingEvents || []; + }, eventType); +}; + export {getBrowserAndPages, getHostedModeServerPort, reloadDevTools}; diff --git a/test/unittests/front_end/elements/BUILD.gn b/test/unittests/front_end/elements/BUILD.gn index 38142722105..a022da41b58 100644 --- a/test/unittests/front_end/elements/BUILD.gn +++ b/test/unittests/front_end/elements/BUILD.gn @@ -4,7 +4,6 @@ ts_library("elements") { testonly = true sources = [ "Adorner_test.ts", - "CSSAngle_test.ts", "CSSPropertyIconResolver_test.ts", "ComputedStyleProperty_test.ts", "ComputedStyleTrace_test.ts", diff --git a/test/unittests/front_end/elements/CSSPropertyIconResolver_test.ts b/test/unittests/front_end/elements/CSSPropertyIconResolver_test.ts index fc07bf809dc..03f441e65b9 100644 --- a/test/unittests/front_end/elements/CSSPropertyIconResolver_test.ts +++ b/test/unittests/front_end/elements/CSSPropertyIconResolver_test.ts @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {findIcon, getPhysicalFlexDirections, PhysicalFlexDirection, reverseDirection, rotateFlexDirectionIcon} from '../../../../front_end/elements/CSSPropertyIconResolver.js'; +import {findIcon, getPhysicalFlexDirections, PhysicalFlexDirection, reverseDirection, rotateFlexAlignContentIcon, rotateFlexDirectionIcon} from '../../../../front_end/elements/CSSPropertyIconResolver.js'; const {assert} = chai; @@ -288,4 +288,78 @@ describe('CSSPropertyIconResolver', () => { `Test 'flex-direction: column-reverse'(${JSON.stringify(test.style)}) failed.`); } }); + + it('can rotate an icon for align-content', () => { + const iconName = 'iconName'; + assert.deepEqual(rotateFlexAlignContentIcon(iconName, PhysicalFlexDirection.LEFT_TO_RIGHT), { + iconName, + rotate: -90, + scaleX: 1, + scaleY: 1, + }); + assert.deepEqual(rotateFlexAlignContentIcon(iconName, PhysicalFlexDirection.RIGHT_TO_LEFT), { + iconName, + rotate: 90, + scaleX: 1, + scaleY: 1, + }); + assert.deepEqual(rotateFlexAlignContentIcon(iconName, PhysicalFlexDirection.TOP_TO_BOTTOM), { + iconName, + rotate: 0, + scaleX: 1, + scaleY: 1, + }); + assert.deepEqual(rotateFlexAlignContentIcon(iconName, PhysicalFlexDirection.BOTTOM_TO_TOP), { + iconName, + rotate: 0, + scaleX: 1, + scaleY: 1, + }); + }); + + it('can find an icon for align-content properties', () => { + const tests = [ + { + style: { + 'flex-direction': 'row', + 'align-content': 'center', + }, + iconName: 'flex-align-content-center-icon', + expected: PhysicalFlexDirection.TOP_TO_BOTTOM, + }, + { + style: { + 'flex-direction': 'column', + 'align-content': 'center', + }, + iconName: 'flex-align-content-center-icon', + expected: PhysicalFlexDirection.LEFT_TO_RIGHT, + }, + { + style: { + 'flex-direction': 'row', + 'align-content': 'center', + 'writing-mode': 'vertical-rl', + }, + iconName: 'flex-align-content-center-icon', + expected: PhysicalFlexDirection.RIGHT_TO_LEFT, + }, + { + style: { + 'flex-direction': 'row', + 'align-content': 'center', + 'writing-mode': 'vertical-lr', + }, + iconName: 'flex-align-content-center-icon', + expected: PhysicalFlexDirection.LEFT_TO_RIGHT, + }, + ]; + + for (const test of tests) { + assert.deepEqual( + findIcon(`align-content: ${test.style['align-content']}`, mapFromStyle(test.style)), + rotateFlexAlignContentIcon(test.iconName, test.expected), + `Test align-content(${JSON.stringify(test.style)}) failed.`); + } + }); }); diff --git a/test/unittests/front_end/elements/ElementsBreadcrumbs_test.ts b/test/unittests/front_end/elements/ElementsBreadcrumbs_test.ts index 6c2f5dd59e2..038e90b748d 100644 --- a/test/unittests/front_end/elements/ElementsBreadcrumbs_test.ts +++ b/test/unittests/front_end/elements/ElementsBreadcrumbs_test.ts @@ -16,6 +16,7 @@ interface MakeCrumbOptions extends Partial { const makeCrumb = (overrides: MakeCrumbOptions = {}) => { const attributes = overrides.attributes || {}; const newCrumb: DOMNode = { + parentNode: null, nodeType: Node.ELEMENT_NODE, id: 1, pseudoType: '', diff --git a/test/unittests/front_end/helpers/DOMHelpers.ts b/test/unittests/front_end/helpers/DOMHelpers.ts index 0d84ac93f2f..511db810ea7 100644 --- a/test/unittests/front_end/helpers/DOMHelpers.ts +++ b/test/unittests/front_end/helpers/DOMHelpers.ts @@ -91,6 +91,22 @@ export function assertElements( nodeList.forEach(e => assert.instanceOf(e, elementClass)); } +export function getElementWithinComponent( + component: T, selector: string, elementClass: Constructor) { + assertShadowRoot(component.shadowRoot); + const element = component.shadowRoot.querySelector(selector); + assertElement(element, elementClass); + return element; +} + +export function getElementsWithinComponent( + component: T, selector: string, elementClass: Constructor) { + assertShadowRoot(component.shadowRoot); + const elements = component.shadowRoot.querySelectorAll(selector); + assertElements(elements, elementClass); + return elements; +} + /* Waits for the given element to have a scrollLeft property of at least desiredScrollLeft */ export function waitForScrollLeft(element: T, desiredScrollLeft: number): Promise { let lastScrollLeft = -1; diff --git a/test/unittests/front_end/inline_editor/BUILD.gn b/test/unittests/front_end/inline_editor/BUILD.gn index b261a24a75f..93696378454 100644 --- a/test/unittests/front_end/inline_editor/BUILD.gn +++ b/test/unittests/front_end/inline_editor/BUILD.gn @@ -4,6 +4,7 @@ ts_library("inline_editor") { testonly = true sources = [ "BezierUI_test.ts", + "CSSAngle_test.ts", "CSSVarSwatch_test.ts", "ColorSwatch_test.ts", ] diff --git a/test/unittests/front_end/elements/CSSAngle_test.ts b/test/unittests/front_end/inline_editor/CSSAngle_test.ts similarity index 82% rename from test/unittests/front_end/elements/CSSAngle_test.ts rename to test/unittests/front_end/inline_editor/CSSAngle_test.ts index a4621bfdecb..99b9fa7b74d 100644 --- a/test/unittests/front_end/elements/CSSAngle_test.ts +++ b/test/unittests/front_end/inline_editor/CSSAngle_test.ts @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {CSSAngle, CSSAngleData, PopoverToggledEvent} from '../../../../front_end/elements/CSSAngle.js'; -import {AngleUnit, getAngleFromDegrees, parseText, roundAngleByUnit} from '../../../../front_end/elements/CSSAngleUtils.js'; +import {CSSAngle, CSSAngleData, PopoverToggledEvent} from '../../../../front_end/inline_editor/CSSAngle.js'; +import {AngleUnit, get2DTranslationsForAngle, getAngleFromDegrees, getRadiansFromAngle, parseText, roundAngleByUnit} from '../../../../front_end/inline_editor/CSSAngleUtils.js'; import {assertShadowRoot, renderElementIntoDOM} from '../helpers/DOMHelpers.js'; const {assert} = chai; @@ -28,6 +28,8 @@ const togglePopover = (root: ShadowRoot) => { }; const initialData: CSSAngleData = { + propertyName: 'background', + propertyValue: 'linear-gradient(45deg, red, green)', angleText: '45deg', containingPane: document.createElement('div'), }; @@ -107,6 +109,20 @@ describe('CSSAngle', () => { assert.strictEqual(getAngleFromDegrees(45, AngleUnit.Deg), 45); }); + it('converts angles in other units to radians correctly', () => { + assert.strictEqual(getRadiansFromAngle(50, AngleUnit.Grad), 0.7853981633974483); + assert.strictEqual(getRadiansFromAngle(45, AngleUnit.Deg), 0.7853981633974483); + assert.strictEqual(getRadiansFromAngle(0.125, AngleUnit.Turn), 0.7853981633974483); + assert.strictEqual(getRadiansFromAngle(1, AngleUnit.Rad), 1); + }); + + it('gets 2D translations for angles correctly', () => { + assert.deepEqual(get2DTranslationsForAngle(45, AngleUnit.Deg, 1), { + translateX: 0.7071067811865475, + translateY: -0.7071067811865476, + }); + }); + it('rounds angles by units correctly', () => { assert.strictEqual(roundAngleByUnit(45.723, AngleUnit.Deg), 46); assert.strictEqual(roundAngleByUnit(45.723, AngleUnit.Grad), 46); diff --git a/test/unittests/front_end/inline_editor/CSSVarSwatch_test.ts b/test/unittests/front_end/inline_editor/CSSVarSwatch_test.ts index 54645168c38..b6d7015d1f7 100644 --- a/test/unittests/front_end/inline_editor/CSSVarSwatch_test.ts +++ b/test/unittests/front_end/inline_editor/CSSVarSwatch_test.ts @@ -103,43 +103,4 @@ describe('CSSVarSwatch', () => { hasColorSwatch: false, }); }); - - it('renders a color swatch for properties that compute to valid colors', () => { - const component = new CSSVarSwatch(); - renderElementIntoDOM(component); - component.data = { - text: 'var(--main-color)', - computedValue: '#f06', - fromFallback: false, - onLinkClick: () => {}, - }; - - assertSwatch(component, { - valueTooltip: '#f06', - linkTooltip: 'Jump to definition', - isDefined: true, - varText: '--main-color', - hasColorSwatch: true, - parsedColor: 'rgb(255, 0, 102)', - }); - }); - - it('doesn\'t get confused with properties that look like colors', () => { - const component = new CSSVarSwatch(); - renderElementIntoDOM(component); - component.data = { - text: 'var(--fake-color)', - computedValue: '#12345', - fromFallback: false, - onLinkClick: () => {}, - }; - - assertSwatch(component, { - valueTooltip: '#12345', - linkTooltip: 'Jump to definition', - isDefined: true, - varText: '--fake-color', - hasColorSwatch: false, - }); - }); }); diff --git a/test/unittests/front_end/inline_editor/ColorSwatch_test.ts b/test/unittests/front_end/inline_editor/ColorSwatch_test.ts index 411c9ec413e..c7b10ff9cfb 100644 --- a/test/unittests/front_end/inline_editor/ColorSwatch_test.ts +++ b/test/unittests/front_end/inline_editor/ColorSwatch_test.ts @@ -140,20 +140,58 @@ describe('ColorSwatch', () => { const swatch = createSwatch('red'); const target = getClickTarget(swatch); - const clickEventsReceived: Event[] = []; + const swatchClickEventsReceived: Event[] = []; const onClick = (e: Event) => { - clickEventsReceived.push(e); + swatchClickEventsReceived.push(e); }; swatch.addEventListener('swatch-click', onClick); dispatchClickEvent(target); dispatchClickEvent(target); dispatchClickEvent(target); - assert.strictEqual(clickEventsReceived.length, 3, 'The right click events were received'); + assert.strictEqual(swatchClickEventsReceived.length, 3, 'The right click events were received'); swatch.removeEventListener('swatch-click', onClick); dispatchClickEvent(target); - assert.strictEqual(clickEventsReceived.length, 3, 'No more click events received after removing listener'); + assert.strictEqual(swatchClickEventsReceived.length, 3, 'No more click events received after removing listener'); + }); + + it('does not dispatch a swatch-click event on shift-click', () => { + const swatch = createSwatch('red'); + const target = getClickTarget(swatch); + + const swatchClickEventsReceived: Event[] = []; + const onClick = (e: Event) => { + swatchClickEventsReceived.push(e); + }; + swatch.addEventListener('swatch-click', onClick); + + dispatchClickEvent(target, {shiftKey: true}); + dispatchClickEvent(target, {shiftKey: true}); + dispatchClickEvent(target, {shiftKey: true}); + + assert.strictEqual(swatchClickEventsReceived.length, 0, 'No swatch-click events are received on shift-click'); + + swatch.removeEventListener('swatch-click', onClick); + }); + + it('does not dispatch a format-changed event on click', () => { + const swatch = createSwatch('red'); + const target = getClickTarget(swatch); + + const formatChangedEventsReceived: Event[] = []; + const onClick = (e: Event) => { + formatChangedEventsReceived.push(e); + }; + swatch.addEventListener('format-changed', onClick); + + dispatchClickEvent(target); + dispatchClickEvent(target); + dispatchClickEvent(target); + + assert.strictEqual(formatChangedEventsReceived.length, 0, 'No format-changed events are received on click'); + + swatch.removeEventListener('format-changed', onClick); }); }); diff --git a/test/unittests/front_end/linear_memory_inspector/LinearMemoryInspector_test.ts b/test/unittests/front_end/linear_memory_inspector/LinearMemoryInspector_test.ts index 3932137dcf7..e2d498c543c 100644 --- a/test/unittests/front_end/linear_memory_inspector/LinearMemoryInspector_test.ts +++ b/test/unittests/front_end/linear_memory_inspector/LinearMemoryInspector_test.ts @@ -5,41 +5,136 @@ import {LinearMemoryInspector} from '../../../../front_end/linear_memory_inspector/LinearMemoryInspector.js'; import {toHexString} from '../../../../front_end/linear_memory_inspector/LinearMemoryInspectorUtils.js'; import {LinearMemoryNavigator} from '../../../../front_end/linear_memory_inspector/LinearMemoryNavigator.js'; -import {LinearMemoryViewer} from '../../../../front_end/linear_memory_inspector/LinearMemoryViewer.js'; -import {assertElement, assertShadowRoot, renderElementIntoDOM} from '../helpers/DOMHelpers.js'; +import {ByteSelectedEvent, LinearMemoryViewer} from '../../../../front_end/linear_memory_inspector/LinearMemoryViewer.js'; +import {getElementsWithinComponent, getElementWithinComponent, getEventPromise, renderElementIntoDOM} from '../helpers/DOMHelpers.js'; + +import {NAVIGATOR_ADDRESS_SELECTOR, NAVIGATOR_HISTORY_BUTTON_SELECTOR, NAVIGATOR_PAGE_BUTTON_SELECTOR} from './LinearMemoryNavigator_test.js'; +import {VIEWER_BYTE_CELL_SELECTOR} from './LinearMemoryViewer_test.js'; const {assert} = chai; +const NAVIGATOR_SELECTOR = 'devtools-linear-memory-inspector-navigator'; +const VIEWER_SELECTOR = 'devtools-linear-memory-inspector-viewer'; + describe('LinearMemoryInspector', () => { + function getViewer(component: LinearMemoryInspector) { + return getElementWithinComponent(component, VIEWER_SELECTOR, LinearMemoryViewer); + } + + function getNavigator(component: LinearMemoryInspector) { + return getElementWithinComponent(component, NAVIGATOR_SELECTOR, LinearMemoryNavigator); + } + function setUpComponent() { const component = new LinearMemoryInspector(); - renderElementIntoDOM(component); - const size = 128; + + const flexWrapper = document.createElement('div'); + flexWrapper.style.width = '500px'; + flexWrapper.style.height = '500px'; + flexWrapper.style.display = 'flex'; + flexWrapper.appendChild(component); + renderElementIntoDOM(flexWrapper); + + const size = 1000; const memory = []; for (let i = 0; i < size; ++i) { memory[i] = i; } - component.data = { + const data = { memory: new Uint8Array(memory), address: 20, }; - return component; + component.data = data; + + return {component, data}; } it('renders the navigator component', async () => { - const component = setUpComponent(); - const shadowRoot = component.shadowRoot; - assertShadowRoot(shadowRoot); - const input = shadowRoot.querySelector('devtools-linear-memory-inspector-navigator'); - assertElement(input, LinearMemoryNavigator); + const {component} = setUpComponent(); + const navigator = getNavigator(component); + assert.isNotNull(navigator); }); it('renders the viewer component', async () => { - const component = setUpComponent(); - const shadowRoot = component.shadowRoot; - assertShadowRoot(shadowRoot); - const input = shadowRoot.querySelector('devtools-linear-memory-inspector-viewer'); - assertElement(input, LinearMemoryViewer); + const {component} = setUpComponent(); + const viewer = getViewer(component); + assert.isNotNull(viewer); + }); + + it('can navigate addresses back and forth in history', async () => { + const {component} = setUpComponent(); + + const navigator = getNavigator(component); + const buttons = getElementsWithinComponent(navigator, NAVIGATOR_HISTORY_BUTTON_SELECTOR, HTMLButtonElement); + const [backwardButton, forwardButton] = buttons; + + const viewer = getViewer(component); + const byteCells = getElementsWithinComponent(viewer, VIEWER_BYTE_CELL_SELECTOR, HTMLSpanElement); + + const visitedByteValue = []; + const historyLength = Math.min(byteCells.length, 10); + + for (let i = 0; i < historyLength; ++i) { + const byteSelectedPromise = getEventPromise(viewer, 'byteSelected'); + byteCells[i].click(); + const byteSelectedEvent = await byteSelectedPromise; + visitedByteValue.push(byteSelectedEvent.data); + } + + for (let i = historyLength - 1; i >= 0; --i) { + const currentByteValue = + getElementWithinComponent(viewer, VIEWER_BYTE_CELL_SELECTOR + '.selected', HTMLSpanElement); + assert.strictEqual(parseInt(currentByteValue.innerText, 16), visitedByteValue[i]); + backwardButton.click(); + } + + for (let i = 0; i < historyLength; ++i) { + const currentByteValue = + getElementWithinComponent(viewer, VIEWER_BYTE_CELL_SELECTOR + '.selected', HTMLSpanElement); + assert.strictEqual(parseInt(currentByteValue.innerText, 16), visitedByteValue[i]); + + forwardButton.click(); + } + }); + + it('can turn the page back and forth', async () => { + const {component} = setUpComponent(); + const navigator = getNavigator(component); + const buttons = getElementsWithinComponent(navigator, NAVIGATOR_PAGE_BUTTON_SELECTOR, HTMLButtonElement); + const [backwardButton, forwardButton] = buttons; + + const address = getElementWithinComponent(navigator, NAVIGATOR_ADDRESS_SELECTOR, HTMLInputElement); + const addressBefore = parseInt(address.value, 16); + + const viewer = getViewer(component); + let numBytesPerPage = viewer.getNumBytesPerPage(); + + forwardButton.click(); + let addressAfter = parseInt(address.value, 16); + let expectedAddressAfter = addressBefore + numBytesPerPage; + assert.strictEqual(addressAfter, expectedAddressAfter); + + backwardButton.click(); + addressAfter = parseInt(address.value, 16); + // The number of bytes per page can change since we render twice: once + // initially to estimate how much we can fit, and then rendering to fit + // the assigned size, so we need to re-retrieve it. + numBytesPerPage = viewer.getNumBytesPerPage(); + expectedAddressAfter -= numBytesPerPage; + assert.strictEqual(addressAfter, Math.max(0, expectedAddressAfter)); + }); + + it('synchronizes selected addresses in navigator and viewer', async () => { + const {component, data} = setUpComponent(); + const navigator = getNavigator(component); + + const address = getElementWithinComponent(navigator, NAVIGATOR_ADDRESS_SELECTOR, HTMLInputElement); + const viewer = getViewer(component); + const selectedByte = getElementWithinComponent(viewer, VIEWER_BYTE_CELL_SELECTOR + '.selected', HTMLSpanElement); + + const actualByteValue = parseInt(selectedByte.innerText, 16); + const expectedByteValue = data.memory[parseInt(address.value, 16)]; + assert.strictEqual(actualByteValue, expectedByteValue); }); it('formats a hexadecimal number', async () => { diff --git a/test/unittests/front_end/linear_memory_inspector/LinearMemoryNavigator_test.ts b/test/unittests/front_end/linear_memory_inspector/LinearMemoryNavigator_test.ts index 283b7cceb42..00e68ad4b3c 100644 --- a/test/unittests/front_end/linear_memory_inspector/LinearMemoryNavigator_test.ts +++ b/test/unittests/front_end/linear_memory_inspector/LinearMemoryNavigator_test.ts @@ -7,6 +7,11 @@ import {assertElement, assertElements, assertShadowRoot, getEventPromise, render const {assert} = chai; +export const NAVIGATOR_ADDRESS_SELECTOR = '[data-input]'; +export const NAVIGATOR_PAGE_BUTTON_SELECTOR = '[data-button=pageNavigation]'; +export const NAVIGATOR_HISTORY_BUTTON_SELECTOR = '[data-button=historyNavigation]'; +export const NAVIGATOR_REFRESH_BUTTON_SELECTOR = '[data-button=refresh]'; + describe('LinearMemoryNavigator', () => { let component: LinearMemoryNavigator; @@ -42,7 +47,7 @@ describe('LinearMemoryNavigator', () => { it('renders navigator address', async () => { const shadowRoot = component.shadowRoot; assertShadowRoot(shadowRoot); - const input = shadowRoot.querySelector('[data-input]'); + const input = shadowRoot.querySelector(NAVIGATOR_ADDRESS_SELECTOR); assertElement(input, HTMLInputElement); assert.strictEqual(input.value, '0x00000014'); }); @@ -54,7 +59,7 @@ describe('LinearMemoryNavigator', () => { const shadowRoot = component.shadowRoot; assertShadowRoot(shadowRoot); - const input = shadowRoot.querySelector('[data-input]'); + const input = shadowRoot.querySelector(NAVIGATOR_ADDRESS_SELECTOR); assertElement(input, HTMLInputElement); assert.strictEqual(input.value, '0x00000010'); }); @@ -64,7 +69,7 @@ describe('LinearMemoryNavigator', () => { const shadowRoot = component.shadowRoot; assertShadowRoot(shadowRoot); - const refreshButton = shadowRoot.querySelector('[data-button=refresh]'); + const refreshButton = shadowRoot.querySelector(NAVIGATOR_REFRESH_BUTTON_SELECTOR); assertElement(refreshButton, HTMLButtonElement); refreshButton.click(); @@ -72,10 +77,10 @@ describe('LinearMemoryNavigator', () => { }); it('sends events when clicking previous and next page', async () => { - await assertNavigationEvents('history-navigation'); + await assertNavigationEvents('historyNavigation'); }); it('sends events when clicking undo and redo', async () => { - await assertNavigationEvents('page-navigation'); + await assertNavigationEvents('pageNavigation'); }); }); diff --git a/test/unittests/front_end/linear_memory_inspector/LinearMemoryViewer_test.ts b/test/unittests/front_end/linear_memory_inspector/LinearMemoryViewer_test.ts index 0301c8cbdd5..5f1d9ba4e2f 100644 --- a/test/unittests/front_end/linear_memory_inspector/LinearMemoryViewer_test.ts +++ b/test/unittests/front_end/linear_memory_inspector/LinearMemoryViewer_test.ts @@ -3,20 +3,25 @@ // found in the LICENSE file. import {ByteSelectedEvent, LinearMemoryViewer} from '../../../../front_end/linear_memory_inspector/LinearMemoryViewer.js'; -import {assertElement, assertElements, assertShadowRoot, getEventPromise, renderElementIntoDOM} from '../helpers/DOMHelpers.js'; +import {assertElement, assertElements, assertShadowRoot, getElementWithinComponent, getEventPromise, renderElementIntoDOM} from '../helpers/DOMHelpers.js'; const {assert} = chai; const NUM_BYTES_PER_GROUP = 4; -const BYTE_CELL_SELECTOR = '.byte-cell'; -const TEXT_CELL_SELECTOR = '.text-cell'; -const ROW_SELECTOR = '.row'; -const ADDRESS_SELECTOR = '.address'; +export const VIEWER_BYTE_CELL_SELECTOR = '.byte-cell'; +export const VIEWER_TEXT_CELL_SELECTOR = '.text-cell'; +export const VIEWER_ROW_SELECTOR = '.row'; +export const VIEWER_ADDRESS_SELECTOR = '.address'; describe('LinearMemoryViewer', () => { function setUpComponent() { const component = new LinearMemoryViewer(); - renderElementIntoDOM(component); + const flexWrapper = document.createElement('div'); + flexWrapper.style.width = '500px'; + flexWrapper.style.height = '500px'; + flexWrapper.style.display = 'flex'; + flexWrapper.appendChild(component); + renderElementIntoDOM(flexWrapper); const data = createComponentData(); component.data = data; return {component, data}; @@ -38,7 +43,7 @@ describe('LinearMemoryViewer', () => { function getCellsPerRow(component: LinearMemoryViewer, cellSelector: string) { assertShadowRoot(component.shadowRoot); - const row = component.shadowRoot.querySelector(ROW_SELECTOR); + const row = component.shadowRoot.querySelector(VIEWER_ROW_SELECTOR); assertElement(row, HTMLDivElement); const cellsPerRow = row.querySelectorAll(cellSelector); assert.isNotEmpty(cellsPerRow); @@ -50,22 +55,22 @@ describe('LinearMemoryViewer', () => { it('renders one address per row', async () => { const {component} = setUpComponent(); assertShadowRoot(component.shadowRoot); - const rows = component.shadowRoot.querySelectorAll(ROW_SELECTOR); - const addresses = component.shadowRoot.querySelectorAll(ADDRESS_SELECTOR); + const rows = component.shadowRoot.querySelectorAll(VIEWER_ROW_SELECTOR); + const addresses = component.shadowRoot.querySelectorAll(VIEWER_ADDRESS_SELECTOR); assert.isNotEmpty(rows); assert.strictEqual(rows.length, addresses.length); }); it('renders addresses depending on the bytes per row', async () => { - const {component} = setUpComponent(); - const bytesPerRow = getCellsPerRow(component, BYTE_CELL_SELECTOR); + const {component, data} = setUpComponent(); + const bytesPerRow = getCellsPerRow(component, VIEWER_BYTE_CELL_SELECTOR); const numBytesPerRow = bytesPerRow.length; assertShadowRoot(component.shadowRoot); - const addresses = component.shadowRoot.querySelectorAll(ADDRESS_SELECTOR); + const addresses = component.shadowRoot.querySelectorAll(VIEWER_ADDRESS_SELECTOR); assert.isNotEmpty(addresses); - for (let i = 0, currentAddress = 0; i < addresses.length; currentAddress += numBytesPerRow, ++i) { + for (let i = 0, currentAddress = data.address; i < addresses.length; currentAddress += numBytesPerRow, ++i) { const addressElement = addresses[i]; assertElement(addressElement, HTMLSpanElement); @@ -83,21 +88,23 @@ describe('LinearMemoryViewer', () => { const component = new LinearMemoryViewer(); component.data = createComponentData(); thinWrapper.appendChild(component); - - const bytesPerRow = getCellsPerRow(component, BYTE_CELL_SELECTOR); + renderElementIntoDOM(thinWrapper); + const bytesPerRow = getCellsPerRow(component, VIEWER_BYTE_CELL_SELECTOR); assert.strictEqual(bytesPerRow.length, NUM_BYTES_PER_GROUP); }); it('renders byte values corresponding to memory set', async () => { const {component, data} = setUpComponent(); assertShadowRoot(component.shadowRoot); - const bytes = component.shadowRoot.querySelectorAll(BYTE_CELL_SELECTOR); + const bytes = component.shadowRoot.querySelectorAll(VIEWER_BYTE_CELL_SELECTOR); assertElements(bytes, HTMLSpanElement); const memory = data.memory; + const bytesPerPage = bytes.length; + const memoryStartAddress = Math.floor(data.address / bytesPerPage) * bytesPerPage; assert.isAtMost(bytes.length, memory.length); for (let i = 0; i < bytes.length; ++i) { - const hex = memory[i].toString().padStart(2, '0'); + const hex = memory[memoryStartAddress + i].toString(16).padStart(2, '0'); assert.strictEqual(bytes[i].innerText, hex); } }); @@ -106,8 +113,8 @@ describe('LinearMemoryViewer', () => { describe('ascii view', () => { it('renders as many ascii values as byte values in a row', async () => { const {component} = setUpComponent(); - const bytes = getCellsPerRow(component, BYTE_CELL_SELECTOR); - const ascii = getCellsPerRow(component, TEXT_CELL_SELECTOR); + const bytes = getCellsPerRow(component, VIEWER_BYTE_CELL_SELECTOR); + const ascii = getCellsPerRow(component, VIEWER_TEXT_CELL_SELECTOR); assert.strictEqual(bytes.length, ascii.length); }); @@ -116,8 +123,8 @@ describe('LinearMemoryViewer', () => { const {component} = setUpComponent(); assertShadowRoot(component.shadowRoot); - const asciiValues = component.shadowRoot.querySelectorAll(TEXT_CELL_SELECTOR); - const byteValues = component.shadowRoot.querySelectorAll(BYTE_CELL_SELECTOR); + const asciiValues = component.shadowRoot.querySelectorAll(VIEWER_TEXT_CELL_SELECTOR); + const byteValues = component.shadowRoot.querySelectorAll(VIEWER_BYTE_CELL_SELECTOR); assertElements(asciiValues, HTMLSpanElement); assertElements(byteValues, HTMLSpanElement); assert.strictEqual(byteValues.length, asciiValues.length); @@ -163,22 +170,45 @@ describe('LinearMemoryViewer', () => { address, }; - assertSelectedCellIsHighlighted(component, BYTE_CELL_SELECTOR, address); - assertSelectedCellIsHighlighted(component, TEXT_CELL_SELECTOR, address); - assertSelectedCellIsHighlighted(component, ADDRESS_SELECTOR, 0); + assertSelectedCellIsHighlighted(component, VIEWER_BYTE_CELL_SELECTOR, address); + assertSelectedCellIsHighlighted(component, VIEWER_TEXT_CELL_SELECTOR, address); + assertSelectedCellIsHighlighted(component, VIEWER_ADDRESS_SELECTOR, 0); }); it('triggers an event', async () => { - const {component} = setUpComponent(); + const {component, data} = setUpComponent(); assertShadowRoot(component.shadowRoot); - const byte = component.shadowRoot.querySelector(BYTE_CELL_SELECTOR); + const byte = component.shadowRoot.querySelector(VIEWER_BYTE_CELL_SELECTOR); assertElement(byte, HTMLSpanElement); - const eventPromise = getEventPromise(component, 'byte-selected'); + const eventPromise = getEventPromise(component, 'byteSelected'); byte.click(); const {data: address} = await eventPromise; - assert.strictEqual(address, 0); + assert.strictEqual(address, data.address); }); }); + + it('switches page view when set addresses are not in same view', async () => { + const thinWrapper = document.createElement('div'); + thinWrapper.style.width = '100px'; + thinWrapper.style.height = '100px'; + thinWrapper.style.display = 'flex'; + + const component = new LinearMemoryViewer(); + const data = createComponentData(); + component.data = data; + thinWrapper.appendChild(component); + renderElementIntoDOM(thinWrapper); + + const addressInView = getElementWithinComponent(component, VIEWER_ADDRESS_SELECTOR, HTMLSpanElement); + const addressInViewBeforeUpdate = addressInView.innerText; + + data.address = data.memory.length - 5; + component.data = data; + + assertElement(addressInView, HTMLSpanElement); + const addressInViewAfterUpdate = addressInView.innerText; + assert.notEqual(addressInViewBeforeUpdate, addressInViewAfterUpdate); + }); }); diff --git a/test/unittests/front_end/platform/BUILD.gn b/test/unittests/front_end/platform/BUILD.gn index e0febc2b2a6..cd6dda13141 100644 --- a/test/unittests/front_end/platform/BUILD.gn +++ b/test/unittests/front_end/platform/BUILD.gn @@ -5,6 +5,7 @@ ts_library("platform") { sources = [ "ArrayUtilities_test.ts", "DateUtilities_test.ts", + "MapUtilities_test.ts", "NumberUtilities_test.ts", "SetUtilities_test.ts", "StringUtilities_test.ts", diff --git a/test/unittests/front_end/platform/MapUtilities_test.ts b/test/unittests/front_end/platform/MapUtilities_test.ts new file mode 100644 index 00000000000..b6531c7d527 --- /dev/null +++ b/test/unittests/front_end/platform/MapUtilities_test.ts @@ -0,0 +1,37 @@ +// Copyright (c) 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {MapUtilities} from '../../../../front_end/platform/platform.js'; + +const {assert} = chai; + +describe('MapUtilities', () => { + describe('inverse', () => { + it('inverts the map returning a multimap with the map\'s values as keys and the map\'s keys as values', () => { + const pairs: readonly(readonly[string, number])[] = [ + ['a', 1], + ['b', 2], + ['c', 3], + ['d', 1], + ]; + const map = new Map(pairs); + + const inverse = MapUtilities.inverse(map); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_key, value] of pairs) { + assert.sameMembers([...inverse.get(value)], [...getKeys(value)]); + } + + function getKeys(lookupValue: number): Set { + const keys = new Set(); + for (const [key, value] of pairs) { + if (value === lookupValue) { + keys.add(key); + } + } + return keys; + } + }); + }); +}); diff --git a/test/unittests/front_end/platform/NumberUtilities_test.ts b/test/unittests/front_end/platform/NumberUtilities_test.ts index 3096984b6cf..aebd3a5bdb6 100644 --- a/test/unittests/front_end/platform/NumberUtilities_test.ts +++ b/test/unittests/front_end/platform/NumberUtilities_test.ts @@ -42,13 +42,13 @@ describe('NumberUtilities', () => { }); it('formats for < 100 megabytes', () => { - const oneAndAHalfMegabytes = 1524 * 1024; - assert.deepEqual(NumberUtilities.bytesToString(oneAndAHalfMegabytes), '1.6\xA0MB'); + const oneAndAHalfMegabytes = 1500 * 1000; + assert.deepEqual(NumberUtilities.bytesToString(oneAndAHalfMegabytes), '1.5\xA0MB'); }); it('formats for > 100 megabytes', () => { - const oneMegabyte = 1024 * 1024; - const twoHundredAndTenMegabytes = oneMegabyte * 200; + const oneMegabyte = 1000 * 1000; + const twoHundredAndTenMegabytes = oneMegabyte * 210; assert.deepEqual(NumberUtilities.bytesToString(twoHundredAndTenMegabytes), '210\xA0MB'); }); }); diff --git a/test/unittests/front_end/ui/Geometry_test.ts b/test/unittests/front_end/ui/Geometry_test.ts index b24b6f82c05..3d0c46b7348 100644 --- a/test/unittests/front_end/ui/Geometry_test.ts +++ b/test/unittests/front_end/ui/Geometry_test.ts @@ -543,4 +543,46 @@ describe('boundsForTransformedPoints', () => { assert.strictEqual(result.minY, 2, 'minY was calculated incorrectly'); assert.strictEqual(result.maxY, 8, 'maxY was calculated incorrectly'); }); + + describe('degreesToRadians', () => { + it('converts degrees to radians correctly', () => { + assert.strictEqual(UI.Geometry.degreesToRadians(45), 0.7853981633974483); + assert.strictEqual(UI.Geometry.degreesToRadians(180), 3.141592653589793); + }); + }); + + describe('degreesToGradians', () => { + it('converts degrees to gradians correctly', () => { + assert.strictEqual(UI.Geometry.degreesToGradians(45), 50); + assert.strictEqual(UI.Geometry.degreesToGradians(180), 200); + }); + }); + + describe('degreesToTurns', () => { + it('converts degrees to turns correctly', () => { + assert.strictEqual(UI.Geometry.degreesToTurns(45), 0.125); + assert.strictEqual(UI.Geometry.degreesToTurns(180), 0.5); + }); + }); + + describe('radiansToDegrees', () => { + it('converts radians to degrees correctly', () => { + assert.strictEqual(UI.Geometry.radiansToDegrees(1), 57.29577951308232); + assert.strictEqual(UI.Geometry.radiansToDegrees(1.5), 85.94366926962348); + }); + }); + + describe('gradiansToRadians', () => { + it('converts gradians to radians correctly', () => { + assert.strictEqual(UI.Geometry.gradiansToRadians(50), 0.7853981633974483); + assert.strictEqual(UI.Geometry.gradiansToRadians(200), 3.141592653589793); + }); + }); + + describe('turnsToRadians', () => { + it('converts turns to radians correctly', () => { + assert.strictEqual(UI.Geometry.gradiansToRadians(0.5), 0.007853981633974483); + assert.strictEqual(UI.Geometry.gradiansToRadians(1), 0.015707963267948967); + }); + }); }); diff --git a/test/webtests/http/tests/devtools/a11y-axe-core/application-panel/service-worker-view-a11y-test.js b/test/webtests/http/tests/devtools/a11y-axe-core/application-panel/service-worker-view-a11y-test.js index 35b37fae34e..762ae5040e7 100644 --- a/test/webtests/http/tests/devtools/a11y-axe-core/application-panel/service-worker-view-a11y-test.js +++ b/test/webtests/http/tests/devtools/a11y-axe-core/application-panel/service-worker-view-a11y-test.js @@ -13,7 +13,7 @@ const scriptURL = 'http://127.0.0.1:8000/devtools/service-workers/resources/service-worker-empty.js'; const scope1 = 'http://127.0.0.1:8000/devtools/service-workers/resources/scope1/'; const scope2 = 'http://127.0.0.1:8000/devtools/service-workers/resources/scope2/'; - Resources.ServiceWorkersView._noThrottle = true; + Resources.ServiceWorkersView.setThrottleDisabledForDebugging = true; UI.panels.resources._sidebar.serviceWorkersTreeElement.select(); ApplicationTestRunner.registerServiceWorker(scriptURL, scope1); diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.json b/third_party/blink/public/devtools_protocol/browser_protocol.json index d917a7737ee..20e2ae79268 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.json +++ b/third_party/blink/public/devtools_protocol/browser_protocol.json @@ -6844,6 +6844,16 @@ "type": "boolean" } ] + }, + { + "id": "DisabledImageType", + "description": "Enum of image types that can be disabled.", + "experimental": true, + "type": "string", + "enum": [ + "avif", + "webp" + ] } ], "commands": [ @@ -7263,6 +7273,20 @@ } ] }, + { + "name": "setDisabledImageTypes", + "experimental": true, + "parameters": [ + { + "name": "imageTypes", + "description": "Image types to disable.", + "type": "array", + "items": { + "$ref": "DisabledImageType" + } + } + ] + }, { "name": "setUserAgentOverride", "description": "Allows overriding user agent with the given string.", @@ -9807,6 +9831,51 @@ "corp-not-same-site" ] }, + { + "id": "CorsError", + "description": "The reason why request was blocked.", + "type": "string", + "enum": [ + "DisallowedByMode", + "InvalidResponse", + "WildcardOriginNotAllowed", + "MissingAllowOriginHeader", + "MultipleAllowOriginValues", + "InvalidAllowOriginValue", + "AllowOriginMismatch", + "InvalidAllowCredentials", + "CorsDisabledScheme", + "PreflightInvalidStatus", + "PreflightDisallowedRedirect", + "PreflightWildcardOriginNotAllowed", + "PreflightMissingAllowOriginHeader", + "PreflightMultipleAllowOriginValues", + "PreflightInvalidAllowOriginValue", + "PreflightAllowOriginMismatch", + "PreflightInvalidAllowCredentials", + "PreflightMissingAllowExternal", + "PreflightInvalidAllowExternal", + "InvalidAllowMethodsPreflightResponse", + "InvalidAllowHeadersPreflightResponse", + "MethodDisallowedByPreflightResponse", + "HeaderDisallowedByPreflightResponse", + "RedirectContainsCredentials" + ] + }, + { + "id": "CorsErrorStatus", + "type": "object", + "properties": [ + { + "name": "corsError", + "$ref": "CorsError" + }, + { + "name": "failedParameter", + "type": "string" + } + ] + }, { "id": "ServiceWorkerResponseSource", "description": "Source of serviceworker response.", @@ -11505,6 +11574,12 @@ "description": "The reason why loading was blocked, if any.", "optional": true, "$ref": "BlockedReason" + }, + { + "name": "corsErrorStatus", + "description": "The reason why loading was blocked by CORS, if any.", + "optional": true, + "$ref": "CorsErrorStatus" } ] }, diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 3f46238a24d..cb5c1d6bb25 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl @@ -3310,6 +3310,17 @@ domain Emulation # Notification sent after the virtual time budget for the current VirtualTimePolicy has run out. experimental event virtualTimeBudgetExpired + # Enum of image types that can be disabled. + experimental type DisabledImageType extends string + enum + avif + webp + + experimental command setDisabledImageTypes + parameters + # Image types to disable. + array of DisabledImageType imageTypes + # Allows overriding user agent with the given string. command setUserAgentOverride parameters @@ -4485,6 +4496,39 @@ domain Network corp-not-same-origin-after-defaulted-to-same-origin-by-coep corp-not-same-site + # The reason why request was blocked. + type CorsError extends string + enum + DisallowedByMode + InvalidResponse + WildcardOriginNotAllowed + MissingAllowOriginHeader + MultipleAllowOriginValues + InvalidAllowOriginValue + AllowOriginMismatch + InvalidAllowCredentials + CorsDisabledScheme + PreflightInvalidStatus + PreflightDisallowedRedirect + PreflightWildcardOriginNotAllowed + PreflightMissingAllowOriginHeader + PreflightMultipleAllowOriginValues + PreflightInvalidAllowOriginValue + PreflightAllowOriginMismatch + PreflightInvalidAllowCredentials + PreflightMissingAllowExternal + PreflightInvalidAllowExternal + InvalidAllowMethodsPreflightResponse + InvalidAllowHeadersPreflightResponse + MethodDisallowedByPreflightResponse + HeaderDisallowedByPreflightResponse + RedirectContainsCredentials + + type CorsErrorStatus extends object + properties + CorsError corsError + string failedParameter + # Source of serviceworker response. type ServiceWorkerResponseSource extends string enum @@ -5235,6 +5279,8 @@ domain Network optional boolean canceled # The reason why loading was blocked, if any. optional BlockedReason blockedReason + # The reason why loading was blocked by CORS, if any. + optional CorsErrorStatus corsErrorStatus # Fired when HTTP request has finished loading. event loadingFinished diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index 179cc999ea1..231984654fa 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5 @@ -446,15 +446,6 @@ valid_type: "str", }, - // - affected_by_forced_colors - // The property value will be overridden with the default value defined in - // the forced colors UA style sheet when forced colors mode is enabled and - // forced-color-adjust is set to auto. - affected_by_forced_colors: { - default: false, - valid_type: "bool", - }, - // - valid_for_first_letter: true // // https://drafts.csswg.org/css-pseudo-4/#first-letter-styling @@ -479,6 +470,14 @@ valid_type: "bool", }, + // - valid_for_highlight: true + // + // https://drafts.csswg.org/css-pseudo-4/#highlight-styling + valid_for_highlight: { + default: false, + valid_type: "bool", + }, + // - is_border // The property, when used by the author, will disable any native // appearance on UI elements. @@ -710,10 +709,10 @@ priority: "High", keywords: ["currentcolor"], typedom_types: ["Keyword"], - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, valid_for_marker: true, + valid_for_highlight: true, }, { name: "direction", @@ -969,6 +968,7 @@ keywords: ["auto", "none"], typedom_types: ["Keyword"], default_value: "auto", + valid_for_highlight: true, }, { name: "-webkit-locale", @@ -1198,9 +1198,9 @@ style_builder_template_args: { initial_color: "ComputedStyleInitialValues::InitialBackgroundColor", }, - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, + valid_for_highlight: true, is_background: true, }, { @@ -1215,7 +1215,6 @@ fill_type: "Image", fill_type_getter: "GetImage", }, - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, is_background: true, @@ -1314,7 +1313,6 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_first_letter: true, is_border: true, computed_value_comparable: true, @@ -1465,7 +1463,6 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_first_letter: true, is_border: true, computed_value_comparable: true, @@ -1517,7 +1514,6 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_first_letter: true, is_border: true, computed_value_comparable: true, @@ -1569,7 +1565,6 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_first_letter: true, is_border: true, computed_value_comparable: true, @@ -1663,7 +1658,6 @@ converter: "ConvertShadowList", keywords: ["none"], typedom_types: ["Keyword"], - affected_by_forced_colors: true, valid_for_first_letter: true, }, { @@ -1742,6 +1736,7 @@ style_builder_custom_functions: ["initial", "inherit", "value"], keywords: ["auto", "currentcolor"], typedom_types: ["Keyword"], + valid_for_highlight: true, }, { name: "clear", @@ -1823,6 +1818,7 @@ type_name: "Vector", default_value: "Vector()", field_template: "external", + valid_for_highlight: true, }, { name: "column-fill", @@ -1919,7 +1915,8 @@ ], default_value: "auto", style_builder_custom_functions: ["initial", "inherit", "value"], - typedom_types: ["Keyword"] + typedom_types: ["Keyword"], + valid_for_highlight: true, }, { name: "cx", @@ -1987,7 +1984,7 @@ setter: "SetFillPaint", getter: "FillPaint", converter: "ConvertSVGPaint", - affected_by_forced_colors: true, + valid_for_highlight: true, }, { name: "fill-opacity", @@ -2373,6 +2370,7 @@ typedom_types: ["Keyword", "Length", "Number", "Percentage"], valid_for_first_letter: true, valid_for_cue: true, + valid_for_marker: true, }, { name: "line-height-step", @@ -2772,7 +2770,6 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_cue: true, }, { @@ -3473,7 +3470,7 @@ setter: "SetStrokePaint", getter: "StrokePaint", converter: "ConvertSVGPaint", - affected_by_forced_colors: true, + valid_for_highlight: true, }, { name: "stroke-dasharray", @@ -3542,7 +3539,8 @@ inherited: true, svg: true, converter: "ConvertUnzoomedLength", - typedom_types: ["Length", "Percentage"] + typedom_types: ["Length", "Percentage"], + valid_for_highlight: true, }, { name: "table-layout", @@ -3629,9 +3627,9 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, + valid_for_highlight: true, computed_value_comparable: true, }, { @@ -3647,6 +3645,7 @@ converter: "ConvertFlags", valid_for_first_letter: true, valid_for_cue: true, + valid_for_highlight: true, computed_value_comparable: true, }, { @@ -3661,6 +3660,7 @@ valid_for_first_letter: true, valid_for_cue: true, valid_for_marker: true, + valid_for_highlight: true, computed_value_comparable: true, }, { @@ -3673,6 +3673,7 @@ default_value: "solid", valid_for_first_letter: true, valid_for_cue: true, + valid_for_highlight: true, computed_value_comparable: true, }, { @@ -3689,6 +3690,7 @@ keywords: ["auto", "from-font"], typedom_types: ["Keyword", "Length", "Percentage"], valid_for_first_letter: true, + valid_for_highlight: true, computed_value_comparable: true, }, { @@ -3740,10 +3742,10 @@ converter: "ConvertShadowList", keywords: ["none"], typedom_types: ["Keyword"], - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, valid_for_marker: true, + valid_for_highlight: true, }, { name: "text-size-adjust", @@ -4159,7 +4161,6 @@ typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, }, { name: "column-rule-style", @@ -4439,7 +4440,6 @@ field_template: "", default_value: "StyleColor(LayoutTheme::TapHighlightColor())", converter: "ConvertStyleColor", - affected_by_forced_colors: true, }, { name: "-webkit-text-combine", @@ -4459,8 +4459,8 @@ computed_style_custom_functions: ["getter"], converter: "ConvertStyleColor", style_builder_template: "color", - affected_by_forced_colors: true, valid_for_marker: true, + valid_for_highlight: true, }, { name: "-webkit-text-emphasis-position", @@ -4493,6 +4493,7 @@ computed_style_custom_functions: ["getter"], converter: "ConvertStyleColor", style_builder_template: "color", + valid_for_highlight: true, }, { name: "-webkit-text-security", @@ -4516,6 +4517,7 @@ computed_style_custom_functions: ["getter"], converter: "ConvertStyleColor", style_builder_template: "color", + valid_for_highlight: true, }, { name: "-webkit-text-stroke-width", @@ -4526,6 +4528,7 @@ default_value: "0", type_name: "float", converter: "ConvertTextStrokeWidth", + valid_for_highlight: true, }, { name: "-webkit-transform-origin-x", @@ -5740,10 +5743,10 @@ computed_style_custom_functions: ["getter", "setter"], style_builder_custom_functions: ["initial", "inherit", "value"], priority: "High", - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, valid_for_marker: true, + valid_for_highlight: true, }, { name: "-internal-visited-caret-color", @@ -5761,6 +5764,7 @@ style_builder_template_args: { initial_color: "StyleAutoColor::AutoColor", }, + valid_for_highlight: true, }, { name: "-internal-visited-column-rule-color", @@ -5774,7 +5778,6 @@ computed_style_custom_functions: ["getter","setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, }, { name: "-internal-visited-background-color", @@ -5791,9 +5794,9 @@ style_builder_template_args: { initial_color: "ComputedStyleInitialValues::InitialBackgroundColor", }, - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, + valid_for_highlight: true, }, { name: "-internal-visited-border-left-color", @@ -5807,7 +5810,6 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, valid_for_first_letter: true, }, { @@ -5822,7 +5824,6 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, valid_for_first_letter: true, }, { @@ -5837,7 +5838,6 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, valid_for_first_letter: true, }, { @@ -5852,7 +5852,6 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, valid_for_first_letter: true, }, { @@ -5905,7 +5904,7 @@ setter: "SetInternalVisitedFillPaint", getter: "FillPaint", converter: "ConvertSVGPaint", - affected_by_forced_colors: true, + valid_for_highlight: true, }, { name: "-internal-visited-outline-color", @@ -5919,7 +5918,6 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, valid_for_cue: true, }, { @@ -5932,7 +5930,7 @@ setter: "SetInternalVisitedStrokePaint", getter: "StrokePaint", converter: "ConvertSVGPaint", - affected_by_forced_colors: true, + valid_for_highlight: true, }, { name: "-internal-visited-text-decoration-color", @@ -5946,9 +5944,9 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, valid_for_first_letter: true, valid_for_cue: true, + valid_for_highlight: true, }, { name: "-internal-visited-text-emphasis-color", @@ -5963,7 +5961,7 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", - affected_by_forced_colors: true, + valid_for_highlight: true, }, { name: "-internal-visited-text-fill-color", @@ -5978,6 +5976,7 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", + valid_for_highlight: true, }, { name: "-internal-visited-text-stroke-color", @@ -5992,6 +5991,7 @@ computed_style_custom_functions: ["getter", "setter"], converter: "ConvertStyleColor", style_builder_template: "visited_color", + valid_for_highlight: true, }, // Name: -internal-empty-line-height: @@ -6016,6 +6016,24 @@ converter: "ConvertInternalEmptyLineHeight", }, + // Name: -internal-align-self-block: + // Value: normal | center + // Applies to: A block child in a normal blow flow context + // If 'center' is specified and the container's block size is not auto, + // it works like "align-self: center" for grid/flex items. + // The block child should create new block formatting context. + { + name: "-internal-align-self-block", + property_methods: ["ParseSingleValue"], + inherited: false, + field_group: "*", + field_template: "primitive", + type_name: "bool", + default_value: "false", + name_for_methods: "AlignSelfBlockCenter", + converter: "ConvertInternalAlignSelfBlock", + }, + // Aliases; these map to the same CSSPropertyID { name: "-epub-caption-side",