chrome-devtools-frontend 1.0.1547147 → 1.0.1547571

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/.stylelintrc.json +5 -1
  2. package/docs/contributing/infrastructure.md +2 -2
  3. package/eslint.config.mjs +3 -2
  4. package/front_end/Images/generate-css-vars.js +1 -1
  5. package/front_end/core/common/common.ts +0 -2
  6. package/front_end/core/i18n/collect-ui-strings.js +1 -1
  7. package/front_end/core/i18n/generate-locales-js.js +1 -1
  8. package/front_end/core/platform/HostRuntime.ts +14 -7
  9. package/front_end/core/platform/api/HostRuntime.ts +28 -3
  10. package/front_end/core/platform/browser/HostRuntime.ts +66 -5
  11. package/front_end/core/platform/node/HostRuntime.ts +76 -4
  12. package/front_end/core/sdk/AnimationModel.ts +1 -1
  13. package/front_end/core/sdk/CSSModel.ts +1 -1
  14. package/front_end/core/sdk/CSSProperty.ts +1 -1
  15. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +1 -1
  16. package/front_end/core/sdk/ConsoleModel.ts +1 -1
  17. package/front_end/core/sdk/Cookie.ts +1 -1
  18. package/front_end/core/sdk/DOMModel.ts +2 -2
  19. package/front_end/core/sdk/DebuggerModel.ts +1 -1
  20. package/front_end/core/sdk/NetworkManager.ts +6 -0
  21. package/front_end/core/sdk/PreloadingModel.ts +1 -1
  22. package/front_end/core/sdk/RemoteObject.ts +1 -1
  23. package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
  24. package/front_end/core/sdk/Script.ts +4 -4
  25. package/front_end/entrypoints/formatter_worker/HTMLFormatter.ts +2 -2
  26. package/front_end/entrypoints/formatter_worker/JavaScriptFormatter.ts +15 -18
  27. package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +8 -5
  28. package/front_end/entrypoints/main/ExecutionContextSelector.ts +1 -1
  29. package/front_end/entrypoints/main/MainImpl.ts +2 -2
  30. package/front_end/generated/Deprecation.ts +19 -0
  31. package/front_end/generated/InspectorBackendCommands.ts +4 -3
  32. package/front_end/generated/SupportedCSSProperties.js +13 -13
  33. package/front_end/generated/protocol-mapping.d.ts +2 -0
  34. package/front_end/generated/protocol-proxy-api.d.ts +4 -0
  35. package/front_end/generated/protocol.ts +16 -27
  36. package/front_end/models/ai_assistance/AiConversation.ts +104 -24
  37. package/front_end/models/ai_assistance/BuiltInAi.ts +131 -134
  38. package/front_end/models/ai_assistance/ChangeManager.ts +9 -0
  39. package/front_end/models/ai_assistance/ConversationHandler.ts +23 -48
  40. package/front_end/models/ai_assistance/agents/AiAgent.ts +8 -5
  41. package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -10
  42. package/front_end/models/formatter/FormatterWorkerPool.ts +9 -7
  43. package/front_end/models/har/Importer.ts +1 -1
  44. package/front_end/models/issues_manager/ContrastCheckTrigger.ts +1 -1
  45. package/front_end/models/persistence/AutomaticFileSystemManager.ts +1 -1
  46. package/front_end/panels/accessibility/AccessibilityNodeView.ts +1 -1
  47. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +80 -153
  48. package/front_end/panels/ai_assistance/components/ChatView.ts +54 -31
  49. package/front_end/panels/application/ExtensionStorageModel.ts +1 -1
  50. package/front_end/panels/application/FrameDetailsView.ts +62 -34
  51. package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
  52. package/front_end/panels/application/components/components.ts +0 -2
  53. package/front_end/panels/console/ConsoleInsightTeaser.ts +166 -100
  54. package/front_end/panels/console/ConsolePrompt.ts +1 -1
  55. package/front_end/panels/console/ConsoleViewMessage.ts +77 -29
  56. package/front_end/panels/console/ConsoleViewport.ts +1 -1
  57. package/front_end/panels/console/consoleInsightTeaser.css +1 -0
  58. package/front_end/panels/coverage/CoverageModel.ts +2 -2
  59. package/front_end/panels/elements/ElementsPanel.ts +1 -1
  60. package/front_end/panels/elements/ElementsTreeOutline.ts +17 -7
  61. package/front_end/panels/elements/NodeStackTraceWidget.ts +6 -5
  62. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -2
  63. package/front_end/panels/explain/components/ConsoleInsight.ts +1 -1
  64. package/front_end/panels/network/RequestConditionsDrawer.ts +64 -20
  65. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +1 -1
  66. package/front_end/panels/profiler/HeapSnapshotProxy.ts +15 -14
  67. package/front_end/panels/recorder/components/StepEditor.ts +1 -1
  68. package/front_end/panels/security/SecurityPanelSidebar.ts +1 -3
  69. package/front_end/panels/settings/KeybindsSettingsTab.ts +1 -1
  70. package/front_end/panels/sources/CSSPlugin.ts +1 -1
  71. package/front_end/panels/sources/DebuggerPlugin.ts +2 -2
  72. package/front_end/panels/sources/NavigatorView.ts +1 -1
  73. package/front_end/panels/sources/SourcesSearchScope.ts +1 -1
  74. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +10 -2
  75. package/front_end/panels/timeline/TimelineFlameChartView.ts +1 -1
  76. package/front_end/panels/timeline/TimelinePanel.ts +7 -7
  77. package/front_end/panels/timeline/TimelineUIUtils.ts +3 -1
  78. package/front_end/panels/timeline/enable-easter-egg.js +1 -1
  79. package/front_end/panels/timeline/utils/Treemap.ts +1 -1
  80. package/front_end/third_party/chromium/README.chromium +1 -1
  81. package/front_end/third_party/puppeteer/README.chromium +2 -2
  82. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/DeviceRequestPrompt.d.ts +66 -0
  83. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/DeviceRequestPrompt.d.ts.map +1 -0
  84. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/DeviceRequestPrompt.js +57 -0
  85. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/DeviceRequestPrompt.js.map +1 -0
  86. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.d.ts +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.js.map +1 -1
  89. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +2 -2
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/api.d.ts +1 -0
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/api.d.ts.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/api.js +1 -0
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/api.js.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js +1 -6
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js.map +1 -1
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +0 -4
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +18 -23
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts +2 -0
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +16 -0
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/DeviceRequestPrompt.d.ts +4 -62
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/DeviceRequestPrompt.d.ts.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/DeviceRequestPrompt.js +9 -73
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/DeviceRequestPrompt.js.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Frame.d.ts +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Frame.d.ts.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Frame.js.map +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  116. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +3 -3
  117. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  118. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts +8 -1
  119. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.d.ts.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.js +11 -1
  121. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConsoleMessage.js.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  124. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  125. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  127. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  129. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +9 -10
  130. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +80 -81
  131. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/DeviceRequestPrompt.d.ts +66 -0
  132. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/DeviceRequestPrompt.d.ts.map +1 -0
  133. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/DeviceRequestPrompt.js +52 -0
  134. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/DeviceRequestPrompt.js.map +1 -0
  135. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.d.ts +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.d.ts.map +1 -1
  137. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.js.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -2
  139. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  140. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/api.d.ts +1 -0
  142. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/api.d.ts.map +1 -1
  143. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/api.js +1 -0
  144. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/api.js.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  146. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js +1 -6
  147. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js.map +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +0 -4
  149. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  150. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +18 -23
  151. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  152. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts +2 -0
  153. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  154. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +16 -0
  155. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  156. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/DeviceRequestPrompt.d.ts +4 -62
  157. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/DeviceRequestPrompt.d.ts.map +1 -1
  158. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/DeviceRequestPrompt.js +6 -69
  159. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/DeviceRequestPrompt.js.map +1 -1
  160. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Frame.d.ts +1 -1
  161. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Frame.d.ts.map +1 -1
  162. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Frame.js.map +1 -1
  163. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +1 -1
  164. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  165. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +3 -3
  166. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  167. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConsoleMessage.d.ts +8 -1
  168. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConsoleMessage.d.ts.map +1 -1
  169. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConsoleMessage.js +11 -1
  170. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConsoleMessage.js.map +1 -1
  171. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  172. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  173. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  174. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  175. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  176. package/front_end/third_party/puppeteer/package/lib/types.d.ts +9 -10
  177. package/front_end/third_party/puppeteer/package/package.json +3 -3
  178. package/front_end/third_party/puppeteer/package/src/api/DeviceRequestPrompt.ts +79 -0
  179. package/front_end/third_party/puppeteer/package/src/api/Frame.ts +1 -1
  180. package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -2
  181. package/front_end/third_party/puppeteer/package/src/api/api.ts +1 -0
  182. package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +1 -9
  183. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +21 -31
  184. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +18 -0
  185. package/front_end/third_party/puppeteer/package/src/cdp/DeviceRequestPrompt.ts +6 -72
  186. package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +2 -4
  187. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +7 -2
  188. package/front_end/third_party/puppeteer/package/src/common/ConsoleMessage.ts +14 -0
  189. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  190. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  191. package/front_end/third_party/puppeteer/puppeteer-tsconfig.json +1 -0
  192. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +4 -0
  193. package/front_end/ui/components/text_editor/javascript.ts +1 -1
  194. package/front_end/ui/legacy/ListWidget.ts +51 -18
  195. package/front_end/ui/legacy/ReportView.ts +1 -1
  196. package/front_end/ui/legacy/TabbedPane.ts +3 -3
  197. package/front_end/ui/legacy/Treeoutline.ts +1 -1
  198. package/front_end/ui/legacy/components/color_picker/ContrastInfo.ts +1 -1
  199. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +3 -2
  200. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +87 -111
  201. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +1 -2
  202. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +40 -11
  203. package/front_end/ui/legacy/components/utils/jsUtils.css +28 -0
  204. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  205. package/front_end/ui/visual_logging/LoggingConfig.ts +2 -1
  206. package/inspector_overlay/tool_window_controls.ts +4 -1
  207. package/mcp/mcp.ts +1 -1
  208. package/package.json +2 -3
  209. package/front_end/core/common/Worker.ts +0 -60
  210. package/front_end/panels/application/components/StackTrace.ts +0 -238
  211. package/front_end/panels/application/components/stackTraceLinkButton.css +0 -16
  212. package/front_end/panels/application/components/stackTraceRow.css +0 -50
