buninu-browser 0.0.2

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 (830) hide show
  1. package/AGENTS.md +13 -0
  2. package/Architecture.md +601 -0
  3. package/LICENSE +21 -0
  4. package/LICENSES/Apache-2.0.txt +202 -0
  5. package/LICENSES/BSD-3-Clause-Skia.txt +29 -0
  6. package/LICENSES/Bitstream-Vera.txt +44 -0
  7. package/LICENSES/CC-BY-4.0.txt +396 -0
  8. package/LICENSES/OFL-1.1.txt +91 -0
  9. package/LICENSES/README.md +9 -0
  10. package/LICENSES/acorn.txt +21 -0
  11. package/LICENSES/chromium.txt +27 -0
  12. package/LICENSES/dropflow.txt +19 -0
  13. package/LICENSES/emscripten.txt +102 -0
  14. package/LICENSES/freetype.txt +169 -0
  15. package/LICENSES/happy-dom.txt +22 -0
  16. package/LICENSES/harfbuzz.txt +42 -0
  17. package/LICENSES/icu.txt +512 -0
  18. package/LICENSES/libjpeg-ijg.txt +260 -0
  19. package/LICENSES/libjpeg-turbo.txt +147 -0
  20. package/LICENSES/libpng.txt +134 -0
  21. package/LICENSES/libwebp.txt +30 -0
  22. package/LICENSES/ses-aura.txt +16 -0
  23. package/LICENSES/ses-caja.txt +13 -0
  24. package/LICENSES/ses-corejs.txt +19 -0
  25. package/LICENSES/ses-v8.txt +9 -0
  26. package/LICENSES/ses.txt +201 -0
  27. package/LICENSES/termdom.txt +21 -0
  28. package/LICENSES/wasmpeg.txt +501 -0
  29. package/LICENSES/woff2.txt +19 -0
  30. package/LICENSES/wuffs.txt +211 -0
  31. package/LICENSES/zlib.txt +22 -0
  32. package/Linux +0 -0
  33. package/PORTING.md +825 -0
  34. package/README.md +283 -0
  35. package/THIRD_PARTY_NOTICES.md +224 -0
  36. package/bunfig.toml +2 -0
  37. package/buninu-browser.js +65 -0
  38. package/index.js +149 -0
  39. package/lib/cdp-server.js +1424 -0
  40. package/lib/cdp.js +203 -0
  41. package/lib/happy-dom/entities-adapter.js +51 -0
  42. package/lib/happy-dom/image-size-adapter.js +8 -0
  43. package/lib/happy-dom/mime-type-adapter.js +27 -0
  44. package/lib/happy-dom/parser.js +53 -0
  45. package/lib/happy-dom/websocket-adapter.js +62 -0
  46. package/lib/headless-shell.js +362 -0
  47. package/lib/input/hit-test.js +78 -0
  48. package/lib/layout/scroll-viewport.js +53 -0
  49. package/lib/layout/text-layout.js +2236 -0
  50. package/lib/log.js +85 -0
  51. package/lib/network/cookie-jar.js +178 -0
  52. package/lib/network/network-service.js +268 -0
  53. package/lib/network/resolver.js +97 -0
  54. package/lib/paint/display-list.js +359 -0
  55. package/lib/paint/frame.js +88 -0
  56. package/lib/paint/gradient.js +207 -0
  57. package/lib/render-tree/index.js +263 -0
  58. package/lib/render-tree/svg.js +210 -0
  59. package/lib/renderer/bindings.js +1291 -0
  60. package/lib/renderer/compositor.js +123 -0
  61. package/lib/renderer/flags.js +20 -0
  62. package/lib/renderer/host.js +503 -0
  63. package/lib/renderer/main.js +234 -0
  64. package/lib/renderer/module-transform.js +399 -0
  65. package/lib/renderer/page-realm.js +1471 -0
  66. package/lib/renderer/page-renderer.js +1691 -0
  67. package/lib/renderer/script-rewrite.js +232 -0
  68. package/lib/renderer/seccomp.js +215 -0
  69. package/lib/renderer/syscall-numbers.js +139 -0
  70. package/lib/style/computed-style.js +2053 -0
  71. package/package.json +39 -0
  72. package/patches/happy-dom/0001-use-bun-entity-adapter.patch +15 -0
  73. package/patches/happy-dom/0002-use-bun-platform-adapters.patch +69 -0
  74. package/patches/happy-dom/README.md +38 -0
  75. package/test/chromium-headless-shell +5 -0
  76. package/test/compositor.test.js +154 -0
  77. package/test/computed-style.test.js +434 -0
  78. package/test/display-list.test.js +128 -0
  79. package/test/entities-adapter.test.js +43 -0
  80. package/test/fixtures/fake-renderer.js +26 -0
  81. package/test/fixtures/seccomp-child.js +32 -0
  82. package/test/fixtures/video.mp4 +0 -0
  83. package/test/flex.test.js +150 -0
  84. package/test/gradient.test.js +56 -0
  85. package/test/grid.test.js +253 -0
  86. package/test/happy-dom-platform-adapters.test.js +18 -0
  87. package/test/headless-shell.test.js +318 -0
  88. package/test/hit-test.test.js +49 -0
  89. package/test/html-parser.test.js +40 -0
  90. package/test/index.test.js +29 -0
  91. package/test/log.test.js +40 -0
  92. package/test/mobile.test.js +85 -0
  93. package/test/network-service.test.js +214 -0
  94. package/test/page-scripts.test.js +552 -0
  95. package/test/poc-backend.js +189 -0
  96. package/test/poc-backend.test.js +154 -0
  97. package/test/positioning.test.js +112 -0
  98. package/test/render-tree.test.js +103 -0
  99. package/test/renderer-host.test.js +69 -0
  100. package/test/resolver.test.js +51 -0
  101. package/test/script-rewrite.test.js +31 -0
  102. package/test/scroll-viewport.test.js +25 -0
  103. package/test/seccomp.test.js +71 -0
  104. package/test/site-isolation.test.js +74 -0
  105. package/test/svg.test.js +61 -0
  106. package/test/text-layout.test.js +419 -0
  107. package/usr/README.md +20 -0
  108. package/usr/lib/canvaskit/LICENSE +29 -0
  109. package/usr/lib/canvaskit/canvaskit.js +264 -0
  110. package/usr/lib/canvaskit/canvaskit.wasm +0 -0
  111. package/usr/share/fonts/DejaVuSansMono-Bold.ttf +0 -0
  112. package/usr/share/fonts/DejaVuSansMono.ttf +0 -0
  113. package/usr/share/fonts/LICENSE-Apache-2.0.txt +202 -0
  114. package/usr/share/fonts/LICENSE-DejaVu.txt +44 -0
  115. package/usr/share/fonts/LICENSE-OFL-1.1.txt +91 -0
  116. package/usr/share/fonts/NotoColorEmoji.ttf +0 -0
  117. package/usr/share/fonts/NotoColorEmojiFlags.ttf +0 -0
  118. package/usr/share/fonts/NotoSansCJK-Regular.ttc +0 -0
  119. package/usr/share/fonts/NotoSansSymbols-Regular-Subsetted.ttf +0 -0
  120. package/usr/share/fonts/NotoSansSymbols-Regular-Subsetted2.ttf +0 -0
  121. package/usr/share/fonts/Roboto-Regular.ttf +0 -0
  122. package/usr/share/fonts/fonts.json +28 -0
  123. package/vendor/acorn/LICENSE +21 -0
  124. package/vendor/acorn/README.md +309 -0
  125. package/vendor/acorn/dist/acorn.mjs +6313 -0
  126. package/vendor/acorn/package.json +50 -0
  127. package/vendor/happy-dom/.editorconfig +8 -0
  128. package/vendor/happy-dom/.eslintignore +6 -0
  129. package/vendor/happy-dom/.eslintrc.cjs +188 -0
  130. package/vendor/happy-dom/.github/CODEOWNERS +2 -0
  131. package/vendor/happy-dom/.github/FUNDING.yml +1 -0
  132. package/vendor/happy-dom/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  133. package/vendor/happy-dom/.github/ISSUE_TEMPLATE/custom.md +10 -0
  134. package/vendor/happy-dom/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  135. package/vendor/happy-dom/.github/PULL_REQUEST_TEMPLATE.md +27 -0
  136. package/vendor/happy-dom/.github/workflows/auto-assign.yml +23 -0
  137. package/vendor/happy-dom/.github/workflows/pull_request.yml +53 -0
  138. package/vendor/happy-dom/.github/workflows/release.yml +143 -0
  139. package/vendor/happy-dom/.husky/pre-commit +1 -0
  140. package/vendor/happy-dom/.prettierignore +1 -0
  141. package/vendor/happy-dom/.prettierrc.cjs +6 -0
  142. package/vendor/happy-dom/.vscode/extensions.json +3 -0
  143. package/vendor/happy-dom/CODE_OF_CONDUCT.md +128 -0
  144. package/vendor/happy-dom/CONTRIBUTING.md +147 -0
  145. package/vendor/happy-dom/LICENSE +21 -0
  146. package/vendor/happy-dom/README.md +62 -0
  147. package/vendor/happy-dom/SECURITY.md +12 -0
  148. package/vendor/happy-dom/cspell.json +34 -0
  149. package/vendor/happy-dom/docs/happy-dom-logo.jpg +0 -0
  150. package/vendor/happy-dom/integration-test/.editorconfig +8 -0
  151. package/vendor/happy-dom/integration-test/LICENSE +21 -0
  152. package/vendor/happy-dom/integration-test/README.md +1 -0
  153. package/vendor/happy-dom/integration-test/package.json +24 -0
  154. package/vendor/happy-dom/package-lock.json +15520 -0
  155. package/vendor/happy-dom/package.json +55 -0
  156. package/vendor/happy-dom/packages/@happy-dom/global-registrator/LICENSE +21 -0
  157. package/vendor/happy-dom/packages/@happy-dom/global-registrator/README.md +60 -0
  158. package/vendor/happy-dom/packages/@happy-dom/global-registrator/package.json +52 -0
  159. package/vendor/happy-dom/packages/@happy-dom/global-registrator/register.js +2 -0
  160. package/vendor/happy-dom/packages/@happy-dom/global-registrator/src/GlobalRegistrator.ts +121 -0
  161. package/vendor/happy-dom/packages/@happy-dom/global-registrator/src/index.ts +3 -0
  162. package/vendor/happy-dom/packages/@happy-dom/global-registrator/tsconfig.json +30 -0
  163. package/vendor/happy-dom/packages/@happy-dom/jest-environment/LICENSE +21 -0
  164. package/vendor/happy-dom/packages/@happy-dom/jest-environment/README.md +71 -0
  165. package/vendor/happy-dom/packages/@happy-dom/jest-environment/package.json +93 -0
  166. package/vendor/happy-dom/packages/@happy-dom/jest-environment/src/index.ts +192 -0
  167. package/vendor/happy-dom/packages/@happy-dom/jest-environment/tsconfig.json +30 -0
  168. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/README.md +48 -0
  169. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/package.json +41 -0
  170. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/src/CanvasAdapter.ts +275 -0
  171. package/vendor/happy-dom/packages/@happy-dom/node-canvas-adapter/src/index.ts +1 -0
  172. package/vendor/happy-dom/packages/@happy-dom/server-renderer/LICENSE +21 -0
  173. package/vendor/happy-dom/packages/@happy-dom/server-renderer/README.md +100 -0
  174. package/vendor/happy-dom/packages/@happy-dom/server-renderer/bin/src/happy-dom-sr.ts +30 -0
  175. package/vendor/happy-dom/packages/@happy-dom/server-renderer/package.json +62 -0
  176. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRenderer.ts +368 -0
  177. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererBrowser.ts +142 -0
  178. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererBrowserWorker.ts +29 -0
  179. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererPage.ts +305 -0
  180. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererPageWorker.ts +55 -0
  181. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/ServerRendererServer.ts +332 -0
  182. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/config/DefaultServerRendererConfiguration.ts +47 -0
  183. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/enums/ServerRendererLogLevelEnum.ts +9 -0
  184. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/enums/ServerRendererModeEnum.ts +8 -0
  185. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/index.ts +19 -0
  186. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IOptionalServerRendererConfiguration.ts +127 -0
  187. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IServerRendererConfiguration.ts +126 -0
  188. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IServerRendererItem.ts +6 -0
  189. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/types/IServerRendererResult.ts +11 -0
  190. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/BrowserWindowPolyfill.ts +138 -0
  191. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/HelpPrinter.ts +36 -0
  192. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/HelpPrinterRows.ts +288 -0
  193. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/PackageVersion.ts +12 -0
  194. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/ProcessArgumentsParser.ts +387 -0
  195. package/vendor/happy-dom/packages/@happy-dom/server-renderer/src/utilities/ServerRendererConfigurationFactory.ts +91 -0
  196. package/vendor/happy-dom/packages/happy-dom/LICENSE +21 -0
  197. package/vendor/happy-dom/packages/happy-dom/README.md +42 -0
  198. package/vendor/happy-dom/packages/happy-dom/package.json +58 -0
  199. package/vendor/happy-dom/packages/happy-dom/src/PropertySymbol.ts +431 -0
  200. package/vendor/happy-dom/packages/happy-dom/src/animation/Animation.ts +273 -0
  201. package/vendor/happy-dom/packages/happy-dom/src/animation/AnimationTimeline.ts +15 -0
  202. package/vendor/happy-dom/packages/happy-dom/src/animation/DocumentTimeline.ts +33 -0
  203. package/vendor/happy-dom/packages/happy-dom/src/animation/KeyframeEffect.ts +295 -0
  204. package/vendor/happy-dom/packages/happy-dom/src/async-task-manager/AsyncTaskManager.ts +340 -0
  205. package/vendor/happy-dom/packages/happy-dom/src/async-task-manager/AsyncTaskManagerDebugError.ts +14 -0
  206. package/vendor/happy-dom/packages/happy-dom/src/base64/Base64.ts +97 -0
  207. package/vendor/happy-dom/packages/happy-dom/src/browser/Browser.ts +123 -0
  208. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserContext.ts +100 -0
  209. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserFrame.ts +232 -0
  210. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserPage.ts +205 -0
  211. package/vendor/happy-dom/packages/happy-dom/src/browser/BrowserSettingsFactory.ts +96 -0
  212. package/vendor/happy-dom/packages/happy-dom/src/browser/DefaultBrowserSettings.ts +67 -0
  213. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowser.ts +129 -0
  214. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowserContext.ts +103 -0
  215. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowserFrame.ts +250 -0
  216. package/vendor/happy-dom/packages/happy-dom/src/browser/detached-browser/DetachedBrowserPage.ts +218 -0
  217. package/vendor/happy-dom/packages/happy-dom/src/browser/enums/BrowserErrorCaptureEnum.ts +10 -0
  218. package/vendor/happy-dom/packages/happy-dom/src/browser/enums/BrowserNavigationCrossOriginPolicyEnum.ts +10 -0
  219. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowser.ts +51 -0
  220. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserContext.ts +44 -0
  221. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserFrame.ts +112 -0
  222. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserPage.ts +110 -0
  223. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserPageViewport.ts +5 -0
  224. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IBrowserSettings.ts +194 -0
  225. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IGoToOptions.ts +17 -0
  226. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IOptionalBrowserPageViewport.ts +5 -0
  227. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IOptionalBrowserSettings.ts +190 -0
  228. package/vendor/happy-dom/packages/happy-dom/src/browser/types/IReloadOptions.ts +27 -0
  229. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserExceptionObserver.ts +123 -0
  230. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameFactory.ts +106 -0
  231. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameNavigator.ts +574 -0
  232. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameScriptEvaluator.ts +71 -0
  233. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameURL.ts +30 -0
  234. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserFrameValidator.ts +84 -0
  235. package/vendor/happy-dom/packages/happy-dom/src/browser/utilities/BrowserPageUtility.ts +56 -0
  236. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasAdapter.ts +63 -0
  237. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasAdapterCaller.ts +9 -0
  238. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasGradient.ts +8 -0
  239. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasPattern.ts +10 -0
  240. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasRenderingContext2D.ts +162 -0
  241. package/vendor/happy-dom/packages/happy-dom/src/canvas/ICanvasShape.ts +7 -0
  242. package/vendor/happy-dom/packages/happy-dom/src/canvas/IImageBitmapOptions.ts +8 -0
  243. package/vendor/happy-dom/packages/happy-dom/src/canvas/ITextMetrics.ts +12 -0
  244. package/vendor/happy-dom/packages/happy-dom/src/canvas/ImageBitmap.ts +162 -0
  245. package/vendor/happy-dom/packages/happy-dom/src/canvas/ImageData.ts +83 -0
  246. package/vendor/happy-dom/packages/happy-dom/src/canvas/OffscreenCanvas.ts +162 -0
  247. package/vendor/happy-dom/packages/happy-dom/src/canvas/TCanvasImage.ts +14 -0
  248. package/vendor/happy-dom/packages/happy-dom/src/canvas/TImageBitmapSource.ts +12 -0
  249. package/vendor/happy-dom/packages/happy-dom/src/clipboard/Clipboard.ts +108 -0
  250. package/vendor/happy-dom/packages/happy-dom/src/clipboard/ClipboardItem.ts +57 -0
  251. package/vendor/happy-dom/packages/happy-dom/src/config/HTMLElementConfig.ts +536 -0
  252. package/vendor/happy-dom/packages/happy-dom/src/config/HTMLElementConfigContentModelEnum.ts +12 -0
  253. package/vendor/happy-dom/packages/happy-dom/src/config/IHTMLElementTagNameMap.ts +181 -0
  254. package/vendor/happy-dom/packages/happy-dom/src/config/ISVGElementTagNameMap.ts +127 -0
  255. package/vendor/happy-dom/packages/happy-dom/src/config/NamespaceURI.ts +8 -0
  256. package/vendor/happy-dom/packages/happy-dom/src/config/SVGElementConfig.ts +70 -0
  257. package/vendor/happy-dom/packages/happy-dom/src/console/IConsole.ts +161 -0
  258. package/vendor/happy-dom/packages/happy-dom/src/console/IVirtualConsoleLogEntry.ts +10 -0
  259. package/vendor/happy-dom/packages/happy-dom/src/console/IVirtualConsoleLogGroup.ts +6 -0
  260. package/vendor/happy-dom/packages/happy-dom/src/console/IVirtualConsolePrinter.ts +58 -0
  261. package/vendor/happy-dom/packages/happy-dom/src/console/VirtualConsole.ts +363 -0
  262. package/vendor/happy-dom/packages/happy-dom/src/console/VirtualConsolePrinter.ts +148 -0
  263. package/vendor/happy-dom/packages/happy-dom/src/console/enums/VirtualConsoleLogLevelEnum.ts +12 -0
  264. package/vendor/happy-dom/packages/happy-dom/src/console/enums/VirtualConsoleLogTypeEnum.ts +29 -0
  265. package/vendor/happy-dom/packages/happy-dom/src/console/utilities/VirtualConsoleLogEntryStringifier.ts +100 -0
  266. package/vendor/happy-dom/packages/happy-dom/src/cookie/CookieContainer.ts +91 -0
  267. package/vendor/happy-dom/packages/happy-dom/src/cookie/DefaultCookie.ts +17 -0
  268. package/vendor/happy-dom/packages/happy-dom/src/cookie/ICookie.ts +14 -0
  269. package/vendor/happy-dom/packages/happy-dom/src/cookie/ICookieContainer.ts +33 -0
  270. package/vendor/happy-dom/packages/happy-dom/src/cookie/IOptionalCookie.ts +16 -0
  271. package/vendor/happy-dom/packages/happy-dom/src/cookie/enums/CookieSameSiteEnum.ts +6 -0
  272. package/vendor/happy-dom/packages/happy-dom/src/cookie/urilities/CookieExpireUtility.ts +16 -0
  273. package/vendor/happy-dom/packages/happy-dom/src/cookie/urilities/CookieStringUtility.ts +119 -0
  274. package/vendor/happy-dom/packages/happy-dom/src/cookie/urilities/CookieURLUtility.ts +27 -0
  275. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/CookieStore.ts +226 -0
  276. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreDeleteOptions.ts +9 -0
  277. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreGetOptions.ts +7 -0
  278. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreItem.ts +13 -0
  279. package/vendor/happy-dom/packages/happy-dom/src/cookie-store/ICookieStoreSetOptions.ts +12 -0
  280. package/vendor/happy-dom/packages/happy-dom/src/css/CSS.ts +63 -0
  281. package/vendor/happy-dom/packages/happy-dom/src/css/CSSRule.ts +84 -0
  282. package/vendor/happy-dom/packages/happy-dom/src/css/CSSRuleTypeEnum.ts +18 -0
  283. package/vendor/happy-dom/packages/happy-dom/src/css/CSSStyleSheet.ts +141 -0
  284. package/vendor/happy-dom/packages/happy-dom/src/css/CSSUnitValue.ts +26 -0
  285. package/vendor/happy-dom/packages/happy-dom/src/css/CSSUnits.ts +31 -0
  286. package/vendor/happy-dom/packages/happy-dom/src/css/MediaList.ts +177 -0
  287. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/CSSPropertyList.ts +1273 -0
  288. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/CSSStyleDeclaration.ts +355 -0
  289. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/ICSSStyleDeclaration.ts +1178 -0
  290. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/CSSComputedStyle.ts +502 -0
  291. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/config/CSSComputedStyleElementDefault.ts +133 -0
  292. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/config/CSSComputedStyleInheritedProperties.ts +39 -0
  293. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/computed-style/config/CSSComputedStyleMeasurementProperties.ts +41 -0
  294. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/CSSPropertyManager.ts +641 -0
  295. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/parsers/CSSPropertyGetParser.ts +741 -0
  296. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/parsers/CSSPropertySetParser.ts +2955 -0
  297. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/types/ICSSPropertyMap.ts +5 -0
  298. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/types/ICSSPropertyValue.ts +4 -0
  299. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/utilities/CSSStringUtility.ts +90 -0
  300. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/utilities/CSSValueFormatter.ts +447 -0
  301. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/property-manager/utilities/CSSVariableFormatter.ts +76 -0
  302. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/utilities/CSSMeasurementConverter.ts +79 -0
  303. package/vendor/happy-dom/packages/happy-dom/src/css/declaration/utilities/CSSTextParser.ts +44 -0
  304. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSConditionRule.ts +20 -0
  305. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSContainerRule.ts +34 -0
  306. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSFontFaceRule.ts +45 -0
  307. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSGroupingRule.ts +84 -0
  308. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSKeyframeRule.ts +53 -0
  309. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSKeyframesRule.ts +147 -0
  310. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSMediaRule.ts +50 -0
  311. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSScopeRule.ts +53 -0
  312. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSStyleRule.ts +73 -0
  313. package/vendor/happy-dom/packages/happy-dom/src/css/rules/CSSSupportsRule.ts +30 -0
  314. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/CSSKeywordValue.ts +35 -0
  315. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/CSSStyleValue.ts +37 -0
  316. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/StylePropertyMap.ts +45 -0
  317. package/vendor/happy-dom/packages/happy-dom/src/css/style-property-map/StylePropertyMapReadOnly.ts +128 -0
  318. package/vendor/happy-dom/packages/happy-dom/src/css/utilities/CSSEscaper.ts +87 -0
  319. package/vendor/happy-dom/packages/happy-dom/src/css/utilities/CSSRuleParser.ts +315 -0
  320. package/vendor/happy-dom/packages/happy-dom/src/custom-element/CustomElementReactionStack.ts +91 -0
  321. package/vendor/happy-dom/packages/happy-dom/src/custom-element/CustomElementRegistry.ts +186 -0
  322. package/vendor/happy-dom/packages/happy-dom/src/custom-element/CustomElementUtility.ts +34 -0
  323. package/vendor/happy-dom/packages/happy-dom/src/custom-element/ICustomElementDefinition.ts +16 -0
  324. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMPoint.ts +84 -0
  325. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMPointReadOnly.ts +117 -0
  326. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMRect.ts +92 -0
  327. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMRectList.ts +34 -0
  328. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMRectReadOnly.ts +129 -0
  329. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMStringMap.ts +93 -0
  330. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMStringMapUtility.ts +33 -0
  331. package/vendor/happy-dom/packages/happy-dom/src/dom/DOMTokenList.ts +363 -0
  332. package/vendor/happy-dom/packages/happy-dom/src/dom/IDOMPointInit.ts +6 -0
  333. package/vendor/happy-dom/packages/happy-dom/src/dom/IDOMRectInit.ts +6 -0
  334. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/DOMMatrix.ts +526 -0
  335. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/DOMMatrixReadOnly.ts +1608 -0
  336. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/IDOMMatrixCompatibleObject.ts +24 -0
  337. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/IDOMMatrixJSON.ts +26 -0
  338. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/TDOMMatrix2DArray.ts +3 -0
  339. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/TDOMMatrix3DArray.ts +20 -0
  340. package/vendor/happy-dom/packages/happy-dom/src/dom/dom-matrix/TDOMMatrixInit.ts +8 -0
  341. package/vendor/happy-dom/packages/happy-dom/src/dom-implementation/DOMImplementation.ts +81 -0
  342. package/vendor/happy-dom/packages/happy-dom/src/dom-parser/DOMParser.ts +47 -0
  343. package/vendor/happy-dom/packages/happy-dom/src/event/DataTransfer.ts +128 -0
  344. package/vendor/happy-dom/packages/happy-dom/src/event/DataTransferItem.ts +47 -0
  345. package/vendor/happy-dom/packages/happy-dom/src/event/DataTransferItemList.ts +44 -0
  346. package/vendor/happy-dom/packages/happy-dom/src/event/Event.ts +222 -0
  347. package/vendor/happy-dom/packages/happy-dom/src/event/EventPhaseEnum.ts +7 -0
  348. package/vendor/happy-dom/packages/happy-dom/src/event/EventTarget.ts +396 -0
  349. package/vendor/happy-dom/packages/happy-dom/src/event/IEventInit.ts +5 -0
  350. package/vendor/happy-dom/packages/happy-dom/src/event/IEventListenerOptions.ts +10 -0
  351. package/vendor/happy-dom/packages/happy-dom/src/event/ITouchInit.ts +16 -0
  352. package/vendor/happy-dom/packages/happy-dom/src/event/IUIEventInit.ts +7 -0
  353. package/vendor/happy-dom/packages/happy-dom/src/event/MessagePort.ts +32 -0
  354. package/vendor/happy-dom/packages/happy-dom/src/event/TEventListener.ts +4 -0
  355. package/vendor/happy-dom/packages/happy-dom/src/event/TEventListenerFunction.ts +3 -0
  356. package/vendor/happy-dom/packages/happy-dom/src/event/TEventListenerObject.ts +5 -0
  357. package/vendor/happy-dom/packages/happy-dom/src/event/Touch.ts +40 -0
  358. package/vendor/happy-dom/packages/happy-dom/src/event/UIEvent.ts +32 -0
  359. package/vendor/happy-dom/packages/happy-dom/src/event/events/AnimationEvent.ts +25 -0
  360. package/vendor/happy-dom/packages/happy-dom/src/event/events/ClipboardEvent.ts +22 -0
  361. package/vendor/happy-dom/packages/happy-dom/src/event/events/CloseEvent.ts +25 -0
  362. package/vendor/happy-dom/packages/happy-dom/src/event/events/CookieChangeEvent.ts +25 -0
  363. package/vendor/happy-dom/packages/happy-dom/src/event/events/CustomEvent.ts +53 -0
  364. package/vendor/happy-dom/packages/happy-dom/src/event/events/ErrorEvent.ts +29 -0
  365. package/vendor/happy-dom/packages/happy-dom/src/event/events/FocusEvent.ts +22 -0
  366. package/vendor/happy-dom/packages/happy-dom/src/event/events/HashChangeEvent.ts +25 -0
  367. package/vendor/happy-dom/packages/happy-dom/src/event/events/IAnimationEventInit.ts +7 -0
  368. package/vendor/happy-dom/packages/happy-dom/src/event/events/IClipboardEventInit.ts +6 -0
  369. package/vendor/happy-dom/packages/happy-dom/src/event/events/ICloseEventInit.ts +7 -0
  370. package/vendor/happy-dom/packages/happy-dom/src/event/events/ICookieChangeEventInit.ts +10 -0
  371. package/vendor/happy-dom/packages/happy-dom/src/event/events/ICustomEventInit.ts +5 -0
  372. package/vendor/happy-dom/packages/happy-dom/src/event/events/IErrorEventInit.ts +8 -0
  373. package/vendor/happy-dom/packages/happy-dom/src/event/events/IFocusEventInit.ts +6 -0
  374. package/vendor/happy-dom/packages/happy-dom/src/event/events/IHashChangeEventInit.ts +6 -0
  375. package/vendor/happy-dom/packages/happy-dom/src/event/events/IInputEventInit.ts +9 -0
  376. package/vendor/happy-dom/packages/happy-dom/src/event/events/IKeyboardEventInit.ts +23 -0
  377. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMediaQueryListEventInit.ts +6 -0
  378. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMediaQueryListInit.ts +6 -0
  379. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMessageEventInit.ts +11 -0
  380. package/vendor/happy-dom/packages/happy-dom/src/event/events/IMouseEventInit.ts +21 -0
  381. package/vendor/happy-dom/packages/happy-dom/src/event/events/IPointerEventInit.ts +19 -0
  382. package/vendor/happy-dom/packages/happy-dom/src/event/events/IPopStateEventInit.ts +6 -0
  383. package/vendor/happy-dom/packages/happy-dom/src/event/events/IProgressEventInit.ts +7 -0
  384. package/vendor/happy-dom/packages/happy-dom/src/event/events/IStorageEventInit.ts +10 -0
  385. package/vendor/happy-dom/packages/happy-dom/src/event/events/ISubmitEventInit.ts +6 -0
  386. package/vendor/happy-dom/packages/happy-dom/src/event/events/ITouchEventInit.ts +12 -0
  387. package/vendor/happy-dom/packages/happy-dom/src/event/events/IWheelEventInit.ts +8 -0
  388. package/vendor/happy-dom/packages/happy-dom/src/event/events/InputEvent.ts +28 -0
  389. package/vendor/happy-dom/packages/happy-dom/src/event/events/KeyboardEvent.ts +80 -0
  390. package/vendor/happy-dom/packages/happy-dom/src/event/events/MediaQueryListEvent.ts +23 -0
  391. package/vendor/happy-dom/packages/happy-dom/src/event/events/MediaStreamTrackEvent.ts +22 -0
  392. package/vendor/happy-dom/packages/happy-dom/src/event/events/MessageEvent.ts +33 -0
  393. package/vendor/happy-dom/packages/happy-dom/src/event/events/MouseEvent.ts +52 -0
  394. package/vendor/happy-dom/packages/happy-dom/src/event/events/PointerEvent.ts +51 -0
  395. package/vendor/happy-dom/packages/happy-dom/src/event/events/PopStateEvent.ts +23 -0
  396. package/vendor/happy-dom/packages/happy-dom/src/event/events/ProgressEvent.ts +25 -0
  397. package/vendor/happy-dom/packages/happy-dom/src/event/events/StorageEvent.ts +30 -0
  398. package/vendor/happy-dom/packages/happy-dom/src/event/events/SubmitEvent.ts +22 -0
  399. package/vendor/happy-dom/packages/happy-dom/src/event/events/TouchEvent.ts +34 -0
  400. package/vendor/happy-dom/packages/happy-dom/src/event/events/WheelEvent.ts +30 -0
  401. package/vendor/happy-dom/packages/happy-dom/src/exception/DOMException.ts +21 -0
  402. package/vendor/happy-dom/packages/happy-dom/src/exception/DOMExceptionNameEnum.ts +23 -0
  403. package/vendor/happy-dom/packages/happy-dom/src/fetch/AbortController.ts +25 -0
  404. package/vendor/happy-dom/packages/happy-dom/src/fetch/AbortSignal.ts +182 -0
  405. package/vendor/happy-dom/packages/happy-dom/src/fetch/Fetch.ts +1072 -0
  406. package/vendor/happy-dom/packages/happy-dom/src/fetch/Headers.ts +177 -0
  407. package/vendor/happy-dom/packages/happy-dom/src/fetch/ReadableStreamWrapper.ts +30 -0
  408. package/vendor/happy-dom/packages/happy-dom/src/fetch/Request.ts +492 -0
  409. package/vendor/happy-dom/packages/happy-dom/src/fetch/ResourceFetch.ts +190 -0
  410. package/vendor/happy-dom/packages/happy-dom/src/fetch/Response.ts +439 -0
  411. package/vendor/happy-dom/packages/happy-dom/src/fetch/SyncFetch.ts +717 -0
  412. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/ICacheablePreflightRequest.ts +7 -0
  413. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/ICacheablePreflightResponse.ts +7 -0
  414. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/ICachedPreflightResponse.ts +5 -0
  415. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/IPreflightResponseCache.ts +33 -0
  416. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/preflight/PreflightResponseCache.ts +94 -0
  417. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/CachedResponseStateEnum.ts +5 -0
  418. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ICacheableRequest.ts +7 -0
  419. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ICacheableResponse.ts +11 -0
  420. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ICachedResponse.ts +40 -0
  421. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/IResponseCache.ts +37 -0
  422. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/IResponseCacheFileSystem.ts +18 -0
  423. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ResponseCache.ts +248 -0
  424. package/vendor/happy-dom/packages/happy-dom/src/fetch/cache/response/ResponseCacheFileSystem.ts +175 -0
  425. package/vendor/happy-dom/packages/happy-dom/src/fetch/certificate/FetchHTTPSCertificate.ts +52 -0
  426. package/vendor/happy-dom/packages/happy-dom/src/fetch/data-uri/DataURIParser.ts +66 -0
  427. package/vendor/happy-dom/packages/happy-dom/src/fetch/multipart/MultipartFormDataParser.ts +174 -0
  428. package/vendor/happy-dom/packages/happy-dom/src/fetch/multipart/MultipartReader.ts +216 -0
  429. package/vendor/happy-dom/packages/happy-dom/src/fetch/preload/PreloadEntry.ts +50 -0
  430. package/vendor/happy-dom/packages/happy-dom/src/fetch/preload/PreloadUtility.ts +33 -0
  431. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IFetchInterceptor.ts +60 -0
  432. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IFetchRequestHeaders.ts +9 -0
  433. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IRequestInit.ts +23 -0
  434. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IResourceFetchResponse.ts +4 -0
  435. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IResponseInit.ts +10 -0
  436. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/ISyncResponse.ts +18 -0
  437. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/IVirtualServer.ts +7 -0
  438. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/THeadersInit.ts +3 -0
  439. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestBody.ts +14 -0
  440. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestCredentials.ts +1 -0
  441. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestInfo.ts +4 -0
  442. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestMode.ts +1 -0
  443. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestRedirect.ts +1 -0
  444. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TRequestReferrerPolicy.ts +10 -0
  445. package/vendor/happy-dom/packages/happy-dom/src/fetch/types/TResponseBody.ts +14 -0
  446. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchBodyUtility.ts +284 -0
  447. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchCORSUtility.ts +23 -0
  448. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts +141 -0
  449. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchRequestReferrerUtility.ts +259 -0
  450. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchRequestValidationUtility.ts +128 -0
  451. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchResponseHeaderUtility.ts +48 -0
  452. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/FetchResponseRedirectUtility.ts +27 -0
  453. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/SyncFetchScriptBuilder.ts +77 -0
  454. package/vendor/happy-dom/packages/happy-dom/src/fetch/utilities/VirtualServerUtility.ts +114 -0
  455. package/vendor/happy-dom/packages/happy-dom/src/file/Blob.ts +163 -0
  456. package/vendor/happy-dom/packages/happy-dom/src/file/File.ts +43 -0
  457. package/vendor/happy-dom/packages/happy-dom/src/file/FileReader.ts +211 -0
  458. package/vendor/happy-dom/packages/happy-dom/src/file/FileReaderEventTypeEnum.ts +9 -0
  459. package/vendor/happy-dom/packages/happy-dom/src/file/FileReaderFormatEnum.ts +7 -0
  460. package/vendor/happy-dom/packages/happy-dom/src/file/FileReaderReadyStateEnum.ts +6 -0
  461. package/vendor/happy-dom/packages/happy-dom/src/form-data/FormData.ts +291 -0
  462. package/vendor/happy-dom/packages/happy-dom/src/history/History.ts +220 -0
  463. package/vendor/happy-dom/packages/happy-dom/src/history/HistoryItemList.ts +72 -0
  464. package/vendor/happy-dom/packages/happy-dom/src/history/HistoryScrollRestorationEnum.ts +5 -0
  465. package/vendor/happy-dom/packages/happy-dom/src/history/IHistoryItem.ts +12 -0
  466. package/vendor/happy-dom/packages/happy-dom/src/html-parser/HTMLParser.ts +920 -0
  467. package/vendor/happy-dom/packages/happy-dom/src/html-serializer/HTMLSerializer.ts +172 -0
  468. package/vendor/happy-dom/packages/happy-dom/src/index.ts +495 -0
  469. package/vendor/happy-dom/packages/happy-dom/src/intersection-observer/IIntersectionObserverInit.ts +16 -0
  470. package/vendor/happy-dom/packages/happy-dom/src/intersection-observer/IntersectionObserver.ts +64 -0
  471. package/vendor/happy-dom/packages/happy-dom/src/intersection-observer/IntersectionObserverEntry.ts +26 -0
  472. package/vendor/happy-dom/packages/happy-dom/src/javascript/IJavaScriptCompiledResult.ts +9 -0
  473. package/vendor/happy-dom/packages/happy-dom/src/javascript/JavaScriptCompiler.ts +381 -0
  474. package/vendor/happy-dom/packages/happy-dom/src/location/Location.ts +319 -0
  475. package/vendor/happy-dom/packages/happy-dom/src/match-media/IMediaQueryRange.ts +5 -0
  476. package/vendor/happy-dom/packages/happy-dom/src/match-media/IMediaQueryRule.ts +4 -0
  477. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryItem.ts +354 -0
  478. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryList.ts +133 -0
  479. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryParser.ts +113 -0
  480. package/vendor/happy-dom/packages/happy-dom/src/match-media/MediaQueryTypeEnum.ts +7 -0
  481. package/vendor/happy-dom/packages/happy-dom/src/module/CSSModule.ts +53 -0
  482. package/vendor/happy-dom/packages/happy-dom/src/module/ECMAScriptModule.ts +194 -0
  483. package/vendor/happy-dom/packages/happy-dom/src/module/ECMAScriptModuleCompiler.ts +961 -0
  484. package/vendor/happy-dom/packages/happy-dom/src/module/JSONModule.ts +58 -0
  485. package/vendor/happy-dom/packages/happy-dom/src/module/ModuleFactory.ts +148 -0
  486. package/vendor/happy-dom/packages/happy-dom/src/module/ModuleURLUtility.ts +199 -0
  487. package/vendor/happy-dom/packages/happy-dom/src/module/UnresolvedModule.ts +81 -0
  488. package/vendor/happy-dom/packages/happy-dom/src/module/enums/ECMAScriptModuleEvaluateStateEnum.ts +7 -0
  489. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleCachedResult.ts +9 -0
  490. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleCompiledResult.ts +19 -0
  491. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleImport.ts +4 -0
  492. package/vendor/happy-dom/packages/happy-dom/src/module/types/IECMAScriptModuleInit.ts +10 -0
  493. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModule.ts +20 -0
  494. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleImportMap.ts +10 -0
  495. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleImportMapRule.ts +4 -0
  496. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleImportMapScope.ts +6 -0
  497. package/vendor/happy-dom/packages/happy-dom/src/module/types/IModuleInit.ts +12 -0
  498. package/vendor/happy-dom/packages/happy-dom/src/module/types/IResolveNodeModules.ts +8 -0
  499. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/IMutationListener.ts +7 -0
  500. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/IMutationObserverInit.ts +14 -0
  501. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationObserver.ts +175 -0
  502. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationObserverListener.ts +115 -0
  503. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationRecord.ts +55 -0
  504. package/vendor/happy-dom/packages/happy-dom/src/mutation-observer/MutationTypeEnum.ts +7 -0
  505. package/vendor/happy-dom/packages/happy-dom/src/navigator/MimeType.ts +35 -0
  506. package/vendor/happy-dom/packages/happy-dom/src/navigator/MimeTypeArray.ts +48 -0
  507. package/vendor/happy-dom/packages/happy-dom/src/navigator/Navigator.ts +247 -0
  508. package/vendor/happy-dom/packages/happy-dom/src/navigator/Plugin.ts +61 -0
  509. package/vendor/happy-dom/packages/happy-dom/src/navigator/PluginArray.ts +58 -0
  510. package/vendor/happy-dom/packages/happy-dom/src/nodes/NodeFactory.ts +38 -0
  511. package/vendor/happy-dom/packages/happy-dom/src/nodes/attr/Attr.ts +119 -0
  512. package/vendor/happy-dom/packages/happy-dom/src/nodes/character-data/CharacterData.ts +218 -0
  513. package/vendor/happy-dom/packages/happy-dom/src/nodes/character-data/CharacterDataUtility.ts +68 -0
  514. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/ChildNodeUtility.ts +100 -0
  515. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/IChildNode.ts +29 -0
  516. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/INonDocumentTypeChildNode.ts +7 -0
  517. package/vendor/happy-dom/packages/happy-dom/src/nodes/child-node/NonDocumentChildNodeUtility.ts +37 -0
  518. package/vendor/happy-dom/packages/happy-dom/src/nodes/comment/Comment.ts +36 -0
  519. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/Document.ts +2310 -0
  520. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/DocumentReadyStateEnum.ts +6 -0
  521. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/DocumentReadyStateManager.ts +52 -0
  522. package/vendor/happy-dom/packages/happy-dom/src/nodes/document/VisibilityStateEnum.ts +6 -0
  523. package/vendor/happy-dom/packages/happy-dom/src/nodes/document-fragment/DocumentFragment.ts +208 -0
  524. package/vendor/happy-dom/packages/happy-dom/src/nodes/document-type/DocumentType.ts +70 -0
  525. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/Element.ts +1842 -0
  526. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/ElementEventAttributeUtility.ts +96 -0
  527. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/HTMLCollection.ts +228 -0
  528. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/NamedNodeMap.ts +274 -0
  529. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/NamedNodeMapProxyFactory.ts +127 -0
  530. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/THTMLCollectionListener.ts +6 -0
  531. package/vendor/happy-dom/packages/happy-dom/src/nodes/element/TNamedNodeMapListener.ts +3 -0
  532. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElement.ts +439 -0
  533. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-area-element/HTMLAreaElement.ts +426 -0
  534. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-audio-element/Audio.ts +28 -0
  535. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-audio-element/HTMLAudioElement.ts +10 -0
  536. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-base-element/HTMLBaseElement.ts +64 -0
  537. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-body-element/HTMLBodyElement.ts +161 -0
  538. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-br-element/HTMLBRElement.ts +7 -0
  539. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-button-element/HTMLButtonElement.ts +406 -0
  540. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-canvas-element/CanvasCaptureMediaStreamTrack.ts +51 -0
  541. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-canvas-element/HTMLCanvasElement.ts +304 -0
  542. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-d-list-element/HTMLDListElement.ts +7 -0
  543. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-data-element/HTMLDataElement.ts +25 -0
  544. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-data-list-element/HTMLDataListElement.ts +28 -0
  545. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-details-element/HTMLDetailsElement.ts +112 -0
  546. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-dialog-element/HTMLDialogElement.ts +104 -0
  547. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-div-element/HTMLDivElement.ts +7 -0
  548. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-document/HTMLDocument.ts +82 -0
  549. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-element/HTMLElement.ts +1149 -0
  550. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-element/HTMLElementUtility.ts +119 -0
  551. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-embed-element/HTMLEmbedElement.ts +90 -0
  552. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-field-set-element/HTMLFieldSetElement.ts +165 -0
  553. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/HTMLFormControlsCollection.ts +35 -0
  554. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/HTMLFormElement.ts +675 -0
  555. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/RadioNodeList.ts +25 -0
  556. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-form-element/THTMLFormControlElement.ts +16 -0
  557. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-head-element/HTMLHeadElement.ts +7 -0
  558. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-heading-element/HTMLHeadingElement.ts +7 -0
  559. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-hr-element/HTMLHRElement.ts +7 -0
  560. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-html-element/HTMLHtmlElement.ts +7 -0
  561. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-hyperlink-element/HTMLHyperlinkElementUtility.ts +329 -0
  562. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-hyperlink-element/IHTMLHyperlinkElement.ts +19 -0
  563. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameElement.ts +460 -0
  564. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-image-element/HTMLImageElement.ts +500 -0
  565. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-image-element/Image.ts +33 -0
  566. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/FileList.ts +34 -0
  567. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElement.ts +1550 -0
  568. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementDateUtility.ts +50 -0
  569. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementSelectionDirectionEnum.ts +6 -0
  570. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementSelectionModeEnum.ts +7 -0
  571. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementValueSanitizer.ts +211 -0
  572. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-input-element/HTMLInputElementValueStepping.ts +92 -0
  573. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-label-element/HTMLLabelElement.ts +128 -0
  574. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-label-element/HTMLLabelElementUtility.ts +45 -0
  575. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-legend-element/HTMLLegendElement.ts +27 -0
  576. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-li-element/HTMLLIElement.ts +31 -0
  577. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-link-element/HTMLLinkElement.ts +501 -0
  578. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-map-element/HTMLMapElement.ts +47 -0
  579. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts +906 -0
  580. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/IMediaTrackCapabilities.ts +21 -0
  581. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/IMediaTrackSettings.ts +5 -0
  582. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/MediaStream.ts +114 -0
  583. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/MediaStreamTrack.ts +182 -0
  584. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/RemotePlayback.ts +47 -0
  585. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrack.ts +156 -0
  586. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackCue.ts +51 -0
  587. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackCueList.ts +37 -0
  588. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackKindEnum.ts +9 -0
  589. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TextTrackList.ts +182 -0
  590. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/TimeRanges.ts +73 -0
  591. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/VTTCue.ts +80 -0
  592. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-media-element/VTTRegion.ts +15 -0
  593. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-menu-element/HTMLMenuElement.ts +7 -0
  594. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-meta-element/HTMLMetaElement.ts +80 -0
  595. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-meter-element/HTMLMeterElement.ts +216 -0
  596. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-mod-element/HTMLModElement.ts +54 -0
  597. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-o-list-element/HTMLOListElement.ts +83 -0
  598. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-object-element/HTMLObjectElement.ts +223 -0
  599. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-opt-group-element/HTMLOptGroupElement.ts +53 -0
  600. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-option-element/HTMLOptionElement.ts +192 -0
  601. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-output-element/HTMLOutputElement.ts +179 -0
  602. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-paragraph-element/HTMLParagraphElement.ts +7 -0
  603. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-param-element/HTMLParamElement.ts +7 -0
  604. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-picture-element/HTMLPictureElement.ts +7 -0
  605. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-pre-element/HTMLPreElement.ts +7 -0
  606. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-progress-element/HTMLProgressElement.ts +100 -0
  607. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-quote-element/HTMLQuoteElement.ts +36 -0
  608. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-script-element/HTMLScriptElement.ts +735 -0
  609. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-select-element/HTMLOptionsCollection.ts +69 -0
  610. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-select-element/HTMLSelectElement.ts +779 -0
  611. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-slot-element/HTMLSlotElement.ts +249 -0
  612. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-source-element/HTMLSourceElement.ts +148 -0
  613. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-span-element/HTMLSpanElement.ts +7 -0
  614. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-style-element/HTMLStyleElement.ts +125 -0
  615. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-caption-element/HTMLTableCaptionElement.ts +7 -0
  616. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-cell-element/HTMLTableCellElement.ts +125 -0
  617. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-col-element/HTMLTableColElement.ts +7 -0
  618. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-element/HTMLTableElement.ts +343 -0
  619. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-row-element/HTMLTableRowElement.ts +149 -0
  620. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-table-section-element/HTMLTableSectionElement.ts +88 -0
  621. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-template-element/HTMLTemplateElement.ts +154 -0
  622. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-text-area-element/HTMLTextAreaElement.ts +649 -0
  623. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-time-element/HTMLTimeElement.ts +27 -0
  624. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-title-element/HTMLTitleElement.ts +48 -0
  625. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-track-element/HTMLTrackElement.ts +164 -0
  626. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-u-list-element/HTMLUListElement.ts +7 -0
  627. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts +9 -0
  628. package/vendor/happy-dom/packages/happy-dom/src/nodes/html-video-element/HTMLVideoElement.ts +10 -0
  629. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedComputedStyleResult.ts +6 -0
  630. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedElementByIdResult.ts +6 -0
  631. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedElementByTagNameResult.ts +6 -0
  632. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedElementsByTagNameResult.ts +6 -0
  633. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedMatchesResult.ts +6 -0
  634. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedQuerySelectorAllResult.ts +7 -0
  635. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedQuerySelectorResult.ts +6 -0
  636. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedResult.ts +3 -0
  637. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/ICachedStyleResult.ts +6 -0
  638. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/Node.ts +1373 -0
  639. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeDocumentPositionEnum.ts +10 -0
  640. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeList.ts +224 -0
  641. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeTypeEnum.ts +13 -0
  642. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/NodeUtility.ts +330 -0
  643. package/vendor/happy-dom/packages/happy-dom/src/nodes/node/TNodeListListener.ts +1 -0
  644. package/vendor/happy-dom/packages/happy-dom/src/nodes/parent-node/IParentNode.ts +109 -0
  645. package/vendor/happy-dom/packages/happy-dom/src/nodes/parent-node/ParentNodeUtility.ts +334 -0
  646. package/vendor/happy-dom/packages/happy-dom/src/nodes/processing-instruction/ProcessingInstruction.ts +22 -0
  647. package/vendor/happy-dom/packages/happy-dom/src/nodes/shadow-root/ShadowRoot.ts +290 -0
  648. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animate-element/SVGAnimateElement.ts +8 -0
  649. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animate-motion-element/SVGAnimateMotionElement.ts +8 -0
  650. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animate-transform-element/SVGAnimateTransformElement.ts +8 -0
  651. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-animation-element/SVGAnimationElement.ts +94 -0
  652. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-circle-element/SVGCircleElement.ts +72 -0
  653. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-clip-path-element/SVGClipPathElement.ts +34 -0
  654. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-component-transfer-function-element/SVGComponentTransferFunctionElement.ts +167 -0
  655. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-defs-element/SVGDefsElement.ts +8 -0
  656. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-desc-element/SVGDescElement.ts +8 -0
  657. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-element/SVGElement.ts +828 -0
  658. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-ellipse-element/SVGEllipseElement.ts +92 -0
  659. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-blend-element/SVGFEBlendElement.ts +192 -0
  660. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-color-matrix-element/SVGFEColorMatrixElement.ts +204 -0
  661. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-component-transfer-element/SVGFEComponentTransferElement.ts +133 -0
  662. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-composite-element/SVGFECompositeElement.ts +186 -0
  663. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-convolve-matrix-element/SVGFEConvolveMatrixElement.ts +366 -0
  664. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-diffuse-lighting-element/SVGFEDiffuseLightingElement.ts +214 -0
  665. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-displacement-map-element/SVGFEDisplacementMapElement.ts +226 -0
  666. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-distant-light-element/SVGFEDistantLightElement.ts +52 -0
  667. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-drop-shadow-element/SVGFEDropShadowElement.ts +227 -0
  668. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-flood-element/SVGFEFloodElement.ts +113 -0
  669. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-a-element/SVGFEFuncAElement.ts +8 -0
  670. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-b-element/SVGFEFuncBElement.ts +8 -0
  671. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-g-element/SVGFEFuncGElement.ts +8 -0
  672. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-func-r-element/SVGFEFuncRElement.ts +8 -0
  673. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-gaussian-blur-element/SVGFEGaussianBlurElement.ts +214 -0
  674. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-image-element/SVGFEImageElement.ts +173 -0
  675. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-merge-element/SVGFEMergeElement.ts +113 -0
  676. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-merge-node-element/SVGFEMergeNodeElement.ts +32 -0
  677. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-morphology-element/SVGFEMorphologyElement.ts +202 -0
  678. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-offset-element/SVGFEOffsetElement.ts +174 -0
  679. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-point-light-element/SVGFEPointLightElement.ts +72 -0
  680. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-specular-lighting-element/SVGFESpecularLightingElement.ts +237 -0
  681. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-spot-light-element/SVGFESpotLightElement.ts +173 -0
  682. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-tile-element/SVGFETileElement.ts +133 -0
  683. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-fe-turbulence-element/SVGFETurbulenceElement.ts +249 -0
  684. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-filter-element/SVGFilterElement.ts +158 -0
  685. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-foreign-object-element/SVGForeignObjectElement.ts +92 -0
  686. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-g-element/SVGGElement.ts +8 -0
  687. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-geometry-element/SVGGeometryElement.ts +94 -0
  688. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-gradient-element/SVGGradientElement.ts +104 -0
  689. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-graphics-element/SVGGraphicsElement.ts +134 -0
  690. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-image-element/SVGImageElement.ts +188 -0
  691. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-line-element/SVGLineElement.ts +92 -0
  692. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-linear-gradient-element/SVGLinearGradientElement.ts +92 -0
  693. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-m-path-element/SVGMPathElement.ts +32 -0
  694. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-marker-element/SVGMarkerElement.ts +230 -0
  695. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-mask-element/SVGMaskElement.ts +137 -0
  696. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-metadata-element/SVGMetadataElement.ts +8 -0
  697. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-path-element/SVGPathElement.ts +8 -0
  698. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-pattern-element/SVGPatternElement.ts +179 -0
  699. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-polygon-element/SVGPolygonElement.ts +53 -0
  700. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-polyline-element/SVGPolylineElement.ts +53 -0
  701. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-radial-gradient-element/SVGRadialGradientElement.ts +112 -0
  702. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-rect-element/SVGRectElement.ts +132 -0
  703. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-script-element/SVGScriptElement.ts +50 -0
  704. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-set-element/SVGSetElement.ts +8 -0
  705. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-stop-element/SVGStopElement.ts +32 -0
  706. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-style-element/SVGStyleElement.ts +143 -0
  707. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-svg-element/SVGSVGElement.ts +601 -0
  708. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-switch-element/SVGSwitchElement.ts +8 -0
  709. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-symbol-element/SVGSymbolElement.ts +8 -0
  710. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-t-span-element/SVGTSpanElement.ts +8 -0
  711. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-content-element/SVGTextContentElement.ts +143 -0
  712. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-element/SVGTextElement.ts +8 -0
  713. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-path-element/SVGTextPathElement.ts +106 -0
  714. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-text-positioning-element/SVGTextPositioningElement.ts +113 -0
  715. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-title-element/SVGTitleElement.ts +8 -0
  716. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-use-element/SVGUseElement.ts +113 -0
  717. package/vendor/happy-dom/packages/happy-dom/src/nodes/svg-view-element/SVGViewElement.ts +8 -0
  718. package/vendor/happy-dom/packages/happy-dom/src/nodes/text/Text.ts +154 -0
  719. package/vendor/happy-dom/packages/happy-dom/src/nodes/xml-document/XMLDocument.ts +10 -0
  720. package/vendor/happy-dom/packages/happy-dom/src/permissions/PermissionNameEnum.ts +32 -0
  721. package/vendor/happy-dom/packages/happy-dom/src/permissions/PermissionStatus.ts +23 -0
  722. package/vendor/happy-dom/packages/happy-dom/src/permissions/Permissions.ts +59 -0
  723. package/vendor/happy-dom/packages/happy-dom/src/query-selector/ISelectorAttribute.ts +7 -0
  724. package/vendor/happy-dom/packages/happy-dom/src/query-selector/ISelectorMatch.ts +3 -0
  725. package/vendor/happy-dom/packages/happy-dom/src/query-selector/ISelectorPseudo.ts +8 -0
  726. package/vendor/happy-dom/packages/happy-dom/src/query-selector/QuerySelector.ts +849 -0
  727. package/vendor/happy-dom/packages/happy-dom/src/query-selector/SelectorCombinatorEnum.ts +9 -0
  728. package/vendor/happy-dom/packages/happy-dom/src/query-selector/SelectorItem.ts +575 -0
  729. package/vendor/happy-dom/packages/happy-dom/src/query-selector/SelectorParser.ts +699 -0
  730. package/vendor/happy-dom/packages/happy-dom/src/query-selector/TGlobalMatchFunction.ts +12 -0
  731. package/vendor/happy-dom/packages/happy-dom/src/range/IRangeBoundaryPoint.ts +9 -0
  732. package/vendor/happy-dom/packages/happy-dom/src/range/Range.ts +1161 -0
  733. package/vendor/happy-dom/packages/happy-dom/src/range/RangeHowEnum.ts +8 -0
  734. package/vendor/happy-dom/packages/happy-dom/src/range/RangeUtility.ts +118 -0
  735. package/vendor/happy-dom/packages/happy-dom/src/resize-observer/ResizeObserver.ts +33 -0
  736. package/vendor/happy-dom/packages/happy-dom/src/screen/Screen.ts +19 -0
  737. package/vendor/happy-dom/packages/happy-dom/src/screen/ScreenDetailed.ts +17 -0
  738. package/vendor/happy-dom/packages/happy-dom/src/screen/ScreenDetails.ts +27 -0
  739. package/vendor/happy-dom/packages/happy-dom/src/selection/Selection.ts +556 -0
  740. package/vendor/happy-dom/packages/happy-dom/src/selection/SelectionDirectionEnum.ts +7 -0
  741. package/vendor/happy-dom/packages/happy-dom/src/storage/Storage.ts +149 -0
  742. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAngle.ts +310 -0
  743. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAngleTypeEnum.ts +9 -0
  744. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedAngle.ts +100 -0
  745. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedBoolean.ts +80 -0
  746. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedEnumeration.ts +119 -0
  747. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedInteger.ts +97 -0
  748. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedLength.ts +100 -0
  749. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedLengthList.ts +101 -0
  750. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedNumber.ts +101 -0
  751. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedNumberList.ts +101 -0
  752. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedPreserveAspectRatio.ts +100 -0
  753. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedRect.ts +100 -0
  754. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedString.ts +83 -0
  755. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGAnimatedTransformList.ts +101 -0
  756. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGLength.ts +375 -0
  757. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGLengthList.ts +489 -0
  758. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGLengthTypeEnum.ts +15 -0
  759. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGMatrix.ts +429 -0
  760. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGNumber.ts +83 -0
  761. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGNumberList.ts +522 -0
  762. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPoint.ts +114 -0
  763. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPointList.ts +526 -0
  764. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPreserveAspectRatio.ts +176 -0
  765. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPreserveAspectRatioAlignEnum.ts +15 -0
  766. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGPreserveAspectRatioMeetOrSliceEnum.ts +7 -0
  767. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGRect.ts +200 -0
  768. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGStringList.ts +422 -0
  769. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGTransform.ts +369 -0
  770. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGTransformList.ts +531 -0
  771. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGTransformTypeEnum.ts +11 -0
  772. package/vendor/happy-dom/packages/happy-dom/src/svg/SVGUnitTypes.ts +26 -0
  773. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/NodeFilter.ts +18 -0
  774. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/NodeFilterMask.ts +28 -0
  775. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/NodeIterator.ts +85 -0
  776. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/TNodeFilter.ts +3 -0
  777. package/vendor/happy-dom/packages/happy-dom/src/tree-walker/TreeWalker.ts +339 -0
  778. package/vendor/happy-dom/packages/happy-dom/src/url/URL.ts +45 -0
  779. package/vendor/happy-dom/packages/happy-dom/src/utilities/AttributeUtility.ts +43 -0
  780. package/vendor/happy-dom/packages/happy-dom/src/utilities/ClassMethodBinder.ts +71 -0
  781. package/vendor/happy-dom/packages/happy-dom/src/utilities/StringUtility.ts +47 -0
  782. package/vendor/happy-dom/packages/happy-dom/src/utilities/XMLEncodeUtility.ts +166 -0
  783. package/vendor/happy-dom/packages/happy-dom/src/validity-state/ValidityState.ts +234 -0
  784. package/vendor/happy-dom/packages/happy-dom/src/version.ts +1 -0
  785. package/vendor/happy-dom/packages/happy-dom/src/web-socket/WebSocket.ts +408 -0
  786. package/vendor/happy-dom/packages/happy-dom/src/web-socket/WebSocketReadyStateEnum.ts +8 -0
  787. package/vendor/happy-dom/packages/happy-dom/src/window/BrowserWindow.ts +3074 -0
  788. package/vendor/happy-dom/packages/happy-dom/src/window/CrossOriginBrowserWindow.ts +152 -0
  789. package/vendor/happy-dom/packages/happy-dom/src/window/DetachedWindowAPI.ts +133 -0
  790. package/vendor/happy-dom/packages/happy-dom/src/window/GlobalWindow.ts +90 -0
  791. package/vendor/happy-dom/packages/happy-dom/src/window/INodeJSGlobal.ts +76 -0
  792. package/vendor/happy-dom/packages/happy-dom/src/window/IOptionalTimerLoopsLimit.ts +4 -0
  793. package/vendor/happy-dom/packages/happy-dom/src/window/IScrollToOptions.ts +5 -0
  794. package/vendor/happy-dom/packages/happy-dom/src/window/ITimerLoopsLimit.ts +4 -0
  795. package/vendor/happy-dom/packages/happy-dom/src/window/VMGlobalPropertyScript.ts +59 -0
  796. package/vendor/happy-dom/packages/happy-dom/src/window/Window.ts +67 -0
  797. package/vendor/happy-dom/packages/happy-dom/src/window/WindowBrowserContext.ts +117 -0
  798. package/vendor/happy-dom/packages/happy-dom/src/window/WindowContextClassExtender.ts +288 -0
  799. package/vendor/happy-dom/packages/happy-dom/src/window/WindowPageOpenUtility.ts +200 -0
  800. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequest.ts +577 -0
  801. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestEventTarget.ts +88 -0
  802. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestReadyStateEnum.ts +9 -0
  803. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestResponseDataParser.ts +70 -0
  804. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpRequestUpload.ts +6 -0
  805. package/vendor/happy-dom/packages/happy-dom/src/xml-http-request/XMLHttpResponseTypeEnum.ts +9 -0
  806. package/vendor/happy-dom/packages/happy-dom/src/xml-parser/XMLParser.ts +744 -0
  807. package/vendor/happy-dom/packages/happy-dom/src/xml-serializer/XMLSerializer.ts +280 -0
  808. package/vendor/happy-dom/turbo.json +52 -0
  809. package/vendor/ses/LICENSE +201 -0
  810. package/vendor/ses/LICENSE-aura +16 -0
  811. package/vendor/ses/LICENSE-caja +13 -0
  812. package/vendor/ses/LICENSE-corejs +19 -0
  813. package/vendor/ses/LICENSE-v8 +9 -0
  814. package/vendor/ses/README.md +968 -0
  815. package/vendor/ses/dist/ses.mjs +15219 -0
  816. package/vendor/ses/package.json +142 -0
  817. package/vendor/wasmpeg/LICENSE +501 -0
  818. package/vendor/wasmpeg/NOTICE +30 -0
  819. package/vendor/wasmpeg/VENDORING.md +35 -0
  820. package/vendor/wasmpeg/dist/cpu.js +2 -0
  821. package/vendor/wasmpeg/dist/cpu.wasm +0 -0
  822. package/vendor/wasmpeg/package.json +45 -0
  823. package/vendor/wasmpeg/source-v1.0.1.tar.gz +0 -0
  824. package/vendor/wasmpeg/src/js/exec.mjs +478 -0
  825. package/vendor/wasmpeg/src/js/ffmpeg.js +94 -0
  826. package/vendor/wasmpeg/src/js/formats.js +84 -0
  827. package/vendor/wasmpeg/src/js/gpu.js +480 -0
  828. package/vendor/wasmpeg/src/js/index.d.ts +154 -0
  829. package/vendor/wasmpeg/src/js/index.js +7 -0
  830. package/vendor/wasmpeg/src/js/wasmpeg.mjs +221 -0
