diff --git a/.vscode/settings.json b/.vscode/settings.json index d2b1a679c5..43a86eafe4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -226,5 +226,6 @@ "C_Cpp.errorSquiggles": "enabled", "eslint.workingDirectories": ["packages/bun-types"], "typescript.tsdk": "node_modules/typescript/lib", - "cmake.configureOnOpen": false + "cmake.configureOnOpen": false, + "git.ignoreLimitWarning": true } diff --git a/packages/bun-debug-adapter-protocol/bun.lockb b/packages/bun-debug-adapter-protocol/bun.lockb index 53d889ee4a..b63aa6d889 100755 Binary files a/packages/bun-debug-adapter-protocol/bun.lockb and b/packages/bun-debug-adapter-protocol/bun.lockb differ diff --git a/packages/bun-debug-adapter-protocol/src/protocol/index.d.ts b/packages/bun-debug-adapter-protocol/src/protocol/index.d.ts index 7a8dcc3128..8df2201414 100644 --- a/packages/bun-debug-adapter-protocol/src/protocol/index.d.ts +++ b/packages/bun-debug-adapter-protocol/src/protocol/index.d.ts @@ -2215,7 +2215,7 @@ export namespace DAP { */ instructionReference: string; /** - * The offset from the instruction reference. + * The offset from the instruction reference in bytes. * This can be negative. */ offset?: number; @@ -2278,6 +2278,13 @@ export namespace DAP { * This can be negative. */ offset?: number; + /** + * A machine-readable explanation of why a breakpoint may not be verified. If a breakpoint is verified or a specific reason is not known, the adapter should omit this property. Possible values include: + * + * - `pending`: Indicates a breakpoint might be verified in the future, but the adapter cannot verify it in the current state. + * - `failed`: Indicates a breakpoint was not able to be verified, and the adapter does not believe it can be verified without intervention. + */ + reason?: "pending" | "failed"; }; /** * The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`. @@ -2587,6 +2594,12 @@ export namespace DAP { * The end column of the range that corresponds to this instruction, if any. */ endColumn?: number; + /** + * A hint for how to present the instruction in the UI. + * + * A value of `invalid` may be used to indicate this instruction is 'filler' and cannot be reached by the program. For example, unreadable memory addresses may be presented is 'invalid.' + */ + presentationHint?: "normal" | "invalid"; }; /** * Logical areas that can be invalidated by the `invalidated` event. diff --git a/packages/bun-debug-adapter-protocol/src/protocol/protocol.json b/packages/bun-debug-adapter-protocol/src/protocol/protocol.json index 41d65608e3..ad060471be 100644 --- a/packages/bun-debug-adapter-protocol/src/protocol/protocol.json +++ b/packages/bun-debug-adapter-protocol/src/protocol/protocol.json @@ -3420,7 +3420,7 @@ }, "offset": { "type": "integer", - "description": "The offset from the instruction reference.\nThis can be negative." + "description": "The offset from the instruction reference in bytes.\nThis can be negative." }, "condition": { "type": "string", @@ -3467,6 +3467,11 @@ "offset": { "type": "integer", "description": "The offset from the instruction reference.\nThis can be negative." + }, + "reason": { + "type": "string", + "description": "A machine-readable explanation of why a breakpoint may not be verified. If a breakpoint is verified or a specific reason is not known, the adapter should omit this property. Possible values include:\n\n- `pending`: Indicates a breakpoint might be verified in the future, but the adapter cannot verify it in the current state.\n - `failed`: Indicates a breakpoint was not able to be verified, and the adapter does not believe it can be verified without intervention.", + "enum": ["pending", "failed"] } }, "required": ["verified"] @@ -3750,6 +3755,11 @@ "endColumn": { "type": "integer", "description": "The end column of the range that corresponds to this instruction, if any." + }, + "presentationHint": { + "type": "string", + "description": "A hint for how to present the instruction in the UI.\n\nA value of `invalid` may be used to indicate this instruction is 'filler' and cannot be reached by the program. For example, unreadable memory addresses may be presented is 'invalid.'", + "enum": ["normal", "invalid"] } }, "required": ["address", "instruction"] diff --git a/packages/bun-inspector-frontend/build.ts b/packages/bun-inspector-frontend/scripts/build.ts similarity index 96% rename from packages/bun-inspector-frontend/build.ts rename to packages/bun-inspector-frontend/scripts/build.ts index b45a3549f6..bb346db177 100644 --- a/packages/bun-inspector-frontend/build.ts +++ b/packages/bun-inspector-frontend/scripts/build.ts @@ -3,11 +3,11 @@ import { copyFileSync, mkdirSync, readdirSync, rmSync, statSync } from "fs"; import { join } from "path"; try { - const basePath = join(import.meta.dir, "../../src/bun.js/WebKit/Source/WebInspectorUI/UserInterface"); + const basePath = join(import.meta.dir, "../../../src/bun.js/WebKit/Source/WebInspectorUI/UserInterface"); const htmlPath = join(basePath, "Main.html"); const backendCommands = join( import.meta.dir, - "../../src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/DerivedSources/inspector/InspectorBackendCommands.js", + "../../../src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/DerivedSources/inspector/InspectorBackendCommands.js", ); const scriptsToBundle = []; const stylesToBundle = []; diff --git a/packages/bun-inspector-protocol/src/protocol/jsc/index.d.ts b/packages/bun-inspector-protocol/src/protocol/jsc/index.d.ts index 88e7f0a901..bf9f280e45 100644 --- a/packages/bun-inspector-protocol/src/protocol/jsc/index.d.ts +++ b/packages/bun-inspector-protocol/src/protocol/jsc/index.d.ts @@ -3047,6 +3047,10 @@ export namespace JSC { * Whether the expression should be considered to be in a user gesture or not. */ emulateUserGesture?: boolean | undefined; + /** + * Whether to automatically await returned promise. + */ + awaitPromise?: boolean | undefined; }; /** * Calls function with given declaration on the given object. Object group of the result is inherited from the target object. diff --git a/packages/bun-inspector-protocol/src/protocol/jsc/protocol.json b/packages/bun-inspector-protocol/src/protocol/jsc/protocol.json index ed3bb67e67..bb8158358f 100644 --- a/packages/bun-inspector-protocol/src/protocol/jsc/protocol.json +++ b/packages/bun-inspector-protocol/src/protocol/jsc/protocol.json @@ -2751,6 +2751,12 @@ "type": "boolean", "optional": true, "description": "Whether the expression should be considered to be in a user gesture or not." + }, + { + "name": "awaitPromise", + "type": "boolean", + "optional": true, + "description": "Whether to automatically await returned promise." } ], "returns": [ @@ -2761,7 +2767,8 @@ "optional": true, "description": "True if the result was thrown during the evaluation." } - ] + ], + "async": true }, { "name": "getPreview", diff --git a/packages/bun-inspector-protocol/src/protocol/v8/index.d.ts b/packages/bun-inspector-protocol/src/protocol/v8/index.d.ts index 579adf70ca..222499e0d0 100644 --- a/packages/bun-inspector-protocol/src/protocol/v8/index.d.ts +++ b/packages/bun-inspector-protocol/src/protocol/v8/index.d.ts @@ -812,7 +812,8 @@ export namespace V8 { | "WarnSameSiteLaxCrossDowngradeLax" | "WarnAttributeValueExceedsMaxSize" | "WarnDomainNonASCII" - | "WarnThirdPartyPhaseout"; + | "WarnThirdPartyPhaseout" + | "WarnCrossSiteRedirectDowngradeChangesInclusion"; export type CookieOperation = "SetCookie" | "ReadCookie"; /** * This information is currently necessary, as the front-end has a difficult @@ -865,6 +866,7 @@ export namespace V8 { | "Script" | "ServiceWorker" | "SharedWorker" + | "SpeculationRules" | "Stylesheet" | "Track" | "Video" @@ -1091,6 +1093,16 @@ export namespace V8 { export type BounceTrackingIssueDetails = { trackingSites: string[]; }; + /** + * This issue warns about third-party sites that are accessing cookies on the + * current page, and have been permitted due to having a global metadata grant. + * Note that in this context 'site' means eTLD+1. For example, if the URL + * `https://example.test:80/web_page` was accessing cookies, the site reported + * would be `example.test`. + */ + export type CookieDeprecationMetadataIssueDetails = { + allowedSites: string[]; + }; export type ClientHintIssueReason = "MetaTagAllowListInvalidOrigin" | "MetaTagModifiedHTML"; export type FederatedAuthRequestIssueDetails = { federatedAuthRequestIssueReason: FederatedAuthRequestIssueReason; @@ -1130,6 +1142,8 @@ export namespace V8 { | "IdTokenHttpNotFound" | "IdTokenNoResponse" | "IdTokenInvalidResponse" + | "IdTokenIdpErrorResponse" + | "IdTokenCrossSiteIdpErrorResponse" | "IdTokenInvalidRequest" | "IdTokenInvalidContentType" | "ErrorIdToken" @@ -1234,6 +1248,7 @@ export namespace V8 { | "ClientHintIssue" | "FederatedAuthRequestIssue" | "BounceTrackingIssue" + | "CookieDeprecationMetadataIssue" | "StylesheetLoadingIssue" | "FederatedAuthUserInfoRequestIssue" | "PropertyRuleIssue"; @@ -1259,6 +1274,7 @@ export namespace V8 { clientHintIssueDetails?: ClientHintIssueDetails | undefined; federatedAuthRequestIssueDetails?: FederatedAuthRequestIssueDetails | undefined; bounceTrackingIssueDetails?: BounceTrackingIssueDetails | undefined; + cookieDeprecationMetadataIssueDetails?: CookieDeprecationMetadataIssueDetails | undefined; stylesheetLoadingIssueDetails?: StylesheetLoadingIssueDetails | undefined; propertyRuleIssueDetails?: PropertyRuleIssueDetails | undefined; federatedAuthUserInfoRequestIssueDetails?: FederatedAuthUserInfoRequestIssueDetails | undefined; @@ -1472,6 +1488,10 @@ export namespace V8 { * The filling strategy */ fillingStrategy: FillingStrategy; + /** + * The form field's DOM node + */ + fieldId: DOM.BackendNodeId; }; /** * Emitted when an address form is filled. @@ -1703,6 +1723,7 @@ export namespace V8 { | "audioCapture" | "backgroundSync" | "backgroundFetch" + | "capturedSurfaceControl" | "clipboardReadWrite" | "clipboardSanitizedWrite" | "displayCapture" @@ -1729,7 +1750,7 @@ export namespace V8 { export type PermissionSetting = "granted" | "denied" | "prompt"; /** * Definition of PermissionDescriptor defined in the Permissions API: - * https://w3c.github.io/permissions/#dictdef-permissiondescriptor. + * https://w3c.github.io/permissions/#dom-permissiondescriptor. */ export type PermissionDescriptor = { /** @@ -3082,6 +3103,10 @@ export namespace V8 { * Font's family name reported by platform. */ familyName: string; + /** + * Font's PostScript name reported by platform. + */ + postScriptName: string; /** * Indicates if the font was downloaded or resolved locally. */ @@ -3212,6 +3237,28 @@ export namespace V8 { inherits: boolean; syntax: string; }; + /** + * CSS font-palette-values rule representation. + */ + export type CSSFontPaletteValuesRule = { + /** + * The css style sheet identifier (absent for user agent stylesheet and user-specified + * stylesheet rules) this rule came from. + */ + styleSheetId?: StyleSheetId | undefined; + /** + * Parent stylesheet's origin. + */ + origin: StyleSheetOrigin; + /** + * Associated font palette name. + */ + fontPaletteName: Value; + /** + * Associated style declaration. + */ + style: CSSStyle; + }; /** * CSS property at-rule representation. */ @@ -3335,6 +3382,12 @@ export namespace V8 { * Text position of a new rule in the target style sheet. */ location: SourceRange; + /** + * NodeId for the DOM node in whose context custom property declarations for registered properties should be + * validated. If omitted, declarations in the new rule text can only be validated statically, which may produce + * incorrect results if the declaration contains a var() for example. + */ + nodeForPropertySyntaxValidation?: DOM.NodeId | undefined; }; /** * Inserts a new rule with the given `ruleText` in a stylesheet with given `styleSheetId`, at the @@ -3552,6 +3605,10 @@ export namespace V8 { * A list of CSS property registrations matching this node. */ cssPropertyRegistrations?: CSSPropertyRegistration[] | undefined; + /** + * A font-palette-values rule matching this node. + */ + cssFontPaletteValuesRule?: CSSFontPaletteValuesRule | undefined; /** * Id of the first parent element that does not have display: contents. */ @@ -3838,6 +3895,12 @@ export namespace V8 { */ export type SetStyleTextsRequest = { edits: StyleDeclarationEdit[]; + /** + * NodeId for the DOM node in whose context custom property declarations for registered properties should be + * validated. If omitted, declarations in the new rule text can only be validated statically, which may produce + * incorrect results if the declaration contains a var() for example. + */ + nodeForPropertySyntaxValidation?: DOM.NodeId | undefined; }; /** * Applies specified style edits one after another in the given order. @@ -6666,6 +6729,12 @@ export namespace V8 { */ maskLength: number; }; + export type DevicePosture = { + /** + * Current posture of the device + */ + type: "continuous" | "folded"; + }; export type MediaFeature = { name: string; value: string; @@ -6706,6 +6775,44 @@ export namespace V8 { bitness?: string | undefined; wow64?: boolean | undefined; }; + /** + * Used to specify sensor types to emulate. + * See https://w3c.github.io/sensors/#automation for more information. + */ + export type SensorType = + | "absolute-orientation" + | "accelerometer" + | "ambient-light" + | "gravity" + | "gyroscope" + | "linear-acceleration" + | "magnetometer" + | "proximity" + | "relative-orientation"; + export type SensorMetadata = { + available?: boolean | undefined; + minimumFrequency?: number | undefined; + maximumFrequency?: number | undefined; + }; + export type SensorReadingSingle = { + value: number; + }; + export type SensorReadingXYZ = { + x: number; + y: number; + z: number; + }; + export type SensorReadingQuaternion = { + x: number; + y: number; + z: number; + w: number; + }; + export type SensorReading = { + single?: SensorReadingSingle | undefined; + xyz?: SensorReadingXYZ | undefined; + quaternion?: SensorReadingQuaternion | undefined; + }; /** * Enum of image types that can be disabled. */ @@ -6886,6 +6993,11 @@ export namespace V8 { * is turned-off. */ displayFeature?: DisplayFeature | undefined; + /** + * If set, the posture of a foldable device. If not set the posture is set + * to continuous. + */ + devicePosture?: DevicePosture | undefined; }; /** * Overrides the values of device screen dimensions (window.screen.width, window.screen.height, @@ -7010,6 +7122,57 @@ export namespace V8 { * @response `Emulation.setGeolocationOverride` */ export type SetGeolocationOverrideResponse = {}; + /** + * undefined + * @request `Emulation.getOverriddenSensorInformation` + */ + export type GetOverriddenSensorInformationRequest = { + type: SensorType; + }; + /** + * undefined + * @response `Emulation.getOverriddenSensorInformation` + */ + export type GetOverriddenSensorInformationResponse = { + requestedSamplingFrequency: number; + }; + /** + * Overrides a platform sensor of a given type. If |enabled| is true, calls to + * Sensor.start() will use a virtual sensor as backend rather than fetching + * data from a real hardware sensor. Otherwise, existing virtual + * sensor-backend Sensor objects will fire an error event and new calls to + * Sensor.start() will attempt to use a real sensor instead. + * @request `Emulation.setSensorOverrideEnabled` + */ + export type SetSensorOverrideEnabledRequest = { + enabled: boolean; + type: SensorType; + metadata?: SensorMetadata | undefined; + }; + /** + * Overrides a platform sensor of a given type. If |enabled| is true, calls to + * Sensor.start() will use a virtual sensor as backend rather than fetching + * data from a real hardware sensor. Otherwise, existing virtual + * sensor-backend Sensor objects will fire an error event and new calls to + * Sensor.start() will attempt to use a real sensor instead. + * @response `Emulation.setSensorOverrideEnabled` + */ + export type SetSensorOverrideEnabledResponse = {}; + /** + * Updates the sensor readings reported by a sensor type previously overriden + * by setSensorOverrideEnabled. + * @request `Emulation.setSensorOverrideReadings` + */ + export type SetSensorOverrideReadingsRequest = { + type: SensorType; + reading: SensorReading; + }; + /** + * Updates the sensor readings reported by a sensor type previously overriden + * by setSensorOverrideEnabled. + * @response `Emulation.setSensorOverrideReadings` + */ + export type SetSensorOverrideReadingsResponse = {}; /** * Overrides the Idle state. * @request `Emulation.setIdleOverride` @@ -7231,7 +7394,7 @@ export namespace V8 { */ userAgent: string; /** - * Browser langugage to emulate. + * Browser language to emulate. */ acceptLanguage?: string | undefined; /** @@ -7313,9 +7476,13 @@ export namespace V8 { */ export type LoginState = "SignIn" | "SignUp"; /** - * Whether the dialog shown is an account chooser or an auto re-authentication dialog. + * The types of FedCM dialogs. */ - export type DialogType = "AccountChooser" | "AutoReauthn" | "ConfirmIdpLogin"; + export type DialogType = "AccountChooser" | "AutoReauthn" | "ConfirmIdpLogin" | "Error"; + /** + * The buttons on the FedCM dialog. + */ + export type DialogButton = "ConfirmIdpLoginContinue" | "ErrorGotIt" | "ErrorMoreDetails"; /** * Corresponds to IdentityRequestAccount */ @@ -7349,6 +7516,14 @@ export namespace V8 { title: string; subtitle?: string | undefined; }; + /** + * Triggered when a dialog is closed, either by user action, JS abort, + * or a command below. + * @event `FedCm.dialogClosed` + */ + export type DialogClosedEvent = { + dialogId: string; + }; /** * undefined * @request `FedCm.enable` @@ -7390,19 +7565,18 @@ export namespace V8 { */ export type SelectAccountResponse = {}; /** - * Only valid if the dialog type is ConfirmIdpLogin. Acts as if the user had - * clicked the continue button. - * @request `FedCm.confirmIdpLogin` + * undefined + * @request `FedCm.clickDialogButton` */ - export type ConfirmIdpLoginRequest = { + export type ClickDialogButtonRequest = { dialogId: string; + dialogButton: DialogButton; }; /** - * Only valid if the dialog type is ConfirmIdpLogin. Acts as if the user had - * clicked the continue button. - * @response `FedCm.confirmIdpLogin` + * undefined + * @response `FedCm.clickDialogButton` */ - export type ConfirmIdpLoginResponse = {}; + export type ClickDialogButtonResponse = {}; /** * undefined * @request `FedCm.dismissDialog` @@ -9967,6 +10141,23 @@ export namespace V8 { */ outlineColor?: DOM.RGBA | undefined; }; + /** + * Configuration for Window Controls Overlay + */ + export type WindowControlsOverlayConfig = { + /** + * Whether the title bar CSS should be shown when emulating the Window Controls Overlay. + */ + showCSS: boolean; + /** + * Seleted platforms to show the overlay. + */ + selectedPlatform: string; + /** + * The theme color defined in app manifest. + */ + themeColor: string; + }; export type ContainerQueryHighlightConfig = { /** * A descriptor for the highlight appearance of container query containers. @@ -10564,6 +10755,21 @@ export namespace V8 { * @response `Overlay.setShowIsolatedElements` */ export type SetShowIsolatedElementsResponse = {}; + /** + * Show Window Controls Overlay for PWA + * @request `Overlay.setShowWindowControlsOverlay` + */ + export type SetShowWindowControlsOverlayRequest = { + /** + * Window Controls Overlay data, null means hide Window Controls Overlay + */ + windowControlsOverlayConfig?: WindowControlsOverlayConfig | undefined; + }; + /** + * Show Window Controls Overlay for PWA + * @response `Overlay.setShowWindowControlsOverlay` + */ + export type SetShowWindowControlsOverlayResponse = {}; } export namespace Page { /** @@ -10622,6 +10828,7 @@ export namespace V8 { | "bluetooth" | "browsing-topics" | "camera" + | "captured-surface-control" | "ch-dpr" | "ch-device-memory" | "ch-downlink" @@ -10677,6 +10884,7 @@ export namespace V8 { | "private-aggregation" | "private-state-token-issuance" | "private-state-token-redemption" + | "publickey-credentials-create" | "publickey-credentials-get" | "run-ad-auction" | "screen-wake-lock" @@ -10686,10 +10894,13 @@ export namespace V8 { | "shared-storage-select-url" | "smart-card" | "storage-access" + | "sub-apps" | "sync-xhr" | "unload" | "usb" + | "usb-unrestricted" | "vertical-scroll" + | "web-printing" | "web-share" | "window-management" | "window-placement" @@ -11307,6 +11518,9 @@ export namespace V8 { | "WebRTCSticky" | "WebTransportSticky" | "WebSocketSticky" + | "SmartCard" + | "LiveMediaStreamTrack" + | "UnloadHandler" | "ContentSecurityHandler" | "ContentWebAuthenticationAPI" | "ContentFileChooser" @@ -11336,6 +11550,24 @@ export namespace V8 { * Types of not restored reasons for back-forward cache. */ export type BackForwardCacheNotRestoredReasonType = "SupportPending" | "PageSupportNeeded" | "Circumstantial"; + export type BackForwardCacheBlockingDetails = { + /** + * Url of the file where blockage happened. Optional because of tests. + */ + url?: string | undefined; + /** + * Function name where blockage happened. Optional because of anonymous functions and tests. + */ + function?: string | undefined; + /** + * Line number in the script (0-based). + */ + lineNumber: number; + /** + * Column number in the script (0-based). + */ + columnNumber: number; + }; export type BackForwardCacheNotRestoredExplanation = { /** * Type of the reason @@ -11351,6 +11583,7 @@ export namespace V8 { * - EmbedderExtensionSentMessageToCachedFrame: the extension ID. */ context?: string | undefined; + details?: BackForwardCacheBlockingDetails[] | undefined; }; export type BackForwardCacheNotRestoredExplanationTree = { /** @@ -12054,25 +12287,6 @@ export namespace V8 { */ adScriptId?: AdScriptId | undefined; }; - /** - * Returns all browser cookies for the page and all of its subframes. Depending - * on the backend support, will return detailed cookie information in the - * `cookies` field. - * @request `Page.getCookies` - */ - export type GetCookiesRequest = {}; - /** - * Returns all browser cookies for the page and all of its subframes. Depending - * on the backend support, will return detailed cookie information in the - * `cookies` field. - * @response `Page.getCookies` - */ - export type GetCookiesResponse = { - /** - * Array of cookie objects. - */ - cookies: Network.Cookie[]; - }; /** * Returns present frame tree structure. * @request `Page.getFrameTree` @@ -12360,6 +12574,10 @@ export namespace V8 { * Whether or not to generate tagged (accessible) PDF. Defaults to embedder choice. */ generateTaggedPDF?: boolean | undefined; + /** + * Whether or not to embed the document outline into the PDF. + */ + generateDocumentOutline?: boolean | undefined; }; /** * Print page as PDF. @@ -13313,7 +13531,6 @@ export namespace V8 { | "MemoryPressureOnTrigger" | "MemoryPressureAfterTriggered" | "PrerenderingDisabledByDevTools" - | "ResourceLoadBlockedByClient" | "SpeculationRuleRemoved" | "ActivatedWithAuxiliaryBrowsingContexts" | "MaxNumOfRunningEagerPrerendersExceeded" @@ -13339,7 +13556,8 @@ export namespace V8 { | "PrefetchFailedNetError" | "PrefetchFailedNon2XX" | "PrefetchFailedPerPageLimitExceeded" - | "PrefetchEvicted" + | "PrefetchEvictedAfterCandidateRemoved" + | "PrefetchEvictedForNewerPrefetch" | "PrefetchHeldback" | "PrefetchIneligibleRetryAfter" | "PrefetchIsPrivacyDecoy" @@ -13362,6 +13580,14 @@ export namespace V8 { | "PrefetchResponseUsed" | "PrefetchSuccessfulButNotUsed" | "PrefetchNotUsedProbeFailed"; + /** + * Information of headers to be displayed when the header mismatch occurred. + */ + export type PrerenderMismatchedHeaders = { + headerName: string; + initialValue?: string | undefined; + activationValue?: string | undefined; + }; /** * Upsert. Currently, it is only emitted when a rule set added. * @event `Preload.ruleSetUpdated` @@ -13415,6 +13641,7 @@ export namespace V8 { * that is incompatible with prerender and has caused the cancellation of the attempt. */ disallowedMojoInterface?: string | undefined; + mismatchedHeaders?: PrerenderMismatchedHeaders[] | undefined; }; /** * Send a list of sources for all preloading attempts in a document. @@ -13837,6 +14064,7 @@ export namespace V8 { scriptResponseTime?: number | undefined; controlledClients?: Target.TargetID[] | undefined; targetId?: Target.TargetID | undefined; + routerRules?: string | undefined; }; /** * ServiceWorker error message. @@ -14241,6 +14469,17 @@ export namespace V8 { key: string; values: string[]; }; + export type AttributionReportingFilterConfig = { + filterValues: AttributionReportingFilterDataEntry[]; + /** + * duration in seconds + */ + lookbackWindow?: number | undefined; + }; + export type AttributionReportingFilterPair = { + filters: AttributionReportingFilterConfig[]; + notFilters: AttributionReportingFilterConfig[]; + }; export type AttributionReportingAggregationKeysEntry = { key: string; value: UnsignedInt128AsBase16; @@ -14255,13 +14494,22 @@ export namespace V8 { */ ends: number[]; }; + export type AttributionReportingTriggerSpec = { + /** + * number instead of integer because not all uint32 can be represented by + * int + */ + triggerData: number[]; + eventReportWindows: AttributionReportingEventReportWindows; + }; + export type AttributionReportingTriggerDataMatching = "exact" | "modulus"; export type AttributionReportingSourceRegistration = { time: Network.TimeSinceEpoch; /** * duration in seconds */ expiry: number; - eventReportWindows: AttributionReportingEventReportWindows; + triggerSpecs: AttributionReportingTriggerSpec[]; /** * duration in seconds */ @@ -14275,6 +14523,7 @@ export namespace V8 { filterData: AttributionReportingFilterDataEntry[]; aggregationKeys: AttributionReportingAggregationKeysEntry[]; debugKey?: UnsignedInt64AsBase10 | undefined; + triggerDataMatching: AttributionReportingTriggerDataMatching; }; export type AttributionReportingSourceRegistrationResult = | "success" @@ -14289,6 +14538,77 @@ export namespace V8 { | "destinationBothLimitsReached" | "reportingOriginsPerSiteLimitReached" | "exceedsMaxChannelCapacity"; + export type AttributionReportingSourceRegistrationTimeConfig = "include" | "exclude"; + export type AttributionReportingAggregatableValueEntry = { + key: string; + /** + * number instead of integer because not all uint32 can be represented by + * int + */ + value: number; + }; + export type AttributionReportingEventTriggerData = { + data: UnsignedInt64AsBase10; + priority: SignedInt64AsBase10; + dedupKey?: UnsignedInt64AsBase10 | undefined; + filters: AttributionReportingFilterPair; + }; + export type AttributionReportingAggregatableTriggerData = { + keyPiece: UnsignedInt128AsBase16; + sourceKeys: string[]; + filters: AttributionReportingFilterPair; + }; + export type AttributionReportingAggregatableDedupKey = { + dedupKey?: UnsignedInt64AsBase10 | undefined; + filters: AttributionReportingFilterPair; + }; + export type AttributionReportingTriggerRegistration = { + filters: AttributionReportingFilterPair; + debugKey?: UnsignedInt64AsBase10 | undefined; + aggregatableDedupKeys: AttributionReportingAggregatableDedupKey[]; + eventTriggerData: AttributionReportingEventTriggerData[]; + aggregatableTriggerData: AttributionReportingAggregatableTriggerData[]; + aggregatableValues: AttributionReportingAggregatableValueEntry[]; + debugReporting: boolean; + aggregationCoordinatorOrigin?: string | undefined; + sourceRegistrationTimeConfig: AttributionReportingSourceRegistrationTimeConfig; + triggerContextId?: string | undefined; + }; + export type AttributionReportingEventLevelResult = + | "success" + | "successDroppedLowerPriority" + | "internalError" + | "noCapacityForAttributionDestination" + | "noMatchingSources" + | "deduplicated" + | "excessiveAttributions" + | "priorityTooLow" + | "neverAttributedSource" + | "excessiveReportingOrigins" + | "noMatchingSourceFilterData" + | "prohibitedByBrowserPolicy" + | "noMatchingConfigurations" + | "excessiveReports" + | "falselyAttributedSource" + | "reportWindowPassed" + | "notRegistered" + | "reportWindowNotStarted" + | "noMatchingTriggerData"; + export type AttributionReportingAggregatableResult = + | "success" + | "internalError" + | "noCapacityForAttributionDestination" + | "noMatchingSources" + | "excessiveAttributions" + | "excessiveReportingOrigins" + | "noHistograms" + | "insufficientBudget" + | "noMatchingSourceFilterData" + | "notRegistered" + | "prohibitedByBrowserPolicy" + | "deduplicated" + | "reportWindowPassed" + | "excessiveReports"; /** * A cache's contents have been modified. * @event `Storage.cacheStorageContentUpdated` @@ -14426,14 +14746,22 @@ export namespace V8 { bucketId: string; }; /** - * TODO(crbug.com/1458532): Add other Attribution Reporting events, e.g. - * trigger registration. + * undefined * @event `Storage.attributionReportingSourceRegistered` */ export type AttributionReportingSourceRegisteredEvent = { registration: AttributionReportingSourceRegistration; result: AttributionReportingSourceRegistrationResult; }; + /** + * undefined + * @event `Storage.attributionReportingTriggerRegistered` + */ + export type AttributionReportingTriggerRegisteredEvent = { + registration: AttributionReportingTriggerRegistration; + eventLevel: AttributionReportingEventLevelResult; + aggregatable: AttributionReportingAggregatableResult; + }; /** * Returns a storage key given a frame id. * @request `Storage.getStorageKeyForFrame` @@ -16297,6 +16625,18 @@ export namespace V8 { * Defaults to false. */ isUserVerified?: boolean | undefined; + /** + * Credentials created by this authenticator will have the backup + * eligibility (BE) flag set to this value. Defaults to false. + * https://w3c.github.io/webauthn/#sctn-credential-backup + */ + defaultBackupEligibility?: boolean | undefined; + /** + * Credentials created by this authenticator will have the backup state + * (BS) flag set to this value. Defaults to false. + * https://w3c.github.io/webauthn/#sctn-credential-backup + */ + defaultBackupState?: boolean | undefined; }; export type Credential = { credentialId: string; @@ -16569,6 +16909,7 @@ export namespace V8 { "DOMStorage.domStorageItemsCleared": DOMStorage.DomStorageItemsClearedEvent; "Emulation.virtualTimeBudgetExpired": Emulation.VirtualTimeBudgetExpiredEvent; "FedCm.dialogShown": FedCm.DialogShownEvent; + "FedCm.dialogClosed": FedCm.DialogClosedEvent; "Fetch.requestPaused": Fetch.RequestPausedEvent; "Fetch.authRequired": Fetch.AuthRequiredEvent; "Input.dragIntercepted": Input.DragInterceptedEvent; @@ -16633,6 +16974,7 @@ export namespace V8 { "Storage.storageBucketCreatedOrUpdated": Storage.StorageBucketCreatedOrUpdatedEvent; "Storage.storageBucketDeleted": Storage.StorageBucketDeletedEvent; "Storage.attributionReportingSourceRegistered": Storage.AttributionReportingSourceRegisteredEvent; + "Storage.attributionReportingTriggerRegistered": Storage.AttributionReportingTriggerRegisteredEvent; "Target.attachedToTarget": Target.AttachedToTargetEvent; "Target.detachedFromTarget": Target.DetachedFromTargetEvent; "Target.receivedMessageFromTarget": Target.ReceivedMessageFromTargetEvent; @@ -16845,6 +17187,9 @@ export namespace V8 { "Emulation.setEmulatedMedia": Emulation.SetEmulatedMediaRequest; "Emulation.setEmulatedVisionDeficiency": Emulation.SetEmulatedVisionDeficiencyRequest; "Emulation.setGeolocationOverride": Emulation.SetGeolocationOverrideRequest; + "Emulation.getOverriddenSensorInformation": Emulation.GetOverriddenSensorInformationRequest; + "Emulation.setSensorOverrideEnabled": Emulation.SetSensorOverrideEnabledRequest; + "Emulation.setSensorOverrideReadings": Emulation.SetSensorOverrideReadingsRequest; "Emulation.setIdleOverride": Emulation.SetIdleOverrideRequest; "Emulation.clearIdleOverride": Emulation.ClearIdleOverrideRequest; "Emulation.setNavigatorOverrides": Emulation.SetNavigatorOverridesRequest; @@ -16865,7 +17210,7 @@ export namespace V8 { "FedCm.enable": FedCm.EnableRequest; "FedCm.disable": FedCm.DisableRequest; "FedCm.selectAccount": FedCm.SelectAccountRequest; - "FedCm.confirmIdpLogin": FedCm.ConfirmIdpLoginRequest; + "FedCm.clickDialogButton": FedCm.ClickDialogButtonRequest; "FedCm.dismissDialog": FedCm.DismissDialogRequest; "FedCm.resetCooldown": FedCm.ResetCooldownRequest; "Fetch.disable": Fetch.DisableRequest; @@ -16949,6 +17294,7 @@ export namespace V8 { "Overlay.setShowViewportSizeOnResize": Overlay.SetShowViewportSizeOnResizeRequest; "Overlay.setShowHinge": Overlay.SetShowHingeRequest; "Overlay.setShowIsolatedElements": Overlay.SetShowIsolatedElementsRequest; + "Overlay.setShowWindowControlsOverlay": Overlay.SetShowWindowControlsOverlayRequest; "Page.addScriptToEvaluateOnLoad": Page.AddScriptToEvaluateOnLoadRequest; "Page.addScriptToEvaluateOnNewDocument": Page.AddScriptToEvaluateOnNewDocumentRequest; "Page.bringToFront": Page.BringToFrontRequest; @@ -16966,7 +17312,6 @@ export namespace V8 { "Page.getManifestIcons": Page.GetManifestIconsRequest; "Page.getAppId": Page.GetAppIdRequest; "Page.getAdScriptId": Page.GetAdScriptIdRequest; - "Page.getCookies": Page.GetCookiesRequest; "Page.getFrameTree": Page.GetFrameTreeRequest; "Page.getLayoutMetrics": Page.GetLayoutMetricsRequest; "Page.getNavigationHistory": Page.GetNavigationHistoryRequest; @@ -17296,6 +17641,9 @@ export namespace V8 { "Emulation.setEmulatedMedia": Emulation.SetEmulatedMediaResponse; "Emulation.setEmulatedVisionDeficiency": Emulation.SetEmulatedVisionDeficiencyResponse; "Emulation.setGeolocationOverride": Emulation.SetGeolocationOverrideResponse; + "Emulation.getOverriddenSensorInformation": Emulation.GetOverriddenSensorInformationResponse; + "Emulation.setSensorOverrideEnabled": Emulation.SetSensorOverrideEnabledResponse; + "Emulation.setSensorOverrideReadings": Emulation.SetSensorOverrideReadingsResponse; "Emulation.setIdleOverride": Emulation.SetIdleOverrideResponse; "Emulation.clearIdleOverride": Emulation.ClearIdleOverrideResponse; "Emulation.setNavigatorOverrides": Emulation.SetNavigatorOverridesResponse; @@ -17316,7 +17664,7 @@ export namespace V8 { "FedCm.enable": FedCm.EnableResponse; "FedCm.disable": FedCm.DisableResponse; "FedCm.selectAccount": FedCm.SelectAccountResponse; - "FedCm.confirmIdpLogin": FedCm.ConfirmIdpLoginResponse; + "FedCm.clickDialogButton": FedCm.ClickDialogButtonResponse; "FedCm.dismissDialog": FedCm.DismissDialogResponse; "FedCm.resetCooldown": FedCm.ResetCooldownResponse; "Fetch.disable": Fetch.DisableResponse; @@ -17400,6 +17748,7 @@ export namespace V8 { "Overlay.setShowViewportSizeOnResize": Overlay.SetShowViewportSizeOnResizeResponse; "Overlay.setShowHinge": Overlay.SetShowHingeResponse; "Overlay.setShowIsolatedElements": Overlay.SetShowIsolatedElementsResponse; + "Overlay.setShowWindowControlsOverlay": Overlay.SetShowWindowControlsOverlayResponse; "Page.addScriptToEvaluateOnLoad": Page.AddScriptToEvaluateOnLoadResponse; "Page.addScriptToEvaluateOnNewDocument": Page.AddScriptToEvaluateOnNewDocumentResponse; "Page.bringToFront": Page.BringToFrontResponse; @@ -17417,7 +17766,6 @@ export namespace V8 { "Page.getManifestIcons": Page.GetManifestIconsResponse; "Page.getAppId": Page.GetAppIdResponse; "Page.getAdScriptId": Page.GetAdScriptIdResponse; - "Page.getCookies": Page.GetCookiesResponse; "Page.getFrameTree": Page.GetFrameTreeResponse; "Page.getLayoutMetrics": Page.GetLayoutMetricsResponse; "Page.getNavigationHistory": Page.GetNavigationHistoryResponse; diff --git a/packages/bun-inspector-protocol/src/protocol/v8/protocol.json b/packages/bun-inspector-protocol/src/protocol/v8/protocol.json index cee8c2ca4b..d5a7db25e8 100644 --- a/packages/bun-inspector-protocol/src/protocol/v8/protocol.json +++ b/packages/bun-inspector-protocol/src/protocol/v8/protocol.json @@ -702,7 +702,8 @@ "WarnSameSiteLaxCrossDowngradeLax", "WarnAttributeValueExceedsMaxSize", "WarnDomainNonASCII", - "WarnThirdPartyPhaseout" + "WarnThirdPartyPhaseout", + "WarnCrossSiteRedirectDowngradeChangesInclusion" ] }, { "id": "CookieOperation", "type": "string", "enum": ["SetCookie", "ReadCookie"] }, @@ -760,6 +761,7 @@ "Script", "ServiceWorker", "SharedWorker", + "SpeculationRules", "Stylesheet", "Track", "Video", @@ -1042,6 +1044,12 @@ "type": "object", "properties": [{ "name": "trackingSites", "type": "array", "items": { "type": "string" } }] }, + { + "id": "CookieDeprecationMetadataIssueDetails", + "description": "This issue warns about third-party sites that are accessing cookies on the\ncurrent page, and have been permitted due to having a global metadata grant.\nNote that in this context 'site' means eTLD+1. For example, if the URL\n`https://example.test:80/web_page` was accessing cookies, the site reported\nwould be `example.test`.", + "type": "object", + "properties": [{ "name": "allowedSites", "type": "array", "items": { "type": "string" } }] + }, { "id": "ClientHintIssueReason", "type": "string", @@ -1085,6 +1093,8 @@ "IdTokenHttpNotFound", "IdTokenNoResponse", "IdTokenInvalidResponse", + "IdTokenIdpErrorResponse", + "IdTokenCrossSiteIdpErrorResponse", "IdTokenInvalidRequest", "IdTokenInvalidContentType", "ErrorIdToken", @@ -1213,6 +1223,7 @@ "ClientHintIssue", "FederatedAuthRequestIssue", "BounceTrackingIssue", + "CookieDeprecationMetadataIssue", "StylesheetLoadingIssue", "FederatedAuthUserInfoRequestIssue", "PropertyRuleIssue" @@ -1256,6 +1267,11 @@ "$ref": "FederatedAuthRequestIssueDetails" }, { "name": "bounceTrackingIssueDetails", "optional": true, "$ref": "BounceTrackingIssueDetails" }, + { + "name": "cookieDeprecationMetadataIssueDetails", + "optional": true, + "$ref": "CookieDeprecationMetadataIssueDetails" + }, { "name": "stylesheetLoadingIssueDetails", "optional": true, "$ref": "StylesheetLoadingIssueDetails" }, { "name": "propertyRuleIssueDetails", "optional": true, "$ref": "PropertyRuleIssueDetails" }, { @@ -1424,7 +1440,8 @@ { "name": "name", "description": "the html name", "type": "string" }, { "name": "value", "description": "the field value", "type": "string" }, { "name": "autofillType", "description": "The actual field type, e.g FAMILY_NAME", "type": "string" }, - { "name": "fillingStrategy", "description": "The filling strategy", "$ref": "FillingStrategy" } + { "name": "fillingStrategy", "description": "The filling strategy", "$ref": "FillingStrategy" }, + { "name": "fieldId", "description": "The form field's DOM node", "$ref": "DOM.BackendNodeId" } ] } ], @@ -1633,6 +1650,7 @@ "audioCapture", "backgroundSync", "backgroundFetch", + "capturedSurfaceControl", "clipboardReadWrite", "clipboardSanitizedWrite", "displayCapture", @@ -1661,7 +1679,7 @@ { "id": "PermissionSetting", "experimental": true, "type": "string", "enum": ["granted", "denied", "prompt"] }, { "id": "PermissionDescriptor", - "description": "Definition of PermissionDescriptor defined in the Permissions API:\nhttps://w3c.github.io/permissions/#dictdef-permissiondescriptor.", + "description": "Definition of PermissionDescriptor defined in the Permissions API:\nhttps://w3c.github.io/permissions/#dom-permissiondescriptor.", "experimental": true, "type": "object", "properties": [ @@ -2871,6 +2889,11 @@ "type": "object", "properties": [ { "name": "familyName", "description": "Font's family name reported by platform.", "type": "string" }, + { + "name": "postScriptName", + "description": "Font's PostScript name reported by platform.", + "type": "string" + }, { "name": "isCustomFont", "description": "Indicates if the font was downloaded or resolved locally.", @@ -2984,6 +3007,22 @@ { "name": "syntax", "type": "string" } ] }, + { + "id": "CSSFontPaletteValuesRule", + "description": "CSS font-palette-values rule representation.", + "type": "object", + "properties": [ + { + "name": "styleSheetId", + "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified\nstylesheet rules) this rule came from.", + "optional": true, + "$ref": "StyleSheetId" + }, + { "name": "origin", "description": "Parent stylesheet's origin.", "$ref": "StyleSheetOrigin" }, + { "name": "fontPaletteName", "description": "Associated font palette name.", "$ref": "Value" }, + { "name": "style", "description": "Associated style declaration.", "$ref": "CSSStyle" } + ] + }, { "id": "CSSPropertyRule", "description": "CSS property at-rule representation.", @@ -3046,6 +3085,13 @@ "name": "location", "description": "Text position of a new rule in the target style sheet.", "$ref": "SourceRange" + }, + { + "name": "nodeForPropertySyntaxValidation", + "description": "NodeId for the DOM node in whose context custom property declarations for registered properties should be\nvalidated. If omitted, declarations in the new rule text can only be validated statically, which may produce\nincorrect results if the declaration contains a var() for example.", + "experimental": true, + "optional": true, + "$ref": "DOM.NodeId" } ], "returns": [{ "name": "rule", "description": "The newly created rule.", "$ref": "CSSRule" }] @@ -3230,6 +3276,12 @@ "type": "array", "items": { "$ref": "CSSPropertyRegistration" } }, + { + "name": "cssFontPaletteValuesRule", + "description": "A font-palette-values rule matching this node.", + "optional": true, + "$ref": "CSSFontPaletteValuesRule" + }, { "name": "parentLayoutNodeId", "description": "Id of the first parent element that does not have display: contents.", @@ -3418,7 +3470,16 @@ { "name": "setStyleTexts", "description": "Applies specified style edits one after another in the given order.", - "parameters": [{ "name": "edits", "type": "array", "items": { "$ref": "StyleDeclarationEdit" } }], + "parameters": [ + { "name": "edits", "type": "array", "items": { "$ref": "StyleDeclarationEdit" } }, + { + "name": "nodeForPropertySyntaxValidation", + "description": "NodeId for the DOM node in whose context custom property declarations for registered properties should be\nvalidated. If omitted, declarations in the new rule text can only be validated statically, which may produce\nincorrect results if the declaration contains a var() for example.", + "experimental": true, + "optional": true, + "$ref": "DOM.NodeId" + } + ], "returns": [ { "name": "styles", @@ -5699,6 +5760,18 @@ } ] }, + { + "id": "DevicePosture", + "type": "object", + "properties": [ + { + "name": "type", + "description": "Current posture of the device", + "type": "string", + "enum": ["continuous", "folded"] + } + ] + }, { "id": "MediaFeature", "type": "object", @@ -5754,6 +5827,70 @@ { "name": "wow64", "optional": true, "type": "boolean" } ] }, + { + "id": "SensorType", + "description": "Used to specify sensor types to emulate.\nSee https://w3c.github.io/sensors/#automation for more information.", + "experimental": true, + "type": "string", + "enum": [ + "absolute-orientation", + "accelerometer", + "ambient-light", + "gravity", + "gyroscope", + "linear-acceleration", + "magnetometer", + "proximity", + "relative-orientation" + ] + }, + { + "id": "SensorMetadata", + "experimental": true, + "type": "object", + "properties": [ + { "name": "available", "optional": true, "type": "boolean" }, + { "name": "minimumFrequency", "optional": true, "type": "number" }, + { "name": "maximumFrequency", "optional": true, "type": "number" } + ] + }, + { + "id": "SensorReadingSingle", + "experimental": true, + "type": "object", + "properties": [{ "name": "value", "type": "number" }] + }, + { + "id": "SensorReadingXYZ", + "experimental": true, + "type": "object", + "properties": [ + { "name": "x", "type": "number" }, + { "name": "y", "type": "number" }, + { "name": "z", "type": "number" } + ] + }, + { + "id": "SensorReadingQuaternion", + "experimental": true, + "type": "object", + "properties": [ + { "name": "x", "type": "number" }, + { "name": "y", "type": "number" }, + { "name": "z", "type": "number" }, + { "name": "w", "type": "number" } + ] + }, + { + "id": "SensorReading", + "experimental": true, + "type": "object", + "properties": [ + { "name": "single", "optional": true, "$ref": "SensorReadingSingle" }, + { "name": "xyz", "optional": true, "$ref": "SensorReadingXYZ" }, + { "name": "quaternion", "optional": true, "$ref": "SensorReadingQuaternion" } + ] + }, { "id": "DisabledImageType", "description": "Enum of image types that can be disabled.", @@ -5905,6 +6042,13 @@ "experimental": true, "optional": true, "$ref": "DisplayFeature" + }, + { + "name": "devicePosture", + "description": "If set, the posture of a foldable device. If not set the posture is set\nto continuous.", + "experimental": true, + "optional": true, + "$ref": "DevicePosture" } ] }, @@ -5989,6 +6133,31 @@ { "name": "accuracy", "description": "Mock accuracy", "optional": true, "type": "number" } ] }, + { + "name": "getOverriddenSensorInformation", + "experimental": true, + "parameters": [{ "name": "type", "$ref": "SensorType" }], + "returns": [{ "name": "requestedSamplingFrequency", "type": "number" }] + }, + { + "name": "setSensorOverrideEnabled", + "description": "Overrides a platform sensor of a given type. If |enabled| is true, calls to\nSensor.start() will use a virtual sensor as backend rather than fetching\ndata from a real hardware sensor. Otherwise, existing virtual\nsensor-backend Sensor objects will fire an error event and new calls to\nSensor.start() will attempt to use a real sensor instead.", + "experimental": true, + "parameters": [ + { "name": "enabled", "type": "boolean" }, + { "name": "type", "$ref": "SensorType" }, + { "name": "metadata", "optional": true, "$ref": "SensorMetadata" } + ] + }, + { + "name": "setSensorOverrideReadings", + "description": "Updates the sensor readings reported by a sensor type previously overriden\nby setSensorOverrideEnabled.", + "experimental": true, + "parameters": [ + { "name": "type", "$ref": "SensorType" }, + { "name": "reading", "$ref": "SensorReading" } + ] + }, { "name": "setIdleOverride", "description": "Overrides the Idle state.", @@ -6136,7 +6305,7 @@ { "name": "userAgent", "description": "User agent to use.", "type": "string" }, { "name": "acceptLanguage", - "description": "Browser langugage to emulate.", + "description": "Browser language to emulate.", "optional": true, "type": "string" }, @@ -6203,9 +6372,15 @@ }, { "id": "DialogType", - "description": "Whether the dialog shown is an account chooser or an auto re-authentication dialog.", + "description": "The types of FedCM dialogs.", "type": "string", - "enum": ["AccountChooser", "AutoReauthn", "ConfirmIdpLogin"] + "enum": ["AccountChooser", "AutoReauthn", "ConfirmIdpLogin", "Error"] + }, + { + "id": "DialogButton", + "description": "The buttons on the FedCM dialog.", + "type": "string", + "enum": ["ConfirmIdpLoginContinue", "ErrorGotIt", "ErrorMoreDetails"] }, { "id": "Account", @@ -6244,6 +6419,11 @@ }, { "name": "subtitle", "optional": true, "type": "string" } ] + }, + { + "name": "dialogClosed", + "description": "Triggered when a dialog is closed, either by user action, JS abort,\nor a command below.", + "parameters": [{ "name": "dialogId", "type": "string" }] } ], "commands": [ @@ -6267,9 +6447,11 @@ ] }, { - "name": "confirmIdpLogin", - "description": "Only valid if the dialog type is ConfirmIdpLogin. Acts as if the user had\nclicked the continue button.", - "parameters": [{ "name": "dialogId", "type": "string" }] + "name": "clickDialogButton", + "parameters": [ + { "name": "dialogId", "type": "string" }, + { "name": "dialogButton", "$ref": "DialogButton" } + ] }, { "name": "dismissDialog", @@ -8743,6 +8925,20 @@ } ] }, + { + "id": "WindowControlsOverlayConfig", + "description": "Configuration for Window Controls Overlay", + "type": "object", + "properties": [ + { + "name": "showCSS", + "description": "Whether the title bar CSS should be shown when emulating the Window Controls Overlay.", + "type": "boolean" + }, + { "name": "selectedPlatform", "description": "Seleted platforms to show the overlay.", "type": "string" }, + { "name": "themeColor", "description": "The theme color defined in app manifest.", "type": "string" } + ] + }, { "id": "ContainerQueryHighlightConfig", "type": "object", @@ -9149,6 +9345,18 @@ "items": { "$ref": "IsolatedElementHighlightConfig" } } ] + }, + { + "name": "setShowWindowControlsOverlay", + "description": "Show Window Controls Overlay for PWA", + "parameters": [ + { + "name": "windowControlsOverlayConfig", + "description": "Window Controls Overlay data, null means hide Window Controls Overlay", + "optional": true, + "$ref": "WindowControlsOverlayConfig" + } + ] } ], "events": [ @@ -9259,6 +9467,7 @@ "bluetooth", "browsing-topics", "camera", + "captured-surface-control", "ch-dpr", "ch-device-memory", "ch-downlink", @@ -9314,6 +9523,7 @@ "private-aggregation", "private-state-token-issuance", "private-state-token-redemption", + "publickey-credentials-create", "publickey-credentials-get", "run-ad-auction", "screen-wake-lock", @@ -9323,10 +9533,13 @@ "shared-storage-select-url", "smart-card", "storage-access", + "sub-apps", "sync-xhr", "unload", "usb", + "usb-unrestricted", "vertical-scroll", + "web-printing", "web-share", "window-management", "window-placement", @@ -9995,6 +10208,9 @@ "WebRTCSticky", "WebTransportSticky", "WebSocketSticky", + "SmartCard", + "LiveMediaStreamTrack", + "UnloadHandler", "ContentSecurityHandler", "ContentWebAuthenticationAPI", "ContentFileChooser", @@ -10029,6 +10245,27 @@ "type": "string", "enum": ["SupportPending", "PageSupportNeeded", "Circumstantial"] }, + { + "id": "BackForwardCacheBlockingDetails", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "url", + "description": "Url of the file where blockage happened. Optional because of tests.", + "optional": true, + "type": "string" + }, + { + "name": "function", + "description": "Function name where blockage happened. Optional because of anonymous functions and tests.", + "optional": true, + "type": "string" + }, + { "name": "lineNumber", "description": "Line number in the script (0-based).", "type": "integer" }, + { "name": "columnNumber", "description": "Column number in the script (0-based).", "type": "integer" } + ] + }, { "id": "BackForwardCacheNotRestoredExplanation", "experimental": true, @@ -10041,6 +10278,12 @@ "description": "Context associated with the reason. The meaning of this context is\ndependent on the reason:\n- EmbedderExtensionSentMessageToCachedFrame: the extension ID.", "optional": true, "type": "string" + }, + { + "name": "details", + "optional": true, + "type": "array", + "items": { "$ref": "BackForwardCacheBlockingDetails" } } ] }, @@ -10298,21 +10541,6 @@ } ] }, - { - "name": "getCookies", - "description": "Returns all browser cookies for the page and all of its subframes. Depending\non the backend support, will return detailed cookie information in the\n`cookies` field.", - "experimental": true, - "deprecated": true, - "redirect": "Network", - "returns": [ - { - "name": "cookies", - "description": "Array of cookie objects.", - "type": "array", - "items": { "$ref": "Network.Cookie" } - } - ] - }, { "name": "getFrameTree", "description": "Returns present frame tree structure.", @@ -10564,6 +10792,13 @@ "experimental": true, "optional": true, "type": "boolean" + }, + { + "name": "generateDocumentOutline", + "description": "Whether or not to embed the document outline into the PDF.", + "experimental": true, + "optional": true, + "type": "boolean" } ], "returns": [ @@ -11563,7 +11798,6 @@ "MemoryPressureOnTrigger", "MemoryPressureAfterTriggered", "PrerenderingDisabledByDevTools", - "ResourceLoadBlockedByClient", "SpeculationRuleRemoved", "ActivatedWithAuxiliaryBrowsingContexts", "MaxNumOfRunningEagerPrerendersExceeded", @@ -11592,7 +11826,8 @@ "PrefetchFailedNetError", "PrefetchFailedNon2XX", "PrefetchFailedPerPageLimitExceeded", - "PrefetchEvicted", + "PrefetchEvictedAfterCandidateRemoved", + "PrefetchEvictedForNewerPrefetch", "PrefetchHeldback", "PrefetchIneligibleRetryAfter", "PrefetchIsPrivacyDecoy", @@ -11616,6 +11851,16 @@ "PrefetchSuccessfulButNotUsed", "PrefetchNotUsedProbeFailed" ] + }, + { + "id": "PrerenderMismatchedHeaders", + "description": "Information of headers to be displayed when the header mismatch occurred.", + "type": "object", + "properties": [ + { "name": "headerName", "type": "string" }, + { "name": "initialValue", "optional": true, "type": "string" }, + { "name": "activationValue", "optional": true, "type": "string" } + ] } ], "commands": [{ "name": "enable" }, { "name": "disable" }], @@ -11665,6 +11910,12 @@ "description": "This is used to give users more information about the name of Mojo interface\nthat is incompatible with prerender and has caused the cancellation of the attempt.", "optional": true, "type": "string" + }, + { + "name": "mismatchedHeaders", + "optional": true, + "type": "array", + "items": { "$ref": "PrerenderMismatchedHeaders" } } ] }, @@ -12049,7 +12300,8 @@ "type": "number" }, { "name": "controlledClients", "optional": true, "type": "array", "items": { "$ref": "Target.TargetID" } }, - { "name": "targetId", "optional": true, "$ref": "Target.TargetID" } + { "name": "targetId", "optional": true, "$ref": "Target.TargetID" }, + { "name": "routerRules", "optional": true, "type": "string" } ] }, { @@ -12357,6 +12609,24 @@ { "name": "values", "type": "array", "items": { "type": "string" } } ] }, + { + "id": "AttributionReportingFilterConfig", + "experimental": true, + "type": "object", + "properties": [ + { "name": "filterValues", "type": "array", "items": { "$ref": "AttributionReportingFilterDataEntry" } }, + { "name": "lookbackWindow", "description": "duration in seconds", "optional": true, "type": "integer" } + ] + }, + { + "id": "AttributionReportingFilterPair", + "experimental": true, + "type": "object", + "properties": [ + { "name": "filters", "type": "array", "items": { "$ref": "AttributionReportingFilterConfig" } }, + { "name": "notFilters", "type": "array", "items": { "$ref": "AttributionReportingFilterConfig" } } + ] + }, { "id": "AttributionReportingAggregationKeysEntry", "experimental": true, @@ -12375,6 +12645,26 @@ { "name": "ends", "description": "duration in seconds", "type": "array", "items": { "type": "integer" } } ] }, + { + "id": "AttributionReportingTriggerSpec", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "triggerData", + "description": "number instead of integer because not all uint32 can be represented by\nint", + "type": "array", + "items": { "type": "number" } + }, + { "name": "eventReportWindows", "$ref": "AttributionReportingEventReportWindows" } + ] + }, + { + "id": "AttributionReportingTriggerDataMatching", + "experimental": true, + "type": "string", + "enum": ["exact", "modulus"] + }, { "id": "AttributionReportingSourceRegistration", "experimental": true, @@ -12382,7 +12672,7 @@ "properties": [ { "name": "time", "$ref": "Network.TimeSinceEpoch" }, { "name": "expiry", "description": "duration in seconds", "type": "integer" }, - { "name": "eventReportWindows", "$ref": "AttributionReportingEventReportWindows" }, + { "name": "triggerSpecs", "type": "array", "items": { "$ref": "AttributionReportingTriggerSpec" } }, { "name": "aggregatableReportWindow", "description": "duration in seconds", "type": "integer" }, { "name": "type", "$ref": "AttributionReportingSourceType" }, { "name": "sourceOrigin", "type": "string" }, @@ -12396,7 +12686,8 @@ "type": "array", "items": { "$ref": "AttributionReportingAggregationKeysEntry" } }, - { "name": "debugKey", "optional": true, "$ref": "UnsignedInt64AsBase10" } + { "name": "debugKey", "optional": true, "$ref": "UnsignedInt64AsBase10" }, + { "name": "triggerDataMatching", "$ref": "AttributionReportingTriggerDataMatching" } ] }, { @@ -12417,6 +12708,135 @@ "reportingOriginsPerSiteLimitReached", "exceedsMaxChannelCapacity" ] + }, + { + "id": "AttributionReportingSourceRegistrationTimeConfig", + "experimental": true, + "type": "string", + "enum": ["include", "exclude"] + }, + { + "id": "AttributionReportingAggregatableValueEntry", + "experimental": true, + "type": "object", + "properties": [ + { "name": "key", "type": "string" }, + { + "name": "value", + "description": "number instead of integer because not all uint32 can be represented by\nint", + "type": "number" + } + ] + }, + { + "id": "AttributionReportingEventTriggerData", + "experimental": true, + "type": "object", + "properties": [ + { "name": "data", "$ref": "UnsignedInt64AsBase10" }, + { "name": "priority", "$ref": "SignedInt64AsBase10" }, + { "name": "dedupKey", "optional": true, "$ref": "UnsignedInt64AsBase10" }, + { "name": "filters", "$ref": "AttributionReportingFilterPair" } + ] + }, + { + "id": "AttributionReportingAggregatableTriggerData", + "experimental": true, + "type": "object", + "properties": [ + { "name": "keyPiece", "$ref": "UnsignedInt128AsBase16" }, + { "name": "sourceKeys", "type": "array", "items": { "type": "string" } }, + { "name": "filters", "$ref": "AttributionReportingFilterPair" } + ] + }, + { + "id": "AttributionReportingAggregatableDedupKey", + "experimental": true, + "type": "object", + "properties": [ + { "name": "dedupKey", "optional": true, "$ref": "UnsignedInt64AsBase10" }, + { "name": "filters", "$ref": "AttributionReportingFilterPair" } + ] + }, + { + "id": "AttributionReportingTriggerRegistration", + "experimental": true, + "type": "object", + "properties": [ + { "name": "filters", "$ref": "AttributionReportingFilterPair" }, + { "name": "debugKey", "optional": true, "$ref": "UnsignedInt64AsBase10" }, + { + "name": "aggregatableDedupKeys", + "type": "array", + "items": { "$ref": "AttributionReportingAggregatableDedupKey" } + }, + { + "name": "eventTriggerData", + "type": "array", + "items": { "$ref": "AttributionReportingEventTriggerData" } + }, + { + "name": "aggregatableTriggerData", + "type": "array", + "items": { "$ref": "AttributionReportingAggregatableTriggerData" } + }, + { + "name": "aggregatableValues", + "type": "array", + "items": { "$ref": "AttributionReportingAggregatableValueEntry" } + }, + { "name": "debugReporting", "type": "boolean" }, + { "name": "aggregationCoordinatorOrigin", "optional": true, "type": "string" }, + { "name": "sourceRegistrationTimeConfig", "$ref": "AttributionReportingSourceRegistrationTimeConfig" }, + { "name": "triggerContextId", "optional": true, "type": "string" } + ] + }, + { + "id": "AttributionReportingEventLevelResult", + "experimental": true, + "type": "string", + "enum": [ + "success", + "successDroppedLowerPriority", + "internalError", + "noCapacityForAttributionDestination", + "noMatchingSources", + "deduplicated", + "excessiveAttributions", + "priorityTooLow", + "neverAttributedSource", + "excessiveReportingOrigins", + "noMatchingSourceFilterData", + "prohibitedByBrowserPolicy", + "noMatchingConfigurations", + "excessiveReports", + "falselyAttributedSource", + "reportWindowPassed", + "notRegistered", + "reportWindowNotStarted", + "noMatchingTriggerData" + ] + }, + { + "id": "AttributionReportingAggregatableResult", + "experimental": true, + "type": "string", + "enum": [ + "success", + "internalError", + "noCapacityForAttributionDestination", + "noMatchingSources", + "excessiveAttributions", + "excessiveReportingOrigins", + "noHistograms", + "insufficientBudget", + "noMatchingSourceFilterData", + "notRegistered", + "prohibitedByBrowserPolicy", + "deduplicated", + "reportWindowPassed", + "excessiveReports" + ] } ], "commands": [ @@ -12782,12 +13202,20 @@ { "name": "storageBucketDeleted", "parameters": [{ "name": "bucketId", "type": "string" }] }, { "name": "attributionReportingSourceRegistered", - "description": "TODO(crbug.com/1458532): Add other Attribution Reporting events, e.g.\ntrigger registration.", "experimental": true, "parameters": [ { "name": "registration", "$ref": "AttributionReportingSourceRegistration" }, { "name": "result", "$ref": "AttributionReportingSourceRegistrationResult" } ] + }, + { + "name": "attributionReportingTriggerRegistered", + "experimental": true, + "parameters": [ + { "name": "registration", "$ref": "AttributionReportingTriggerRegistration" }, + { "name": "eventLevel", "$ref": "AttributionReportingEventLevelResult" }, + { "name": "aggregatable", "$ref": "AttributionReportingAggregatableResult" } + ] } ] }, @@ -14065,6 +14493,18 @@ "description": "Sets whether User Verification succeeds or fails for an authenticator.\nDefaults to false.", "optional": true, "type": "boolean" + }, + { + "name": "defaultBackupEligibility", + "description": "Credentials created by this authenticator will have the backup\neligibility (BE) flag set to this value. Defaults to false.\nhttps://w3c.github.io/webauthn/#sctn-credential-backup", + "optional": true, + "type": "boolean" + }, + { + "name": "defaultBackupState", + "description": "Credentials created by this authenticator will have the backup state\n(BS) flag set to this value. Defaults to false.\nhttps://w3c.github.io/webauthn/#sctn-credential-backup", + "optional": true, + "type": "boolean" } ] }, diff --git a/packages/bun-inspector-protocol/test/inspector/worker.js b/packages/bun-inspector-protocol/test/inspector/worker.js new file mode 100644 index 0000000000..efbc46d563 --- /dev/null +++ b/packages/bun-inspector-protocol/test/inspector/worker.js @@ -0,0 +1 @@ +console.log(process.execArgv); diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index dde2564118..3f3160462a 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -4814,10 +4814,6 @@ restart: visitedProperties.append(Identifier::fromUid(vm, prop)); ZigString key = toZigString(prop); - - if (key.len == 0) - return true; - JSC::JSValue propertyValue = JSValue(); if (objectToUse == object) { diff --git a/src/js/internal/debugger.ts b/src/js/internal/debugger.ts index abb1ec3736..248ba95eef 100644 --- a/src/js/internal/debugger.ts +++ b/src/js/internal/debugger.ts @@ -208,7 +208,6 @@ function versionInfo(): unknown { return { "Protocol-Version": "1.3", "Browser": "Bun", - // @ts-ignore: Missing types for `navigator` "User-Agent": navigator.userAgent, "WebKit-Version": process.versions.webkit, "Bun-Version": Bun.version, @@ -264,27 +263,32 @@ function bufferedWriter(writer: Writer): Writer { const defaultHostname = "localhost"; const defaultPort = 6499; -function parseUrl(url: string): URL { - try { - if (!url) { - return new URL(randomId(), `ws://${defaultHostname}:${defaultPort}/`); - } else if (url.startsWith("/")) { - return new URL(url, `ws://${defaultHostname}:${defaultPort}/`); - } else if (/^[a-z+]+:\/\//i.test(url)) { - return new URL(url); - } else if (/^\d+$/.test(url)) { - return new URL(randomId(), `ws://${defaultHostname}:${url}/`); - } else if (!url.includes("/") && url.includes(":")) { - return new URL(randomId(), `ws://${url}/`); - } else if (!url.includes(":")) { - const [hostname, pathname] = url.split("/", 2); - return new URL(`ws://${hostname}:${defaultPort}/${pathname}`); - } else { - return new URL(randomId(), `ws://${url}`); +function parseUrl(input: string): URL { + const url = new URL(`ws://${defaultHostname}:${defaultPort}/${randomId()}`); + for (const part of input.split(/(\[[a-z0-9:]+\])|:/).filter(Boolean)) { + if (/^\d+$/.test(part)) { + url.port = part; + continue; + } + if (part.startsWith("[")) { + url.hostname = part; + continue; + } + if (part.startsWith("/")) { + url.pathname = part; + continue; + } + const [hostname, ...pathnames] = part.split("/"); + if (/^\d+$/.test(hostname)) { + url.port = hostname; + } else { + url.hostname = hostname; + } + if (pathnames.length) { + url.pathname = `/${pathnames.join("/")}`; } - } catch { - throw new TypeError(`Invalid hostname or URL: '${url}'`); } + return url; } function randomId() { diff --git a/test/bun.lockb b/test/bun.lockb index d166b9b608..4289360c49 100755 Binary files a/test/bun.lockb and b/test/bun.lockb differ diff --git a/test/cli/inspect/inspect.test.ts b/test/cli/inspect/inspect.test.ts new file mode 100644 index 0000000000..033afb5640 --- /dev/null +++ b/test/cli/inspect/inspect.test.ts @@ -0,0 +1,259 @@ +import { describe, test, expect, afterEach } from "bun:test"; +import { bunExe, bunEnv, randomPort } from "harness"; +import { Subprocess, spawn } from "bun"; +import { WebSocket } from "ws"; + +let inspectee: Subprocess; + +const anyPort = expect.stringMatching(/^\d+$/); +const anyPathname = expect.stringMatching(/^\/[a-z0-9]+$/); +const tests = [ + { + args: ["--inspect"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: anyPathname, + }, + }, + { + args: ["--inspect=0"], + url: { + protocol: "ws:", + hostname: "localhost", + port: anyPort, + pathname: anyPathname, + }, + }, + { + args: [`--inspect=${randomPort()}`], + url: { + protocol: "ws:", + hostname: "localhost", + port: anyPort, + pathname: anyPathname, + }, + }, + { + args: ["--inspect=localhost"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: anyPathname, + }, + }, + { + args: ["--inspect=localhost/"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: "/", + }, + }, + { + args: ["--inspect=localhost:0"], + url: { + protocol: "ws:", + hostname: "localhost", + port: anyPort, + pathname: anyPathname, + }, + }, + { + args: ["--inspect=localhost:0/"], + url: { + protocol: "ws:", + hostname: "localhost", + port: anyPort, + pathname: "/", + }, + }, + { + args: ["--inspect=localhost/foo/bar"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: "/foo/bar", + }, + }, + { + args: ["--inspect=127.0.0.1"], + url: { + protocol: "ws:", + hostname: "127.0.0.1", + port: "6499", + pathname: anyPathname, + }, + }, + { + args: ["--inspect=127.0.0.1/"], + url: { + protocol: "ws:", + hostname: "127.0.0.1", + port: "6499", + pathname: "/", + }, + }, + { + args: ["--inspect=127.0.0.1:0/"], + url: { + protocol: "ws:", + hostname: "127.0.0.1", + port: anyPort, + pathname: "/", + }, + }, + { + args: ["--inspect=[::1]"], + url: { + protocol: "ws:", + hostname: "[::1]", + port: "6499", + pathname: anyPathname, + }, + }, + { + args: ["--inspect=[::1]:0"], + url: { + protocol: "ws:", + hostname: "[::1]", + port: anyPort, + pathname: anyPathname, + }, + }, + { + args: ["--inspect=[::1]:0/"], + url: { + protocol: "ws:", + hostname: "[::1]", + port: anyPort, + pathname: "/", + }, + }, + { + args: ["--inspect=/"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: "/", + }, + }, + { + args: ["--inspect=/foo"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: "/foo", + }, + }, + { + args: ["--inspect=/foo/baz/"], + url: { + protocol: "ws:", + hostname: "localhost", + port: "6499", + pathname: "/foo/baz/", + }, + }, + { + args: ["--inspect=:0"], + url: { + protocol: "ws:", + hostname: "localhost", + port: anyPort, + pathname: anyPathname, + }, + }, + { + args: ["--inspect=:0/"], + url: { + protocol: "ws:", + hostname: "localhost", + port: anyPort, + pathname: "/", + }, + }, +]; + +for (const { args, url: expected } of tests) { + test(`bun ${args.join(" ")}`, async () => { + inspectee = spawn({ + cwd: import.meta.dir, + cmd: [bunExe(), ...args, "inspectee.js"], + env: bunEnv, + stdout: "ignore", + stderr: "pipe", + }); + + let url: URL | undefined; + let stderr = ""; + const decoder = new TextDecoder(); + for await (const chunk of inspectee.stderr as ReadableStream) { + stderr += decoder.decode(chunk); + for (const line of stderr.split("\n")) { + try { + url = new URL(line); + } catch { + // Ignore + } + if (url?.protocol.includes("ws")) { + break; + } + } + if (stderr.includes("Listening:")) { + break; + } + } + + if (!url) { + process.stderr.write(stderr); + throw new Error("Unable to find listening URL"); + } + + const { protocol, hostname, port, pathname } = url; + expect({ + protocol, + hostname, + port, + pathname, + }).toMatchObject(expected); + + const webSocket = new WebSocket(url); + expect( + new Promise((resolve, reject) => { + webSocket.addEventListener("open", () => resolve()); + webSocket.addEventListener("error", cause => reject(new Error("WebSocket error", { cause }))); + webSocket.addEventListener("close", cause => reject(new Error("WebSocket closed", { cause }))); + }), + ).resolves.toBeUndefined(); + + webSocket.send(JSON.stringify({ id: 1, method: "Runtime.evaluate", params: { expression: "1 + 1" } })); + expect( + new Promise(resolve => { + webSocket.addEventListener("message", ({ data }) => { + resolve(JSON.parse(data.toString())); + }); + }), + ).resolves.toMatchObject({ + id: 1, + result: { + result: { + type: "number", + value: 2, + }, + }, + }); + + webSocket.close(); + }); +} + +afterEach(() => { + inspectee?.kill(); +}); diff --git a/test/cli/inspect/inspectee.js b/test/cli/inspect/inspectee.js new file mode 100644 index 0000000000..e2d1f60984 --- /dev/null +++ b/test/cli/inspect/inspectee.js @@ -0,0 +1,3 @@ +console.log("Hello"); + +setTimeout(() => {}, 30_000); diff --git a/test/cli/watch/watch.test.ts b/test/cli/watch/watch.test.ts new file mode 100644 index 0000000000..fc4d65a1da --- /dev/null +++ b/test/cli/watch/watch.test.ts @@ -0,0 +1,33 @@ +import { describe, test, expect, afterEach } from "bun:test"; +import type { Subprocess } from "bun"; +import { spawn } from "bun"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; +import { mkdtempSync, writeFileSync } from "node:fs"; +import { bunExe, bunEnv } from "harness"; + +let watchee: Subprocess; + +describe("bun --watch", () => { + const cwd = mkdtempSync(join(tmpdir(), "bun-test-")); + const path = join(cwd, "watchee.js"); + + const updateFile = (i: number) => { + writeFileSync(path, `console.log(${i});`); + }; + + test("should watch files", async () => { + watchee = spawn({ + cwd, + cmd: [bunExe(), "--watch", "watchee.js"], + env: bunEnv, + stdout: "inherit", + stderr: "inherit", + }); + await Bun.sleep(2000); + }); +}); + +afterEach(() => { + watchee?.kill(); +}); diff --git a/test/harness.ts b/test/harness.ts index 2e2c64eeaf..f3aae8154f 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -1,6 +1,7 @@ -import { gc as bunGC, stdout, unsafe, which } from "bun"; +import { gc as bunGC, unsafe, which } from "bun"; import { expect } from "bun:test"; -export const bunEnv: any = { + +export const bunEnv: NodeJS.ProcessEnv = { ...process.env, GITHUB_ACTIONS: "false", BUN_DEBUG_QUIET_LOGS: "1", @@ -174,6 +175,10 @@ export function fakeNodeRun(dir: string, file: string | string[], env?: Record