package/.stylelintrc.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "extends": "stylelint-config-standard",
3
- "plugins": ["./scripts/stylelint_rules/lib/use_theme_colors.mjs"],
3
+ "plugins": [
4
+ "./scripts/stylelint_rules/lib/use_theme_colors.mjs",
5
+ "./scripts/stylelint_rules/lib/check_highlight_scope.mjs"
6
+ ],
4
7
  "rules": {
5
8
  "plugin/use_theme_colors": true,
9
+ "plugin/check_highlight_scope": true,
6
10
  "alpha-value-notation": "percentage",
7
11
  "color-function-notation": "modern",
8
12
  "hue-degree-notation": "angle",
@@ -217,12 +217,12 @@ Below is a detailed description of what happens in such a build:
217
217
  - It does a `bot_update` of its own
218
218
  - Generates the GN files (`gn` step)
219
219
  - Compiles (`compile`) the project
220
- - Reads the e2e_non_hosted test lists
220
+ - Reads the e2e test lists
221
221
  - Creates a CAS archive with project and the compilation output
222
222
  - Outputs the `compilator_properties`
223
223
  - Once the compilator is done we read the `compilator_properties` to find
224
224
  - the `cas_digest` to be used when triggering tests on swarming
225
- - the `e2e_non_hosted_test_list` for sharding the e2e tests execution
225
+ - the `e2e_test_list` for sharding the e2e tests execution
226
226
  - Write the e2e test list at the location where building would have written it
227
227
  - The default test run phase starts at `Run tests` step:
228
228
  - We trigger all tests on swarming in parallel (`Trigger Tests`) substep.
package/eslint.config.mjs CHANGED
@@ -10,7 +10,7 @@ import jsdocPlugin from 'eslint-plugin-jsdoc';
10
10
  import litPlugin from 'eslint-plugin-lit';
11
11
  import mochaPlugin from 'eslint-plugin-mocha';
12
12
  import globals from 'globals';
13
- import { join } from 'path';
13
+ import { join } from 'node:path';
14
14
  import typescriptEslint from 'typescript-eslint';
15
15
 
16
16
  import devToolsPlugin from './scripts/eslint_rules/plugin.mjs';
@@ -60,7 +60,7 @@ export default defineConfig([
60
60
  'scripts/protocol_typescript/*.js',
61
61
  'scripts/deps/tests/fixtures',
62
62
  'test/**/fixtures/',
63
- 'test/e2e_non_hosted/**/*.js',
63
+ 'test/e2e/**/*.js',
64
64
  'test/shared/**/*.js',
65
65
  ]),
66
66
  {
@@ -284,6 +284,7 @@ export default defineConfig([
284
284
  },
285
285
  },
286
286
  ],
287
+ 'import/enforce-node-protocol-usage': ['error', 'always'],
287
288
  // Try to spot '// console.log()' left over from debugging
288
289
  '@devtools/no-commented-out-console': 'error',
289
290
  // Prevent imports being commented out rather than deleted.
@@ -1,7 +1,7 @@
1
1
  // Copyright 2020 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- const path = require('path');
4
+ const path = require('node:path');
5
5
 
6
6
  const {writeIfChanged} = require('../../scripts/build/ninja/write-if-changed.js');
7
7
  const [, , buildTimestamp, targetGenDir, targetName, ...imageSources] = process.argv;
@@ -33,7 +33,6 @@ import * as StringOutputStream from './StringOutputStream.js';
33
33
  import * as TextDictionary from './TextDictionary.js';
34
34
  import * as Throttler from './Throttler.js';
35
35
  import * as Trie from './Trie.js';
36
- import * as Worker from './Worker.js';
37
36
 
38
37
  /*
39
38
  * This is re-exported here because we moved UIString into platform from
@@ -73,5 +72,4 @@ export {
73
72
  TextDictionary,
74
73
  Throttler,
75
74
  Trie,
76
- Worker,
77
75
  };
@@ -3,7 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  const glob = require('glob');
6
- const path = require('path');
6
+ const path = require('node:path');
7
7
  const yargs = require('yargs');
8
8
  const {hideBin} = require('yargs/helpers');
9
9
 
@@ -2,7 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- const path = require('path');
5
+ const path = require('node:path');
6
6
  const yargs = require('yargs');
7
7
  const {hideBin} = require('yargs/helpers');
8
8
 
@@ -3,15 +3,22 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import type * as Api from './api/api.js';
6
- import * as Browser from './browser/browser.js';
7
- import * as Node from './node/node.js';
8
6
 
9
- export const HOST_RUNTIME = ((): Api.HostRuntime.HostRuntime => {
10
- if (Node.HostRuntime.IS_NODE) {
11
- return Node.HostRuntime.HOST_RUNTIME;
7
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
8
+ // @ts-ignore 'process' is not available when type-checking against browser types.
9
+ export const IS_NODE = typeof (process as unknown) !== 'undefined' && process.versions?.node !== null;
10
+
11
+ export const IS_BROWSER =
12
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
13
+ // @ts-ignore 'window' is not available when type-checking against node.js types.
14
+ typeof window !== 'undefined' || (typeof self !== 'undefined' && typeof self.postMessage === 'function');
15
+
16
+ export const HOST_RUNTIME = await (async(): Promise<Api.HostRuntime.HostRuntime> => {
17
+ if (IS_NODE) {
18
+ return (await import('./node/node.js')).HostRuntime.HOST_RUNTIME;
12
19
  }
13
- if (Browser.HostRuntime.IS_BROWSER) {
14
- return Browser.HostRuntime.HOST_RUNTIME;
20
+ if (IS_BROWSER) {
21
+ return (await import('./browser/browser.js')).HostRuntime.HOST_RUNTIME;
15
22
  }
16
23
 
17
24
  throw new Error('Unknown runtime!');
@@ -8,13 +8,38 @@
8
8
  */
9
9
  export interface HostRuntime {
10
10
  createWorker(url: string): Worker;
11
+ workerScope: WorkerScope;
11
12
  }
12
13
 
13
14
  /**
14
15
  * Abstracts away the differences between browser web workers and Node.js worker threads.
15
16
  */
16
17
  export interface Worker {
17
- // TODO(crbug.com/461952544): Actually add some methods here.
18
- // Leave one marker method to make this non-empty.
19
- dispose?(): void;
18
+ postMessage(message: unknown, transfer?: WorkerTransferable[]): void;
19
+
20
+ dispose(): void;
21
+ terminate(immediately?: boolean): void;
22
+
23
+ set onmessage(listener: (event: WorkerMessageEvent) => void);
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ set onerror(listener: (event: any) => void);
26
+ }
27
+
28
+ /**
29
+ * Currently we ony transfer MessagePorts to workers, but it's possible to add
30
+ * more things (like ReadableStream) as long as it's present in all runtimes.
31
+ */
32
+ export type WorkerTransferable = typeof MessagePort.prototype;
33
+
34
+ /**
35
+ * Used by workers to communicate with their parent.
36
+ */
37
+ export interface WorkerScope {
38
+ postMessage(message: unknown): void;
39
+ set onmessage(listener: (event: WorkerMessageEvent) => void);
40
+ }
41
+
42
+ export interface WorkerMessageEvent {
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ readonly data: any;
20
45
  }
@@ -4,11 +4,72 @@
4
4
 
5
5
  import type * as Api from '../api/api.js';
6
6
 
7
- export const IS_BROWSER =
8
- typeof window !== 'undefined' || (typeof self !== 'undefined' && typeof self.postMessage === 'function');
7
+ class WebWorkerScope implements Api.HostRuntime.WorkerScope {
8
+ postMessage(message: unknown): void {
9
+ self.postMessage(message);
10
+ }
9
11
 
10
- export const HOST_RUNTIME: Api.HostRuntime.HostRuntime = {
11
- createWorker(): Api.HostRuntime.Worker {
12
- throw new Error('unimplemented');
12
+ set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => void) {
13
+ self.onmessage = listener;
14
+ }
15
+ }
16
+
17
+ class WebWorker implements Api.HostRuntime.Worker {
18
+ readonly #workerPromise: Promise<Worker>;
19
+ #disposed?: boolean;
20
+ #rejectWorkerPromise?: (error: Error) => void;
21
+
22
+ constructor(workerLocation: string) {
23
+ this.#workerPromise = new Promise((fulfill, reject) => {
24
+ this.#rejectWorkerPromise = reject;
25
+ const worker = new Worker(new URL(workerLocation), {type: 'module'});
26
+ worker.onerror = event => {
27
+ console.error(`Failed to load worker for ${workerLocation}:`, event);
28
+ };
29
+ worker.onmessage = (event: MessageEvent<unknown>) => {
30
+ console.assert(event.data === 'workerReady');
31
+ worker.onmessage = null;
32
+ fulfill(worker);
33
+ };
34
+ });
35
+ }
36
+
37
+ postMessage(message: unknown, transfer?: Api.HostRuntime.WorkerTransferable[]): void {
38
+ void this.#workerPromise.then(worker => {
39
+ if (!this.#disposed) {
40
+ worker.postMessage(message, transfer ?? []);
41
+ }
42
+ });
43
+ }
44
+
45
+ dispose(): void {
46
+ this.#disposed = true;
47
+ void this.#workerPromise.then(worker => worker.terminate());
13
48
  }
