@gabrielbryk/arc-devtools-mcp 1.3.0
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.
- package/LICENSE +202 -0
- package/README.md +977 -0
- package/build/src/HeapSnapshotManager.js +148 -0
- package/build/src/McpContext.js +737 -0
- package/build/src/McpPage.js +315 -0
- package/build/src/McpResponse.js +990 -0
- package/build/src/Mutex.js +38 -0
- package/build/src/PageCollector.js +297 -0
- package/build/src/ServiceWorkerCollector.js +171 -0
- package/build/src/SlimMcpResponse.js +19 -0
- package/build/src/TextSnapshot.js +236 -0
- package/build/src/ToolHandler.js +223 -0
- package/build/src/WaitForHelper.js +190 -0
- package/build/src/bin/check-latest-version.js +50 -0
- package/build/src/bin/chrome-devtools-cli-options.js +978 -0
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +412 -0
- package/build/src/bin/chrome-devtools-mcp-main.js +72 -0
- package/build/src/bin/chrome-devtools-mcp.js +23 -0
- package/build/src/bin/chrome-devtools.js +189 -0
- package/build/src/browser.js +253 -0
- package/build/src/daemon/client.js +160 -0
- package/build/src/daemon/daemon.js +261 -0
- package/build/src/daemon/types.js +7 -0
- package/build/src/daemon/utils.js +115 -0
- package/build/src/devtools/DevToolsConnectionAdapter.js +70 -0
- package/build/src/devtools/DevtoolsUtils.js +369 -0
- package/build/src/devtools/McpHostBindingAdapter.js +165 -0
- package/build/src/formatters/ConsoleFormatter.js +288 -0
- package/build/src/formatters/HeapSnapshotFormatter.js +97 -0
- package/build/src/formatters/IssueFormatter.js +193 -0
- package/build/src/formatters/NetworkFormatter.js +238 -0
- package/build/src/formatters/SnapshotFormatter.js +135 -0
- package/build/src/index.js +153 -0
- package/build/src/issue-descriptions.js +40 -0
- package/build/src/logger.js +37 -0
- package/build/src/polyfill.js +8 -0
- package/build/src/telemetry/ClearcutLogger.js +169 -0
- package/build/src/telemetry/WatchdogClient.js +61 -0
- package/build/src/telemetry/errors.js +18 -0
- package/build/src/telemetry/flagUtils.js +89 -0
- package/build/src/telemetry/metricsRegistry.js +89 -0
- package/build/src/telemetry/persistence.js +72 -0
- package/build/src/telemetry/transformation.js +134 -0
- package/build/src/telemetry/types.js +31 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +205 -0
- package/build/src/telemetry/watchdog/main.js +128 -0
- package/build/src/third_party/THIRD_PARTY_NOTICES +3637 -0
- package/build/src/third_party/bundled-packages.json +12 -0
- package/build/src/third_party/devtools-formatter-worker.js +15301 -0
- package/build/src/third_party/devtools-heap-snapshot-worker.js +9870 -0
- package/build/src/third_party/index.js +159597 -0
- package/build/src/third_party/issue-descriptions/CoepCoopSandboxedIframeCannotNavigateToCoopPage.md +4 -0
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +8 -0
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +18 -0
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +7 -0
- package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +10 -0
- package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +5 -0
- package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +5 -0
- package/build/src/third_party/issue-descriptions/LowTextContrast.md +5 -0
- package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +9 -0
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +9 -0
- package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +8 -0
- package/build/src/third_party/issue-descriptions/arInsecureContext.md +7 -0
- package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +5 -0
- package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +6 -0
- package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +5 -0
- package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +4 -0
- package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +18 -0
- package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +19 -0
- package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +8 -0
- package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +9 -0
- package/build/src/third_party/issue-descriptions/arSourceIgnored.md +13 -0
- package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +12 -0
- package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +10 -0
- package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +11 -0
- package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +3 -0
- package/build/src/third_party/issue-descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
- package/build/src/third_party/issue-descriptions/clientHintMetaTagModifiedHTML.md +4 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +12 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +12 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +7 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
- package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +12 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +4 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeDomainNonAscii.md +11 -0
- package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +8 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +7 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutRead.md +6 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +6 -0
- package/build/src/third_party/issue-descriptions/cookieWarnDomainNonAscii.md +11 -0
- package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantRead.md +4 -0
- package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantSet.md +4 -0
- package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +6 -0
- package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutSet.md +6 -0
- package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +6 -0
- package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +7 -0
- package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +7 -0
- package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +5 -0
- package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +7 -0
- package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +19 -0
- package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +5 -0
- package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +5 -0
- package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +6 -0
- package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +5 -0
- package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +5 -0
- package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +8 -0
- package/build/src/third_party/issue-descriptions/cspEvalViolation.md +9 -0
- package/build/src/third_party/issue-descriptions/cspInlineViolation.md +10 -0
- package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +5 -0
- package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +8 -0
- package/build/src/third_party/issue-descriptions/cspURLViolation.md +10 -0
- package/build/src/third_party/issue-descriptions/deprecation.md +3 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsEmptyList.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestInvalidEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidAudience.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidIssuedAt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidNonce.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidSdHash.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidTyp.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingAud.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingCnf.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingIat.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingNonce.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingSdHash.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbSignatureFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmailVerified.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidHolderKey.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuedAt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuer.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtJwksMissingKeys.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingCnf.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIat.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIss.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtSignatureFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtUnsupportedHeaderAlg.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -0
- package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +7 -0
- package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
- package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +8 -0
- package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
- package/build/src/third_party/issue-descriptions/genericResponseWasBlockedByORB.md +4 -0
- package/build/src/third_party/issue-descriptions/heavyAd.md +10 -0
- package/build/src/third_party/issue-descriptions/mixedContent.md +5 -0
- package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +7 -0
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +9 -0
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +9 -0
- package/build/src/third_party/issue-descriptions/permissionElementCspFrameAncestorsMissing.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementGeolocationDeprecated.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementLowContrast.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +6 -0
- package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +6 -0
- package/build/src/third_party/issue-descriptions/permissionElementPermissionsPolicyBlocked.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementRegistrationFailed.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +7 -0
- package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +3 -0
- package/build/src/third_party/issue-descriptions/propertyRuleInvalidNameIssue.md +3 -0
- package/build/src/third_party/issue-descriptions/propertyRuleIssue.md +7 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +7 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +7 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +3 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +3 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +3 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +3 -0
- package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +7 -0
- package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +7 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorDictionaryLoadFailure.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInsufficientResources.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidMatchField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidTTLField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoMatchField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonIntegerTTLField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonListMatchDestField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonSecureContext.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringIdField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringInMatchDestList.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringMatchField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonTokenTypeField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorRequestAborted.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorShuttingDown.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorTooLongIdField.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorUnsupportedType.md +3 -0
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +14 -0
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +15 -0
- package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +8 -0
- package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +7 -0
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +11 -0
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +14 -0
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +15 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +8 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +13 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +4 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +5 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +11 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +12 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +6 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +8 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +11 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +11 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +10 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +5 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +6 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +11 -0
- package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +4 -0
- package/build/src/third_party/issue-descriptions/stylesheetRequestFailed.md +3 -0
- package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +3 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +12 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +17 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +14 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +15 -0
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +61598 -0
- package/build/src/tools/ToolDefinition.js +73 -0
- package/build/src/tools/categories.js +36 -0
- package/build/src/tools/console.js +98 -0
- package/build/src/tools/emulation.js +84 -0
- package/build/src/tools/extensions.js +101 -0
- package/build/src/tools/input.js +469 -0
- package/build/src/tools/lighthouse.js +136 -0
- package/build/src/tools/memory.js +227 -0
- package/build/src/tools/network.js +125 -0
- package/build/src/tools/pages.js +419 -0
- package/build/src/tools/performance.js +200 -0
- package/build/src/tools/screencast.js +117 -0
- package/build/src/tools/screenshot.js +169 -0
- package/build/src/tools/script.js +151 -0
- package/build/src/tools/slim/tools.js +88 -0
- package/build/src/tools/snapshot.js +61 -0
- package/build/src/tools/thirdPartyDeveloper.js +85 -0
- package/build/src/tools/tools.js +56 -0
- package/build/src/tools/webmcp.js +66 -0
- package/build/src/trace-processing/parse.js +85 -0
- package/build/src/types.js +7 -0
- package/build/src/utils/check-for-updates.js +74 -0
- package/build/src/utils/files.js +61 -0
- package/build/src/utils/id.js +16 -0
- package/build/src/utils/keyboard.js +297 -0
- package/build/src/utils/pagination.js +50 -0
- package/build/src/utils/string.js +37 -0
- package/build/src/utils/types.js +7 -0
- package/build/src/version.js +10 -0
- package/package.json +100 -0
- package/skills/a11y-debugging/SKILL.md +89 -0
- package/skills/a11y-debugging/references/a11y-snippets.md +92 -0
- package/skills/chrome-devtools/SKILL.md +72 -0
- package/skills/chrome-devtools-cli/SKILL.md +153 -0
- package/skills/chrome-devtools-cli/references/installation.md +14 -0
- package/skills/debug-optimize-lcp/SKILL.md +121 -0
- package/skills/debug-optimize-lcp/references/elements-and-size.md +27 -0
- package/skills/debug-optimize-lcp/references/lcp-breakdown.md +23 -0
- package/skills/debug-optimize-lcp/references/lcp-snippets.md +79 -0
- package/skills/debug-optimize-lcp/references/optimization-strategies.md +38 -0
- package/skills/memory-leak-debugging/SKILL.md +50 -0
- package/skills/memory-leak-debugging/references/common-leaks.md +33 -0
- package/skills/memory-leak-debugging/references/compare_snapshots.js +109 -0
- package/skills/memory-leak-debugging/references/memlab.md +29 -0
- package/skills/troubleshooting/SKILL.md +98 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google Inc.
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
export class Mutex {
|
|
7
|
+
static Guard = class Guard {
|
|
8
|
+
#mutex;
|
|
9
|
+
constructor(mutex) {
|
|
10
|
+
this.#mutex = mutex;
|
|
11
|
+
}
|
|
12
|
+
dispose() {
|
|
13
|
+
return this.#mutex.release();
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
#locked = false;
|
|
17
|
+
#acquirers = [];
|
|
18
|
+
// This is FIFO.
|
|
19
|
+
async acquire() {
|
|
20
|
+
if (!this.#locked) {
|
|
21
|
+
this.#locked = true;
|
|
22
|
+
return new Mutex.Guard(this);
|
|
23
|
+
}
|
|
24
|
+
const { resolve, promise } = Promise.withResolvers();
|
|
25
|
+
this.#acquirers.push(resolve);
|
|
26
|
+
await promise;
|
|
27
|
+
return new Mutex.Guard(this);
|
|
28
|
+
}
|
|
29
|
+
release() {
|
|
30
|
+
const resolve = this.#acquirers.shift();
|
|
31
|
+
if (!resolve) {
|
|
32
|
+
this.#locked = false;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
resolve();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=Mutex.js.map
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { FakeIssuesManager } from './devtools/DevtoolsUtils.js';
|
|
7
|
+
import { logger } from './logger.js';
|
|
8
|
+
import { DevTools } from './third_party/index.js';
|
|
9
|
+
import { createIdGenerator, stableIdSymbol, } from './utils/id.js';
|
|
10
|
+
export class UncaughtError {
|
|
11
|
+
details;
|
|
12
|
+
targetId;
|
|
13
|
+
constructor(details, targetId) {
|
|
14
|
+
this.details = details;
|
|
15
|
+
this.targetId = targetId;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class PageCollector {
|
|
19
|
+
#browser;
|
|
20
|
+
#listenersInitializer;
|
|
21
|
+
#listeners = new WeakMap();
|
|
22
|
+
maxNavigationSaved = 3;
|
|
23
|
+
/**
|
|
24
|
+
* This maps a Page to a list of navigations with a sub-list
|
|
25
|
+
* of all collected resources.
|
|
26
|
+
* The newer navigations come first.
|
|
27
|
+
*/
|
|
28
|
+
storage = new WeakMap();
|
|
29
|
+
constructor(browser, listeners) {
|
|
30
|
+
this.#browser = browser;
|
|
31
|
+
this.#listenersInitializer = listeners;
|
|
32
|
+
}
|
|
33
|
+
async init(pages) {
|
|
34
|
+
for (const page of pages) {
|
|
35
|
+
this.addPage(page);
|
|
36
|
+
}
|
|
37
|
+
this.#browser.on('targetcreated', this.#onTargetCreated);
|
|
38
|
+
this.#browser.on('targetdestroyed', this.#onTargetDestroyed);
|
|
39
|
+
}
|
|
40
|
+
dispose() {
|
|
41
|
+
this.#browser.off('targetcreated', this.#onTargetCreated);
|
|
42
|
+
this.#browser.off('targetdestroyed', this.#onTargetDestroyed);
|
|
43
|
+
}
|
|
44
|
+
#onTargetCreated = async (target) => {
|
|
45
|
+
try {
|
|
46
|
+
const page = await target.page();
|
|
47
|
+
if (!page) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.addPage(page);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
logger?.('Error getting a page for a target onTargetCreated', err);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
#onTargetDestroyed = async (target) => {
|
|
57
|
+
try {
|
|
58
|
+
const page = await target.page();
|
|
59
|
+
if (!page) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.cleanupPageDestroyed(page);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger?.('Error getting a page for a target onTargetDestroyed', err);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
addPage(page) {
|
|
69
|
+
this.#initializePage(page);
|
|
70
|
+
}
|
|
71
|
+
#initializePage(page) {
|
|
72
|
+
if (this.storage.has(page)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const idGenerator = createIdGenerator();
|
|
76
|
+
const storedLists = [[]];
|
|
77
|
+
this.storage.set(page, storedLists);
|
|
78
|
+
const listeners = this.#listenersInitializer(value => {
|
|
79
|
+
const withId = value;
|
|
80
|
+
withId[stableIdSymbol] = idGenerator();
|
|
81
|
+
const navigations = this.storage.get(page) ?? [[]];
|
|
82
|
+
navigations[0].push(withId);
|
|
83
|
+
});
|
|
84
|
+
listeners['framenavigated'] = (frame) => {
|
|
85
|
+
// Only split the storage on main frame navigation
|
|
86
|
+
if (frame !== page.mainFrame()) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this.splitAfterNavigation(page);
|
|
90
|
+
};
|
|
91
|
+
for (const [name, listener] of Object.entries(listeners)) {
|
|
92
|
+
page.on(name, listener);
|
|
93
|
+
}
|
|
94
|
+
this.#listeners.set(page, listeners);
|
|
95
|
+
}
|
|
96
|
+
splitAfterNavigation(page) {
|
|
97
|
+
const navigations = this.storage.get(page);
|
|
98
|
+
if (!navigations) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Add the latest navigation first
|
|
102
|
+
navigations.unshift([]);
|
|
103
|
+
navigations.splice(this.maxNavigationSaved);
|
|
104
|
+
}
|
|
105
|
+
cleanupPageDestroyed(page) {
|
|
106
|
+
const listeners = this.#listeners.get(page);
|
|
107
|
+
if (listeners) {
|
|
108
|
+
for (const [name, listener] of Object.entries(listeners)) {
|
|
109
|
+
page.off(name, listener);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.storage.delete(page);
|
|
113
|
+
}
|
|
114
|
+
getData(page, includePreservedData) {
|
|
115
|
+
const navigations = this.storage.get(page);
|
|
116
|
+
if (!navigations) {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
if (!includePreservedData) {
|
|
120
|
+
return navigations[0];
|
|
121
|
+
}
|
|
122
|
+
const data = [];
|
|
123
|
+
for (let index = this.maxNavigationSaved; index >= 0; index--) {
|
|
124
|
+
if (navigations[index]) {
|
|
125
|
+
data.push(...navigations[index]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return data;
|
|
129
|
+
}
|
|
130
|
+
getIdForResource(resource) {
|
|
131
|
+
return resource[stableIdSymbol] ?? -1;
|
|
132
|
+
}
|
|
133
|
+
getById(page, stableId) {
|
|
134
|
+
const navigations = this.storage.get(page);
|
|
135
|
+
if (!navigations) {
|
|
136
|
+
throw new Error('No requests found for selected page');
|
|
137
|
+
}
|
|
138
|
+
const item = this.find(page, item => item[stableIdSymbol] === stableId);
|
|
139
|
+
if (!item) {
|
|
140
|
+
throw new Error('Request not found for selected page');
|
|
141
|
+
}
|
|
142
|
+
return item;
|
|
143
|
+
}
|
|
144
|
+
find(page, filter) {
|
|
145
|
+
const navigations = this.storage.get(page);
|
|
146
|
+
if (!navigations) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
for (const navigation of navigations) {
|
|
150
|
+
const item = navigation.find(filter);
|
|
151
|
+
if (item) {
|
|
152
|
+
return item;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export class ConsoleCollector extends PageCollector {
|
|
159
|
+
#subscribedPages = new WeakMap();
|
|
160
|
+
addPage(page) {
|
|
161
|
+
super.addPage(page);
|
|
162
|
+
if (!this.#subscribedPages.has(page)) {
|
|
163
|
+
const subscriber = new PageEventSubscriber(page);
|
|
164
|
+
this.#subscribedPages.set(page, subscriber);
|
|
165
|
+
void subscriber.subscribe();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
cleanupPageDestroyed(page) {
|
|
169
|
+
super.cleanupPageDestroyed(page);
|
|
170
|
+
this.#subscribedPages.get(page)?.unsubscribe();
|
|
171
|
+
this.#subscribedPages.delete(page);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
class PageEventSubscriber {
|
|
175
|
+
#issueManager = new FakeIssuesManager();
|
|
176
|
+
#issueAggregator = new DevTools.IssueAggregator(this.#issueManager);
|
|
177
|
+
#seenKeys = new Set();
|
|
178
|
+
#seenIssues = new Set();
|
|
179
|
+
#page;
|
|
180
|
+
#session;
|
|
181
|
+
#targetId;
|
|
182
|
+
constructor(page) {
|
|
183
|
+
this.#page = page;
|
|
184
|
+
// @ts-expect-error use existing CDP client (internal Puppeteer API).
|
|
185
|
+
this.#session = this.#page._client();
|
|
186
|
+
// @ts-expect-error use internal Puppeteer API to get target ID
|
|
187
|
+
this.#targetId = this.#session.target()._targetId;
|
|
188
|
+
}
|
|
189
|
+
#resetIssueAggregator() {
|
|
190
|
+
this.#issueManager = new FakeIssuesManager();
|
|
191
|
+
if (this.#issueAggregator) {
|
|
192
|
+
this.#issueAggregator.removeEventListener("AggregatedIssueUpdated" /* DevTools.IssueAggregatorEvents.AGGREGATED_ISSUE_UPDATED */, this.#onAggregatedIssue);
|
|
193
|
+
}
|
|
194
|
+
this.#issueAggregator = new DevTools.IssueAggregator(this.#issueManager);
|
|
195
|
+
this.#issueAggregator.addEventListener("AggregatedIssueUpdated" /* DevTools.IssueAggregatorEvents.AGGREGATED_ISSUE_UPDATED */, this.#onAggregatedIssue);
|
|
196
|
+
}
|
|
197
|
+
async subscribe() {
|
|
198
|
+
this.#resetIssueAggregator();
|
|
199
|
+
this.#page.on('framenavigated', this.#onFrameNavigated);
|
|
200
|
+
this.#page.on('issue', this.#onIssueAdded);
|
|
201
|
+
this.#session.on('Runtime.exceptionThrown', this.#onExceptionThrown);
|
|
202
|
+
}
|
|
203
|
+
unsubscribe() {
|
|
204
|
+
this.#seenKeys.clear();
|
|
205
|
+
this.#seenIssues.clear();
|
|
206
|
+
this.#page.off('framenavigated', this.#onFrameNavigated);
|
|
207
|
+
this.#page.off('issue', this.#onIssueAdded);
|
|
208
|
+
this.#session.off('Runtime.exceptionThrown', this.#onExceptionThrown);
|
|
209
|
+
if (this.#issueAggregator) {
|
|
210
|
+
this.#issueAggregator.removeEventListener("AggregatedIssueUpdated" /* DevTools.IssueAggregatorEvents.AGGREGATED_ISSUE_UPDATED */, this.#onAggregatedIssue);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
#onAggregatedIssue = (event) => {
|
|
214
|
+
if (this.#seenIssues.has(event.data)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
this.#seenIssues.add(event.data);
|
|
218
|
+
this.#page.emit('devtoolsAggregatedIssue', event.data);
|
|
219
|
+
};
|
|
220
|
+
#onExceptionThrown = (event) => {
|
|
221
|
+
this.#page.emit('uncaughtError', new UncaughtError(event.exceptionDetails, this.#targetId));
|
|
222
|
+
};
|
|
223
|
+
// On navigation, we reset issue aggregation.
|
|
224
|
+
#onFrameNavigated = (frame) => {
|
|
225
|
+
// Only split the storage on main frame navigation
|
|
226
|
+
if (frame !== frame.page().mainFrame()) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
this.#seenKeys.clear();
|
|
230
|
+
this.#seenIssues.clear();
|
|
231
|
+
this.#resetIssueAggregator();
|
|
232
|
+
};
|
|
233
|
+
#onIssueAdded = (inspectorIssue) => {
|
|
234
|
+
try {
|
|
235
|
+
// DevTools currently defines this protocol issue code but has no
|
|
236
|
+
// IssuesManager handler for it, so calling into the mapper only warns.
|
|
237
|
+
if (String(inspectorIssue.code) === 'PerformanceIssue') {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const issue = DevTools.createIssuesFromProtocolIssue(null,
|
|
241
|
+
// @ts-expect-error Protocol types diverge.
|
|
242
|
+
inspectorIssue)[0];
|
|
243
|
+
if (!issue) {
|
|
244
|
+
logger?.('No issue mapping for for the issue: ', inspectorIssue.code);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const primaryKey = issue.primaryKey();
|
|
248
|
+
if (this.#seenKeys.has(primaryKey)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
this.#seenKeys.add(primaryKey);
|
|
252
|
+
this.#issueManager.dispatchEventToListeners("IssueAdded" /* DevTools.IssuesManagerEvents.ISSUE_ADDED */, {
|
|
253
|
+
issue,
|
|
254
|
+
// @ts-expect-error We don't care that issues model is null
|
|
255
|
+
issuesModel: null,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
logger?.('Error creating a new issue', error);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
export class NetworkCollector extends PageCollector {
|
|
264
|
+
constructor(browser, listeners = collect => {
|
|
265
|
+
return {
|
|
266
|
+
request: req => {
|
|
267
|
+
collect(req);
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}) {
|
|
271
|
+
super(browser, listeners);
|
|
272
|
+
}
|
|
273
|
+
splitAfterNavigation(page) {
|
|
274
|
+
const navigations = this.storage.get(page) ?? [];
|
|
275
|
+
if (!navigations) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const requests = navigations[0];
|
|
279
|
+
const lastRequestIdx = requests.findLastIndex(request => {
|
|
280
|
+
return request.frame() === page.mainFrame()
|
|
281
|
+
? request.isNavigationRequest()
|
|
282
|
+
: false;
|
|
283
|
+
});
|
|
284
|
+
// Keep all requests since the last navigation request including that
|
|
285
|
+
// navigation request itself.
|
|
286
|
+
// Keep the reference
|
|
287
|
+
if (lastRequestIdx !== -1) {
|
|
288
|
+
const fromCurrentNavigation = requests.splice(lastRequestIdx);
|
|
289
|
+
navigations.unshift(fromCurrentNavigation);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
navigations.unshift([]);
|
|
293
|
+
}
|
|
294
|
+
navigations.splice(this.maxNavigationSaved);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=PageCollector.js.map
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { UncaughtError } from './PageCollector.js';
|
|
7
|
+
import { createIdGenerator, stableIdSymbol } from './utils/id.js';
|
|
8
|
+
const CHROME_EXTENSION_PREFIX = 'chrome-extension://';
|
|
9
|
+
export class ServiceWorkerSubscriber {
|
|
10
|
+
#target;
|
|
11
|
+
#callback;
|
|
12
|
+
#session;
|
|
13
|
+
#worker;
|
|
14
|
+
constructor(target, callback) {
|
|
15
|
+
this.#target = target;
|
|
16
|
+
this.#callback = callback;
|
|
17
|
+
}
|
|
18
|
+
async subscribe() {
|
|
19
|
+
this.#session = await this.#target.createCDPSession();
|
|
20
|
+
await this.#session.send('Runtime.enable');
|
|
21
|
+
this.#session.on('Runtime.exceptionThrown', this.#onExceptionThrown);
|
|
22
|
+
this.#worker = (await this.#target.worker()) ?? undefined;
|
|
23
|
+
if (this.#worker) {
|
|
24
|
+
this.#worker.on('console', this.#onConsole);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async unsubscribe() {
|
|
28
|
+
if (this.#worker) {
|
|
29
|
+
this.#worker.off('console', this.#onConsole);
|
|
30
|
+
}
|
|
31
|
+
await this.#session?.detach();
|
|
32
|
+
}
|
|
33
|
+
#onConsole = (message) => {
|
|
34
|
+
this.#callback(message);
|
|
35
|
+
};
|
|
36
|
+
#onExceptionThrown = (event) => {
|
|
37
|
+
const url = this.#target.url();
|
|
38
|
+
const extensionId = extractExtensionId(url);
|
|
39
|
+
if (extensionId) {
|
|
40
|
+
this.#callback(new UncaughtError(event.exceptionDetails, extensionId));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export class ServiceWorkerConsoleCollector {
|
|
45
|
+
#storage = new Map();
|
|
46
|
+
#maxLogs;
|
|
47
|
+
#browser;
|
|
48
|
+
#serviceWorkerSubscribers = new Map();
|
|
49
|
+
#idGenerator = createIdGenerator();
|
|
50
|
+
constructor(browser, maxLogs = 1000) {
|
|
51
|
+
this.#browser = browser;
|
|
52
|
+
this.#maxLogs = maxLogs;
|
|
53
|
+
}
|
|
54
|
+
async init(workers) {
|
|
55
|
+
if (!this.#browser) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.#browser.on('targetcreated', this.#onTargetCreated);
|
|
59
|
+
this.#browser.on('targetdestroyed', this.#onTargetDestroyed);
|
|
60
|
+
for (const worker of workers) {
|
|
61
|
+
void this.#onTargetCreated(worker.target);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
dispose() {
|
|
65
|
+
if (!this.#browser) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.#browser.off('targetcreated', this.#onTargetCreated);
|
|
69
|
+
this.#browser.off('targetdestroyed', this.#onTargetDestroyed);
|
|
70
|
+
for (const subscriber of this.#serviceWorkerSubscribers.values()) {
|
|
71
|
+
subscriber.unsubscribe().catch(err => {
|
|
72
|
+
if (err instanceof Error &&
|
|
73
|
+
!err.message.includes('Target closed') &&
|
|
74
|
+
!err.message.includes('Session closed')) {
|
|
75
|
+
// Swallow error as we are tearing down the system
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
this.#serviceWorkerSubscribers.clear();
|
|
80
|
+
}
|
|
81
|
+
#onTargetCreated = async (target) => {
|
|
82
|
+
if (this.#serviceWorkerSubscribers.has(target)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const origin = target.url();
|
|
86
|
+
if (target.type() === 'service_worker' && isExtensionOrigin(origin)) {
|
|
87
|
+
const extensionId = extractExtensionId(origin);
|
|
88
|
+
if (!extensionId) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const subscriber = new ServiceWorkerSubscriber(target, item => {
|
|
92
|
+
this.addLog(extensionId, item);
|
|
93
|
+
});
|
|
94
|
+
try {
|
|
95
|
+
await subscriber.subscribe();
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
if (err instanceof Error &&
|
|
99
|
+
!err.message.includes('Target closed') &&
|
|
100
|
+
!err.message.includes('Session closed')) {
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
this.#serviceWorkerSubscribers.set(target, subscriber);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
#onTargetDestroyed = async (target) => {
|
|
108
|
+
const subscriber = this.#serviceWorkerSubscribers.get(target);
|
|
109
|
+
if (subscriber) {
|
|
110
|
+
try {
|
|
111
|
+
await subscriber.unsubscribe();
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
if (err instanceof Error &&
|
|
115
|
+
!err.message.includes('Target closed') &&
|
|
116
|
+
!err.message.includes('Session closed')) {
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
this.#serviceWorkerSubscribers.delete(target);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
addLog(extensionId, log) {
|
|
124
|
+
const logs = this.#storage.get(extensionId) ?? [];
|
|
125
|
+
const withId = log;
|
|
126
|
+
withId[stableIdSymbol] = this.#idGenerator();
|
|
127
|
+
logs.push(withId);
|
|
128
|
+
if (logs.length > this.#maxLogs) {
|
|
129
|
+
logs.shift();
|
|
130
|
+
}
|
|
131
|
+
this.#storage.set(extensionId, logs);
|
|
132
|
+
}
|
|
133
|
+
getData(extensionId) {
|
|
134
|
+
return this.#storage.get(extensionId) ?? [];
|
|
135
|
+
}
|
|
136
|
+
getById(extensionId, stableId) {
|
|
137
|
+
const logs = this.#storage.get(extensionId);
|
|
138
|
+
if (!logs) {
|
|
139
|
+
throw new Error('No logs found for selected extension');
|
|
140
|
+
}
|
|
141
|
+
const item = logs.find(item => item[stableIdSymbol] === stableId);
|
|
142
|
+
if (item) {
|
|
143
|
+
return item;
|
|
144
|
+
}
|
|
145
|
+
throw new Error('Log not found for selected extension');
|
|
146
|
+
}
|
|
147
|
+
find(extensionId, filter) {
|
|
148
|
+
const logs = this.#storage.get(extensionId);
|
|
149
|
+
if (!logs) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
return logs.find(filter);
|
|
153
|
+
}
|
|
154
|
+
clearLogs(extensionId) {
|
|
155
|
+
this.#storage.delete(extensionId);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function extractExtensionId(origin) {
|
|
159
|
+
if (!origin || !isExtensionOrigin(origin)) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const pathPart = origin.substring(CHROME_EXTENSION_PREFIX.length);
|
|
163
|
+
const slashIndex = pathPart.indexOf('/');
|
|
164
|
+
// if there's no / it means that pathPart is now the extensionId, otherwise
|
|
165
|
+
// we take everything until the first /
|
|
166
|
+
return slashIndex === -1 ? pathPart : pathPart.substring(0, slashIndex);
|
|
167
|
+
}
|
|
168
|
+
function isExtensionOrigin(origin) {
|
|
169
|
+
return origin.startsWith(CHROME_EXTENSION_PREFIX);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=ServiceWorkerCollector.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { McpResponse } from './McpResponse.js';
|
|
7
|
+
export class SlimMcpResponse extends McpResponse {
|
|
8
|
+
async handle(_toolName, _context) {
|
|
9
|
+
const text = {
|
|
10
|
+
type: 'text',
|
|
11
|
+
text: this.responseLines.join('\n'),
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
content: [text],
|
|
15
|
+
structuredContent: text,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=SlimMcpResponse.js.map
|