@@ -0,0 +1,1691 @@
1
+ /**
2
+ * The page pipeline of one renderer: parse, style, layout, display list and
3
+ * CanvasKit raster, plus the page-side input helpers (scrolling, hit testing,
4
+ * hints). It never touches the network: subresources come through the
5
+ * injected `fetchResource`, which the renderer process forwards to the
6
+ * controller over IPC. Navigation and history belong to the controller;
7
+ * pages ask for navigation through `requestNavigation`.
8
+ *
9
+ * Page scripts run through `page-realm.js` once `setScripting()` enables a
10
+ * mode. DOM changes made by scripts only mark the page dirty; style, layout
11
+ * and raster run when something reads them (hit testing, geometry APIs) or
12
+ * at the next rendering opportunity, which is throttled to the cost of a
13
+ * relayout so timers and animations cannot keep the thread busy.
14
+ *
15
+ * Raster output goes to the compositor (`onFrame`) as tiles: the viewport
16
+ * first, then, when idle, a taller tile around it so the compositor can
17
+ * scroll without waiting for this thread.
18
+ *
19
+ * Documents load in stages: when subresources take longer than
20
+ * PREVIEW_DELAY_MS, a preview styled only by the user-agent defaults and
21
+ * inline <style> is shown and scrollable, then the styled page replaces it,
22
+ * then scripts run. `loadDocument` resolves at the first paint; `whenLoaded`
23
+ * after the load event.
24
+ */
25
+ import CanvasKitInit from "../../usr/lib/canvaskit/canvaskit.js";
26
+ import { parseHTMLDocument } from "../happy-dom/parser.js";
27
+ import { layoutText } from "../layout/text-layout.js";
28
+ import { ScrollViewport } from "../layout/scroll-viewport.js";
29
+ import { elementBounds, hitTest, interactiveRegions } from "../input/hit-test.js";
30
+ import { RenderTreeBuilder, renderTreeText } from "../render-tree/index.js";
31
+ import { StyleEngine } from "../style/computed-style.js";
32
+ import { buildDisplayList, visibleItems } from "../paint/display-list.js";
33
+ import { backgroundBytes, cropViewport, encodeImage } from "../paint/frame.js";
34
+ import { createPageRealm } from "./page-realm.js";
35
+ import { MOBILE_USER_AGENT } from "./flags.js";
36
+
37
+ // Captured at load: in host mode page scripts share this global object.
38
+ const hostPerformance = globalThis.performance;
39
+ const hostSetTimeout = globalThis.setTimeout;
40
+ const hostClearTimeout = globalThis.clearTimeout;
41
+
42
+ /** How long subresources may take before a preview of the unstyled document is shown. */
43
+ export const PREVIEW_DELAY_MS = 300;
44
+
45
+ const canvasKitDirectory = new URL("../../usr/lib/canvaskit/", import.meta.url);
46
+ const fontDirectory = new URL("../../usr/share/fonts/", import.meta.url);
47
+
48
+ /**
49
+ * @param {{
50
+ * fetchResource(url: string, kind: "stylesheet" | "image" | "script" | "metadata" | "video"):
51
+ * Promise<{ ok: boolean, status: number, url: string, contentType: string, body: Uint8Array }>,
52
+ * requestNavigation?(url: string): void,
53
+ * reportError?(message: string): void,
54
+ * pageFetch?(request: object): Promise<object>,
55
+ * webSockets?: { open(url, protocols, onEvent): number, send(id, data): void, close(id, code, reason): void } | null,
56
+ * setCookie?(value: string): void,
57
+ * consoleMessage?: ((level: string, text: string) => void) | null,
58
+ * trace?: ((text: string) => void) | null,
59
+ * onFrame?: ((frame: object) => void) | null,
60
+ * onLifecycle?: ((name: "DOMContentLoaded" | "load", generation: number) => void) | null,
61
+ * videoDecoder?: object | null,
62
+ * }} options
63
+ */
64
+ export async function createPageRenderer({
65
+ fetchResource,
66
+ requestNavigation = () => {},
67
+ reportError = () => {},
68
+ pageFetch = () => Promise.reject(new TypeError("network access is not available")),
69
+ webSockets = null,
70
+ setCookie = () => {},
71
+ consoleMessage = null,
72
+ trace = null,
73
+ onFrame = null,
74
+ onLifecycle = null,
75
+ videoDecoder = null,
76
+ mobile = false,
77
+ }) {
78
+ const wasmBinary = await Bun.file(new URL("canvaskit.wasm", canvasKitDirectory)).arrayBuffer();
79
+ const CanvasKit = await CanvasKitInit({ wasmBinary });
80
+ const fontCatalogue = await Bun.file(new URL("fonts.json", fontDirectory)).json();
81
+ const uiFontNames = [fontCatalogue.sets.ui.regular, ...fontCatalogue.sets.ui.fallback];
82
+ const monospaceFontNames = [fontCatalogue.sets.terminal.regular, fontCatalogue.sets.terminal.bold];
83
+ const fontBuffers = await Promise.all([...uiFontNames, ...monospaceFontNames].map((name) =>
84
+ Bun.file(new URL(fontCatalogue.fonts[name].file, fontDirectory)).arrayBuffer()));
85
+ // A TypefaceFontProvider registers each file under an explicit family name.
86
+ // CanvasKit does not pick a static bold face by weight within one family, so
87
+ // the monospace bold file gets its own catalogue name and is chosen by weight.
88
+ const fontProvider = CanvasKit.TypefaceFontProvider.Make();
89
+ const loadedFamilies = new Map();
90
+ [...uiFontNames, ...monospaceFontNames].forEach((name, index) => {
91
+ const family = (fontCatalogue.fonts[name].families ?? [name])[0];
92
+ fontProvider.registerFont(fontBuffers[index], family);
93
+ loadedFamilies.set(family.toLowerCase(), family);
94
+ });
95
+ // One font collection for every paragraph: building each paragraph from
96
+ // the provider made a new collection, so Skia's font matching and fallback
97
+ // caches started cold every time (about 3x slower per paragraph).
98
+ const fontCollection = CanvasKit.FontCollection.Make();
99
+ fontCollection.setDefaultFontManager(fontProvider);
100
+ fontCollection.enableFontFallback();
101
+
102
+ const fontFamilies = uiFontNames.map((name) => (fontCatalogue.fonts[name].families ?? [name])[0]);
103
+ const sansSerifFamily = fontFamilies[0];
104
+ const monospaceFamily = fontCatalogue.sets.terminal.regular;
105
+ const monospaceBoldFamily = fontCatalogue.sets.terminal.bold;
106
+ // Maps CSS generic and common platform family names onto the bundled fonts.
107
+ const genericFamilies = new Map([
108
+ ["monospace", monospaceFamily], ["ui-monospace", monospaceFamily], ["menlo", monospaceFamily],
109
+ ["consolas", monospaceFamily], ["monaco", monospaceFamily], ["courier", monospaceFamily],
110
+ ["courier new", monospaceFamily], ["sans-serif", sansSerifFamily], ["serif", sansSerifFamily],
111
+ ["system-ui", sansSerifFamily], ["-apple-system", sansSerifFamily], ["blinkmacsystemfont", sansSerifFamily],
112
+ ["ui-sans-serif", sansSerifFamily], ["arial", sansSerifFamily], ["helvetica", sansSerifFamily],
113
+ ]);
114
+ const resolvedFamilies = new Map();
115
+ /** First available family from a computed font-family list, then the UI fallbacks. */
116
+ function resolveFontFamilies(families = ["sans-serif"], weight = 400) {
117
+ const bold = weight >= 600;
118
+ const key = `${bold}\n${families.join("\n")}`;
119
+ let resolved = resolvedFamilies.get(key);
120
+ if (!resolved) {
121
+ let primary = families
122
+ .map((family) => loadedFamilies.get(family.toLowerCase()) ?? genericFamilies.get(family.toLowerCase()))
123
+ .find(Boolean) ?? sansSerifFamily;
124
+ if (bold && primary === monospaceFamily) primary = monospaceBoldFamily;
125
+ resolved = [primary, ...fontFamilies.filter((family) => family !== primary)];
126
+ resolvedFamilies.set(key, resolved);
127
+ }
128
+ return resolved;
129
+ }
130
+ const graphemes = new Intl.Segmenter(undefined, { granularity: "grapheme" });
131
+ const emojiPresentation = /^\p{Emoji_Presentation}/u;
132
+ const renderTreeBuilder = new RenderTreeBuilder();
133
+ const styleEngine = new StyleEngine();
134
+ const viewport = new ScrollViewport(800, 600);
135
+ const page = {
136
+ url: "about:blank",
137
+ title: "",
138
+ document: null,
139
+ renderTree: null,
140
+ layout: null,
141
+ displayList: null,
142
+ window: null,
143
+ width: 800,
144
+ height: 600,
145
+ deviceScaleFactor: 1,
146
+ pageScale: 1,
147
+ needsPaint: true,
148
+ loading: false,
149
+ hints: [],
150
+ hintsVisible: false,
151
+ styleSheets: [],
152
+ backgroundColor: "rgba(255, 255, 255, 1)",
153
+ resources: new WeakMap(),
154
+ decodedImages: [],
155
+ videos: new Map(),
156
+ realm: null,
157
+ // "off" until the renderer process has set up its sandbox.
158
+ scripting: "off",
159
+ dirty: false,
160
+ userAgent: mobile ? MOBILE_USER_AGENT : "Mozilla/5.0 (X11; Linux) BuninuBrowser/0.0.1",
161
+ // document.cookie as last reported by the controller (non-HttpOnly only).
162
+ cookie: "",
163
+ };
164
+
165
+ function makeParagraph(text, computedStyle = null, fontSize = computedStyle?.fontSize ?? 16, scale = 1) {
166
+ const color = canvasColor(CanvasKit, computedStyle?.color ?? "rgba(0, 0, 0, 1)");
167
+ const weight = computedStyle?.fontWeight ?? 400;
168
+ const families = resolveFontFamilies(computedStyle?.fontFamily, weight);
169
+ const emojiFontFamilies = [
170
+ ...families.filter((name) => name.includes("Emoji")),
171
+ ...families.filter((name) => !name.includes("Emoji")),
172
+ ];
173
+ // text-decoration lines, drawn by SkParagraph under/over/through the glyphs.
174
+ const decoration = computedStyle?.decoration ? {
175
+ decoration: computedStyle.decoration.lines.reduce((mask, line) => mask | ({
176
+ underline: CanvasKit.UnderlineDecoration, overline: CanvasKit.OverlineDecoration, "line-through": CanvasKit.LineThroughDecoration,
177
+ })[line], 0),
178
+ decorationColor: canvasColor(CanvasKit, computedStyle.decoration.color),
179
+ decorationThickness: 1,
180
+ } : {};
181
+ const style = new CanvasKit.ParagraphStyle({
182
+ textStyle: {
183
+ color,
184
+ fontFamilies: families,
185
+ fontSize: Math.max(1, Math.round(fontSize * scale)),
186
+ fontStyle: { weight },
187
+ // Roboto is a variable font; static fonts ignore the axis and match by weight.
188
+ fontVariations: [{ axis: "wght", value: weight }],
189
+ ...decoration,
190
+ },
191
+ maxLines: 1,
192
+ });
193
+ const builder = CanvasKit.ParagraphBuilder.MakeFromFontCollection(style, fontCollection);
194
+ for (const { segment } of graphemes.segment(text || " ")) {
195
+ const emoji = emojiPresentation.test(segment) || segment.includes("\uFE0F");
196
+ if (emoji) {
197
+ builder.pushStyle(CanvasKit.TextStyle({
198
+ color,
199
+ ...decoration,
200
+ fontFamilies: emojiFontFamilies,
201
+ fontSize: Math.max(1, Math.round(fontSize * scale)),
202
+ fontStyle: { weight: computedStyle?.fontWeight ?? 400 },
203
+ }));
204
+ }
205
+ builder.addText(segment);
206
+ if (emoji) builder.pop();
207
+ }
208
+ const paragraph = builder.build();
209
+ builder.delete();
210
+ return paragraph;
211
+ }
212
+
213
+ // Text widths depend only on the font (families, rounded size, weight),
214
+ // not on the element, so they are cached per font across elements,
215
+ // relayouts and documents. The cache is dropped when it grows too large.
216
+ const MAX_MEASURED_TEXTS = 200_000;
217
+ const measuredWidths = new Map();
218
+ let measuredCount = 0;
219
+
220
+ function measureText(text, computedStyle = null) {
221
+ if (!text) return 0;
222
+ const fontKey = fontKeyOf(computedStyle);
223
+ let widths = measuredWidths.get(fontKey);
224
+ if (!widths) measuredWidths.set(fontKey, widths = new Map());
225
+ let width = widths.get(text);
226
+ if (width === undefined) {
227
+ const paragraph = makeParagraph(text, computedStyle);
228
+ paragraph.layout(100_000);
229
+ // getLongestLine() drops trailing white space, which line breaking needs.
230
+ width = paragraph.getMaxIntrinsicWidth();
231
+ paragraph.delete();
232
+ if (++measuredCount > MAX_MEASURED_TEXTS) {
233
+ measuredWidths.clear();
234
+ measuredCount = 1;
235
+ measuredWidths.set(fontKey, widths = new Map());
236
+ }
237
+ widths.set(text, width);
238
+ }
239
+ return width;
240
+ }
241
+
242
+ // Computed styles are immutable and shared, so each one's key is computed once.
243
+ const fontKeys = new WeakMap();
244
+ function fontKeyOf(computedStyle) {
245
+ if (computedStyle && typeof computedStyle === "object") {
246
+ const cached = fontKeys.get(computedStyle);
247
+ if (cached) return cached;
248
+ }
249
+ const weight = computedStyle?.fontWeight ?? 400;
250
+ const key = `${Math.max(1, Math.round(computedStyle?.fontSize ?? 16))}/${weight}/${
251
+ resolveFontFamilies(computedStyle?.fontFamily, weight).join(",")}`;
252
+ if (computedStyle && typeof computedStyle === "object") fontKeys.set(computedStyle, key);
253
+ return key;
254
+ }
255
+
256
+ const fontMetricsCache = new Map();
257
+ function fontMetrics(computedStyle = null) {
258
+ const key = `${computedStyle?.fontSize ?? 16}/${computedStyle?.fontWeight ?? 400}/${computedStyle?.fontFamily?.join(",")}`;
259
+ let metrics = fontMetricsCache.get(key);
260
+ if (!metrics) {
261
+ const paragraph = makeParagraph("Hg", computedStyle);
262
+ paragraph.layout(100_000);
263
+ metrics = { ascent: paragraph.getAlphabeticBaseline(), height: paragraph.getHeight() };
264
+ paragraph.delete();
265
+ fontMetricsCache.set(key, metrics);
266
+ }
267
+ return metrics;
268
+ }
269
+
270
+ // Compositor state. The compositor owns scrolling; `syncedScroll` is the
271
+ // position both sides agree on, and `scrollEpoch` changes whenever this
272
+ // thread scrolls on its own (keys, fragments, script, a new document).
273
+ let scrollEpoch = 0;
274
+ let syncedScroll = { x: 0, y: 0 };
275
+ let tileSerial = 0;
276
+ let lastTile = null;
277
+ let encoded = { key: "", png: "" };
278
+ let prepaintTimer = null;
279
+ let frameTimer = null;
280
+ let lastRebuildMs = 0;
281
+
282
+ // What the latest tile was rasterized from. A rebuild that produces the
283
+ // same display list (script changes that do not affect rendering, repeated
284
+ // relayouts) reuses the tile instead of rasterizing again, like Blink's
285
+ // PaintController reusing cached display items
286
+ // (platform/graphics/paint/paint_controller.cc, BSD).
287
+ let rasterized = { list: null, overlay: "", background: "", scale: 0 };
288
+
289
+ /** Hint overlay contents, as a comparable key. */
290
+ function overlayKey() {
291
+ const hints = page.hintsVisible
292
+ ? page.hints.map((hint) => `${hint.label}@${hint.x + hint.scrollX},${hint.y + hint.scrollY}`).join(";")
293
+ : "";
294
+ return hints;
295
+ }
296
+
297
+ function sameRasterInput() {
298
+ if (rasterized.scale !== page.deviceScaleFactor || rasterized.background !== page.backgroundColor) return false;
299
+ if (rasterized.overlay !== overlayKey()) return false;
300
+ if (page.displayList?.items.some((item) => item.fixed)
301
+ && (rasterized.scrollX !== viewport.x || rasterized.scrollY !== viewport.y)) return false;
302
+ if (rasterized.list === page.displayList) return true;
303
+ if (!rasterized.list || !page.displayList || !Bun.deepEquals(rasterized.list.items, page.displayList.items)) return false;
304
+ rasterized.list = page.displayList;
305
+ return true;
306
+ }
307
+
308
+ /** Rasterizes the viewport and hands it to the compositor. */
309
+ function render() {
310
+ const width = Math.max(1, Math.floor(page.width));
311
+ const height = Math.max(1, Math.floor(page.height));
312
+ const region = { x: viewport.x, y: viewport.y, width, height };
313
+ if (lastTile && tileCovers(lastTile, region) && sameRasterInput()) {
314
+ page.needsPaint = false;
315
+ // Only this thread's scroll position changed: tell the compositor.
316
+ if (viewport.x !== syncedScroll.x || viewport.y !== syncedScroll.y) publish(lastTile);
317
+ } else {
318
+ publish(rasterTile(region));
319
+ }
320
+ schedulePrepaint();
321
+ }
322
+
323
+ /** Rasterizes a page rectangle (CSS pixels) into RGBA pixels. */
324
+ function rasterTile(region) {
325
+ const scale = page.deviceScaleFactor;
326
+ const pixelWidth = Math.max(1, Math.round(region.width * scale));
327
+ const pixelHeight = Math.max(1, Math.round(region.height * scale));
328
+ const surface = CanvasKit.MakeSurface(pixelWidth, pixelHeight);
329
+ if (!surface) throw new Error(`Unable to create a ${pixelWidth}x${pixelHeight} CanvasKit surface`);
330
+ const canvas = surface.getCanvas();
331
+ canvas.clear(canvasColor(CanvasKit, page.backgroundColor));
332
+ paintDisplayList(canvas, page.displayList, region, scale);
333
+ drawHints(canvas, region);
334
+ surface.flush();
335
+ const image = surface.makeImageSnapshot();
336
+ const pixels = image.readPixels(0, 0, {
337
+ width: pixelWidth,
338
+ height: pixelHeight,
339
+ colorType: CanvasKit.ColorType.RGBA_8888,
340
+ alphaType: CanvasKit.AlphaType.Unpremul,
341
+ colorSpace: CanvasKit.ColorSpace.SRGB,
342
+ });
343
+ image.delete();
344
+ surface.delete();
345
+ page.needsPaint = false;
346
+ rasterized = {
347
+ list: page.displayList, overlay: overlayKey(), background: page.backgroundColor, scale: page.deviceScaleFactor,
348
+ scrollX: viewport.x, scrollY: viewport.y,
349
+ };
350
+ return {
351
+ pixels,
352
+ pixelWidth,
353
+ pixelHeight,
354
+ x: region.x,
355
+ y: region.y,
356
+ width: region.width,
357
+ height: region.height,
358
+ scale,
359
+ background: backgroundBytes(page.backgroundColor),
360
+ };
361
+ }
362
+
363
+ function publish(tile) {
364
+ lastTile = tile;
365
+ tileSerial++;
366
+ if (viewport.x !== syncedScroll.x || viewport.y !== syncedScroll.y) {
367
+ scrollEpoch++;
368
+ syncedScroll = { x: viewport.x, y: viewport.y };
369
+ }
370
+ onFrame?.({
371
+ tile,
372
+ viewport: { width: page.width, height: page.height },
373
+ content: { width: viewport.contentWidth, height: viewport.contentHeight },
374
+ scroll: { ...syncedScroll },
375
+ scrollEpoch,
376
+ });
377
+ }
378
+
379
+ /** The region the idle prepaint covers: half a viewport above, one below. */
380
+ function prepaintRegion() {
381
+ const width = Math.max(1, Math.floor(page.width));
382
+ const height = Math.max(1, Math.floor(page.height));
383
+ const top = Math.max(0, Math.floor(viewport.y - height / 2));
384
+ const bottom = Math.max(top + height, Math.min(Math.ceil(viewport.contentHeight), Math.ceil(viewport.y + height * 2)));
385
+ return { x: viewport.x, y: top, width, height: bottom - top };
386
+ }
387
+
388
+ function tileCovers(tile, region) {
389
+ return tile && tile.scale === page.deviceScaleFactor
390
+ && tile.x === region.x && tile.width === region.width
391
+ && tile.y <= region.y && tile.y + tile.height >= region.y + region.height;
392
+ }
393
+
394
+ /** After a paint or a compositor scroll, rasterize around the viewport once this thread is idle. */
395
+ function schedulePrepaint() {
396
+ if (!onFrame) return;
397
+ hostClearTimeout(prepaintTimer);
398
+ prepaintTimer = hostSetTimeout(() => {
399
+ prepaintTimer = null;
400
+ // A pending relayout does not stop this: the current layout, even if
401
+ // slightly stale, is better than background where the user scrolled.
402
+ const width = Math.max(1, Math.floor(page.width));
403
+ const height = Math.max(1, Math.floor(page.height));
404
+ // Still covered with a quarter viewport to spare in both directions
405
+ // (as far as the page goes).
406
+ const top = Math.max(0, viewport.y - height / 4);
407
+ const bottom = Math.max(viewport.y + height, Math.min(viewport.contentHeight, viewport.y + height * 1.25));
408
+ if (tileCovers(lastTile, { x: viewport.x, y: top, width, height: bottom - top }) && sameRasterInput()) return;
409
+ publish(rasterTile(prepaintRegion()));
410
+ }, 30);
411
+ }
412
+
413
+ /** A rendering opportunity for DOM changes nobody has asked to see yet. */
414
+ function scheduleFrame() {
415
+ if (!onFrame || frameTimer || page.loading) return;
416
+ frameTimer = hostSetTimeout(() => {
417
+ frameTimer = null;
418
+ refresh();
419
+ }, Math.max(50, lastRebuildMs));
420
+ }
421
+
422
+ /** The viewport as a PNG (base64), cut from the latest tile. */
423
+ async function viewportPng() {
424
+ if (!lastTile) return "";
425
+ const key = `${tileSerial}:${viewport.x}:${viewport.y}`;
426
+ if (encoded.key !== key) {
427
+ const { pixels, width, height } = cropViewport(lastTile, viewport.x, viewport.y, page.width, page.height);
428
+ encoded = { key, png: Buffer.from(await encodeImage(pixels, width, height)).toString("base64") };
429
+ }
430
+ return encoded.png;
431
+ }
432
+
433
+ /** Rasterizes display items intersecting the viewport onto a CanvasKit canvas. */
434
+ const paintFailures = new Set();
435
+
436
+ function paintDisplayList(canvas, displayList, view, scale) {
437
+ if (!displayList) return;
438
+ const pixel = (value) => Math.round(value * scale);
439
+ const deviceRect = (rect) => CanvasKit.XYWHRect(
440
+ pixel(rect.x - view.x), pixel(rect.y - view.y), pixel(rect.width), pixel(rect.height),
441
+ );
442
+ const deviceRRect = (rect, radii) => radii && (radii.x > 0 || radii.y > 0)
443
+ ? CanvasKit.RRectXY(deviceRect(rect), radii.x * scale, radii.y * scale)
444
+ : null;
445
+ // Returns a paint plus a release function that also frees its shader.
446
+ const fillPaint = (item) => {
447
+ const paint = new CanvasKit.Paint();
448
+ const shader = item.gradient ? gradientShader(item.gradient, view, scale) : null;
449
+ if (shader) paint.setShader(shader);
450
+ else paint.setColor(canvasColor(CanvasKit, item.color));
451
+ paint.release = () => {
452
+ shader?.delete();
453
+ paint.delete();
454
+ };
455
+ return paint;
456
+ };
457
+ const drawBox = (rect, radii, paint) => {
458
+ const rounded = deviceRRect(rect, radii);
459
+ if (rounded) canvas.drawRRect(rounded, paint);
460
+ else canvas.drawRect(deviceRect(rect), paint);
461
+ };
462
+ for (const item of visibleItems(displayList, view, viewport)) {
463
+ const saved = item.fixed || item.clipRect || item.opacity < 1 ? canvas.save() : null;
464
+ try {
465
+ if (item.fixed) canvas.translate(viewport.x * scale, viewport.y * scale);
466
+ if (item.clipRect) canvas.clipRect(deviceRect(item.clipRect), CanvasKit.ClipOp.Intersect, true);
467
+ if (item.opacity < 1) {
468
+ const layer = new CanvasKit.Paint();
469
+ layer.setAlphaf(item.opacity);
470
+ canvas.saveLayer(layer, deviceRect(item.bounds));
471
+ layer.delete();
472
+ }
473
+ paintItem(item);
474
+ } catch (error) {
475
+ // One failing item must not take down the page or the browser process.
476
+ if (!paintFailures.has(item.op)) {
477
+ paintFailures.add(item.op);
478
+ process.stderr.write(`paint ${item.op} failed: ${error?.message ?? error}\n`);
479
+ }
480
+ } finally {
481
+ if (saved !== null) canvas.restoreToCount(saved);
482
+ }
483
+ }
484
+
485
+ // Inline SVG: shapes in viewBox units, fitted into the box (xMidYMid meet).
486
+ function drawSvg(item) {
487
+ const { svg, rect } = item;
488
+ const [viewX, viewY, viewWidth, viewHeight] = svg.viewBox ?? [0, 0, rect.width, rect.height];
489
+ const fit = Math.min(rect.width / viewWidth, rect.height / viewHeight);
490
+ const offsetX = (rect.width - viewWidth * fit) / 2;
491
+ const offsetY = (rect.height - viewHeight * fit) / 2;
492
+ canvas.save();
493
+ canvas.clipRect(deviceRect(rect), CanvasKit.ClipOp.Intersect, true);
494
+ canvas.translate((rect.x - view.x + offsetX) * scale, (rect.y - view.y + offsetY) * scale);
495
+ canvas.scale(fit * scale, fit * scale);
496
+ canvas.translate(-viewX, -viewY);
497
+ const paint = new CanvasKit.Paint();
498
+ paint.setAntiAlias(true);
499
+ const colorWithAlpha = (color, alpha) => {
500
+ const value = canvasColor(CanvasKit, color);
501
+ value[3] *= alpha;
502
+ return value;
503
+ };
504
+ for (const shape of svg.shapes) {
505
+ const path = CanvasKit.Path.MakeFromSVGString(shape.d);
506
+ if (!path) continue;
507
+ path.setFillType(shape.fillRule === "evenodd" ? CanvasKit.FillType.EvenOdd : CanvasKit.FillType.Winding);
508
+ const [a, b, c, d, e, f] = shape.matrix;
509
+ canvas.save();
510
+ canvas.concat([a, c, e, b, d, f, 0, 0, 1]);
511
+ if (shape.fill && shape.fillOpacity > 0) {
512
+ paint.setStyle(CanvasKit.PaintStyle.Fill);
513
+ paint.setColor(colorWithAlpha(shape.fill, shape.fillOpacity));
514
+ canvas.drawPath(path, paint);
515
+ }
516
+ if (shape.stroke && shape.strokeOpacity > 0 && shape.strokeWidth > 0) {
517
+ paint.setStyle(CanvasKit.PaintStyle.Stroke);
518
+ paint.setStrokeWidth(shape.strokeWidth);
519
+ paint.setColor(colorWithAlpha(shape.stroke, shape.strokeOpacity));
520
+ canvas.drawPath(path, paint);
521
+ }
522
+ canvas.restore();
523
+ path.delete();
524
+ }
525
+ paint.delete();
526
+ canvas.restore();
527
+ }
528
+
529
+ function paintItem(item) {
530
+ if (item.op === "fillRect") {
531
+ const paint = fillPaint(item);
532
+ drawBox(item.rect, item.radii, paint);
533
+ paint.release();
534
+ } else if (item.op === "border") {
535
+ paintBorder(canvas, item, view, scale);
536
+ } else if (item.op === "drawShadow") {
537
+ const paint = new CanvasKit.Paint();
538
+ paint.setAntiAlias(true);
539
+ paint.setColor(canvasColor(CanvasKit, item.color));
540
+ // Blink converts a CSS blur radius to a Gaussian sigma of blur / 2.
541
+ const filter = item.blur > 0
542
+ ? CanvasKit.MaskFilter.MakeBlur(CanvasKit.BlurStyle.Normal, pixel(item.blur) / 2, true)
543
+ : null;
544
+ if (filter) paint.setMaskFilter(filter);
545
+ canvas.save();
546
+ const clip = deviceRRect(item.clip, item.clipRadii);
547
+ if (clip) canvas.clipRRect(clip, CanvasKit.ClipOp.Difference, true);
548
+ else canvas.clipRect(deviceRect(item.clip), CanvasKit.ClipOp.Difference, true);
549
+ drawBox(item.rect, item.radii, paint);
550
+ canvas.restore();
551
+ filter?.delete();
552
+ paint.delete();
553
+ } else if (item.op === "drawImage") {
554
+ const resource = displayList.images[item.image];
555
+ canvas.save();
556
+ const clip = deviceRRect(item.rect, item.radii);
557
+ if (clip) canvas.clipRRect(clip, CanvasKit.ClipOp.Intersect, true);
558
+ canvas.drawImageRect(
559
+ resource.image,
560
+ CanvasKit.XYWHRect(0, 0, resource.width, resource.height),
561
+ deviceRect(item.rect),
562
+ null,
563
+ false,
564
+ );
565
+ canvas.restore();
566
+ } else if (item.op === "drawVideo") {
567
+ const resource = displayList.images[item.image];
568
+ const rect = deviceRect(item.rect);
569
+ const paint = new CanvasKit.Paint();
570
+ canvas.save();
571
+ canvas.clipRect(rect, CanvasKit.ClipOp.Intersect, true);
572
+ paint.setColor(CanvasKit.Color(0, 0, 0, 1));
573
+ canvas.drawRect(rect, paint);
574
+ if (resource?.image) {
575
+ canvas.drawImageRect(resource.image,
576
+ CanvasKit.XYWHRect(0, 0, resource.bitmapWidth ?? resource.width, resource.bitmapHeight ?? resource.height),
577
+ rect, null, false);
578
+ }
579
+ const centerX = rect[0] + (rect[2] - rect[0]) / 2;
580
+ const centerY = rect[1] + (rect[3] - rect[1]) / 2;
581
+ paint.setColor(CanvasKit.Color(0, 0, 0, 0.65));
582
+ if (!resource?.playing) {
583
+ canvas.drawCircle(centerX, centerY, 22 * scale, paint);
584
+ paint.setColor(CanvasKit.Color(255, 255, 255, 1));
585
+ const path = CanvasKit.Path.MakeFromSVGString(
586
+ `M ${centerX - 6 * scale} ${centerY - 10 * scale} L ${centerX + 11 * scale} ${centerY} L ${centerX - 6 * scale} ${centerY + 10 * scale} Z`);
587
+ if (path) { canvas.drawPath(path, paint); path.delete(); }
588
+ } else {
589
+ const bar = CanvasKit.XYWHRect(rect[0], rect[3] - 24 * scale, rect[2] - rect[0], 24 * scale);
590
+ canvas.drawRect(bar, paint);
591
+ paint.setColor(CanvasKit.Color(255, 255, 255, 1));
592
+ canvas.drawRect(CanvasKit.XYWHRect(rect[0] + 10 * scale, rect[3] - 18 * scale, 4 * scale, 12 * scale), paint);
593
+ canvas.drawRect(CanvasKit.XYWHRect(rect[0] + 17 * scale, rect[3] - 18 * scale, 4 * scale, 12 * scale), paint);
594
+ }
595
+ canvas.restore();
596
+ paint.delete();
597
+ } else if (item.op === "drawSvg") {
598
+ drawSvg(item);
599
+ } else if (item.op === "drawText") {
600
+ const textStyle = {
601
+ color: item.color, fontSize: item.font.size, fontWeight: item.font.weight, fontFamily: item.font.family,
602
+ decoration: item.decoration,
603
+ };
604
+ const paragraph = makeParagraph(item.text, textStyle, undefined, scale);
605
+ paragraph.layout(pixel(Math.max(1, view.width + view.x - item.x)));
606
+ if (item.gradient) {
607
+ // background-clip:text: draw glyphs, then keep the gradient only where they are.
608
+ canvas.saveLayer(null, deviceRect(item.bounds));
609
+ canvas.drawParagraph(paragraph, pixel(item.x - view.x), pixel(item.y - view.y));
610
+ const paint = fillPaint(item);
611
+ paint.setBlendMode(CanvasKit.BlendMode.SrcIn);
612
+ canvas.drawRect(deviceRect(item.bounds), paint);
613
+ paint.release();
614
+ canvas.restore();
615
+ } else {
616
+ canvas.drawParagraph(paragraph, pixel(item.x - view.x), pixel(item.y - view.y));
617
+ }
618
+ paragraph.delete();
619
+ }
620
+ }
621
+ }
622
+
623
+ /**
624
+ * Paints a border as the ring between the outer and inner rounded rects.
625
+ * Differently coloured sides are each clipped to the trapezoid running from
626
+ * the outer to the inner corners, so a single side follows the corner curve.
627
+ * Every style is currently painted solid.
628
+ */
629
+ function paintBorder(canvas, item, view, scale) {
630
+ const [top, right, bottom, left] = item.widths.map((width) => width * scale);
631
+ const X0 = (item.rect.x - view.x) * scale;
632
+ const Y0 = (item.rect.y - view.y) * scale;
633
+ const X1 = X0 + item.rect.width * scale;
634
+ const Y1 = Y0 + item.rect.height * scale;
635
+ const rx = item.radii.x * scale;
636
+ const ry = item.radii.y * scale;
637
+ const [x0, y0, x1, y1] = [X0 + left, Y0 + top, Math.max(X0 + left, X1 - right), Math.max(Y0 + top, Y1 - bottom)];
638
+ const outer = Float32Array.of(X0, Y0, X1, Y1, rx, ry, rx, ry, rx, ry, rx, ry);
639
+ const inner = Float32Array.of(x0, y0, x1, y1,
640
+ Math.max(0, rx - left), Math.max(0, ry - top), Math.max(0, rx - right), Math.max(0, ry - top),
641
+ Math.max(0, rx - right), Math.max(0, ry - bottom), Math.max(0, rx - left), Math.max(0, ry - bottom));
642
+ const sides = [
643
+ [X0, Y0, X1, Y0, x1, y0, x0, y0],
644
+ [X1, Y0, X1, Y1, x1, y1, x1, y0],
645
+ [X1, Y1, X0, Y1, x0, y1, x1, y1],
646
+ [X0, Y1, X0, Y0, x0, y0, x0, y1],
647
+ ];
648
+ const uniform = item.colors.every((color, index) =>
649
+ color === item.colors[0] && (item.widths[index] > 0) === (item.widths[0] > 0));
650
+ const paint = new CanvasKit.Paint();
651
+ paint.setAntiAlias(true);
652
+ if (uniform) {
653
+ paint.setColor(canvasColor(CanvasKit, item.colors[0]));
654
+ canvas.drawDRRect(outer, inner, paint);
655
+ } else {
656
+ sides.forEach((points, index) => {
657
+ if (!(item.widths[index] > 0)) return;
658
+ // CanvasKit paths are immutable; build the trapezoid with a PathBuilder.
659
+ const builder = new CanvasKit.PathBuilder();
660
+ builder.addPolygon(Float32Array.from(points), true);
661
+ const path = builder.detachAndDelete();
662
+ canvas.save();
663
+ canvas.clipPath(path, CanvasKit.ClipOp.Intersect, true);
664
+ paint.setColor(canvasColor(CanvasKit, item.colors[index]));
665
+ canvas.drawDRRect(outer, inner, paint);
666
+ canvas.restore();
667
+ path.delete();
668
+ });
669
+ }
670
+ paint.delete();
671
+ }
672
+
673
+ function gradientShader(gradient, view, scale) {
674
+ const colors = gradient.stops.map((stop) => canvasColor(CanvasKit, stop.color));
675
+ const offsets = gradient.stops.map((stop) => stop.offset);
676
+ const mode = gradient.repeating ? CanvasKit.TileMode.Repeat : CanvasKit.TileMode.Clamp;
677
+ // Interpolate in premultiplied space like CSS, so fades to transparent stay clean.
678
+ const premul = 1;
679
+ const point = (x, y) => [(x - view.x) * scale, (y - view.y) * scale];
680
+ if (gradient.type === "linear") {
681
+ return CanvasKit.Shader.MakeLinearGradient(
682
+ point(gradient.x0, gradient.y0), point(gradient.x1, gradient.y1),
683
+ colors, offsets, mode, null, premul,
684
+ );
685
+ }
686
+ const [cx, cy] = point(gradient.cx, gradient.cy);
687
+ const ellipse = CanvasKit.Matrix.multiply(
688
+ CanvasKit.Matrix.translated(cx, cy),
689
+ CanvasKit.Matrix.scaled(1, gradient.ry / gradient.rx),
690
+ CanvasKit.Matrix.translated(-cx, -cy),
691
+ );
692
+ return CanvasKit.Shader.MakeRadialGradient([cx, cy], gradient.rx * scale, colors, offsets, mode, ellipse, premul);
693
+ }
694
+
695
+ // Overlays are placed in page coordinates (viewport position plus the
696
+ // scroll offset when they were created), so they stay on their element.
697
+ function drawHints(canvas, region) {
698
+ if (!page.hintsVisible) return;
699
+ const paint = new CanvasKit.Paint();
700
+ paint.setColor(CanvasKit.Color(255, 238, 0, 1));
701
+ for (const hint of page.hints) {
702
+ const x = hint.x + hint.scrollX - region.x;
703
+ const y = hint.y + hint.scrollY - region.y;
704
+ canvas.drawRect(CanvasKit.XYWHRect(
705
+ x * page.deviceScaleFactor,
706
+ y * page.deviceScaleFactor,
707
+ Math.max(18, hint.label.length * 10) * page.deviceScaleFactor,
708
+ 18 * page.deviceScaleFactor,
709
+ ), paint);
710
+ const builder = CanvasKit.ParagraphBuilder.MakeFromFontCollection(new CanvasKit.ParagraphStyle({
711
+ textStyle: {
712
+ color: CanvasKit.BLACK,
713
+ fontFamilies,
714
+ fontSize: 13 * page.deviceScaleFactor,
715
+ },
716
+ maxLines: 1,
717
+ }), fontCollection);
718
+ builder.addText(hint.label.toUpperCase());
719
+ const paragraph = builder.build();
720
+ builder.delete();
721
+ paragraph.layout(30 * page.deviceScaleFactor);
722
+ canvas.drawParagraph(
723
+ paragraph,
724
+ (x + 2) * page.deviceScaleFactor,
725
+ y * page.deviceScaleFactor,
726
+ );
727
+ paragraph.delete();
728
+ }
729
+ paint.delete();
730
+ }
731
+
732
+ function replaceDocument(html, url, styleSheets = [], imageResources = emptyImageResources()) {
733
+ replaceParsedDocument(parseHTMLDocument(html, url), styleSheets, imageResources);
734
+ }
735
+
736
+ function replaceParsedDocument(parsed, styleSheets = [], imageResources = emptyImageResources()) {
737
+ disposeVideos();
738
+ page.realm?.dispose();
739
+ page.realm = null;
740
+ page.window?.happyDOM?.abort?.();
741
+ for (const image of page.decodedImages) image.delete();
742
+ page.window = parsed.window;
743
+ page.document = parsed.document;
744
+ page.title = parsed.document.title;
745
+ page.styleSheets = styleSheets;
746
+ page.resources = imageResources.map;
747
+ initializeVideos(parsed.document, page.resources);
748
+ page.decodedImages = imageResources.decoded;
749
+ imageRequests = new WeakMap();
750
+ const timing = styleAndLayout();
751
+ trace?.(`${page.url}: first style ${timing.style}ms, layout ${timing.layout}ms`);
752
+ viewport.scrollTo(0, 0);
753
+ viewport.setContentSize(page.layout.width, page.layout.height);
754
+ page.hints = [];
755
+ page.hintsVisible = false;
756
+ page.needsPaint = true;
757
+ }
758
+
759
+ /** Style, render tree, layout and display list of the current document. */
760
+ function styleAndLayout() {
761
+ const started = hostPerformance.now();
762
+ styleEngine.compute(page.document, page.styleSheets, { width: page.width, height: page.height, mobile });
763
+ page.backgroundColor = documentBackground(page.document, styleEngine);
764
+ page.renderTree = renderTreeBuilder.build(page.document, styleEngine, page.resources);
765
+ const styled = hostPerformance.now();
766
+ page.layout = layoutText(page.renderTree, {
767
+ measureText, fontMetrics, width: page.width, viewportHeight: page.height, x: 0, y: 0,
768
+ });
769
+ page.displayList = buildDisplayList(page.layout, page.renderTree);
770
+ viewport.setContentSize(page.layout.width, page.layout.height);
771
+ return { style: Math.round(styled - started), layout: Math.round(hostPerformance.now() - styled) };
772
+ }
773
+
774
+ function rebuildRenderTree(reason = "update") {
775
+ const started = hostPerformance.now();
776
+ page.dirty = false;
777
+ page.needsPaint = true;
778
+ page.title = page.document?.title ?? page.title;
779
+ const timing = styleAndLayout();
780
+ lastRebuildMs = hostPerformance.now() - started;
781
+ trace?.(`${page.url}: restyle and relayout (${reason}) ${Math.round(lastRebuildMs)}ms`
782
+ + ` (style ${timing.style}ms, layout ${timing.layout}ms)`);
783
+ }
784
+
785
+ // Each loadDocument starts a generation; stages of a superseded load stop.
786
+ let loadGeneration = 0;
787
+ let loaded = Promise.resolve();
788
+ let imageRequests = new WeakMap();
789
+
790
+ /**
791
+ * Commits a document the controller fetched. `response` carries the body
792
+ * text and metadata, or `error` when the network request failed. Resolves
793
+ * with the load's generation at the first paint (a preview or the styled
794
+ * page); the rest of the load continues, see `whenLoaded`.
795
+ */
796
+ function loadDocument(document) {
797
+ const generation = ++loadGeneration;
798
+ let commit;
799
+ const committed = new Promise((resolve, reject) => {
800
+ commit = { resolve: () => resolve(generation), reject };
801
+ });
802
+ page.loading = true;
803
+ loaded = runLoad(document, generation, commit)
804
+ .catch((error) => {
805
+ commit.reject(error);
806
+ if (generation === loadGeneration) reportError(error);
807
+ })
808
+ .finally(() => {
809
+ commit.resolve();
810
+ if (generation === loadGeneration) page.loading = false;
811
+ });
812
+ return committed;
813
+ }
814
+
815
+ async function runLoad({
816
+ url, source = "", contentType = "text/html", status = 200, statusText = "", error = null, cookie = "",
817
+ }, generation, commit) {
818
+ const current = () => generation === loadGeneration;
819
+ const finish = () => {
820
+ page.loading = false;
821
+ onLifecycle?.("DOMContentLoaded", generation);
822
+ onLifecycle?.("load", generation);
823
+ };
824
+ page.url = url;
825
+ page.cookie = typeof cookie === "string" ? cookie : "";
826
+ if (error) {
827
+ replaceDocument("", url);
828
+ page.title = "Network error";
829
+ page.document.body.textContent = error;
830
+ rebuildRenderTree();
831
+ render();
832
+ commit.resolve();
833
+ finish();
834
+ return;
835
+ }
836
+ if (url === "about:blank") {
837
+ replaceDocument("", url);
838
+ render();
839
+ commit.resolve();
840
+ finish();
841
+ return;
842
+ }
843
+ let phaseStart = hostPerformance.now();
844
+ const phase = trace ? (name) => {
845
+ const now = hostPerformance.now();
846
+ trace(`${url}: ${name} ${Math.round(now - phaseStart)}ms`);
847
+ phaseStart = now;
848
+ } : () => {};
849
+ const isHtml = contentType.toLowerCase().includes("html");
850
+ const parsed = parseHTMLDocument(isHtml ? source : "<body></body>", url);
851
+ phase("parse");
852
+ const resources = isHtml
853
+ ? Promise.all([loadStyleSheets(parsed.document, url), loadImageResources(parsed.document, url)])
854
+ : Promise.resolve([[], emptyImageResources()]);
855
+ let timer;
856
+ let ready = await Promise.race([
857
+ resources,
858
+ new Promise((resolve) => (timer = hostSetTimeout(resolve, PREVIEW_DELAY_MS, null))),
859
+ ]);
860
+ hostClearTimeout(timer);
861
+ if (!current()) return discard(resources, parsed);
862
+ if (!ready) {
863
+ // Subresources are slow: show the document with the user-agent
864
+ // defaults and its inline <style> sheets meanwhile.
865
+ replaceParsedDocument(parsed, inlineStyleSheets(parsed.document), emptyImageResources());
866
+ render();
867
+ phase("preview");
868
+ commit.resolve();
869
+ ready = await resources;
870
+ if (!current()) return discard(resources);
871
+ phase(`${ready[0].length} stylesheets and ${ready[1].decoded.length} images`);
872
+ // Same document, now styled; the scroll position is kept.
873
+ for (const image of page.decodedImages) image.delete();
874
+ page.styleSheets = ready[0];
875
+ page.resources = ready[1].map;
876
+ initializeVideos(page.document, page.resources);
877
+ page.decodedImages = ready[1].decoded;
878
+ imageRequests = new WeakMap();
879
+ rebuildRenderTree("stylesheets loaded");
880
+ } else {
881
+ phase(`${ready[0].length} stylesheets and ${ready[1].decoded.length} images`);
882
+ replaceParsedDocument(parsed, ready[0], ready[1]);
883
+ }
884
+ phase("style and layout");
885
+ if (!isHtml) {
886
+ page.document.body.textContent = source;
887
+ rebuildRenderTree();
888
+ }
889
+ if (status < 200 || status > 299) {
890
+ page.document.body.textContent = `HTTP ${status} ${statusText}\n${page.document.body.textContent}`;
891
+ rebuildRenderTree();
892
+ }
893
+ render();
894
+ phase("raster");
895
+ commit.resolve();
896
+ if (isHtml && page.scripting !== "off") {
897
+ page.realm = createPageRealm({
898
+ window: page.window,
899
+ document: page.document,
900
+ mode: page.scripting,
901
+ hooks: realmHooks(generation),
902
+ });
903
+ await page.realm.runDocumentScripts();
904
+ if (!current()) return;
905
+ phase("scripts");
906
+ page.loading = false;
907
+ refresh();
908
+ void hydrateGitHubBranchInfo(generation);
909
+ phase("style, layout and raster after scripts");
910
+ } else {
911
+ finish();
912
+ }
913
+ }
914
+
915
+ /** Frees what a superseded load fetched. */
916
+ async function discard(resources, parsed = null) {
917
+ parsed?.window?.happyDOM?.abort?.();
918
+ const [, images] = await resources.catch(() => [[], emptyImageResources()]);
919
+ for (const image of images.decoded) image.delete();
920
+ }
921
+
922
+ function inlineStyleSheets(document) {
923
+ return [...document.querySelectorAll("style")].map((element) => element.textContent ?? "");
924
+ }
925
+
926
+ /** Brings style, layout and raster up to date; returns whether it repainted. */
927
+ function refresh() {
928
+ if (page.dirty) {
929
+ initializeVideos(page.document, page.resources);
930
+ const staleImages = queueImageResources();
931
+ rebuildRenderTree();
932
+ for (const image of staleImages) {
933
+ const index = page.decodedImages.indexOf(image);
934
+ if (index >= 0) page.decodedImages.splice(index, 1);
935
+ image.delete();
936
+ }
937
+ }
938
+ if (!page.needsPaint) return false;
939
+ render();
940
+ return true;
941
+ }
942
+
943
+ function editFocusedText(text, backspace = false) {
944
+ const element = page.document.activeElement;
945
+ if (!element || !["INPUT", "TEXTAREA"].includes(element.tagName) || element.disabled || element.readOnly) return;
946
+ if (element.tagName === "INPUT" && !["text", "search", "url", "email", "tel", "password"].includes(element.type)) return;
947
+ const value = String(element.value ?? "");
948
+ let start = Number.isInteger(element.selectionStart) ? element.selectionStart : value.length;
949
+ const end = Number.isInteger(element.selectionEnd) ? element.selectionEnd : start;
950
+ if (backspace && start === end && start > 0) start = [...value.slice(0, start)].slice(0, -1).join("").length;
951
+ if (backspace && start === end) return;
952
+ if (page.realm) {
953
+ const prevented = page.realm.dispatch(element, new page.window.InputEvent("beforeinput", {
954
+ bubbles: true, cancelable: true, data: backspace ? null : text,
955
+ inputType: backspace ? "deleteContentBackward" : "insertText",
956
+ }));
957
+ if (prevented) return;
958
+ }
959
+ element.value = value.slice(0, start) + text + value.slice(end);
960
+ element.setSelectionRange?.(start + text.length, start + text.length);
961
+ if (page.realm) page.realm.dispatch(element, new page.window.Event("input", { bubbles: true }));
962
+ page.dirty = true;
963
+ }
964
+
965
+ function realmHooks(generation) {
966
+ return {
967
+ touch() {
968
+ page.dirty = true;
969
+ scheduleFrame();
970
+ },
971
+ playVideo,
972
+ pauseVideo,
973
+ videoState,
974
+ lifecycle(name) {
975
+ if (generation === loadGeneration) onLifecycle?.(name, generation);
976
+ },
977
+ afterTask() {},
978
+ boundsOf(element) {
979
+ if (page.dirty) rebuildRenderTree("script read geometry");
980
+ return viewportBounds(element);
981
+ },
982
+ viewport: () => ({
983
+ width: page.width,
984
+ height: page.height,
985
+ scrollX: viewport.x,
986
+ scrollY: viewport.y,
987
+ devicePixelRatio: page.deviceScaleFactor,
988
+ pageScale: page.pageScale,
989
+ mobile,
990
+ }),
991
+ scrollTo(x, y) {
992
+ if (page.dirty) rebuildRenderTree("script scrolled");
993
+ if (viewport.scrollTo(x, y)) render();
994
+ },
995
+ computedStyle(element) {
996
+ if (!element) return null;
997
+ if (page.dirty) rebuildRenderTree("getComputedStyle");
998
+ return styleEngine.get(element);
999
+ },
1000
+ navigate: (url) => requestNavigation(String(url)),
1001
+ async fetchScript(url) {
1002
+ const response = await fetchResource(url, "script");
1003
+ if (!response.ok) throw new Error(`script ${url} failed with HTTP ${response.status}`);
1004
+ return new TextDecoder().decode(response.body);
1005
+ },
1006
+ reportError,
1007
+ consoleMessage,
1008
+ userAgent: () => page.userAgent,
1009
+ documentCookie: () => page.cookie,
1010
+ setDocumentCookie(value) {
1011
+ page.cookie = mergeDocumentCookie(page.cookie, String(value));
1012
+ setCookie(String(value));
1013
+ },
1014
+ webSockets,
1015
+ async pageFetch(request) {
1016
+ const response = await pageFetch(request);
1017
+ if (typeof response.documentCookie === "string") page.cookie = response.documentCookie;
1018
+ return response;
1019
+ },
1020
+ };
1021
+ }
1022
+
1023
+ /** The border box of an element's layout box in viewport coordinates. */
1024
+ function viewportBounds(element) {
1025
+ let fixed = false;
1026
+ for (let ancestor = element; ancestor && ancestor.nodeType === 1; ancestor = ancestor.parentElement) {
1027
+ if (styleEngine.get(ancestor)?.position === "fixed") { fixed = true; break; }
1028
+ }
1029
+ const scrollX = fixed ? 0 : viewport.x;
1030
+ const scrollY = fixed ? 0 : viewport.y;
1031
+ let nodeId = null;
1032
+ for (const node of page.renderTree.nodesById.values()) {
1033
+ if (node.domNode === element && !node.pseudo) {
1034
+ nodeId = node.id;
1035
+ break;
1036
+ }
1037
+ }
1038
+ const box = nodeId == null ? null : page.layout.boxes.find((candidate) => candidate.nodeId === nodeId && !candidate.inline);
1039
+ if (box) return { left: box.x - scrollX, top: box.y - scrollY, width: box.width, height: box.height };
1040
+ const content = elementBounds(page.renderTree, page.layout, element);
1041
+ return content
1042
+ ? { left: content.left - scrollX, top: content.top - scrollY, width: content.width, height: content.height }
1043
+ : null;
1044
+ }
1045
+
1046
+ /**
1047
+ * Scrolls to the fragment's target (HTML §7.4.6.4); returns whether one
1048
+ * was found. `prefix` looks for "<prefix><fragment>" instead.
1049
+ */
1050
+ function scrollToFragment(href, prefix = "") {
1051
+ const url = new URL(href);
1052
+ if (!url.hash || url.hash === "#") {
1053
+ viewport.scrollTo(0, 0);
1054
+ return true;
1055
+ }
1056
+ let identifier;
1057
+ try {
1058
+ identifier = prefix + decodeURIComponent(url.hash.slice(1));
1059
+ } catch {
1060
+ identifier = prefix + url.hash.slice(1);
1061
+ }
1062
+ const target = page.document.getElementById(identifier)
1063
+ ?? [...page.document.getElementsByTagName("a")]
1064
+ .find((element) => element.getAttribute("name") === identifier);
1065
+ const bounds = target && elementBounds(page.renderTree, page.layout, target);
1066
+ if (bounds) viewport.scrollTo(viewport.x, bounds.top);
1067
+ return Boolean(target);
1068
+ }
1069
+
1070
+ function collectHints() {
1071
+ const chars = ["a", "s", "d", "f", "j", "k", "l"];
1072
+ const regions = interactiveRegions(page.renderTree, page.layout, viewport, viewport).slice(0, 49);
1073
+ const labels = regions.length <= chars.length
1074
+ ? chars
1075
+ : chars.flatMap((first) => chars.map((second) => first + second));
1076
+ page.hints = regions.map((region, index) => {
1077
+ const rect = region.rects[0];
1078
+ const id = String(index);
1079
+ region.element.setAttribute("data-casty-hint-id", id);
1080
+ return {
1081
+ id,
1082
+ label: labels[index],
1083
+ type: ["INPUT", "TEXTAREA", "SELECT"].includes(region.element.tagName) ? "focus" : "click",
1084
+ x: Math.round(Math.max(0, rect.left)),
1085
+ y: Math.round(Math.max(0, rect.top)),
1086
+ scrollX: viewport.x,
1087
+ scrollY: viewport.y,
1088
+ cx: Math.round((rect.left + rect.right) / 2),
1089
+ cy: Math.round((rect.top + rect.bottom) / 2),
1090
+ element: region.element,
1091
+ };
1092
+ });
1093
+ page.hintsVisible = true;
1094
+ render();
1095
+ return page.hints.map(({ element, scrollX, scrollY, ...hint }) => hint);
1096
+ }
1097
+
1098
+ function clearHints() {
1099
+ for (const hint of page.hints) hint.element.removeAttribute("data-casty-hint-id");
1100
+ page.hints = [];
1101
+ page.hintsVisible = false;
1102
+ render();
1103
+ }
1104
+
1105
+ const api = {
1106
+ loadDocument,
1107
+ /** Enables page scripts once the sandbox is ready: "ses", "host", or "off". */
1108
+ setScripting(mode) {
1109
+ page.scripting = ["ses", "host"].includes(mode) ? mode : "off";
1110
+ },
1111
+ setUserAgent(userAgent) {
1112
+ if (typeof userAgent === "string" && userAgent) page.userAgent = userAgent;
1113
+ },
1114
+ /** Messages the page logged, for diagnostics. */
1115
+ consoleMessages() {
1116
+ return page.realm?.console ?? [];
1117
+ },
1118
+ /** Same-document navigation: keep the document, move to the fragment. */
1119
+ async showFragment(url) {
1120
+ page.url = url;
1121
+ const found = scrollToFragment(url);
1122
+ // Pages that map fragments to their own targets scroll from a hashchange
1123
+ // listener. Rendered Markdown (GitHub, Gitea) prefixes heading ids with
1124
+ // "user-content-" and relies on such a script; if the page did not
1125
+ // scroll, go to that target instead.
1126
+ const before = viewport.y;
1127
+ await page.realm?.navigateToFragment(url);
1128
+ if (!found && viewport.y === before) scrollToFragment(url, "user-content-");
1129
+ render();
1130
+ },
1131
+ url() {
1132
+ return page.url;
1133
+ },
1134
+ scrollTo(x, y) {
1135
+ if (viewport.scrollTo(x, y)) render();
1136
+ return { x: viewport.x, y: viewport.y };
1137
+ },
1138
+ /**
1139
+ * `pageScale` is how much the client's viewport coordinates are scaled up
1140
+ * from the page's (--mobile on a wide viewport); pages read it as
1141
+ * visualViewport.scale.
1142
+ */
1143
+ resize(width, height, deviceScaleFactor = 1, pageScale = 1) {
1144
+ page.pageScale = Number.isFinite(pageScale) && pageScale > 0 ? pageScale : 1;
1145
+ page.width = width;
1146
+ page.height = height;
1147
+ page.deviceScaleFactor = Number.isFinite(deviceScaleFactor) && deviceScaleFactor > 0
1148
+ ? deviceScaleFactor
1149
+ : 1;
1150
+ viewport.resize(width, height);
1151
+ rebuildRenderTree();
1152
+ render();
1153
+ },
1154
+ screenshot() {
1155
+ refresh();
1156
+ return viewportPng();
1157
+ },
1158
+ /**
1159
+ * Diagnostics (not exposed over IPC): page-space border boxes and chosen
1160
+ * computed style fields of the elements matching `selector`.
1161
+ */
1162
+ inspect(selector, fields = ["display", "position", "width", "height"], limit = 20) {
1163
+ refresh();
1164
+ return [...(page.document?.querySelectorAll(selector) ?? [])].slice(0, limit).map((element) => {
1165
+ const bounds = viewportBounds(element);
1166
+ const style = styleEngine.get(element);
1167
+ return {
1168
+ element: `${element.tagName.toLowerCase()}${element.id ? `#${element.id}` : ""}${
1169
+ element.getAttribute("class") ? `.${element.getAttribute("class").trim().split(/\s+/).slice(0, 2).join(".")}` : ""}`,
1170
+ box: bounds && {
1171
+ x: Math.round(bounds.left + viewport.x), y: Math.round(bounds.top + viewport.y),
1172
+ width: Math.round(bounds.width), height: Math.round(bounds.height),
1173
+ },
1174
+ style: Object.fromEntries(fields.map((field) => [field, style[field]])),
1175
+ };
1176
+ });
1177
+ },
1178
+ /** Diagnostics: the element containing `text` and its ancestors, with boxes and style fields. */
1179
+ ancestry(text, fields = ["display", "width", "position"]) {
1180
+ refresh();
1181
+ const walker = page.document.createTreeWalker(page.document.body, 4);
1182
+ let node = walker.nextNode();
1183
+ while (node && !(node.data.includes(text) && node.parentElement && viewportBounds(node.parentElement))) node = walker.nextNode();
1184
+ const chain = [];
1185
+ for (let element = node?.parentElement; element && chain.length < 25; element = element.parentElement) {
1186
+ const bounds = viewportBounds(element);
1187
+ const style = styleEngine.get(element);
1188
+ chain.push({
1189
+ element: `${element.tagName.toLowerCase()}.${(element.getAttribute("class") ?? "").split(/\s+/).slice(0, 2).join(".")}`,
1190
+ box: bounds && { x: Math.round(bounds.left + viewport.x), width: Math.round(bounds.width) },
1191
+ style: Object.fromEntries(fields.map((field) => [field, style[field]])),
1192
+ });
1193
+ }
1194
+ return chain;
1195
+ },
1196
+ /** Diagnostics (not exposed over IPC): display items whose text contains `text`. */
1197
+ displayItems(text) {
1198
+ refresh();
1199
+ return (page.displayList?.items ?? []).filter((item) => item.text?.includes(text));
1200
+ },
1201
+ /** Diagnostics: display items covering a page point, in paint order, with their elements. */
1202
+ itemsAt(x, y) {
1203
+ refresh();
1204
+ return (page.displayList?.items ?? []).map((item, index) => ({ index, item })).filter(({ item }) =>
1205
+ item.bounds.x <= x && x < item.bounds.x + item.bounds.width && item.bounds.y <= y && y < item.bounds.y + item.bounds.height)
1206
+ .map(({ index, item }) => {
1207
+ const node = page.renderTree?.nodesById.get(item.nodeId);
1208
+ const element = node?.domNode?.nodeType === 1 ? node.domNode : node?.domNode?.parentElement;
1209
+ return { index, op: item.op, color: item.color, text: item.text, bounds: item.bounds,
1210
+ element: element && `${element.tagName.toLowerCase()}.${(element.getAttribute("class") ?? "").split(/\s+/).slice(0, 2).join(".")}` };
1211
+ });
1212
+ },
1213
+ /** Resolves once the current document has fired its load event (or was replaced). */
1214
+ async whenLoaded() {
1215
+ let pending;
1216
+ do {
1217
+ pending = loaded;
1218
+ await pending;
1219
+ } while (pending !== loaded);
1220
+ },
1221
+ /** The compositor scrolled: follow it, and rasterize around the new position when idle. */
1222
+ applyCompositorScroll(x, y) {
1223
+ viewport.scrollTo(x, y);
1224
+ syncedScroll = { x: viewport.x, y: viewport.y };
1225
+ schedulePrepaint();
1226
+ },
1227
+ title() {
1228
+ refresh();
1229
+ // Live value: scripts may have set document.title without touching layout.
1230
+ return page.document?.title || page.title;
1231
+ },
1232
+ scroll(deltaX, deltaY) {
1233
+ if (viewport.scrollBy(deltaX, deltaY)) render();
1234
+ return { x: viewport.x, y: viewport.y };
1235
+ },
1236
+ press(key, options = {}) {
1237
+ refresh();
1238
+ // Pages see keydown/keyup first; preventDefault() cancels the default scroll.
1239
+ if (page.realm) {
1240
+ const target = page.document.activeElement ?? page.document.body;
1241
+ const modifiers = Number(options?.modifiers) || 0;
1242
+ const init = {
1243
+ key: String(key), code: String(options?.code ?? ""), repeat: Boolean(options?.repeat),
1244
+ altKey: Boolean(modifiers & 1), ctrlKey: Boolean(modifiers & 2),
1245
+ metaKey: Boolean(modifiers & 4), shiftKey: Boolean(modifiers & 8),
1246
+ bubbles: true, cancelable: true,
1247
+ };
1248
+ const prevented = page.realm.dispatch(target, new page.window.KeyboardEvent("keydown", init));
1249
+ if (!prevented && !init.ctrlKey && !init.metaKey && !init.altKey) {
1250
+ if (key === "Backspace") editFocusedText("", true);
1251
+ else if (key === "Enter" && target.tagName === "TEXTAREA") editFocusedText("\n");
1252
+ else if (String(key).length === 1) editFocusedText(String(key));
1253
+ }
1254
+ page.realm.dispatch(target, new page.window.KeyboardEvent("keyup", init));
1255
+ if (refresh() || prevented) return { x: viewport.x, y: viewport.y };
1256
+ }
1257
+ const pageStep = Math.max(31, viewport.height - 31);
1258
+ const delta = {
1259
+ ArrowUp: -31,
1260
+ ArrowDown: 31,
1261
+ PageUp: -pageStep,
1262
+ PageDown: pageStep,
1263
+ " ": pageStep,
1264
+ }[key];
1265
+ let changed = false;
1266
+ if (key === "Home") changed = viewport.scrollTo(viewport.x, 0);
1267
+ else if (key === "End") changed = viewport.scrollTo(viewport.x, viewport.contentHeight);
1268
+ else if (delta !== undefined) changed = viewport.scrollBy(0, delta);
1269
+ if (changed) render();
1270
+ return { x: viewport.x, y: viewport.y };
1271
+ },
1272
+ type(text) {
1273
+ editFocusedText(String(text ?? ""));
1274
+ refresh();
1275
+ },
1276
+ scrollOffset() {
1277
+ return { x: viewport.x, y: viewport.y };
1278
+ },
1279
+ /**
1280
+ * Clicks at a viewport point: the page receives a click event first, and
1281
+ * unless it calls preventDefault() a link under the point is returned for
1282
+ * the controller to navigate to.
1283
+ */
1284
+ click(x, y) {
1285
+ refresh();
1286
+ const region = hitTest(page.renderTree, page.layout, x, y, viewport, viewport);
1287
+ if (!region) return null;
1288
+ if (["INPUT", "TEXTAREA", "SELECT", "BUTTON"].includes(region.element.tagName)) {
1289
+ region.element.focus();
1290
+ }
1291
+ if (page.realm) {
1292
+ const event = new page.window.MouseEvent("click", {
1293
+ bubbles: true, cancelable: true, clientX: Number(x), clientY: Number(y), button: 0,
1294
+ });
1295
+ const prevented = page.realm.dispatch(region.element, event);
1296
+ refresh();
1297
+ if (prevented) return null;
1298
+ }
1299
+ if (region.element.tagName === "VIDEO") {
1300
+ const state = page.videos.get(region.element);
1301
+ if (state?.playing) pauseVideo(region.element);
1302
+ else void playVideo(region.element);
1303
+ return null;
1304
+ }
1305
+ const anchor = region.element.closest?.("a[href]");
1306
+ if (!anchor) return null;
1307
+ const href = new URL(anchor.getAttribute("href"), page.url).href;
1308
+ if (href.startsWith("javascript:")) {
1309
+ this.runJavaScriptURL(href);
1310
+ return null;
1311
+ }
1312
+ return href;
1313
+ },
1314
+ /**
1315
+ * Navigating to a javascript: URL runs its percent-decoded source as a
1316
+ * classic script in the current document (HTML §7.4.2.3.4); the page
1317
+ * stays. Nothing runs when scripting is off.
1318
+ */
1319
+ runJavaScriptURL(url) {
1320
+ if (!page.realm || !/^javascript:/i.test(String(url))) return;
1321
+ let source = String(url).slice("javascript:".length);
1322
+ try {
1323
+ source = decodeURIComponent(source);
1324
+ } catch {}
1325
+ page.realm.run(source);
1326
+ refresh();
1327
+ },
1328
+ async evaluate(expression) {
1329
+ const source = expression.trim();
1330
+ const utilityExpression = source.match(
1331
+ /^\(async\(\)=>\{return await \((.*)\)\}\)\(\)$/s,
1332
+ )?.[1]?.trim() ?? source;
1333
+ if (source.includes("const CLICKABLE") && source.includes("data-casty-hint-id")) {
1334
+ return JSON.stringify(collectHints());
1335
+ }
1336
+ if (source.includes("hint target disappeared")) {
1337
+ const id = source.match(/data-casty-hint-id=\"(\d+)\"/)?.[1];
1338
+ const hint = page.hints.find((item) => item.id === id);
1339
+ return hint ? { x: hint.cx, y: hint.cy } : null;
1340
+ }
1341
+ if (source.includes("const overlay") && source.includes("removeAttribute('data-casty-hint-id')")) {
1342
+ clearHints();
1343
+ return undefined;
1344
+ }
1345
+ if (source.includes("__casty_hints") && source.includes("old.remove()")) {
1346
+ page.hintsVisible = false;
1347
+ render();
1348
+ return undefined;
1349
+ }
1350
+ if (source.includes("const el = document.getElementById('__casty_hints')")) {
1351
+ page.hintsVisible = false;
1352
+ render();
1353
+ return undefined;
1354
+ }
1355
+ if (source.includes("label.startsWith(")) return undefined;
1356
+ if (/^(?:\(\)\s*=>\s*)?document\.title$/.test(utilityExpression)) {
1357
+ return page.document?.title ?? "";
1358
+ }
1359
+ if (/^(?:\(\)\s*=>\s*)?document\.body\.textContent$/.test(utilityExpression)) {
1360
+ return page.document?.body?.textContent ?? "";
1361
+ }
1362
+ if (/^(?:\(\)\s*=>\s*)?document\.body\.innerText$/.test(utilityExpression)) {
1363
+ return renderTreeText(page.renderTree);
1364
+ }
1365
+ if (/^(?:\(\)\s*=>\s*)?document\.documentElement\.outerHTML$/.test(utilityExpression)) {
1366
+ return page.document?.documentElement?.outerHTML ?? "";
1367
+ }
1368
+ if (/^(?:\(\)\s*=>\s*)?(?:window\.)?scrollX$/.test(utilityExpression)) return viewport.x;
1369
+ if (/^(?:\(\)\s*=>\s*)?(?:window\.)?scrollY$/.test(utilityExpression)) return viewport.y;
1370
+ // Anything else is page script; only structured-clone-safe results leave the renderer.
1371
+ if (!page.realm) return undefined;
1372
+ let value = page.realm.evaluate(utilityExpression);
1373
+ if (value !== null && typeof value === "object" && typeof value.then === "function") {
1374
+ value = await Promise.race([
1375
+ Promise.resolve(value),
1376
+ new Promise((resolve) => hostSetTimeout(resolve, 5000, undefined)),
1377
+ ]).catch((error) => String(error?.message ?? error));
1378
+ }
1379
+ refresh();
1380
+ return cloneableResult(value);
1381
+ },
1382
+ dispose() {
1383
+ hostClearTimeout(prepaintTimer);
1384
+ hostClearTimeout(frameTimer);
1385
+ page.realm?.dispose();
1386
+ disposeVideos();
1387
+ page.window?.happyDOM?.abort?.();
1388
+ for (const image of page.decodedImages) image.delete();
1389
+ fontCollection.delete();
1390
+ fontProvider.delete();
1391
+ },
1392
+ };
1393
+
1394
+ replaceDocument("", "about:blank");
1395
+ render();
1396
+ return api;
1397
+
1398
+ async function loadStyleSheets(document, documentUrl) {
1399
+ // Fetched in parallel; the cascade keeps document order.
1400
+ const sheets = [...document.querySelectorAll("style, link[rel~='stylesheet']")].map(async (element) => {
1401
+ if (element.tagName === "STYLE") return element.textContent ?? "";
1402
+ const href = element.getAttribute("href");
1403
+ if (!href) return null;
1404
+ try {
1405
+ const response = await fetchResource(new URL(href, documentUrl).href, "stylesheet");
1406
+ return response.ok ? new TextDecoder().decode(response.body) : null;
1407
+ } catch {
1408
+ // A failed stylesheet must not prevent the document itself from loading.
1409
+ return null;
1410
+ }
1411
+ });
1412
+ return (await Promise.all(sheets)).filter((sheet) => sheet !== null);
1413
+ }
1414
+
1415
+ async function loadImageResources(document, documentUrl) {
1416
+ const map = new WeakMap();
1417
+ const decoded = [];
1418
+ await Promise.all([...document.querySelectorAll("img")].map(async (element) => {
1419
+ const src = element.getAttribute("src");
1420
+ if (!src) return;
1421
+ try {
1422
+ const response = await fetchResource(new URL(src, documentUrl).href, "image");
1423
+ if (!response.ok) return;
1424
+ // Untrusted image bytes are decoded here, inside the renderer.
1425
+ const bytes = response.body;
1426
+ const { width, height } = await new Bun.Image(bytes).metadata();
1427
+ const image = CanvasKit.MakeImageFromEncoded(bytes);
1428
+ if (!image) return;
1429
+ const resource = Object.freeze({ width, height, image, url: response.url });
1430
+ map.set(element, resource);
1431
+ decoded.push(image);
1432
+ } catch {
1433
+ // Broken images keep their fallback replaced-element dimensions.
1434
+ }
1435
+ }));
1436
+ return { map, decoded };
1437
+ }
1438
+
1439
+ function initializeVideos(document, resources) {
1440
+ for (const element of document.querySelectorAll("video")) {
1441
+ if (resources.get(element)) continue;
1442
+ const width = Number(element.getAttribute("width")) || 300;
1443
+ const height = Number(element.getAttribute("height")) || 150;
1444
+ resources.set(element, { width, height, bitmapWidth: 0, bitmapHeight: 0,
1445
+ image: null, playing: false, url: "" });
1446
+ }
1447
+ }
1448
+
1449
+ function videoSource(element) {
1450
+ const src = element.getAttribute("src") ?? element.querySelector("source[src]")?.getAttribute("src");
1451
+ try { return src ? new URL(src, page.url).href : null; } catch { return null; }
1452
+ }
1453
+
1454
+ function videoState(element) {
1455
+ const state = page.videos.get(element);
1456
+ return { paused: !state?.playing, currentTime: state?.time ?? 0, duration: state?.duration ?? NaN };
1457
+ }
1458
+
1459
+ function pauseVideo(element) {
1460
+ const state = page.videos.get(element);
1461
+ if (!state) return;
1462
+ if (!state.decoder) {
1463
+ closeVideo(state);
1464
+ page.videos.delete(element);
1465
+ rasterized.list = null;
1466
+ render();
1467
+ return;
1468
+ }
1469
+ state.playing = false;
1470
+ state.resource.playing = false;
1471
+ hostClearTimeout(state.timer);
1472
+ rasterized.list = null;
1473
+ render();
1474
+ }
1475
+
1476
+ async function playVideo(element) {
1477
+ if (!videoDecoder) return;
1478
+ const resource = page.resources.get(element);
1479
+ const url = videoSource(element);
1480
+ if (!resource || !url) return;
1481
+ let state = page.videos.get(element);
1482
+ if (state?.playing) return;
1483
+ if (!state || state.url !== url) {
1484
+ if (state) closeVideo(state);
1485
+ const generation = loadGeneration;
1486
+ state = { element, url, resource, decoder: null, image: null, timer: null, playing: true,
1487
+ time: 0, duration: NaN, generation, document: page.document };
1488
+ page.videos.set(element, state);
1489
+ resource.playing = true;
1490
+ rasterized.list = null;
1491
+ render();
1492
+ try {
1493
+ const response = await fetchResource(url, "video");
1494
+ if (!response.ok) throw new Error(`video ${url} failed with HTTP ${response.status}`);
1495
+ if (generation !== loadGeneration || state.document !== page.document || !state.playing) return;
1496
+ state.decoder = await videoDecoder.decode(response.body, { format: "mp4" });
1497
+ trace?.(`video decoded ${url}: ${state.decoder.width}x${state.decoder.height}`);
1498
+ if (generation !== loadGeneration || state.document !== page.document || !state.playing) {
1499
+ state.decoder.close();
1500
+ return;
1501
+ }
1502
+ const metadata = await videoDecoder.probe(response.body);
1503
+ state.duration = metadata.duration ?? NaN;
1504
+ resource.width = state.decoder.width;
1505
+ resource.height = state.decoder.height;
1506
+ page.dirty = true;
1507
+ refresh();
1508
+ } catch (error) {
1509
+ if (state.document === page.document) reportError(error);
1510
+ closeVideo(state);
1511
+ page.videos.delete(element);
1512
+ resource.playing = false;
1513
+ rasterized.list = null;
1514
+ render();
1515
+ return;
1516
+ }
1517
+ } else {
1518
+ state.playing = true;
1519
+ resource.playing = true;
1520
+ }
1521
+ drawNextVideoFrame(state);
1522
+ }
1523
+
1524
+ function drawNextVideoFrame(state) {
1525
+ if (!state.playing || state.generation !== loadGeneration || state.document !== page.document) return;
1526
+ const started = hostPerformance.now();
1527
+ const width = Math.min(480, state.decoder.width);
1528
+ const height = Math.max(1, Math.round(width * state.decoder.height / state.decoder.width));
1529
+ const pixels = state.decoder.nextFrame(width, height);
1530
+ if (state.time === 0) trace?.(`video first frame ${state.url}: ${pixels?.length ?? 0} bytes`);
1531
+ if (!pixels) {
1532
+ state.playing = false;
1533
+ state.resource.playing = false;
1534
+ rasterized.list = null;
1535
+ render();
1536
+ return;
1537
+ }
1538
+ const image = CanvasKit.MakeImage({ width, height, alphaType: CanvasKit.AlphaType.Unpremul,
1539
+ colorType: CanvasKit.ColorType.RGBA_8888, colorSpace: CanvasKit.ColorSpace.SRGB }, pixels, width * 4);
1540
+ if (!image) return pauseVideo(state.element);
1541
+ const previous = state.image;
1542
+ state.image = image;
1543
+ state.resource.image = image;
1544
+ state.resource.bitmapWidth = width;
1545
+ state.resource.bitmapHeight = height;
1546
+ state.time += 1 / (state.decoder.fps || 30);
1547
+ rasterized.list = null;
1548
+ render();
1549
+ previous?.delete();
1550
+ if (state.playing) state.timer = hostSetTimeout(() => drawNextVideoFrame(state),
1551
+ Math.max(1, 1000 / (state.decoder.fps || 30) - (hostPerformance.now() - started)));
1552
+ }
1553
+
1554
+ function closeVideo(state) {
1555
+ state.playing = false;
1556
+ hostClearTimeout(state.timer);
1557
+ state.decoder?.close();
1558
+ state.image?.delete();
1559
+ state.resource.image = null;
1560
+ state.resource.playing = false;
1561
+ }
1562
+
1563
+ function disposeVideos() {
1564
+ for (const state of page.videos.values()) closeVideo(state);
1565
+ page.videos.clear();
1566
+ }
1567
+
1568
+ async function hydrateGitHubBranchInfo(generation) {
1569
+ if (new URL(page.url).hostname !== "github.com") return;
1570
+ const document = page.document;
1571
+ const bar = document.querySelector('[data-testid="branch-info-bar"]');
1572
+ const embedded = document.querySelector('script[data-target="react-app.embeddedData"]');
1573
+ if (!bar?.querySelector(".Skeleton") || !embedded) return;
1574
+ try {
1575
+ const payload = JSON.parse(embedded.textContent ?? "").payload;
1576
+ const fork = payload?.codeViewLayoutRoute?.repo;
1577
+ const parent = payload?.sidebarAbout?.repo?.parentRepo;
1578
+ const branch = payload?.codeViewRepoRoute?.refInfo;
1579
+ if (!fork?.isFork || !parent?.ownerLogin || !parent?.name || branch?.refType !== "branch") return;
1580
+ const repoUrl = `https://api.github.com/repos/${encodeURIComponent(parent.ownerLogin)}/${encodeURIComponent(parent.name)}`;
1581
+ const compareUrl = `${repoUrl}/compare/HEAD...${encodeURIComponent(fork.ownerLogin)}:${encodeURIComponent(branch.name)}`;
1582
+ const [repoResponse, compareResponse] = await Promise.all([
1583
+ fetchResource(repoUrl, "metadata"), fetchResource(compareUrl, "metadata"),
1584
+ ]);
1585
+ if (!repoResponse.ok || !compareResponse.ok) return;
1586
+ const decoder = new TextDecoder();
1587
+ const defaultBranch = JSON.parse(decoder.decode(repoResponse.body)).default_branch;
1588
+ const comparison = JSON.parse(decoder.decode(compareResponse.body));
1589
+ const ahead = comparison.ahead_by;
1590
+ const behind = comparison.behind_by;
1591
+ if (!defaultBranch || !Number.isInteger(ahead) || !Number.isInteger(behind)) return;
1592
+ if (generation !== loadGeneration || document !== page.document || !bar.querySelector(".Skeleton")) return;
1593
+ const baseName = `${parent.ownerLogin}/${parent.name}:${defaultBranch}`;
1594
+ const status = behind > 0
1595
+ ? `This branch is ${ahead} commits ahead of and ${behind} commits behind ${baseName}.`
1596
+ : `This branch is ${ahead} commits ahead of ${baseName}.`;
1597
+ bar.textContent = status;
1598
+ page.dirty = true;
1599
+ refresh();
1600
+ } catch {
1601
+ // GitHub's own client can still replace the loading placeholder.
1602
+ }
1603
+ }
1604
+
1605
+ function queueImageResources() {
1606
+ const document = page.document;
1607
+ const generation = loadGeneration;
1608
+ const staleImages = [];
1609
+ for (const element of document.querySelectorAll("img")) {
1610
+ const src = element.getAttribute("src");
1611
+ if (!src || imageRequests.get(element) === src) continue;
1612
+ let url;
1613
+ try { url = new URL(src, page.url).href; } catch { continue; }
1614
+ if (page.resources.get(element)?.url === url) {
1615
+ imageRequests.set(element, src);
1616
+ continue;
1617
+ }
1618
+ imageRequests.set(element, src);
1619
+ const oldImage = page.resources.get(element)?.image;
1620
+ if (oldImage) staleImages.push(oldImage);
1621
+ page.resources.delete(element);
1622
+ fetchResource(url, "image").then(async (response) => {
1623
+ if (!response.ok) return;
1624
+ const bytes = response.body;
1625
+ const { width, height } = await new Bun.Image(bytes).metadata();
1626
+ const image = CanvasKit.MakeImageFromEncoded(bytes);
1627
+ if (!image) return;
1628
+ if (generation !== loadGeneration || document !== page.document || element.getAttribute("src") !== src) {
1629
+ image.delete();
1630
+ return;
1631
+ }
1632
+ page.resources.set(element, Object.freeze({ width, height, image, url: response.url }));
1633
+ page.decodedImages.push(image);
1634
+ page.dirty = true;
1635
+ refresh();
1636
+ }).catch(() => {
1637
+ // A failed image retains its fallback replaced-element dimensions.
1638
+ });
1639
+ }
1640
+ return staleImages;
1641
+ }
1642
+ }
1643
+
1644
+ function canvasColor(CanvasKit, value) {
1645
+ const match = /^rgba\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)$/.exec(value);
1646
+ return match
1647
+ ? CanvasKit.Color(Number(match[1]), Number(match[2]), Number(match[3]), Number(match[4]))
1648
+ : CanvasKit.BLACK;
1649
+ }
1650
+
1651
+ /**
1652
+ * Applies a document.cookie assignment to the local copy until the
1653
+ * controller's jar (the authority) reports the next value.
1654
+ */
1655
+ function mergeDocumentCookie(current, assignment) {
1656
+ const [pair, ...attributes] = assignment.split(";");
1657
+ const equals = pair.indexOf("=");
1658
+ if (equals < 1) return current;
1659
+ const name = pair.slice(0, equals).trim();
1660
+ const value = pair.slice(equals + 1).trim();
1661
+ const expired = attributes.some((attribute) => {
1662
+ const [key, argument = ""] = attribute.split("=").map((part) => part.trim().toLowerCase());
1663
+ return (key === "max-age" && Number(argument) <= 0)
1664
+ || (key === "expires" && Date.parse(argument) <= Date.now());
1665
+ });
1666
+ const entries = current ? current.split("; ").filter((entry) => !entry.startsWith(`${name}=`)) : [];
1667
+ if (!expired) entries.push(`${name}=${value}`);
1668
+ return entries.join("; ");
1669
+ }
1670
+
1671
+ /** Page values leave the renderer only as primitives or JSON data. */
1672
+ function cloneableResult(value) {
1673
+ if (value === null || ["string", "number", "boolean", "undefined"].includes(typeof value)) return value;
1674
+ try {
1675
+ return JSON.parse(JSON.stringify(value));
1676
+ } catch {
1677
+ return String(value);
1678
+ }
1679
+ }
1680
+
1681
+ function documentBackground(document, styleEngine) {
1682
+ for (const element of [document.body, document.documentElement]) {
1683
+ const color = element && styleEngine.get(element).backgroundColor;
1684
+ if (color && color !== "rgba(0, 0, 0, 0)") return color;
1685
+ }
1686
+ return "rgba(255, 255, 255, 1)";
1687
+ }
1688
+
1689
+ function emptyImageResources() {
1690
+ return { map: new WeakMap(), decoded: [] };
1691
+ }