49
+
50
+ terminate(immediately = false): void {
51
+ if (immediately) {
52
+ this.#rejectWorkerPromise?.(new Error('Worker terminated'));
53
+ }
54
+ this.dispose();
55
+ }
56
+
57
+ set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => void) {
58
+ void this.#workerPromise.then(worker => {
59
+ worker.onmessage = listener;
60
+ });
61
+ }
62
+
63
+ set onerror(listener: (event: unknown) => void) {
64
+ void this.#workerPromise.then(worker => {
65
+ worker.onerror = listener;
66
+ });
67
+ }
68
+ }
69
+
70
+ export const HOST_RUNTIME: Api.HostRuntime.HostRuntime = {
71
+ createWorker(url: string): Api.HostRuntime.Worker {
72
+ return new WebWorker(url);
73
+ },
74
+ workerScope: new WebWorkerScope(),
14
75
  };
@@ -2,12 +2,84 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as WorkerThreads from 'node:worker_threads';
6
+
5
7
  import type * as Api from '../api/api.js';
6
8
 
7
- export const IS_NODE = typeof (process as unknown) !== 'undefined' && process.versions?.node !== null;
9
+ class NodeWorkerScope implements Api.HostRuntime.WorkerScope {
10
+ postMessage(message: unknown): void {
11
+ WorkerThreads.parentPort?.postMessage(message);
12
+ }
8
13
 
9
- export const HOST_RUNTIME: Api.HostRuntime.HostRuntime = {
10
- createWorker(): Api.HostRuntime.Worker {
11
- throw new Error('unimplemented');
14
+ set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => void) {
15
+ WorkerThreads.parentPort?.on('message', data => {
16
+ listener({data});
17
+ });
18
+ }
19
+ }
20
+
21
+ class NodeWorker implements Api.HostRuntime.Worker {
22
+ readonly #workerPromise: Promise<WorkerThreads.Worker>;
23
+ #disposed = false;
24
+ #rejectWorkerPromise?: (error: Error) => void;
25
+
26
+ constructor(url: string) {
27
+ this.#workerPromise = new Promise((resolve, reject) => {
28
+ this.#rejectWorkerPromise = reject;
29
+ const worker = new WorkerThreads.Worker(new URL(url));
30
+ worker.once('message', (message: unknown) => {
31
+ if (message === 'workerReady') {
32
+ resolve(worker);
33
+ }
34
+ });
35
+ worker.on('error', reject);
36
+ });
37
+ }
38
+
39
+ postMessage(message: unknown): void {
40
+ void this.#workerPromise.then(worker => {
41
+ if (!this.#disposed) {
42
+ worker.postMessage(message);
43
+ }
44
+ });
45
+ }
46
+
47
+ dispose(): void {
48
+ this.#disposed = true;
49
+ void this.#workerPromise.then(worker => worker.terminate());
50
+ }
51
+
52
+ terminate(immediately?: boolean): void {
53
+ if (immediately) {
54
+ this.#rejectWorkerPromise?.(new Error('Worker terminated'));
55
+ }
56
+ this.dispose();
57
+ }
58
+
59
+ set onmessage(listener: (event: unknown) => void) {
60
+ void this.#workerPromise.then(worker => {
61
+ worker.on('message', data => {
62
+ if (!this.#disposed) {
63
+ listener({data});
64
+ }
65
+ });
66
+ });
12
67
  }
68
+
69
+ set onerror(listener: (event: unknown) => void) {
70
+ void this.#workerPromise.then(worker => {
71
+ worker.on('error', (error: Error) => {
72
+ if (!this.#disposed) {
73
+ listener({type: 'error', ...error});
74
+ }
75
+ });
76
+ });
77
+ }
78
+ }
79
+
80
+ export const HOST_RUNTIME: Api.HostRuntime.HostRuntime = {
81
+ createWorker(url: string): Api.HostRuntime.Worker {
82
+ return new NodeWorker(url);
83
+ },
84
+ workerScope: new NodeWorkerScope(),
13
85
  };
@@ -375,7 +375,7 @@ export class AnimationModel extends SDKModel<EventTypes> {
375
375
  const animation = await AnimationImpl.parsePayload(this, payload);
376
376
  // Ignore Web Animations custom effects & groups.
377
377
  const keyframesRule = animation.source().keyframesRule();
378
- if (animation.type() === 'WebAnimation' && keyframesRule && keyframesRule.keyframes().length === 0) {
378
+ if (animation.type() === 'WebAnimation' && keyframesRule?.keyframes().length === 0) {
379
379
  this.#pendingAnimations.delete(animation.id());
380
380
  } else {
381
381
  this.#animationsById.set(animation.id(), animation);
@@ -190,7 +190,7 @@ export class CSSModel extends SDKModel<EventTypes> {
190
190
 
191
191
  const {styles} =
192
192
  await this.agent.invoke_setStyleTexts({edits: [{styleSheetId, range: range.serializeToObject(), text}]});
193
- if (!styles || styles.length !== 1) {
193
+ if (styles?.length !== 1) {
194
194
  return false;
195
195
  }
196
196
 
@@ -292,7 +292,7 @@ export class CSSProperty extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
292
292
  }
293
293
  if (cssMetadata().isGridAreaDefiningProperty(propertyName)) {
294
294
  const rowResult = GridAreaRowRegex.exec(token);
295
- if (rowResult && rowResult.index === 0 && !propertyText.trimEnd().endsWith(']')) {
295
+ if (rowResult?.index === 0 && !propertyText.trimEnd().endsWith(']')) {
296
296
  propertyText = propertyText.trimEnd() + '\n' + doubleIndent;
297
297
  }
298
298
  }
@@ -1237,7 +1237,7 @@ export class AnchorFunctionMatcher extends matcherBase(AnchorFunctionMatch) {
1237
1237
  if (node.name === 'VariableName') {
1238
1238
  // Double-dashed anchor reference to be rendered with a link to its matching anchor.
1239
1239
  let parent = node.parent;
1240
- if (!parent || parent.name !== 'ArgList') {
1240
+ if (parent?.name !== 'ArgList') {
1241
1241
  return null;
1242
1242
  }
1243
1243
  parent = parent.parent;
@@ -432,7 +432,7 @@ export class ConsoleModel extends SDKModel<EventTypes> {
432
432
  const callFunctionResult =
433
433
  await globalObject.callFunction(saveVariable, [RemoteObject.toCallArgument(remoteObject)]);
434
434
  globalObject.release();
435
- if (callFunctionResult.wasThrown || !callFunctionResult.object || callFunctionResult.object.type !== 'string') {
435
+ if (callFunctionResult.wasThrown || callFunctionResult.object?.type !== 'string') {
436
436
  failedToSave(callFunctionResult.object || null);
437
437
  } else {
438
438
  const text = (callFunctionResult.object.value as string);
@@ -278,7 +278,7 @@ export class Cookie {
278
278
  // extension cookie tests currently use the funtionality, and if we
279
279
  // ever decide to implement that it should be done by preventing
280
280
  // such cookies from being set.
281
- if (!domain || domain[0] !== '.') {
281
+ if (domain?.[0] !== '.') {
282
282
  return false;
283
283
  }
284
284
 
@@ -746,7 +746,7 @@ export class DOMNode {
746
746
  }
747
747
 
748
748
  const oldAttribute = oldAttributesMap.get(name);
749
- if (!oldAttribute || oldAttribute.value !== value) {
749
+ if (oldAttribute?.value !== value) {
750
750
  attributesChanged = true;
751
751
  }
752
752
  }
@@ -1671,7 +1671,7 @@ export class DOMModel extends SDKModel<EventTypes> {
1671
1671
  }
1672
1672
  const {nodeIds} =
1673
1673
  await this.agent.invoke_getSearchResults({searchId: this.#searchId, fromIndex: index, toIndex: index + 1});
1674
- return nodeIds && nodeIds.length === 1 ? this.nodeForId(nodeIds[0]) : null;
1674
+ return nodeIds?.length === 1 ? this.nodeForId(nodeIds[0]) : null;
1675
1675
  }
1676
1676
 
1677
1677
  private cancelSearch(): void {
@@ -858,7 +858,7 @@ export class DebuggerModel extends SDKModel<EventTypes> {
858
858
  let functionName: RemoteObject|null = null;
859
859
  if (response.properties) {
860
860
  for (const prop of response.properties) {
861
- if (prop.name === 'name' && prop.value && prop.value.type === 'string') {
861
+ if (prop.name === 'name' && prop.value?.type === 'string') {
862
862
  functionName = prop.value;
863
863
  }
864
864
  }
@@ -1502,6 +1502,12 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
1502
1502
  this.updateNetworkRequest(networkRequest);
1503
1503
  }
1504
1504
 
1505
+ directUDPSocketJoinedMulticastGroup(_event: Protocol.Network.DirectUDPSocketJoinedMulticastGroupEvent): void {
1506
+ }
1507
+
1508
+ directUDPSocketLeftMulticastGroup(_event: Protocol.Network.DirectUDPSocketLeftMulticastGroupEvent): void {
1509
+ }
1510
+
1505
1511
  trustTokenOperationDone(event: Protocol.Network.TrustTokenOperationDoneEvent): void {
1506
1512
  const request = this.#requestsById.get(event.requestId);
1507
1513
  if (!request) {
@@ -47,7 +47,7 @@ export class PreloadingModel extends SDKModel<EventTypes> {
47
47
  void this.agent.invoke_enable();
48
48
 
49
49
  const targetInfo = target.targetInfo();
50
- if (targetInfo !== undefined && targetInfo.subtype === 'prerender') {
50
+ if (targetInfo?.subtype === 'prerender') {
51
51
  this.lastPrimaryPageModel = TargetManager.instance().primaryPageTarget()?.model(PreloadingModel) || null;
52
52
  }
53
53
 
@@ -970,7 +970,7 @@ export class RemoteArray {
970
970
  }
971
971
 
972
972
  static objectAsArray(object: RemoteObject|null): RemoteArray {
973
- if (!object || object.type !== 'object' || (object.subtype !== 'array' && object.subtype !== 'typedarray')) {
973
+ if (object?.type !== 'object' || (object.subtype !== 'array' && object.subtype !== 'typedarray')) {
974
974
  throw new Error('Object is empty or not an array');
975
975
  }
976
976
  return new RemoteArray(object);
@@ -891,7 +891,7 @@ export class ResourceTreeFrame {
891
891
 
892
892
  addRequest(request: NetworkRequest): void {
893
893
  let resource = this.resourcesMap.get(request.url());
894
- if (resource && resource.request === request) {
894
+ if (resource?.request === request) {
895
895
  // Already in the tree, we just got an extra update.
896
896
  return;
897
897
  }
@@ -27,7 +27,7 @@
27
27
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
  */
29
29
 
30
- import type * as Platform from '../../core/platform/platform.js';
30
+ import * as Platform from '../../core/platform/platform.js';
31
31
  import * as Protocol from '../../generated/protocol.js';
32
32
  import * as TextUtils from '../../models/text_utils/text_utils.js';
33
33
  import * as Common from '../common/common.js';
@@ -504,10 +504,10 @@ function frameIdForScript(script: Script): Protocol.Page.FrameId|null {
504
504
  export const sourceURLRegex = /^[\x20\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/;
505
505
 
506
506
  export async function disassembleWasm(content: string): Promise<TextUtils.WasmDisassembly.WasmDisassembly> {
507
- const worker = Common.Worker.WorkerWrapper.fromURL(
508
- new URL('../../entrypoints/wasmparser_worker/wasmparser_worker-entrypoint.js', import.meta.url));
507
+ const worker = Platform.HostRuntime.HOST_RUNTIME.createWorker(
508
+ new URL('../../entrypoints/wasmparser_worker/wasmparser_worker-entrypoint.js', import.meta.url).toString());
509
509
  const promise = new Promise<TextUtils.WasmDisassembly.WasmDisassembly>((resolve, reject) => {
510
- worker.onmessage = ({data}: MessageEvent) => {
510
+ worker.onmessage = ({data}) => {
511
511
  if ('method' in data) {
512
512
  switch (data.method) {
513
513
  case 'disassemble':
@@ -260,8 +260,8 @@ export class HTMLModel {
260
260
  this.#updateDOM(token);
261
261
 
262
262
  const element = this.#stack[this.#stack.length - 1];
263
- if (element && (element.name === 'script' || element.name === 'style') && element.openTag &&
264
- element.openTag.endOffset === lastOffset) {
263
+ if (element && (element.name === 'script' || element.name === 'style') &&
264
+ element.openTag?.endOffset === lastOffset) {
265
265
  return AbortTokenization;
266
266
  }
267
267
 
@@ -174,7 +174,7 @@ export class JavaScriptFormatter {
174
174
  return 'sts';
175
175
  }
176
176
  } else if (nodeType === 'ObjectPattern') {
177
- if (node.parent && node.parent.type === 'VariableDeclarator' && AT.punctuator(token, '{')) {
177
+ if (node.parent?.type === 'VariableDeclarator' && AT.punctuator(token, '{')) {
178
178
  return 'st';
179
179
  }
180
180
  if (AT.punctuator(token, ',')) {
@@ -203,7 +203,7 @@ export class JavaScriptFormatter {
203
203
  }
204
204
  } else if (nodeType === 'WithStatement') {
205
205
  if (AT.punctuator(token, ')')) {
206
- return node.body && node.body.type === 'BlockStatement' ? 'ts' : 'tn>';
206
+ return node.body?.type === 'BlockStatement' ? 'ts' : 'tn>';
207
207
  }
208
208
  } else if (nodeType === 'SwitchStatement') {
209
209
  if (AT.punctuator(token, '{')) {
@@ -269,11 +269,11 @@ export class JavaScriptFormatter {
269
269
  }
270
270
  } else if (nodeType === 'IfStatement') {
271
271
  if (AT.punctuator(token, ')')) {
272
- return node.consequent && node.consequent.type === 'BlockStatement' ? 'ts' : 'tn>';
272
+ return node.consequent?.type === 'BlockStatement' ? 'ts' : 'tn>';
273
273
  }
274
274
 
275
275
  if (AT.keyword(token, 'else')) {
276
- const preFormat = node.consequent && node.consequent.type === 'BlockStatement' ? 'st' : 'n<t';
276
+ const preFormat = node.consequent?.type === 'BlockStatement' ? 'st' : 'n<t';
277
277
  let postFormat = 'n>';
278
278
  if (node.alternate && (node.alternate.type === 'BlockStatement' || node.alternate.type === 'IfStatement')) {
279
279
  postFormat = 's';
@@ -285,7 +285,7 @@ export class JavaScriptFormatter {
285
285
  return 'ts';
286
286
  }
287
287
  } else if (nodeType === 'SequenceExpression' && AT.punctuator(token, ',')) {
288
- return node.parent && node.parent.type === 'SwitchCase' ? 'ts' : 'tn';
288
+ return node.parent?.type === 'SwitchCase' ? 'ts' : 'tn';
289
289
  } else if (nodeType === 'ForStatement' || nodeType === 'ForOfStatement' || nodeType === 'ForInStatement') {
290
290
  if (AT.punctuator(token, ';')) {
291
291
  return 'ts';
@@ -295,14 +295,14 @@ export class JavaScriptFormatter {
295
295
  }
296
296
 
297
297
  if (AT.punctuator(token, ')')) {
298
- return node.body && node.body.type === 'BlockStatement' ? 'ts' : 'tn>';
298
+ return node.body?.type === 'BlockStatement' ? 'ts' : 'tn>';
299
299
  }
300
300
  } else if (nodeType === 'WhileStatement') {
301
301
  if (AT.punctuator(token, ')')) {
302
- return node.body && node.body.type === 'BlockStatement' ? 'ts' : 'tn>';
302
+ return node.body?.type === 'BlockStatement' ? 'ts' : 'tn>';
303
303
  }
304
304
  } else if (nodeType === 'DoWhileStatement') {
305
- const blockBody = node.body && node.body.type === 'BlockStatement';
305
+ const blockBody = node.body?.type === 'BlockStatement';
306
306
  if (AT.keyword(token, 'do')) {
307
307
  return blockBody ? 'ts' : 'tn>';
308
308
  }
@@ -369,34 +369,31 @@ export class JavaScriptFormatter {
369
369
  return 'n<';
370
370
  }
371
371
  } else if (nodeType === 'BlockStatement') {
372
- if (node.parent && node.parent.type === 'IfStatement') {
372
+ if (node.parent?.type === 'IfStatement') {
373
373
  const parentNode = (node.parent as Acorn.ESTree.IfStatement);
374
374
  if (parentNode.alternate && parentNode.consequent === node) {
375
375
  return '';
376
376
  }
377
377
  }
378
- if (node.parent && node.parent.type === 'FunctionExpression' && node.parent.parent &&
379
- node.parent.parent.type === 'Property') {
378
+ if (node.parent?.type === 'FunctionExpression' && node.parent.parent?.type === 'Property') {
380
379
  return '';
381
380
  }
382
- if (node.parent && node.parent.type === 'FunctionExpression' && node.parent.parent &&
383
- node.parent.parent.type === 'VariableDeclarator') {
381
+ if (node.parent?.type === 'FunctionExpression' && node.parent.parent?.type === 'VariableDeclarator') {
384
382
  return '';
385
383
  }
386
- if (node.parent && node.parent.type === 'FunctionExpression' && node.parent.parent &&
387
- node.parent.parent.type === 'CallExpression') {
384
+ if (node.parent?.type === 'FunctionExpression' && node.parent.parent?.type === 'CallExpression') {
388
385
  return '';
389
386
  }
390
- if (node.parent && node.parent.type === 'DoWhileStatement') {
387
+ if (node.parent?.type === 'DoWhileStatement') {
391
388
  return '';
392
389
  }
393
- if (node.parent && node.parent.type === 'TryStatement') {
390
+ if (node.parent?.type === 'TryStatement') {
394
391
  const parentNode = (node.parent as Acorn.ESTree.TryStatement);
395
392
  if (parentNode.block === node) {
396
393
  return 's';
397
394
  }
398
395
  }
399
- if (node.parent && node.parent.type === 'CatchClause') {
396
+ if (node.parent?.type === 'CatchClause') {
400
397
  const parentNode = (node.parent as Acorn.ESTree.CatchClause);
401
398
  // @ts-expect-error We are doing a subtype check, without properly checking whether
402
399
  // it exists. We can't fix that, unless we use proper typechecking